<commit_before># coding: utf-8
import responses
import pytest
import kiteconnect.exceptions as ex

from .conftest import fp

def test_set_access_token(kiteconnect):
    """Check for token exception when invalid token is set."""
    kiteconnect.root = "https://api.kite.trade"
    kiteconnect.set_access_token("invalid_token")
    with pytest.raises(ex.TokenException):
        kiteconnect.positions()

@responses.activate
def test_positions(kiteconnect):
    """Test positions."""
    responses.add(
        responses.GET,
        "%s%s" % (kiteconnect.root, kiteconnect._routes["portfolio.positions"]),
        body=open(fp("responses/positions.json"), "r").read(),
        content_type="application/json"
    )
    positions = kiteconnect.positions()
    assert type(positions) == dict
    assert "day" in positions
    assert "net" in positions

@responses.activate
def test_holdings(kiteconnect):
    """Test holdings."""
    responses.add(
        responses.GET,
        "%s%s" % (kiteconnect.root, kiteconnect._routes["portfolio.holdings"]),
        body=open(fp("responses/holdings.json"), "r").read(),
        content_type="application/json"
    )
    holdings = kiteconnect.holdings()
    assert type(holdings) == list

@responses.activate
def test_margins(kiteconnect):
    """Test margins."""
    responses.add(
        responses.GET,
        "%s%s" % (kiteconnect.root, kiteconnect._routes["user.margins"]),
        body=open(fp("responses/margins.json"), "r").read(),
        content_type="application/json"
    )
    margins = kiteconnect.margins()
    assert type(margins) == dict
    assert kiteconnect.MARGIN_EQUITY in margins
    assert kiteconnect.MARGIN_COMMODITY in margins

@responses.activate
def test_margins_segmentwise(kiteconnect):
    """Test margins for individual segments."""
    responses.add(
        responses.GET,
        "%s%s" % (
            kiteconnect.root,
            kiteconnect._routes["user.margins.segment"].format(
                segment=kiteconnect.MARGIN_COMMODITY
            )
        ),
        body=open(fp("responses/margins.json"), "r").read(),
        content_type="application/json"
    )
    commodity = kiteconnect.margins(segment=kiteconnect.MARGIN_COMMODITY)
    assert type(commodity) == dict

@responses.activate
def test_orders(kiteconnect):
    """Test orders."""
    responses.add(
        responses.GET,
        "%s%s" % (kiteconnect.root, kiteconnect._routes["orders"]),
        body=open(fp("responses/orders.json"), "r").read(),
        content_type="application/json"
    )
    orders = kiteconnect.orders()
    assert type(orders) == list

@responses.activate
def test_trades(kiteconnect):
    """Test trades."""
    responses.add(
        responses.GET,
        "%s%s" % (kiteconnect.root, kiteconnect._routes["trades"]),
        body=open(fp("responses/trades.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.trades()
    assert type(trades) == list

@responses.activate
def test_instruments(kiteconnect):
    """Test mf instruments fetch."""
    responses.add(
        responses.GET,
        "%s%s" % (kiteconnect.root, kiteconnect._routes["market.instruments.all"]),
        body=open(fp("responses/instruments_all.csv"), "r").read(),
        content_type="text/csv"
    )
    trades = kiteconnect.instruments()
    assert type(trades) == list

@responses.activate
def test_mf_orders(kiteconnect):
    """Test mf orders get."""
    responses.add(
        responses.GET,
        "%s%s" % (kiteconnect.root, kiteconnect._routes["mf.orders"]),
        body=open(fp("responses/mf_orders.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.mf_orders()
    assert type(trades) == list

@responses.activate
def test_mf_individual_order(kiteconnect):
    """Test mf orders get."""
    responses.add(
        responses.GET,
        "%s%s/%s" % (kiteconnect.root, kiteconnect._routes["mf.orders"], "abc123"),
        body=open(fp("responses/mf_individual_order.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.mf_orders(order_id="abc123")
    assert type(trades) == dict

@responses.activate
def test_mf_sips(kiteconnect):
    """Test mf sips get."""
    responses.add(
        responses.GET,
        "%s%s" % (kiteconnect.root, kiteconnect._routes["mf.sips"]),
        body=open(fp("responses/mf_sips.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.mf_sips()
    assert type(trades) == list

@responses.activate
def test_mf_individual_sip(kiteconnect):
    """Test mf sips get."""
    responses.add(
        responses.GET,
        "%s%s/%s" % (kiteconnect.root, kiteconnect._routes["mf.sips"], "abc123"),
        body=open(fp("responses/mf_individual_sip.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.mf_sips(sip_id="abc123")
    assert type(trades) == dict

@responses.activate
def test_mf_holdings(kiteconnect):
    """Test mf holdings."""
    responses.add(
        responses.GET,
        "%s%s" % (kiteconnect.root, kiteconnect._routes["mf.holdings"]),
        body=open(fp("responses/mf_holdings.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.mf_holdings()
    assert type(trades) == list

@responses.activate
def test_mf_instruments(kiteconnect):
    """Test mf instruments fetch."""
    responses.add(
        responses.GET,
        "%s%s" % (kiteconnect.root, kiteconnect._routes["mf.instruments"]),
        body=open(fp("responses/mf_instruments.csv"), "r").read(),
        content_type="text/csv"
    )
    trades = kiteconnect.mf_instruments()
    assert type(trades) == list
<commit_msg>Use format method for string formatting in tests<commit_after># coding: utf-8
import responses
import pytest
import kiteconnect.exceptions as ex

from .conftest import fp

def test_set_access_token(kiteconnect):
    """Check for token exception when invalid token is set."""
    kiteconnect.root = "https://api.kite.trade"
    kiteconnect.set_access_token("invalid_token")
    with pytest.raises(ex.TokenException):
        kiteconnect.positions()

@responses.activate
def test_positions(kiteconnect):
    """Test positions."""
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, kiteconnect._routes["portfolio.positions"]),
        body=open(fp("responses/positions.json"), "r").read(),
        content_type="application/json"
    )
    positions = kiteconnect.positions()
    assert type(positions) == dict
    assert "day" in positions
    assert "net" in positions

@responses.activate
def test_holdings(kiteconnect):
    """Test holdings."""
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, kiteconnect._routes["portfolio.holdings"]),
        body=open(fp("responses/holdings.json"), "r").read(),
        content_type="application/json"
    )
    holdings = kiteconnect.holdings()
    assert type(holdings) == list

@responses.activate
def test_margins(kiteconnect):
    """Test margins."""
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, kiteconnect._routes["user.margins"]),
        body=open(fp("responses/margins.json"), "r").read(),
        content_type="application/json"
    )
    margins = kiteconnect.margins()
    assert type(margins) == dict
    assert kiteconnect.MARGIN_EQUITY in margins
    assert kiteconnect.MARGIN_COMMODITY in margins

@responses.activate
def test_margins_segmentwise(kiteconnect):
    """Test margins for individual segments."""
    responses.add(
        responses.GET,
        "{0}{1}".format(
            kiteconnect.root,
            kiteconnect._routes["user.margins.segment"].format(
                segment=kiteconnect.MARGIN_COMMODITY
            )
        ),
        body=open(fp("responses/margins.json"), "r").read(),
        content_type="application/json"
    )
    commodity = kiteconnect.margins(segment=kiteconnect.MARGIN_COMMODITY)
    assert type(commodity) == dict

@responses.activate
def test_orders(kiteconnect):
    """Test orders."""
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, kiteconnect._routes["orders"]),
        body=open(fp("responses/orders.json"), "r").read(),
        content_type="application/json"
    )
    orders = kiteconnect.orders()
    assert type(orders) == list

@responses.activate
def test_trades(kiteconnect):
    """Test trades."""
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, kiteconnect._routes["trades"]),
        body=open(fp("responses/trades.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.trades()
    assert type(trades) == list

@responses.activate
def test_instruments(kiteconnect):
    """Test mf instruments fetch."""
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, kiteconnect._routes["market.instruments.all"]),
        body=open(fp("responses/instruments_all.csv"), "r").read(),
        content_type="text/csv"
    )
    trades = kiteconnect.instruments()
    assert type(trades) == list

@responses.activate
@responses.activate
def test_mf_orders(kiteconnect):
    """Test mf orders get."""
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, kiteconnect._routes["mf.orders"]),
        body=open(fp("responses/mf_orders.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.mf_orders()
    assert type(trades) == list

@responses.activate
def test_mf_individual_order(kiteconnect):
    """Test mf orders get."""
    url = kiteconnect._routes["mf.order.info"].format(order_id="abc123")
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, url),
        body=open(fp("responses/mf_individual_order.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.mf_orders(order_id="abc123")
    assert type(trades) == dict

@responses.activate
def test_mf_sips(kiteconnect):
    """Test mf sips get."""
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, kiteconnect._routes["mf.sips"]),
        body=open(fp("responses/mf_sips.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.mf_sips()
    assert type(trades) == list

@responses.activate
def test_mf_individual_sip(kiteconnect):
    """Test mf sips get."""
    url = kiteconnect._routes["mf.sip.info"].format(sip_id="abc123")
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, url),
        body=open(fp("responses/mf_individual_sip.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.mf_sips(sip_id="abc123")
    assert type(trades) == dict

@responses.activate
def test_mf_holdings(kiteconnect):
    """Test mf holdings."""
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, kiteconnect._routes["mf.holdings"]),
        body=open(fp("responses/mf_holdings.json"), "r").read(),
        content_type="application/json"
    )
    trades = kiteconnect.mf_holdings()
    assert type(trades) == list

@responses.activate
def test_mf_instruments(kiteconnect):
    """Test mf instruments fetch."""
    responses.add(
        responses.GET,
        "{0}{1}".format(kiteconnect.root, kiteconnect._routes["mf.instruments"]),
        body=open(fp("responses/mf_instruments.csv"), "r").read(),
        content_type="text/csv"
    )
    trades = kiteconnect.mf_instruments()
    assert type(trades) == list
<|endoftext|>


<commit_before>import time
import gc

import pytest

import vanilla

class TestHub(object):
    def test_spawn(self):
        h = vanilla.Hub()
        a = []

        h.spawn_later(10, lambda: a.append(1))
        h.spawn(lambda: a.append(2))

        h.sleep(1)
        assert a == [2]

        h.sleep(10)
        assert a == [2, 1]

class TestPiping(object):
    def test_stream(self):
        h = vanilla.Hub()

        @h.stream
        def counter(sender):
            for i in xrange(10):
                sender.send(i)

        assert counter.recv() == 0
        h.sleep(10)
        assert counter.recv() == 1

    def test_abandoned_sender(self):
        h = vanilla.Hub()

        check_sender, check_recver = h.pipe()

        # test abondoned after pause
        sender, recver = h.pipe()

        @h.spawn
        def _():
            pytest.raises(vanilla.Abandoned, sender.send, 10)
            check_sender.send('done')

        # sleep so the spawn runs and the send pauses
        h.sleep(1)
        del recver
        gc.collect()
        assert check_recver.recv() == 'done'

        # test abondoned before pause
        sender, recver = h.pipe()

        @h.spawn
        def _():
            pytest.raises(vanilla.Abandoned, sender.send, 10)
            check_sender.send('done')

        del recver
        gc.collect()
        assert check_recver.recv() == 'done'

    def test_abandoned_recver(self):
        h = vanilla.Hub()

        check_sender, check_recver = h.pipe()

        # test abondoned after pause
        sender, recver = h.pipe()

        @h.spawn
        def _():
            pytest.raises(vanilla.Abandoned, recver.recv)
            check_sender.send('done')

        # sleep so the spawn runs and the recv pauses
        h.sleep(1)
        del sender
        gc.collect()
        assert check_recver.recv() == 'done'

        # test abondoned before pause
        sender, recver = h.pipe()

        @h.spawn
        def _():
            pytest.raises(vanilla.Abandoned, recver.recv)
            check_sender.send('done')

        del sender
        gc.collect()
        assert check_recver.recv() == 'done'

    def test_pulse(self):
        h = vanilla.Hub()

        trigger = h.pulse(20)
        pytest.raises(vanilla.Timeout, trigger.recv, timeout=0)

        h.sleep(20)
        assert trigger.recv(timeout=0)
        pytest.raises(vanilla.Timeout, trigger.recv, timeout=0)

        h.sleep(20)
        assert trigger.recv(timeout=0)
        pytest.raises(vanilla.Timeout, trigger.recv, timeout=0)

        # TODO: test abandoned

    def test_select(self):
        h = vanilla.Hub()

        s1, r1 = h.pipe()
        s2, r2 = h.pipe()
        check_s, check_r = h.pipe()

        @h.spawn
        def _():
            check_s.send(r1.recv())

        @h.spawn
        def _():
            s2.send(10)
            check_s.send('done')

        ch, item = h.select([s1, r2])
        assert ch == s1
        s1.send(20)

        ch, item = h.select([s1, r2])
        assert ch == r2
        assert item == 10

        assert check_r.recv() == 20
        assert check_r.recv() == 'done'

    def test_select_timeout(self):
        h = vanilla.Hub()

        s1, r1 = h.pipe()
        s2, r2 = h.pipe()
        check_s, check_r = h.pipe()

        pytest.raises(vanilla.Timeout, h.select, [s1, r2], timeout=0)

        @h.spawn
        def _():
            h.sleep(20)
            check_s.send(r1.recv())

        pytest.raises(vanilla.Timeout, h.select, [s1, r2], timeout=10)

        ch, item = h.select([s1, r2], timeout=20)
        assert ch == s1
        s1.send(20)
        assert check_r.recv() == 20

        @h.spawn
        def _():
            h.sleep(20)
            s2.send(10)
            check_s.send('done')

        pytest.raises(vanilla.Timeout, h.select, [s1, r2], timeout=10)

        ch, item = h.select([s1, r2], timeout=20)
        assert ch == r2
        assert item == 10
        assert check_r.recv() == 'done'

    def test_timeout(self):
        h = vanilla.Hub()

        sender, recver = h.pipe()
        check_sender, check_recver = h.pipe()

        pytest.raises(vanilla.Timeout, sender.send, 12, timeout=0)
        pytest.raises(vanilla.Timeout, recver.recv, timeout=0)
        pytest.raises(vanilla.Timeout, sender.send, 12, timeout=0)

        @h.spawn
        def _():
            h.sleep(20)
            check_sender.send(recver.recv())

        pytest.raises(vanilla.Timeout, sender.send, 12, timeout=10)
        sender.send(12, timeout=20)
        assert check_recver.recv() == 12

        @h.spawn
        def _():
            h.sleep(20)
            sender.send(12)

        pytest.raises(vanilla.Timeout, recver.recv, timeout=10)
        assert recver.recv(timeout=20) == 12

    """
    def test_buffer(self):
        h = vanilla.Hub()
        sender, recver = buffer(h, 2)
        sender.send(1)
        sender.send(2)
        assert recver.recv() == 1
        assert recver.recv() == 2
    """

def test_lazy():
    class C(object):
        @vanilla.lazy
        def now(self):
            return time.time()

    c = C()
    want = c.now
    time.sleep(0.01)
    assert c.now == want

def test_Scheduler():
    s = vanilla.Scheduler()
    s.add(4, 'f2')
    s.add(9, 'f4')
    s.add(3, 'f1')
    item3 = s.add(7, 'f3')

    assert 0.003 - s.timeout() < 0.0005
    assert len(s) == 4

    s.remove(item3)
    assert 0.003 - s.timeout() < 0.0005
    assert len(s) == 3

    assert s.pop() == ('f1', ())
    assert 0.004 - s.timeout() < 0.0005
    assert len(s) == 2

    assert s.pop() == ('f2', ())
    assert 0.009 - s.timeout() < 0.0005
    assert len(s) == 1

    assert s.pop() == ('f4', ())
    assert not s
<commit_msg>reorder tests<commit_after>import time
import gc

import pytest

import vanilla

class TestHub(object):
    def test_spawn(self):
        h = vanilla.Hub()
        a = []

        h.spawn_later(10, lambda: a.append(1))
        h.spawn(lambda: a.append(2))

        h.sleep(1)
        assert a == [2]

        h.sleep(10)
        assert a == [2, 1]

class TestPiping(object):
    def test_timeout(self):
        h = vanilla.Hub()

        sender, recver = h.pipe()
        check_sender, check_recver = h.pipe()

        pytest.raises(vanilla.Timeout, sender.send, 12, timeout=0)
        pytest.raises(vanilla.Timeout, recver.recv, timeout=0)
        pytest.raises(vanilla.Timeout, sender.send, 12, timeout=0)

        @h.spawn
        def _():
            h.sleep(20)
            check_sender.send(recver.recv())

        pytest.raises(vanilla.Timeout, sender.send, 12, timeout=10)
        sender.send(12, timeout=20)
        assert check_recver.recv() == 12

        @h.spawn
        def _():
            h.sleep(20)
            sender.send(12)

        pytest.raises(vanilla.Timeout, recver.recv, timeout=10)
        assert recver.recv(timeout=20) == 12

    def test_select(self):
        h = vanilla.Hub()

        s1, r1 = h.pipe()
        s2, r2 = h.pipe()
        check_s, check_r = h.pipe()

        @h.spawn
        def _():
            check_s.send(r1.recv())

        @h.spawn
        def _():
            s2.send(10)
            check_s.send('done')

        ch, item = h.select([s1, r2])
        assert ch == s1
        s1.send(20)

        ch, item = h.select([s1, r2])
        assert ch == r2
        assert item == 10

        assert check_r.recv() == 20
        assert check_r.recv() == 'done'

    def test_select_timeout(self):
        h = vanilla.Hub()

        s1, r1 = h.pipe()
        s2, r2 = h.pipe()
        check_s, check_r = h.pipe()

        pytest.raises(vanilla.Timeout, h.select, [s1, r2], timeout=0)

        @h.spawn
        def _():
            h.sleep(20)
            check_s.send(r1.recv())

        pytest.raises(vanilla.Timeout, h.select, [s1, r2], timeout=10)

        ch, item = h.select([s1, r2], timeout=20)
        assert ch == s1
        s1.send(20)
        assert check_r.recv() == 20

        @h.spawn
        def _():
            h.sleep(20)
            s2.send(10)
            check_s.send('done')

        pytest.raises(vanilla.Timeout, h.select, [s1, r2], timeout=10)

        ch, item = h.select([s1, r2], timeout=20)
        assert ch == r2
        assert item == 10
        assert check_r.recv() == 'done'

    def test_abandoned_sender(self):
        h = vanilla.Hub()

        check_sender, check_recver = h.pipe()

        # test abondoned after pause
        sender, recver = h.pipe()

        @h.spawn
        def _():
            pytest.raises(vanilla.Abandoned, sender.send, 10)
            check_sender.send('done')

        # sleep so the spawn runs and the send pauses
        h.sleep(1)
        del recver
        gc.collect()
        assert check_recver.recv() == 'done'

        # test abondoned before pause
        sender, recver = h.pipe()

        @h.spawn
        def _():
            pytest.raises(vanilla.Abandoned, sender.send, 10)
            check_sender.send('done')

        del recver
        gc.collect()
        assert check_recver.recv() == 'done'

    def test_abandoned_recver(self):
        h = vanilla.Hub()

        check_sender, check_recver = h.pipe()

        # test abondoned after pause
        sender, recver = h.pipe()

        @h.spawn
        def _():
            pytest.raises(vanilla.Abandoned, recver.recv)
            check_sender.send('done')

        # sleep so the spawn runs and the recv pauses
        h.sleep(1)
        del sender
        gc.collect()
        assert check_recver.recv() == 'done'

        # test abondoned before pause
        sender, recver = h.pipe()

        @h.spawn
        def _():
            pytest.raises(vanilla.Abandoned, recver.recv)
            check_sender.send('done')

        del sender
        gc.collect()
        assert check_recver.recv() == 'done'

    def test_stream(self):
        h = vanilla.Hub()

        @h.stream
        def counter(sender):
            for i in xrange(10):
                sender.send(i)

        assert counter.recv() == 0
        h.sleep(10)
        assert counter.recv() == 1

    def test_pulse(self):
        h = vanilla.Hub()

        trigger = h.pulse(20)
        pytest.raises(vanilla.Timeout, trigger.recv, timeout=0)

        h.sleep(20)
        assert trigger.recv(timeout=0)
        pytest.raises(vanilla.Timeout, trigger.recv, timeout=0)

        h.sleep(20)
        assert trigger.recv(timeout=0)
        pytest.raises(vanilla.Timeout, trigger.recv, timeout=0)

        # TODO: test abandoned

    """
    def test_buffer(self):
        h = vanilla.Hub()
        sender, recver = buffer(h, 2)
        sender.send(1)
        sender.send(2)
        assert recver.recv() == 1
        assert recver.recv() == 2
    """

def test_lazy():
    class C(object):
        @vanilla.lazy
        def now(self):
            return time.time()

    c = C()
    want = c.now
    time.sleep(0.01)
    assert c.now == want

def test_Scheduler():
    s = vanilla.Scheduler()
    s.add(4, 'f2')
    s.add(9, 'f4')
    s.add(3, 'f1')
    item3 = s.add(7, 'f3')

    assert 0.003 - s.timeout() < 0.0005
    assert len(s) == 4

    s.remove(item3)
    assert 0.003 - s.timeout() < 0.0005
    assert len(s) == 3

    assert s.pop() == ('f1', ())
    assert 0.004 - s.timeout() < 0.0005
    assert len(s) == 2

    assert s.pop() == ('f2', ())
    assert 0.009 - s.timeout() < 0.0005
    assert len(s) == 1

    assert s.pop() == ('f4', ())
    assert not s
<|endoftext|>


<commit_before>from display import *
from matrix import *
from math import *

from linalg import *

def draw_line(screen, p0, p1, color):
    plotxyz = lambda p: plot(screen, color, p[0], p[1], p[2])
    bresenham(p0, p1, plotxyz)

def generate_line(p0, p1, L=[]):
    f = lambda p: L.append( (p[0], p[1], p[2]) )
    bresenham(p0, p1, f)
    #print p0, p1
    #print L
    #print
    return L

def bresenham(p0, p1, operation):
    (x0, y0, z0) = p0
    (x1, y1, z1) = p1

    dx = x1 - x0
    dy = y1 - y0

    if dx + dy < 0:
        bresenham(p1, p0, operation)
        return

    def z_of(x, y):
        if (x0, y0) == (x1, y1):
            return max(z0, z1)
        else:
            return dot_product([z0, z1], barycentric([[x0, y0], [x1, y1]], [x, y]))

    do_xy = lambda x, y: operation((x, y, z_of(x, y) ))

    if dx == 0:
        y = int(y0)
        while y <= y1:
            do_xy(int(x0), y)
            y += 1
    elif dy == 0:
        x = int(x0)
        while x <= x1:
            do_xy(x, int(y0))
            x += 1
    elif dy < 0:
        d = 0
        x = int(x0)
        y = int(y0)
        while x <= x1:
            do_xy(x, y)
            if d > 0:
                y -= 1
                d -= dx
            x += 1
            d -= dy
    elif dx < 0:
        d = 0
        x = int(x0)
        y = int(y0)
        while y <= y1:
            do_xy(x, y)
            if d > 0:
                x -= 1
                d -= dy
            y += 1
            d -= dx
    elif dx > dy:
        d = 0
        x = int(x0)
        y = int(y0)
        while x <= x1:
            do_xy(x, y)
            if d > 0:
                y += 1
                d -= dx
            x += 1
            d += dy
    else:
        d = 0
        x = int(x0)
        y = int(y0)
        while y <= y1:
            do_xy(x, y)
            if d > 0:
                x += 1
                d -= dy
            y += 1
            d += dx

def draw_lines( matrix, screen, color ):
    if len(matrix) == 0:
        return

    if len(matrix) % 2:
        raise ValueError("Need at least 2 points to draw a line")

    p = 0
    while p < len( matrix ) - 1:
        draw_line( screen, (matrix[p][0], matrix[p][1], matrix[p][2]),
                   (matrix[p+1][0], matrix[p+1][1], matrix[p+1][2]), color )
        p += 2

def draw_polygons(matrix, screen, color):
    if len(matrix) == 0:
        return

    if len(matrix) % 3:
        raise ValueError("Need 3 points to draw a triangle")

    for p in range(0, len(matrix), 3):
        draw_triangle(matrix, p, screen, color, fill=True)

def draw_triangle(matrix, index, screen, color, fill=False):
    # Shorthand for the three vertices
    p0 = matrix[index]
    p1 = matrix[index + 1]
    p2 = matrix[index + 2]

    normal = surface_normal(matrix, index)

    # default is [0, 0, 1]
    view = [0, 0, 1]

    edges = [p0, p1, p1, p2, p2, p0]

    frontness = dot_product(view, normal)

    # Front faces
    if frontness > 0:
        # Fill the triangle
        if fill:
            # sort vertices by y-coordinate so we can scanline bottom to top
            vertices = sorted([p0, p1, p2], key = lambda p: p[1])
            bottom = vertices[0][:3]
            middle = vertices[1][:3]
            top    = vertices[2][:3]

            L = generate_line(middle, top, generate_line(bottom, top, generate_line(bottom, middle)))
            #print L

            for y in range(int(bottom[1]), int(top[1])):
                # fetch by y-coordinate, then sort by x-coordinate
                # to get the leftmost and rightmost points
                foo = sorted([p for p in L if p[1] == y])
                #print foo
                #if not foo:
                #    print 'foo is empty ----------------------------------------------------------'
                #    print y
                if len(foo) == 1:
                #    print 'len(foo) == 1 ---------------------------------------------------------'
                #    print y
                    plot(screen, color, foo[0][0], foo[0][1], foo[0][2])
                if len(foo) >= 2:
                    draw_line(screen, foo[0], foo[-1], color)
        else:
            # Just draw the borders
            draw_lines(edges, screen, color)

def centroid(matrix, index):
    # Shorthand for the three vertices
    p0 = matrix[index]
    p1 = matrix[index + 1]
    p2 = matrix[index + 2]

    # Average of the 3 points
    return [(p0[i] + p1[i] + p2[i])/3 for i in range(len(p0))]

def surface_normal(matrix, index):
    # Shorthand for the three vertices
    p0 = matrix[index]
    p1 = matrix[index + 1]
    p2 = matrix[index + 2]

    # the 2 edge vectors
    a = [p1[i] - p0[i] for i in range(3)]
    b = [p2[i] - p0[i] for i in range(3)]

    # Area of triangle is half the cross product
    #return [c / 2 for c in cross_product(a, b)]
    # But to keep it simple, we'll return the cross product
    return cross_product(a, b)

'''
@param vertices: A matrix of (n+1) points representing the vertices of the n-simplex
@param point: The coordinates of the point we want to transform

Algorithm:
1. Project the point onto the line, plane, etc. of the simplex
2. Find the inverse of the vertex matrix
3. Multiply the matrix inverse by the projected point to get the barycentric coordinates
'''
def barycentric(vertices, point):
    # case 1: line segment
    # Using part of projection algorithm courtesy of Wikibooks:
    # https://en.wikibooks.org/wiki/Linear_Algebra/Orthogonal_Projection_Onto_a_Line
    if len(vertices) == 2:
        line_vector = subtract(vertices[1], vertices[0])
        point_vector = subtract(point, vertices[0])
        beta = dot_product(point_vector, line_vector) / dot_product(line_vector, line_vector)
        return [1 - beta, beta]
    # case 2: triangle
    # algorithm courtesy of Maplesoft: https://www.maplesoft.com/support/help/maple/view.aspx?path=MathApps%2FProjectionOfVectorOntoPlane
    elif len(vertices) == 3:
        n = surface_normal(vertices, 0)
        proj = point - project(point, n)
    elif len(vertices) < 2:
        raise ValueError("I can't find the barycentric coordinates with a point!")
    else:
        raise ValueError("I'm too lazy to find barycentric coordinates with a %d-simplex!" % (len(vertices) - 1))

'''
Converts an edge or polygon matrix to a list of tuples to be used as set elements or dict keys.
'''
def as_tuples(matrix):
    return [tuple(p[:3]) for p in matrix]

'''
Creates a sparse list (dict) of polygon matrix indices and their surface normals.
'''
def surface_normals(polygons):
    return {i: surface_normal(polygons, i) for i in range(0, len(polygons), 3)}

'''
Converts a polygon matrix to a dict of points (as tuples) and their vertex normals.
'''
def vertex_normals(polygons):
    # First, convert the points to tuples
    points_list = as_tuples(polygons)
    points = set(points_list)

    # Next, map the points to the indices of triangles in which they appear
    points_triangles = {p: [i - (i % 3) for i, s in enumerate(points_list) if s == p] for p in points}

    # Then, transform the dict by converting each value (list of indices) to the sum of the surface normals
    surface_normals = surface_normals(polygons)

    # Map triangle indices to their surface normals and sum them
    return {p: vector_sum( [surface_normals[i] for i in points_triangles[p]] ) for p in points}
<commit_msg>optimize<commit_after>from display import *
from matrix import *
from math import *

from linalg import *

def draw_line(screen, p0, p1, color):
    plotxyz = lambda p: plot(screen, color, p[0], p[1], p[2])
    bresenham(p0, p1, plotxyz)

def generate_line(p0, p1, L=[]):
    f = lambda p: L.append( (p[0], p[1], p[2]) )
    bresenham(p0, p1, f)
    #print p0, p1
    #print L
    #print
    return L

def bresenham(p0, p1, operation):
    (x0, y0, z0) = p0
    (x1, y1, z1) = p1

    dx = x1 - x0
    dy = y1 - y0

    if dx + dy < 0:
        bresenham(p1, p0, operation)
        return

    def z_of(x, y):
        if (x0, y0) == (x1, y1):
            return max(z0, z1)
        else:
            return dot_product([z0, z1], barycentric([[x0, y0], [x1, y1]], [x, y]))

    do_xy = lambda x, y: operation((x, y, z_of(x, y) ))

    if dx == 0:
        y = int(y0)
        while y <= y1:
            do_xy(int(x0), y)
            y += 1
    elif dy == 0:
        x = int(x0)
        while x <= x1:
            do_xy(x, int(y0))
            x += 1
    elif dy < 0:
        d = 0
        x = int(x0)
        y = int(y0)
        while x <= x1:
            do_xy(x, y)
            if d > 0:
                y -= 1
                d -= dx
            x += 1
            d -= dy
    elif dx < 0:
        d = 0
        x = int(x0)
        y = int(y0)
        while y <= y1:
            do_xy(x, y)
            if d > 0:
                x -= 1
                d -= dy
            y += 1
            d -= dx
    elif dx > dy:
        d = 0
        x = int(x0)
        y = int(y0)
        while x <= x1:
            do_xy(x, y)
            if d > 0:
                y += 1
                d -= dx
            x += 1
            d += dy
    else:
        d = 0
        x = int(x0)
        y = int(y0)
        while y <= y1:
            do_xy(x, y)
            if d > 0:
                x += 1
                d -= dy
            y += 1
            d += dx

def draw_lines( matrix, screen, color ):
    if len(matrix) == 0:
        return

    if len(matrix) % 2:
        raise ValueError("Need at least 2 points to draw a line")

    p = 0
    while p < len( matrix ) - 1:
        draw_line( screen, (matrix[p][0], matrix[p][1], matrix[p][2]),
                   (matrix[p+1][0], matrix[p+1][1], matrix[p+1][2]), color )
        p += 2

def draw_polygons(matrix, screen, color):
    if len(matrix) == 0:
        return

    if len(matrix) % 3:
        raise ValueError("Need 3 points to draw a triangle")

    for p in range(0, len(matrix), 3):
        draw_triangle(matrix, p, screen, color, fill=True)

def draw_triangle(matrix, index, screen, color, fill=False):
    # Shorthand for the three vertices
    p0 = matrix[index]
    p1 = matrix[index + 1]
    p2 = matrix[index + 2]

    normal = surface_normal(matrix, index)

    # default is [0, 0, 1]
    view = [0, 0, 1]

    edges = [p0, p1, p1, p2, p2, p0]

    frontness = dot_product(view, normal)

    # Front faces
    if frontness > 0:
        # Fill the triangle
        if fill:
            # sort vertices by y-coordinate so we can scanline bottom to top
            vertices = sorted([p0, p1, p2], key = lambda p: p[1])
            bottom = vertices[0][:3]
            middle = vertices[1][:3]
            top    = vertices[2][:3]

            L = generate_line(middle, top, generate_line(bottom, top, generate_line(bottom, middle)))
            #print L

            for y in range(int(bottom[1]), int(top[1])):
                # fetch by y-coordinate, then sort by x-coordinate
                # to get the leftmost and rightmost points
                foo = sorted([p for p in L if p[1] == y])
                #print foo
                #if not foo:
                #    print 'foo is empty ----------------------------------------------------------'
                #    print y
                if len(foo) > 0:
                    draw_line(screen, foo[0], foo[-1], color)
        else:
            # Just draw the borders
            draw_lines(edges, screen, color)

def centroid(matrix, index):
    # Shorthand for the three vertices
    p0 = matrix[index]
    p1 = matrix[index + 1]
    p2 = matrix[index + 2]

    # Average of the 3 points
    return [(p0[i] + p1[i] + p2[i])/3 for i in range(len(p0))]

def surface_normal(matrix, index):
    # Shorthand for the three vertices
    p0 = matrix[index]
    p1 = matrix[index + 1]
    p2 = matrix[index + 2]

    # the 2 edge vectors
    a = [p1[i] - p0[i] for i in range(3)]
    b = [p2[i] - p0[i] for i in range(3)]

    # Area of triangle is half the cross product
    #return [c / 2 for c in cross_product(a, b)]
    # But to keep it simple, we'll return the cross product
    return cross_product(a, b)

'''
@param vertices: A matrix of (n+1) points representing the vertices of the n-simplex
@param point: The coordinates of the point we want to transform

Algorithm:
1. Project the point onto the line, plane, etc. of the simplex
2. Find the inverse of the vertex matrix
3. Multiply the matrix inverse by the projected point to get the barycentric coordinates
'''
def barycentric(vertices, point):
    # case 1: line segment
    # Using part of projection algorithm courtesy of Wikibooks:
    # https://en.wikibooks.org/wiki/Linear_Algebra/Orthogonal_Projection_Onto_a_Line
    if len(vertices) == 2:
        line_vector = subtract(vertices[1], vertices[0])
        point_vector = subtract(point, vertices[0])
        beta = dot_product(point_vector, line_vector) / dot_product(line_vector, line_vector)
        return [1 - beta, beta]
    # case 2: triangle
    # algorithm courtesy of Maplesoft: https://www.maplesoft.com/support/help/maple/view.aspx?path=MathApps%2FProjectionOfVectorOntoPlane
    elif len(vertices) == 3:
        n = surface_normal(vertices, 0)
        proj = point - project(point, n)
    elif len(vertices) < 2:
        raise ValueError("I can't find the barycentric coordinates with a point!")
    else:
        raise ValueError("I'm too lazy to find barycentric coordinates with a %d-simplex!" % (len(vertices) - 1))

'''
Converts an edge or polygon matrix to a list of tuples to be used as set elements or dict keys.
'''
def as_tuples(matrix):
    return [tuple(p[:3]) for p in matrix]

'''
Creates a sparse list (dict) of polygon matrix indices and their surface normals.
'''
def surface_normals(polygons):
    return {i: surface_normal(polygons, i) for i in range(0, len(polygons), 3)}

'''
Converts a polygon matrix to a dict of points (as tuples) and their vertex normals.
'''
def vertex_normals(polygons):
    # First, convert the points to tuples
    points_list = as_tuples(polygons)
    points = set(points_list)

    # Next, map the points to the indices of triangles in which they appear
    points_triangles = {p: [i - (i % 3) for i, s in enumerate(points_list) if s == p] for p in points}

    # Then, transform the dict by converting each value (list of indices) to the sum of the surface normals
    surface_normals = surface_normals(polygons)

    # Map triangle indices to their surface normals and sum them
    return {p: vector_sum( [surface_normals[i] for i in points_triangles[p]] ) for p in points}
<|endoftext|>


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

'''
Roles in this namespace are meant to provide virtualenvs and run commands inside a virtualenv, for Debian distributions.
'''

from contextlib import contextmanager
import os

from provy.core import Role

class VirtualenvRole(Role):
    '''
    This role provides virtualenv management. It also provides virtualenvwrapper provisioning, although it's not internally used in this role.
    When using the object as a context manager (that is, using a "with" block) it will make sure that the virtual environment is created and that the commands that run inside it run within this same virtual environment (which affects, for example, the python and pip commands).
    Context manager parameters
    env_name - name of the virtual environment to be created and to keep activated when running commands inside the context manager.
    system_site_packages - if True, will include system-wide site-packages in the virtual environment. Defaults to False.
    Properties
    base_directory - directory where the virtual environment subdirectory will be put at. For example, if you set it as "/home/johndoe/my_envs", and use venv("some_env"), it will create a virtual environment at "/home/johndoe/my_envs/some_env". Defaults to $HOME/.virtualenvs .
    user - the user with which the virtual environment should be created. Defaults to the context user.
    Sample usage

    from provy.core import Role
    from provy.more.debian import VirtualenvRole

    class MySampleRole(Role):
        def provision(self):

            # this example uses the defaults provided
            with self.using(PipRole) as pip, self.using(VirtualenvRole) as venv, venv('fancylib'):
                pip.ensure_package_installed('django')

            # this is when you want to set a different base virtualenv directory and user, and include the system-wide site-packages.
            with self.using(PipRole) as pip, self.using(VirtualenvRole) as venv:
                venv.base_directory = '/home/johndoe/Envs'
                venv.user = 'johndoe'
                with venv('fancylib2', system_site_packages=True):
                    pip.ensure_package_installed('tornado')

    '''

    def __init__(self, prov, context):
        super(VirtualenvRole, self).__init__(prov, context)
        self.user = context['user']
        self.base_directory = os.path.join(self.__get_user_dir(), '.virtualenvs')

    def __get_user_dir(self):
        if self.user == 'root':
            return '/root'
        else:
            return '/home/%s' % self.user

    @contextmanager
    def __call__(self, env_name, system_site_packages=False):
        from fabric.api import prefix

        env_dir = os.path.join(self.base_directory, env_name)

        if not self.env_exists(env_name):
            self.create_env(env_name, system_site_packages=system_site_packages)

        with prefix('source %s/bin/activate' % env_dir):
            yield

    def provision(self):
        '''
        Installs virtualenv and virtualenvwrapper, and their dependencies. This method should be called upon if overriden in base classes, or virtualenv won't work properly in the remote server.
        Sample usage

        from provy.core import Role
        from provy.more.debian import VirtualenvRole

        class MySampleRole(Role):
            def provision(self):
                self.provision_role(VirtualenvRole) # does not need to be called if using with block.

        '''

        from provy.more.debian import PipRole

        with self.using(PipRole) as pip:
            pip.ensure_package_installed('virtualenv')
            pip.ensure_package_installed('virtualenvwrapper')

    def create_env(self, env_name, system_site_packages=False):
        '''
        Creates a virtual environment.
        Parameters
        env_name - name of the virtual environment to be created.
        system_site_packages - if True, will include system-wide site-packages in the virtual environment. Defaults to False.
        Sample usage

        from provy.core import Role
        from provy.more.debian import VirtualenvRole

        class MySampleRole(Role):
            def provision(self):
                with self.using(VirtualenvRole) as venv:
                    env_dir = venv.create_env('fancylib') # will return the directory where the virtual environment was created

        '''
        env_dir = os.path.join(self.base_directory, env_name)
        site_packages_arg = '--system-site-packages ' if system_site_packages else ''
        self.execute('virtualenv %s%s' % (site_packages_arg, env_dir), user=self.user)
        return env_dir

    def env_exists(self, env_name):
        '''
        Checks if a virtual environment exists.
        Parameters
        env_name - name of the virtual environment to be checked.
        Sample usage

        from provy.core import Role
        from provy.more.debian import VirtualenvRole

        class MySampleRole(Role):
            def provision(self):
                with self.using(VirtualenvRole) as venv:
                    venv.env_exists('fancylib') # True or False

        '''
        virtual_env_dir = os.path.join(self.base_directory, env_name)
        return self.remote_exists_dir(virtual_env_dir)
<commit_msg>Refactoring VirtualenvRole and improving documentation<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

'''
Roles in this namespace are meant to provide virtualenvs and run commands inside a virtualenv, for Debian distributions.
'''

from contextlib import contextmanager
import os

from provy.core import Role

class VirtualenvRole(Role):
    '''
    This role provides virtualenv management. It also provides virtualenvwrapper provisioning, although it's not internally used in this role.
    When using the object as a context manager (that is, using a "with" block) it will make sure that the virtual environment is created and that the commands that run inside it run within this same virtual environment (which affects, for example, the python and pip commands).
    If the virtual environment already exists, it just bypasses the creation procedure.
    Context manager parameters
    env_name - name of the virtual environment to be created and to keep activated when running commands inside the context manager.
    system_site_packages - if True, will include system-wide site-packages in the virtual environment. Defaults to False.
    Properties
    base_directory - directory where the virtual environment subdirectory will be put at. For example, if you set it as "/home/johndoe/my_envs", and use venv("some_env"), it will create a virtual environment at "/home/johndoe/my_envs/some_env". Defaults to $HOME/.virtualenvs .
    user - the user with which the virtual environment should be created. Defaults to the context user.
    Sample usage

    from provy.core import Role
    from provy.more.debian import VirtualenvRole

    class MySampleRole(Role):
        def provision(self):

            # this example uses the defaults provided
            with self.using(PipRole) as pip, self.using(VirtualenvRole) as venv, venv('fancylib'):
                pip.ensure_package_installed('django')

            # this is when you want to set a different base virtualenv directory and user, and include the system-wide site-packages.
            with self.using(PipRole) as pip, self.using(VirtualenvRole) as venv:
                venv.base_directory = '/home/johndoe/Envs'
                venv.user = 'johndoe'
                with venv('fancylib2', system_site_packages=True):
                    pip.ensure_package_installed('tornado')

    '''

    def __init__(self, prov, context):
        super(VirtualenvRole, self).__init__(prov, context)
        self.user = context['user']
        self.base_directory = os.path.join(self.__get_user_dir(), '.virtualenvs')

    def __get_user_dir(self):
        if self.user == 'root':
            return '/root'
        else:
            return '/home/%s' % self.user

    def env_dir(self, env_name):
        '''
        Gets the virtual environment directory for a given environment name.
        Please note that this doesn't check if the env actually exists.
        Sample usage

        from provy.core import Role
        from provy.more.debian import VirtualenvRole

        class MySampleRole(Role):
            def provision(self):
                with self.using(VirtualenvRole) as venv, venc('fancylib'):
                    self.env_dir('fancylib')

        '''
        return os.path.join(self.base_directory, env_name)

    @contextmanager
    def __call__(self, env_name, system_site_packages=False):
        from fabric.api import prefix

        if not self.env_exists(env_name):
            self.create_env(env_name, system_site_packages=system_site_packages)

        with prefix('source %s/bin/activate' % self.env_dir(env_name)):
            yield

    def provision(self):
        '''
        Installs virtualenv and virtualenvwrapper, and their dependencies. This method should be called upon if overriden in base classes, or virtualenv won't work properly in the remote server.
        Sample usage

        from provy.core import Role
        from provy.more.debian import VirtualenvRole

        class MySampleRole(Role):
            def provision(self):
                self.provision_role(VirtualenvRole) # does not need to be called if using with block.

        '''

        from provy.more.debian import PipRole

        with self.using(PipRole) as pip:
            pip.ensure_package_installed('virtualenv')
            pip.ensure_package_installed('virtualenvwrapper')

    def create_env(self, env_name, system_site_packages=False):
        '''
        Creates a virtual environment.
        Parameters
        env_name - name of the virtual environment to be created.
        system_site_packages - if True, will include system-wide site-packages in the virtual environment. Defaults to False.
        Sample usage

        from provy.core import Role
        from provy.more.debian import VirtualenvRole

        class MySampleRole(Role):
            def provision(self):
                with self.using(VirtualenvRole) as venv:
                    env_dir = venv.create_env('fancylib') # will return the directory where the virtual environment was created

        '''
        env_dir = self.env_dir(env_name)
        site_packages_arg = '--system-site-packages ' if system_site_packages else ''
        self.execute('virtualenv %s%s' % (site_packages_arg, env_dir), user=self.user)
        return env_dir

    def env_exists(self, env_name):
        '''
        Checks if a virtual environment exists.
        Parameters
        env_name - name of the virtual environment to be checked.
        Sample usage

        from provy.core import Role
        from provy.more.debian import VirtualenvRole

        class MySampleRole(Role):
            def provision(self):
                with self.using(VirtualenvRole) as venv:
                    venv.env_exists('fancylib') # True or False

        '''
        return self.remote_exists_dir(self.env_dir(env_name))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from .notifications import NotificationMethod, SingleNotificationMethod, BulkNotificationMethod
from part.test_part import BaseNotificationIntegrationTest

class NotificationTests(BaseNotificationIntegrationTest):

    def test_NotificationMethod(self):
        """ensure the implementation requirements are tested"""

        class FalseNotificationMethod(NotificationMethod):
            METHOD_NAME = 'FalseNotification'

        class AnotherFalseNotificationMethod(NotificationMethod):
            METHOD_NAME = 'AnotherFalseNotification'

            def send(self):
                """a comment so we do not need a pass"""

        class NoNameNotificationMethod(NotificationMethod):

            def send(self):
                """a comment so we do not need a pass"""

        class WrongContextNotificationMethod(NotificationMethod):
            METHOD_NAME = 'WrongContextNotification'
            CONTEXT_EXTRA = [
                'aa',
                ('aa', 'bb', ),
                ('templates', 'ccc', ),
                (123, )
            ]

            def send(self):
                """a comment so we do not need a pass"""

        # no send / send bulk
        with self.assertRaises(NotImplementedError):
            FalseNotificationMethod('', '', '', '', )

        # no METHOD_NAME
        with self.assertRaises(NotImplementedError):
            NoNameNotificationMethod('', '', '', '', )

        # a not existant context check
        with self.assertRaises(NotImplementedError):
            WrongContextNotificationMethod('', '', '', '', )

        # no get_targets
        with self.assertRaises(NotImplementedError):
            AnotherFalseNotificationMethod('', '', '', {'name': 1, 'message': 2, }, )

    def test_errors_passing(self):
        """ensure that errors do not kill the whole delivery"""

        class ErrorImplementation(SingleNotificationMethod):
            METHOD_NAME = 'ErrorImplementation'

            def get_targets(self):
                return [1, ]

            def send(self, target):
                raise KeyError('This could be any error')

        self._notification_run()

class ClassNotificationTests(BaseNotificationIntegrationTest):

    def test_SingleNotificationMethod(self):
        """ensure the implementation requirements are tested"""

        class WrongImplementation(SingleNotificationMethod):
            METHOD_NAME = 'WrongImplementation1'

            def get_targets(self):
                return [1, ]

        with self.assertRaises(NotImplementedError):
            self._notification_run()

    def test_BulkNotificationMethod(self):
        """ensure the implementation requirements are tested"""

        class WrongImplementation(BulkNotificationMethod):
            METHOD_NAME = 'WrongImplementation2'

            def get_targets(self):
                return [1, ]

        with self.assertRaises(NotImplementedError):
            self._notification_run()

# A integration test for notifications is provided in test_part.PartNotificationTest
<commit_msg>rename<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from .notifications import NotificationMethod, SingleNotificationMethod, BulkNotificationMethod
from part.test_part import BaseNotificationIntegrationTest

class BaseNotificationTests(BaseNotificationIntegrationTest):

    def test_NotificationMethod(self):
        """ensure the implementation requirements are tested"""

        class FalseNotificationMethod(NotificationMethod):
            METHOD_NAME = 'FalseNotification'

        class AnotherFalseNotificationMethod(NotificationMethod):
            METHOD_NAME = 'AnotherFalseNotification'

            def send(self):
                """a comment so we do not need a pass"""

        class NoNameNotificationMethod(NotificationMethod):

            def send(self):
                """a comment so we do not need a pass"""

        class WrongContextNotificationMethod(NotificationMethod):
            METHOD_NAME = 'WrongContextNotification'
            CONTEXT_EXTRA = [
                'aa',
                ('aa', 'bb', ),
                ('templates', 'ccc', ),
                (123, )
            ]

            def send(self):
                """a comment so we do not need a pass"""

        # no send / send bulk
        with self.assertRaises(NotImplementedError):
            FalseNotificationMethod('', '', '', '', )

        # no METHOD_NAME
        with self.assertRaises(NotImplementedError):
            NoNameNotificationMethod('', '', '', '', )

        # a not existant context check
        with self.assertRaises(NotImplementedError):
            WrongContextNotificationMethod('', '', '', '', )

        # no get_targets
        with self.assertRaises(NotImplementedError):
            AnotherFalseNotificationMethod('', '', '', {'name': 1, 'message': 2, }, )

    def test_errors_passing(self):
        """ensure that errors do not kill the whole delivery"""

        class ErrorImplementation(SingleNotificationMethod):
            METHOD_NAME = 'ErrorImplementation'

            def get_targets(self):
                return [1, ]

            def send(self, target):
                raise KeyError('This could be any error')

        self._notification_run()

class ClassNotificationTests(BaseNotificationIntegrationTest):

    def test_SingleNotificationMethod(self):
        """ensure the implementation requirements are tested"""

        class WrongImplementation(SingleNotificationMethod):
            METHOD_NAME = 'WrongImplementation1'

            def get_targets(self):
                return [1, ]

        with self.assertRaises(NotImplementedError):
            self._notification_run()

    def test_BulkNotificationMethod(self):
        """ensure the implementation requirements are tested"""

        class WrongImplementation(BulkNotificationMethod):
            METHOD_NAME = 'WrongImplementation2'

            def get_targets(self):
                return [1, ]

        with self.assertRaises(NotImplementedError):
            self._notification_run()

# A integration test for notifications is provided in test_part.PartNotificationTest
<|endoftext|>


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

import asyncio
import os
from toxicbuild.core.utils import log
from toxicbuild.master import create_settings_and_connect
from toxicbuild.slave import create_settings
from toxicbuild.ui import create_settings as create_settings_ui
from toxicbuild.output import (
    create_settings_and_connect as create_settings_output)
from tests.functional import (REPO_DIR,
                              SLAVE_ROOT_DIR, MASTER_ROOT_DIR, UI_ROOT_DIR,
                              OUTPUT_ROOT_DIR)

# settings needed to the test data. This needs to be before the
# import from ui.models

toxicmaster_conf = os.environ.get('TOXICMASTER_SETTINGS')
if not toxicmaster_conf:
    toxicmaster_conf = os.path.join(MASTER_ROOT_DIR, 'toxicmaster.conf')
    os.environ['TOXICMASTER_SETTINGS'] = toxicmaster_conf

toxicslave_conf = os.environ.get('TOXICSLAVE_SETTINGS')
if not toxicslave_conf:
    toxicslave_conf = os.path.join(SLAVE_ROOT_DIR, 'toxicslave.conf')
    os.environ['TOXICSLAVE_SETTINGS'] = toxicslave_conf

toxicweb_conf = os.environ.get('TOXICUI_SETTINGS')
if not toxicweb_conf:
    toxicweb_conf = os.path.join(UI_ROOT_DIR, 'toxicui.conf')
    os.environ['TOXICUI_SETTINGS'] = toxicweb_conf

toxicoutput_conf = os.environ.get('TOXICOUTPUT_SETTINGS')
if not toxicoutput_conf:
    toxicoutput_conf = os.path.join(OUTPUT_ROOT_DIR, 'toxicoutput.conf')
    os.environ['TOXICOUTPUT_SETTINGS'] = toxicoutput_conf

create_settings()
create_settings_ui()
create_settings_and_connect()
create_settings_output()

from toxicbuild.master.exchanges import scheduler_action  # noqa f402
from toxicbuild.ui import settings
from toxicbuild.master.users import User  # noqa f402
from toxicbuild.ui.models import Slave, Repository  # noqa 402
from tests.functional import (start_slave, stop_slave,  # noqa 402
                              start_master, stop_master,
                              start_poller, stop_poller,
                              start_scheduler, stop_scheduler,
                              start_output, stop_output,
                              start_webui, stop_webui,
                              REPO_DIR)
from tests.webui import SeleniumBrowser  # noqa 402

def create_browser(context):
    """Creates a new selenium browser using Chrome driver and
    sets it in the behave context.

    :param context: Behave's context."""
    context.browser = SeleniumBrowser()

def quit_browser(context):
    """Quits the selenium browser.

    :param context: Behave's context."""
    context.browser.quit()

@asyncio.coroutine
def create_slave(context):
    """Creates a slave to be used in repo tests"""

    yield from Slave.add(context.user, name='repo-slave', host='localhost',
                         owner=context.user,
                         port=2222,
                         token='123',
                         use_ssl=True,
                         validate_cert=False)

@asyncio.coroutine
def del_slave(context):
    """Deletes the slaves created in the tests"""

    slaves = yield from Slave.list(context.user)
    for slave in slaves:
        try:
            yield from slave.delete()
        except Exception as e:
            log('Error deleting slave ' + str(e), level='warning')

@asyncio.coroutine
def create_repo(context):
    """Creates a new repo to be used in tests"""

    yield from scheduler_action.connection.connect()
    yield from scheduler_action.declare()

    repo = yield from Repository.add(context.user,
                                     name='repo-bla', update_seconds=1,
                                     owner=context.user,
                                     vcs_type='git', url=REPO_DIR,
                                     slaves=['repo-slave'])

    yield from repo.add_branch('master', False)

async def create_user(context):
    user = User(email='someguy@bla.com', is_superuser=True)
    user.set_password('123')
    await user.save()
    context.user = user
    context.user.id = str(context.user.id)

async def del_user(context):
    await context.user.delete()

@asyncio.coroutine
def del_repo(context):
    """Deletes the repositories created in tests."""

    repos = yield from Repository.list(context.user)
    for repo in repos:
        try:
            yield from repo.delete()
            yield from scheduler_action.declare()
            yield from scheduler_action.queue_delete()
            yield from scheduler_action.connection.disconnect()
        except Exception as e:
            log('Error deleting repo ' + str(e), level='warning')

    from toxicbuild.master.repository import Repository as RepoModel

    yield from RepoModel.drop_collection()

async def create_root_user(context):
    user = User(id=settings.ROOT_USER_ID, username='already-exists',
                email='nobody@nowhere.nada', allowed_actions=['add_user'])
    await user.save()

def before_all(context):
    start_slave()
    start_poller()
    start_scheduler()
    start_output()
    start_master()
    start_webui()

    create_browser(context)

    async def create(context):
        await create_user(context)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(create(context))

def before_feature(context, feature):
    """Executed before every feature. It starts a slave, a master,
    a webui and creates a selenium browser.

    :param context: Behave's context.
    :param feature: The feature being executed."""

    async def create(context):
        await create_slave(context)

        if 'waterfall.feature' in feature.filename:
            await create_repo(context)

        elif 'register.feature' in feature.filename:
            await create_root_user(context)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(create(context))

def after_feature(context, feature):
    """Executed after every feature. It stops the webui, the master,
    the slave, quits the selenium browser and deletes data created in
    tests.

    :param context: Behave's context.
    :param feature: The feature that was executed."""

    async def delete(context):
        await del_slave(context)
        await del_repo(context)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(delete(context))

def before_scenario(context, scenario):
    if scenario.name == 'A user cancels a build':
        # we stop the slave so we can be sure the build is pending
        # when we try to cancel it
        stop_slave()

def after_scenario(context, scenario):
    if scenario.name == 'A user cancels a build':
        # starting it for the other tests, if any
        start_slave()

def after_all(context):

    stop_webui()
    stop_output()
    stop_scheduler()
    stop_poller()
    stop_master()
    stop_slave()

    async def delete(context):
        await del_user(context)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(delete(context))

    quit_browser(context)
<commit_msg>pylint<commit_after># -*- coding: utf-8 -*-

import asyncio
import os
from toxicbuild.core.utils import log
from toxicbuild.master import create_settings_and_connect
from toxicbuild.slave import create_settings
from toxicbuild.ui import create_settings as create_settings_ui
from toxicbuild.output import (
    create_settings_and_connect as create_settings_output)
from tests.functional import (REPO_DIR,
                              SLAVE_ROOT_DIR, MASTER_ROOT_DIR, UI_ROOT_DIR,
                              OUTPUT_ROOT_DIR)

# settings needed to the test data. This needs to be before the
# import from ui.models

toxicmaster_conf = os.environ.get('TOXICMASTER_SETTINGS')
if not toxicmaster_conf:
    toxicmaster_conf = os.path.join(MASTER_ROOT_DIR, 'toxicmaster.conf')
    os.environ['TOXICMASTER_SETTINGS'] = toxicmaster_conf

toxicslave_conf = os.environ.get('TOXICSLAVE_SETTINGS')
if not toxicslave_conf:
    toxicslave_conf = os.path.join(SLAVE_ROOT_DIR, 'toxicslave.conf')
    os.environ['TOXICSLAVE_SETTINGS'] = toxicslave_conf

toxicweb_conf = os.environ.get('TOXICUI_SETTINGS')
if not toxicweb_conf:
    toxicweb_conf = os.path.join(UI_ROOT_DIR, 'toxicui.conf')
    os.environ['TOXICUI_SETTINGS'] = toxicweb_conf

toxicoutput_conf = os.environ.get('TOXICOUTPUT_SETTINGS')
if not toxicoutput_conf:
    toxicoutput_conf = os.path.join(OUTPUT_ROOT_DIR, 'toxicoutput.conf')
    os.environ['TOXICOUTPUT_SETTINGS'] = toxicoutput_conf

create_settings()
create_settings_ui()
create_settings_and_connect()
create_settings_output()

from toxicbuild.master.exchanges import scheduler_action  # noqa f402
from toxicbuild.ui import settings  # noqa f402
from toxicbuild.master.users import User  # noqa f402
from toxicbuild.ui.models import Slave, Repository  # noqa 402
from tests.functional import (start_slave, stop_slave,  # noqa 402
                              start_master, stop_master,
                              start_poller, stop_poller,
                              start_scheduler, stop_scheduler,
                              start_output, stop_output,
                              start_webui, stop_webui,
                              REPO_DIR)
from tests.webui import SeleniumBrowser  # noqa 402

def create_browser(context):
    """Creates a new selenium browser using Chrome driver and
    sets it in the behave context.

    :param context: Behave's context."""
    context.browser = SeleniumBrowser()

def quit_browser(context):
    """Quits the selenium browser.

    :param context: Behave's context."""
    context.browser.quit()

@asyncio.coroutine
def create_slave(context):
    """Creates a slave to be used in repo tests"""

    yield from Slave.add(context.user, name='repo-slave', host='localhost',
                         owner=context.user,
                         port=2222,
                         token='123',
                         use_ssl=True,
                         validate_cert=False)

@asyncio.coroutine
def del_slave(context):
    """Deletes the slaves created in the tests"""

    slaves = yield from Slave.list(context.user)
    for slave in slaves:
        try:
            yield from slave.delete()
        except Exception as e:
            log('Error deleting slave ' + str(e), level='warning')

@asyncio.coroutine
def create_repo(context):
    """Creates a new repo to be used in tests"""

    yield from scheduler_action.connection.connect()
    yield from scheduler_action.declare()

    repo = yield from Repository.add(context.user,
                                     name='repo-bla', update_seconds=1,
                                     owner=context.user,
                                     vcs_type='git', url=REPO_DIR,
                                     slaves=['repo-slave'])

    yield from repo.add_branch('master', False)

async def create_user(context):
    user = User(email='someguy@bla.com', is_superuser=True)
    user.set_password('123')
    await user.save()
    context.user = user
    context.user.id = str(context.user.id)

async def del_user(context):
    await context.user.delete()

@asyncio.coroutine
def del_repo(context):
    """Deletes the repositories created in tests."""

    repos = yield from Repository.list(context.user)
    for repo in repos:
        try:
            yield from repo.delete()
            yield from scheduler_action.declare()
            yield from scheduler_action.queue_delete()
            yield from scheduler_action.connection.disconnect()
        except Exception as e:
            log('Error deleting repo ' + str(e), level='warning')

    from toxicbuild.master.repository import Repository as RepoModel

    yield from RepoModel.drop_collection()

async def create_root_user(context):
    user = User(id=settings.ROOT_USER_ID, username='already-exists',
                email='nobody@nowhere.nada', allowed_actions=['add_user'])
    await user.save()

def before_all(context):
    start_slave()
    start_poller()
    start_scheduler()
    start_output()
    start_master()
    start_webui()

    create_browser(context)

    async def create(context):
        await create_user(context)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(create(context))

def before_feature(context, feature):
    """Executed before every feature. It starts a slave, a master,
    a webui and creates a selenium browser.

    :param context: Behave's context.
    :param feature: The feature being executed."""

    async def create(context):
        await create_slave(context)

        if 'waterfall.feature' in feature.filename:
            await create_repo(context)

        elif 'register.feature' in feature.filename:
            await create_root_user(context)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(create(context))

def after_feature(context, feature):
    """Executed after every feature. It stops the webui, the master,
    the slave, quits the selenium browser and deletes data created in
    tests.

    :param context: Behave's context.
    :param feature: The feature that was executed."""

    async def delete(context):
        await del_slave(context)
        await del_repo(context)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(delete(context))

def before_scenario(context, scenario):
    if scenario.name == 'A user cancels a build':
        # we stop the slave so we can be sure the build is pending
        # when we try to cancel it
        stop_slave()

def after_scenario(context, scenario):
    if scenario.name == 'A user cancels a build':
        # starting it for the other tests, if any
        start_slave()

def after_all(context):

    stop_webui()
    stop_output()
    stop_scheduler()
    stop_poller()
    stop_master()
    stop_slave()

    async def delete(context):
        await del_user(context)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(delete(context))

    quit_browser(context)
<|endoftext|>


<commit_before>import md5
import os
import sys

import list_reducer
from list_reducer import TESTRESULT_KEEPPREFIX
from list_reducer import TESTRESULT_KEEPSUFFIX
from list_reducer import TESTRESULT_NOFAILURE

import swift_tools

class ReduceMiscompilingFunctions(list_reducer.ListReducer):

    def __init__(self, functions, silextract, tester):
        list_reducer.ListReducer.__init__(self, functions)
        self.silextract = silextract
        self.tester = tester

    def run_test(self, prefix, suffix):
        if len(suffix) > 0 and self._test_funclist(suffix):
            return (TESTRESULT_KEEPSUFFIX, prefix, suffix)
        if len(prefix) > 0 and self._test_funclist(prefix):
            return (TESTRESULT_KEEPPREFIX, prefix, suffix)
        return (TESTRESULT_NOFAILURE, prefix, suffix)

    # Split functions in a module into two groups: Those that are under
    # consideration for miscompilation vs those that are not. Eventually, we
    # will split the module into separate partial modules and then compile so
    # we can find miscompiles. For now, we just look for crashsers in the
    # optimizer.
    def _test_funclist(self, funcs):
        funclist_hash = self.get_funclist_hash(funcs)
        funclist_path = os.path.join(self.silextract.config.work_dir,
                                     'func_list_' + funclist_hash)
        with open(funclist_path, 'w') as funclist_file:
            for f in funcs:
                funclist_file.write(f + '\n')

        print("Checking to see if the program is misoptimized with func "
              "list: %s" % funclist_path)

        # Split the module into the two halves of the program.
        (outfile_stem, outfile_invert_stem) = \
            self.get_output_filename_stems(funclist_hash)
        outfile = self.silextract.get_suffixed_filename(outfile_stem)
        outfile_invert = \
            self.silextract.get_suffixed_filename(outfile_invert_stem)
        self.silextract.invoke_with_functions(funclist_path, outfile)
        self.silextract.invoke_with_functions(funclist_path, outfile_invert,
                                              invert=True)
        return self.tester(outfile, outfile_stem, outfile_invert,
                           outfile_invert_stem)

    def get_output_filename_stems(self, funclist_hash):
        filename_stem = funclist_hash
        return (filename_stem, filename_stem + '_invert')

    def get_funclist_hash(self, funcs):
        m = md5.new()
        for f in funcs:
            m.update(f)
        return m.hexdigest()

class OptimizerTester(object):

    def __init__(self, silopt, passes):
        self.silopt = silopt
        self.result = None
        self.passes = ['-' + p for p in passes]
        m = md5.new()
        for p in passes:
            m.update(p)
        self.pass_hash = m.hexdigest()

    def get_filepaths(self, optstem, nooptstem):
        f = self.silopt.get_suffixed_filename
        return (f(optstem + '_' + self.pass_hash),
                f(nooptstem + '_' + self.pass_hash))

    def __call__(self, filepath_to_opt, filepath_to_opt_stem,
                 filepath_to_notopt, filepath_to_notopt_stem):
        (out_optpath, out_nooptpath) = \
            self.get_filepaths(filepath_to_opt_stem, filepath_to_notopt_stem)
        sys.stdout.write("Trying to optimize functions...")
        self.silopt.input_file = filepath_to_opt
        result = self.silopt.invoke_with_passlist(self.passes, out_optpath)
        if result['exit_code'] == 0:
            print(' NOCRASH!\n')
        else:
            self.result = self.silopt.input_file
            print(' CRASH!\n')
        return result['exit_code']

def function_bug_reducer(input_file, nm, sil_opt_invoker, sil_extract_invoker,
                         pass_list):
    functions = [s[1] for s in nm.get_symbols(input_file) if s[0] == 'F']

    print("Base case crashes! Trying to reduce *.sib file")

    # Otherwise, reduce the list of pases that cause the optimzier to crash.
    tester = OptimizerTester(sil_opt_invoker, pass_list)
    r = ReduceMiscompilingFunctions(functions, sil_extract_invoker,
                                    tester)
    if not r.reduce_list():
        print("Failed to find miscompiling pass list!")
    sil_opt_invoker.input_file = tester.result
    cmdline = sil_opt_invoker.cmdline_with_passlist(pass_list)
    print("*** Successfully Reduced file!")
    print("*** Final File: %s" % sil_opt_invoker.input_file)
    print("*** Final Functions: %s" % (' '.join(r.target_list)))
    print("*** Repro command line: %s" % (' '.join(cmdline)))

def invoke_function_bug_reducer(args):
    """Given a path to a sib file with canonical sil, attempt to find a perturbed
list of function given a specific pass that causes the perf pipeline to crash
    """
    tools = swift_tools.SwiftTools(args.swift_build_dir)
    config = swift_tools.SILToolInvokerConfig(args)
    nm = swift_tools.SILNMInvoker(config, tools)

    input_file = args.input_file
    extra_args = args.extra_args
    sil_opt_invoker = swift_tools.SILOptInvoker(config, tools,
                                                input_file,
                                                extra_args)

    # Make sure that the base case /does/ crash.
    filename = sil_opt_invoker.get_suffixed_filename('base_case')
    result = sil_opt_invoker.invoke_with_passlist(args.pass_list, filename)
    # If we succeed, there is no further work to do.
    if result['exit_code'] == 0:
        print("Success with PassList: %s" % (' '.join(args.pass_list)))
        return

    sil_extract_invoker = swift_tools.SILFuncExtractorInvoker(config,
                                                              tools,
                                                              input_file)

    function_bug_reducer(input_file, nm, sil_opt_invoker, sil_extract_invoker,
                         args.pass_list)

def add_parser_arguments(parser):
    """Add parser arguments for func_bug_reducer"""
    parser.set_defaults(func=invoke_function_bug_reducer)
    parser.add_argument('input_file', help='The input file to optimize')
    parser.add_argument('--module-cache', help='The module cache to use')
    parser.add_argument('--sdk', help='The sdk to pass to sil-func-extractor')
    parser.add_argument('--target', help='The target to pass to '
                        'sil-func-extractor')
    parser.add_argument('--resource-dir',
                        help='The resource-dir to pass to sil-func-extractor')
    parser.add_argument('--work-dir',
                        help='Working directory to use for temp files',
                        default='bug_reducer')
    parser.add_argument('--module-name',
                        help='The name of the module we are optimizing')
    parser.add_argument('--pass', help='pass to test', dest='pass_list',
                        action='append')
    parser.add_argument('--extra-silopt-arg', help='extra argument to pass to '
                        'sil-opt',
                        dest='extra_args', action='append')
<commit_msg>spelling: optimizer<commit_after>import md5
import os
import sys

import list_reducer
from list_reducer import TESTRESULT_KEEPPREFIX
from list_reducer import TESTRESULT_KEEPSUFFIX
from list_reducer import TESTRESULT_NOFAILURE

import swift_tools

class ReduceMiscompilingFunctions(list_reducer.ListReducer):

    def __init__(self, functions, silextract, tester):
        list_reducer.ListReducer.__init__(self, functions)
        self.silextract = silextract
        self.tester = tester

    def run_test(self, prefix, suffix):
        if len(suffix) > 0 and self._test_funclist(suffix):
            return (TESTRESULT_KEEPSUFFIX, prefix, suffix)
        if len(prefix) > 0 and self._test_funclist(prefix):
            return (TESTRESULT_KEEPPREFIX, prefix, suffix)
        return (TESTRESULT_NOFAILURE, prefix, suffix)

    # Split functions in a module into two groups: Those that are under
    # consideration for miscompilation vs those that are not. Eventually, we
    # will split the module into separate partial modules and then compile so
    # we can find miscompiles. For now, we just look for crashsers in the
    # optimizer.
    def _test_funclist(self, funcs):
        funclist_hash = self.get_funclist_hash(funcs)
        funclist_path = os.path.join(self.silextract.config.work_dir,
                                     'func_list_' + funclist_hash)
        with open(funclist_path, 'w') as funclist_file:
            for f in funcs:
                funclist_file.write(f + '\n')

        print("Checking to see if the program is misoptimized with func "
              "list: %s" % funclist_path)

        # Split the module into the two halves of the program.
        (outfile_stem, outfile_invert_stem) = \
            self.get_output_filename_stems(funclist_hash)
        outfile = self.silextract.get_suffixed_filename(outfile_stem)
        outfile_invert = \
            self.silextract.get_suffixed_filename(outfile_invert_stem)
        self.silextract.invoke_with_functions(funclist_path, outfile)
        self.silextract.invoke_with_functions(funclist_path, outfile_invert,
                                              invert=True)
        return self.tester(outfile, outfile_stem, outfile_invert,
                           outfile_invert_stem)

    def get_output_filename_stems(self, funclist_hash):
        filename_stem = funclist_hash
        return (filename_stem, filename_stem + '_invert')

    def get_funclist_hash(self, funcs):
        m = md5.new()
        for f in funcs:
            m.update(f)
        return m.hexdigest()

class OptimizerTester(object):

    def __init__(self, silopt, passes):
        self.silopt = silopt
        self.result = None
        self.passes = ['-' + p for p in passes]
        m = md5.new()
        for p in passes:
            m.update(p)
        self.pass_hash = m.hexdigest()

    def get_filepaths(self, optstem, nooptstem):
        f = self.silopt.get_suffixed_filename
        return (f(optstem + '_' + self.pass_hash),
                f(nooptstem + '_' + self.pass_hash))

    def __call__(self, filepath_to_opt, filepath_to_opt_stem,
                 filepath_to_notopt, filepath_to_notopt_stem):
        (out_optpath, out_nooptpath) = \
            self.get_filepaths(filepath_to_opt_stem, filepath_to_notopt_stem)
        sys.stdout.write("Trying to optimize functions...")
        self.silopt.input_file = filepath_to_opt
        result = self.silopt.invoke_with_passlist(self.passes, out_optpath)
        if result['exit_code'] == 0:
            print(' NOCRASH!\n')
        else:
            self.result = self.silopt.input_file
            print(' CRASH!\n')
        return result['exit_code']

def function_bug_reducer(input_file, nm, sil_opt_invoker, sil_extract_invoker,
                         pass_list):
    functions = [s[1] for s in nm.get_symbols(input_file) if s[0] == 'F']

    print("Base case crashes! Trying to reduce *.sib file")

    # Otherwise, reduce the list of pases that cause the optimizer to crash.
    tester = OptimizerTester(sil_opt_invoker, pass_list)
    r = ReduceMiscompilingFunctions(functions, sil_extract_invoker,
                                    tester)
    if not r.reduce_list():
        print("Failed to find miscompiling pass list!")
    sil_opt_invoker.input_file = tester.result
    cmdline = sil_opt_invoker.cmdline_with_passlist(pass_list)
    print("*** Successfully Reduced file!")
    print("*** Final File: %s" % sil_opt_invoker.input_file)
    print("*** Final Functions: %s" % (' '.join(r.target_list)))
    print("*** Repro command line: %s" % (' '.join(cmdline)))

def invoke_function_bug_reducer(args):
    """Given a path to a sib file with canonical sil, attempt to find a perturbed
list of function given a specific pass that causes the perf pipeline to crash
    """
    tools = swift_tools.SwiftTools(args.swift_build_dir)
    config = swift_tools.SILToolInvokerConfig(args)
    nm = swift_tools.SILNMInvoker(config, tools)

    input_file = args.input_file
    extra_args = args.extra_args
    sil_opt_invoker = swift_tools.SILOptInvoker(config, tools,
                                                input_file,
                                                extra_args)

    # Make sure that the base case /does/ crash.
    filename = sil_opt_invoker.get_suffixed_filename('base_case')
    result = sil_opt_invoker.invoke_with_passlist(args.pass_list, filename)
    # If we succeed, there is no further work to do.
    if result['exit_code'] == 0:
        print("Success with PassList: %s" % (' '.join(args.pass_list)))
        return

    sil_extract_invoker = swift_tools.SILFuncExtractorInvoker(config,
                                                              tools,
                                                              input_file)

    function_bug_reducer(input_file, nm, sil_opt_invoker, sil_extract_invoker,
                         args.pass_list)

def add_parser_arguments(parser):
    """Add parser arguments for func_bug_reducer"""
    parser.set_defaults(func=invoke_function_bug_reducer)
    parser.add_argument('input_file', help='The input file to optimize')
    parser.add_argument('--module-cache', help='The module cache to use')
    parser.add_argument('--sdk', help='The sdk to pass to sil-func-extractor')
    parser.add_argument('--target', help='The target to pass to '
                        'sil-func-extractor')
    parser.add_argument('--resource-dir',
                        help='The resource-dir to pass to sil-func-extractor')
    parser.add_argument('--work-dir',
                        help='Working directory to use for temp files',
                        default='bug_reducer')
    parser.add_argument('--module-name',
                        help='The name of the module we are optimizing')
    parser.add_argument('--pass', help='pass to test', dest='pass_list',
                        action='append')
    parser.add_argument('--extra-silopt-arg', help='extra argument to pass to '
                        'sil-opt',
                        dest='extra_args', action='append')
<|endoftext|>