コード例 #1
0
 def test_check_with_too_low_pressure(self, test_sensor_class):
     test_sensor_instance = Mock()
     test_sensor_instance.sample_pressure.return_value = 15
     test_sensor_class.return_value = test_sensor_instance
     alarm = Alarm()
     alarm.check()
     self.assertTrue(alarm.is_alarm_on)
コード例 #2
0
ファイル: test_alarm.py プロジェクト: mjcowdrill/python
 def test_check_with_too_low_pressure(self, test_sensor_class):
     test_sensor_instance = Mock()
     test_sensor_instance.sample_pressure.return_value = 15
     test_sensor_class.return_value = test_sensor_instance
     alarm = Alarm()
     alarm.check()
     self.assertTrue(alarm.is_alarm_on)
コード例 #3
0
 def test_high_pressure_with_monkeypatch(self, test_sensor_class):
     test_sensor_instance = Mock()
     test_sensor_instance.sample_pressure.return_value = 22
     test_sensor_class.return_value = test_sensor_instance
     alarm = Alarm()
     alarm.check()
     self.assertTrue(alarm.is_alarm_on)
コード例 #4
0
    def test_calls_play_sound_then_time_is_over(self):
        player = SoundPlayer()
        player.play = MagicMock()
        alarm = Alarm(0, player)

        alarm.check()

        player.play.assert_called()
コード例 #5
0
ファイル: test_alarm.py プロジェクト: mjcowdrill/python
 def test_check_with_too_high_pressure(self):
     with patch('alarm.Sensor') as test_sensor_class:
         test_sensor_instance = Mock()
         test_sensor_instance.sample_pressure.return_value = 22
         test_sensor_class.return_value=test_sensor_instance
         alarm = Alarm()
         alarm.check()
         self.assertTrue(alarm.is_alarm_on)
コード例 #6
0
ファイル: test_alarm.py プロジェクト: rt-learn-lang/python3
 def test_check_with_too_high_pressure_sounds_alarm(self):
     with patch('alarm.Sensor') as test_sensor_class:
         test_sensor_instance = Mock()
         test_sensor_instance.sample_pressure.return_value = 22
         test_sensor_class.return_value = test_sensor_instance
         alarm = Alarm()
         alarm.check()
         self.assertTrue(alarm.is_alarm_on)
コード例 #7
0
def test_alarm_with_monkey_patching_different(test_sensor_class):
    test_sensor_instance = Mock()
    test_sensor_instance.sample_pressure.return_value = 16
    test_sensor_class.return_value = test_sensor_instance

    alarm = Alarm()
    alarm.check()

    assert alarm.is_alarm_on
コード例 #8
0
ファイル: test_alarm.py プロジェクト: EldanGS/Engineering
def test_alarm_with_too_low_pressure(test_sensor_class):
    test_sensor_instance = Mock()
    test_sensor_instance.sample_pressure.return_value = 16
    test_sensor_class.return_value = test_sensor_instance

    alarm = Alarm()
    alarm.check()

    assert alarm.is_alarm_on
コード例 #9
0
def test_alarm_with_monkey_patching():
    with patch('alarm.Sensor') as test_sensor_class:
        test_sensor_instance = Mock()
        test_sensor_instance.sample_pressure.return_value = 22
        test_sensor_class.return_value = test_sensor_instance

        alarm = Alarm()
        alarm.check()
        assert alarm.is_alarm_on
コード例 #10
0
 def test_check_with_too_high_pressure(self):
     # all references in Alarm module to the Sensor class and get them to
     # replace with a test double and get reference to as test_sensor_class
     with patch('alarm.Sensor') as test_sensor_class:
         # create another test double
         test_sensor_instance = Mock()
         # respond to the method sample_pressure
         test_sensor_instance.sample_pressure.return_value = 22
         # we tell sensor class that is should return this test double when
         # it's constructor is called
         test_sensor_class.return_value = test_sensor_instance
         # when we call the Alarm constuctor, it will consctruct an instance
         # of test sense a class and that class will now how it gets a call
         # to the sample_pressure method
         alarm = Alarm()
         alarm.check()
         self.assertTrue(alarm.is_alarm_on)
コード例 #11
0
def test_low_pressure_activates_alarm():
    alarm = Alarm(sensor=StubSensor())
    alarm.check()
    assert alarm.is_alarm_on

    from alarm import Alarm
    from sensor import Sensor

    def test_alarm_is_off_by_default():
        alarm = Alarm()
        assert not alarm.is_alarm_on

    class StubSensor:
        def sample_pressure(self):
            return 15

    def test_low_pressure_activates_alarm():
        alarm = Alarm(sensor=StubSensor())
        alarm.check()
        assert alarm.is_alarm_on
コード例 #12
0
class AlarmTest(unittest.TestCase):
    def setUp(self):
        pass

    def test_activate_alarm(self):
        attrs = {'pop_next_pressure_psi_value.return_value': 22}
        sensor = Mock(spec=Sensor, **attrs)
        display = Mock(spec=Display)
        self._alarm = Alarm(sensor, display)

        self._alarm.check()

        display.print.assert_called_with("Alarm activated!")

    def test_alarm_no_activated(self):
        attrs = {'pop_next_pressure_psi_value.return_value': 21}
        sensor = Mock(spec=Sensor, **attrs)
        display = Mock(spec=Display)
        self._alarm = Alarm(sensor, display)

        self._alarm.check()

        display.print.assert_not_called()
コード例 #13
0
def test_check_too_low_pressure_sounds(low_sensor):
    alarm = Alarm(low_sensor)
    alarm.check()
    assert alarm.is_alarm_on
コード例 #14
0
 def test_high_pressure_sounds_alarm(self):
     alarm = Alarm(sensor=TestSensor(22))
     alarm.check()
     self.assertTrue(alarm.is_alarm_on)
コード例 #15
0
 def test_check_normal_pressure_doesnt_sound_alarm(self):
     alarm = Alarm(sensor=TestSensor(18))
     alarm.check()
     self.assertFalse(alarm.is_alarm_on)
コード例 #16
0
 def test_check_temp_ok_with_mock(self):
     test_sensor = MagicMock(Sensor)
     test_sensor.sample_temperature.return_value = 20
     alarm = Alarm(sensor=test_sensor)
     alarm.check()
     self.assertFalse(alarm.is_alarm_on)
コード例 #17
0
ファイル: test_alarm.py プロジェクト: ganqzz/sandbox_py
def test_normal_pressure_alarm_stays_off():
    stub_sensor = Mock(Sensor)
    stub_sensor.sample_pressure.return_value = 18
    alarm = Alarm(stub_sensor)
    alarm.check()
    assert not alarm.is_alarm_on
コード例 #18
0
 def test_check_temp_ok_with_mock(self):
     test_sensor = MagicMock(Sensor)
     test_sensor.sample_temperature.return_value = 20
     alarm = Alarm(sensor=test_sensor)
     alarm.check()
     self.assertFalse(alarm.is_alarm_on)
コード例 #19
0
 def test_check_too_high_temp_sounds_alarm(self):
     alarm = Alarm(sensor=TestSensor(32))
     alarm.check()
     self.assertTrue(alarm.is_alarm_on)
コード例 #20
0
def test_check_too_low_pressure_sounds(low_sensor):
    alarm = Alarm(low_sensor)
    alarm.check()
    assert alarm.is_alarm_on
コード例 #21
0
ファイル: test_alarm.py プロジェクト: copyleftdev/Plural
 def test_check_normal_pressure_doesnt_sound_alarm(self):
     alarm = Alarm(sensor=TestSensor(18))
     alarm.check()
     self.assertFalse(alarm.is_alarm_on)
コード例 #22
0
class Indicator(object):
    def __init__(self, coin, settings=None):
        self.coin = coin  # reference to main object
        self.alarm = Alarm(self)  # alarm

        self.prices = {}
        self.currency = ''
        self.volumecurrency = ''
        self.default_label = 'cur'
        self.latest_response = 0  # helps with discarding outdated responses

        self.settings = Settings(
            settings)  # override pre-set values if settings is set

        # get the various settings for this indicator
        self.refresh_frequency = self.settings.get_refresh()
        self.active_exchange = self.settings.get_exchange()
        self.active_asset_pair = self.settings.get_asset_pair()

        # load all the exchange modules and the classes contained within
        self.EXCHANGES = []
        self.CURRENCIES = {}

        for exchange in self.coin.exchanges:
            class_name = exchange.capitalize()
            class_ = getattr(importlib.import_module('exchanges.' + exchange),
                             class_name)

            self.EXCHANGES.append({
                'code':
                exchange,
                'name':
                class_name,
                'instance':
                class_(self),
                'default_label':
                class_.CONFIG.get('default_label') or 'cur'
            })
            self.CURRENCIES[exchange] = class_.CONFIG.get('asset_pairs')

    # initialisation and start of indicator and exchanges
    def start(self):
        icon = self.coin.config['project_root'] + '/resources/icon_32px.png'
        self.indicator = AppIndicator.Indicator.new(
            "CoinPriceIndicator_" + str(len(self.coin.instances)), icon,
            AppIndicator.IndicatorCategory.APPLICATION_STATUS)
        self.indicator.set_status(AppIndicator.IndicatorStatus.ACTIVE)
        self.indicator.set_menu(self._menu())
        self._start_exchange()

    # updates GUI menus with data stored in the object
    def update_gui(self):
        logging.debug('Updating GUI, last response was: ' +
                      str(self.latest_response))

        if self.prices.get(self.default_label):
            label = self.currency + self.prices.get(self.default_label)
        else:
            label = 'select default label'

        self.indicator.set_label(label, label)

        for item, name in CATEGORIES:
            price_menu_item = self.price_menu_items.get(item)  # get menu item

            # assigns prices to the corresponding menu items
            # if such a price value is returned from the exchange
            if self.prices.get(item):
                if item == self.default_label:
                    price_menu_item.set_active(True)
                    if self.alarm.active:
                        if self.alarm.check(float(self.prices.get(item))):
                            self.alarm.deactivate()

                price_menu_item.set_label(name + self.currency +
                                          self.prices.get(item))
                price_menu_item.show()
            # if no such price value is returned, hide the menu item
            else:
                price_menu_item.hide()

        # slightly different behaviour for volume menu item
        if self.prices.get('vol'):
            self.volume_item.set_label('Vol (' + self.volumecurrency + '):\t' +
                                       self.prices.get('vol'))
            self.volume_item.show()
        else:
            self.volume_item.hide()

    # (re)starts the exchange logic and its timer
    def _start_exchange(self):
        logging.info("Loading " + self.active_asset_pair + " from " +
                     self.active_exchange + " (" +
                     str(self.refresh_frequency) + "s)")

        # stop any running timers, clear error counter
        if hasattr(self, 'exchange_instance'):
            self.exchange_instance.stop()

        # don't show any data until first response is in
        self.indicator.set_label('loading', 'loading')
        for item in self.price_group:
            item.set_active(False)
            item.set_label('loading')

        self.volume_item.set_label('loading')
        home_currency = self.active_asset_pair.lower()[1:4]

        if isfile(
                self.coin.config.get('project_root') + '/resources/' +
                home_currency + '.png'):
            self.indicator.set_icon(
                self.coin.config.get('project_root') + '/resources/' +
                home_currency + '.png')
        else:
            self.indicator.set_icon(
                self.coin.config.get('project_root') +
                '/resources/unknown-coin.png')

        # load new exchange instance
        self.exchange_instance = [
            e.get('instance') for e in self.EXCHANGES
            if self.active_exchange == e.get('code')
        ][0]
        self.default_label = [
            e.get('default_label')
            for e in self.EXCHANGES if self.active_exchange == e.get('code')
        ][0] or 'bid'

        # start the timers and logic
        self.exchange_instance.start()

    # promotes a price value to the main label position
    def _make_label(self, widget, label):
        if widget.get_active():
            self.default_label = label
            if self.price_menu_items.get(self.default_label):
                new_label = self.prices.get(label)
                if new_label:
                    self.indicator.set_label(self.currency + new_label,
                                             new_label)

    def _menu(self):
        menu = Gtk.Menu()
        self.price_group = [
        ]  # so that a radio button can be set on the active one

        # hacky way to get every price item on the menu and filled
        self.price_menu_items = {}
        for price_type, name in CATEGORIES:
            self.price_menu_items[
                price_type] = Gtk.RadioMenuItem.new_with_label(
                    self.price_group, 'loading...')
            self.price_menu_items[price_type].connect('toggled',
                                                      self._make_label,
                                                      price_type)
            self.price_group.append(self.price_menu_items.get(price_type))
            menu.append(self.price_menu_items.get(price_type))

        # trading volume display
        self.volume_item = Gtk.MenuItem('loading...')
        menu.append(self.volume_item)

        menu.append(Gtk.SeparatorMenuItem())

        # exchange choice menu
        self.exchange_menu = Gtk.MenuItem("Exchange")
        self.exchange_menu.set_submenu(self._menu_exchange())
        menu.append(self.exchange_menu)

        # refresh rate choice menu
        self.refresh_menu = Gtk.MenuItem("Refresh")
        self.refresh_menu.set_submenu(self._menu_refresh())
        menu.append(self.refresh_menu)

        self.alarm_menu = Gtk.MenuItem("Set Alert" + u"\u2026")
        self.alarm_menu.connect("activate", self._alarm_settings)
        menu.append(self.alarm_menu)

        menu.append(Gtk.SeparatorMenuItem())

        # menu to remove current indicator from app
        remove_item = Gtk.MenuItem("Remove Ticker")
        remove_item.connect("activate", self._remove)
        menu.append(remove_item)

        menu.show_all()

        return menu

    def _menu_refresh(self):
        refresh_menu = Gtk.Menu()

        group = []
        for ri in REFRESH_TIMES:
            item = Gtk.RadioMenuItem.new_with_label(group, str(ri) + ' sec')
            group.append(item)
            refresh_menu.append(item)

            if self.refresh_frequency == ri:
                item.set_active(True)
            item.connect('activate', self._menu_refresh_change, ri)

        return refresh_menu

    def _menu_refresh_change(self, widget, ri):
        if widget.get_active():
            self.refresh_frequency = ri
            self.settings.set_refresh(self.refresh_frequency)
            self.exchange_instance.stop().start()

    def _menu_exchange(self):
        exchange_list_menu = Gtk.Menu()
        self.exchange_group = []
        subgroup = []  # group all asset pairs of all exchange menus together
        for exchange in self.EXCHANGES:
            item = Gtk.RadioMenuItem.new_with_label(self.exchange_group,
                                                    exchange.get('name'))
            item.set_submenu(self._menu_asset_pairs(exchange, subgroup))
            item.connect('toggled', self._handle_toggle, exchange.get('code'))
            self.exchange_group.append(item)
            exchange_list_menu.append(item)

            if self.active_exchange == exchange.get('code'):
                item.set_active(True)

        return exchange_list_menu

    # this eliminates the strange side-effect that an item stays active
    # when you hover over it and then mouse out
    def _handle_toggle(self, widget, exchange_code):
        if self.active_exchange != exchange_code:
            widget.set_active(False)
        else:
            widget.set_active(True)

    def _menu_asset_pairs(self, exchange, subgroup):
        asset_pairs_menu = Gtk.Menu()
        for asset in self.CURRENCIES[exchange.get('code')]:
            item = Gtk.RadioMenuItem.new_with_label(subgroup, asset['name'])
            subgroup.append(item)
            asset_pairs_menu.append(item)

            if self.active_asset_pair == asset[
                    'isocode'] and self.active_exchange == exchange.get(
                        'code'):
                item.set_active(True)

            item.connect('activate', self._menu_asset_pairs_change,
                         asset['isocode'], exchange)

        return asset_pairs_menu

    # if the asset pairs change
    def _menu_asset_pairs_change(self, widget, asset_pair, exchange):
        if widget.get_active():
            self.active_exchange = exchange.get('code')
            tentative_asset_pair = [
                item.get('isocode')
                for item in self.CURRENCIES[exchange.get('code')]
                if item.get('isocode') == self.active_asset_pair
            ]
            if len(tentative_asset_pair) == 0:
                self.active_asset_pair = self.CURRENCIES[exchange.get(
                    'code')][0]['isocode']
            else:
                self.active_asset_pair = tentative_asset_pair[0]

            self.active_asset_pair = asset_pair
            self.settings.set_exchange(self.active_exchange)
            self.settings.set_asset_pair(self.active_asset_pair)

            # set parent (exchange) menu item to active
            for exchange_menu_item in self.exchange_group:
                if self.active_exchange == exchange_menu_item.get_label(
                ).lower():
                    exchange_menu_item.set_active(True)

            self._start_exchange()

    def _remove(self, widget):
        if len(self.coin.instances) == 1:  # is this the last ticker?
            Gtk.main_quit()  # then quit entirely
        else:  # otherwise just remove this one
            self.coin.instances.remove(self)
            self.exchange_instance.stop()
            del self.indicator

    def _alarm_settings(self, widget):
        AlarmSettingsWindow(self)
コード例 #23
0
def test_check_normal_pressure_doesnt_sound_alarm(normal_sensor):
    alarm = Alarm(normal_sensor)
    alarm.check()
    assert not alarm.is_alarm_on
コード例 #24
0
def test_check_normal_pressure_doesnt_sound_alarm_with_mock(mocker):
    test_sensor = Mock(Sensor)
    test_sensor.sample_pressure.return_value = 18
    alarm = Alarm(test_sensor)
    alarm.check()
    assert not alarm.is_alarm_on
コード例 #25
0
def test_check_too_high_pressure_sounds(high_sensor):
    alarm = Alarm(high_sensor)
    alarm.check()
    assert alarm.is_alarm_on
コード例 #26
0
def test_check_too_high_pressure_sounds(high_sensor):
    alarm = Alarm(high_sensor)
    alarm.check()
    assert alarm.is_alarm_on
コード例 #27
0
 def test_check_too_low_temp_sounds_alarm(self):
     alarm = Alarm(sensor=TestSensor(2))  # arrange
     alarm.check()  # act
     self.assertTrue(alarm.is_alarm_on)  # assert
コード例 #28
0
def test_check_normal_pressure_doesnt_sound_alarm_with_mock(mocker):
    test_sensor = Mock(Sensor)
    test_sensor.sample_pressure.return_value = 18
    alarm = Alarm(test_sensor)
    alarm.check()
    assert not alarm.is_alarm_on
コード例 #29
0
 def test_check_normal_temp_doesnt_sounds_alarm(self):
     alarm = Alarm(sensor=TestSensor(20))
     alarm.check()
     self.assertFalse(alarm.is_alarm_on)
コード例 #30
0
import unittest

from unittest.mock import Mock

from alarm import Alarm
from sensor import Sensor

class Alarmtest(unittest.TestCase):

    def test_alarm_is_off_by_default(self):
	    alarm = Alarm()
		self.assertFalse(alarm.is_alarm_on)
	
	def test_check_too_low_pressure_sounds_alarm(self)
	    alarm = Alarm(sensor=TestSensor(15))
		alarm.check()
		self.assertTrue(alarm.is_alarm_on)
		
	def test_check_too_high_pressure_sounds_alarm(self)
	    alarm = Alarm(sensor=TestSensor(22))
		alarm.check()
		self.assertTrue(alarm.is_alarm_on)
		
	def test_check_normal_pressure_doesnt_sound_alarm(self)
	    alarm = Alarm(sensor=TestSensor(18))
		alarm.check()
		self.assertFalse(alarm.is_alarm_on)
	
	def test_check_with_pressure_ok_with_mock_fwi(self):
        test_sensor = Mock(Sensor)	
	    test_sensor.sample_pressure.return_value = 18
コード例 #31
0
ファイル: test_alarm.py プロジェクト: ganqzz/sandbox_py
def test_low_pressure_activates_alarm():
    alarm = Alarm(sensor=StubSensor())
    alarm.check()
    assert alarm.is_alarm_on
コード例 #32
0
 def test_normal_pressure_with_unittest_mock(self):
     test_sensor = Mock(Sensor)
     test_sensor.sample_pressure.return_value = 18
     alarm = Alarm(test_sensor)
     alarm.check()
     self.assertFalse(alarm.is_alarm_on)
コード例 #33
0
class Indicator(object):
    def __init__(self, coin, exchange, asset_pair, refresh, default_label):
        self.coin = coin # reference to main object
        self.alarm = Alarm(self) # alarm
        self.exchange = self.coin.find_exchange_by_code(exchange).get('class')(self)
        self.exchange.set_asset_pair_from_code(asset_pair)
        self.refresh_frequency = refresh
        self.default_label = default_label

        self.prices = {}
        self.latest_response = 0 # helps with discarding outdated responses

    # initialisation and start of indicator and exchanges
    def start(self):
        icon = self.coin.config.get('project_root') + '/resources/icon_32px.png'
        self.indicator_widget = AppIndicator.Indicator.new("CoinPriceIndicator_" + str(len(self.coin.instances)), icon, AppIndicator.IndicatorCategory.APPLICATION_STATUS)
        self.indicator_widget.set_status(AppIndicator.IndicatorStatus.ACTIVE)
        self.indicator_widget.set_menu(self._menu())
        self._start_exchange()

    # updates GUI menus with data stored in the object
    def update_gui(self):
        logging.debug('Updating GUI, last response was: ' + str(self.latest_response))

        self.symbol = self.exchange.get_symbol()
        self.volumecurrency = self.exchange.get_volume_currency()

        if self.prices.get(self.default_label):
            label = self.symbol + self.prices.get(self.default_label)
        else:
            label = 'select default label'

        self.indicator_widget.set_label(label, label)
        
        for item, name in CATEGORIES:
            price_menu_item = self.price_menu_items.get(item) # get menu item

            # assigns prices to the corresponding menu items
            # if such a price value is returned from the exchange
            if self.prices.get(item):
                if item == self.default_label:
                    price_menu_item.set_active(True)
                    if self.alarm.active:
                        if self.alarm.check(float(self.prices.get(item))):
                            self.alarm.deactivate()

                price_menu_item.set_label(name + self.symbol + self.prices.get(item))
                price_menu_item.show()
            # if no such price value is returned, hide the menu item
            else:
                price_menu_item.hide()

        # slightly different behaviour for volume menu item
        if self.prices.get('vol'):
            self.volume_item.set_label('Vol (' + self.volumecurrency + '):\t' + self.prices.get('vol'))
            self.volume_item.show()
        else:
            self.volume_item.hide()

    # (re)starts the exchange logic and its timer
    def _start_exchange(self):
        logging.info("Loading " + self.exchange.asset_pair.get('pair') + " from " + self.exchange.get_name() + " (" + str(self.refresh_frequency) + "s)")

        # don't show any data until first response is in
        GLib.idle_add(self.indicator_widget.set_label, 'loading', 'loading')
        for item in self.price_group:
            GLib.idle_add(item.set_active, False)
            GLib.idle_add(item.set_label, 'loading')

        self.volume_item.set_label('loading')

        # set icon for asset if it exists
        currency = self.exchange.asset_pair.get('base').lower()

        if isfile(self.coin.config.get('project_root') + '/resources/' + currency + '.png'):
            self.indicator_widget.set_icon(self.coin.config.get('project_root') + '/resources/' + currency + '.png')
        else:
            self.indicator_widget.set_icon(self.coin.config.get('project_root') + '/resources/unknown-coin.png')

        self._make_default_label(self.default_label)

        # start the timers and logic
        self.exchange.start()

    # promotes a price value to the main label position
    def _menu_make_label(self, widget, label):
        if widget.get_active():
            self._make_default_label(label)
            self.coin.save_settings()

    def _make_default_label(self, label):
        self.default_label = label
        if self.price_menu_items.get(self.default_label):
            new_label = self.prices.get(label)
            if new_label:
                self.indicator_widget.set_label(self.symbol + new_label, new_label)

    def _menu(self):
        menu = Gtk.Menu()
        self.price_group = [] # so that a radio button can be set on the active one

        # hacky way to get every price item on the menu and filled
        self.price_menu_items = {}
        for price_type, name in CATEGORIES:
            self.price_menu_items[price_type] = Gtk.RadioMenuItem.new_with_label(self.price_group, 'loading...')
            self.price_menu_items[price_type].connect('toggled', self._menu_make_label, price_type)
            self.price_group.append(self.price_menu_items.get(price_type))
            menu.append(self.price_menu_items.get(price_type))

        # trading volume display
        self.volume_item = Gtk.MenuItem('loading...')
        menu.append(self.volume_item)

        menu.append(Gtk.SeparatorMenuItem())

        # asset choice menu
        self.asset_menu = Gtk.MenuItem("Assets")
        self.asset_menu.set_submenu(self._menu_bases())
        menu.append(self.asset_menu)

        # refresh rate choice menu
        self.refresh_menu = Gtk.MenuItem("Refresh")
        self.refresh_menu.set_submenu(self._menu_refresh())
        menu.append(self.refresh_menu)

        # alert menu
        self.alarm_menu = Gtk.MenuItem("Set Alert" + u"\u2026")
        self.alarm_menu.connect("activate", self._alarm_settings)
        menu.append(self.alarm_menu)

        menu.append(Gtk.SeparatorMenuItem())

        # menu to remove current indicator from app
        remove_item = Gtk.MenuItem("Remove Ticker")
        remove_item.connect("activate", self._remove)
        menu.append(remove_item)

        menu.show_all()

        return menu

    ##
    # Gets called by exchange instance when new asset pairs are discovered
    # 
    def rebuild_asset_menu(self):
        self.exchange.stop()
        self.indicator_widget.set_label('loading...', 'loading')
        GLib.idle_add(self.asset_menu.set_submenu, None)
        GLib.idle_add(self.asset_menu.set_submenu, self._menu_bases())
        GLib.idle_add(self.asset_menu.show_all)
        self.exchange.start()

    def _menu_refresh(self):
        refresh_menu = Gtk.Menu()

        group = []
        for ri in REFRESH_TIMES:
            item = Gtk.RadioMenuItem.new_with_label(group, str(ri) + ' sec')
            group.append(item)
            refresh_menu.append(item)

            if self.refresh_frequency == ri:
                item.set_active(True)
            item.connect('activate', self._menu_refresh_change, ri)

        return refresh_menu

    def _menu_refresh_change(self, widget, ri):
        if widget.get_active():
            self.refresh_frequency = ri
            self.coin.save_settings()
            self.exchange.stop().start()

    def rebuild_recents_menu(self):
        counter = 0 
        for item in self._build_recents_menu():
            self.recent_group['base_group'][counter] = item
            self.recent_group['base_group'][counter].show()
            counter += 1

    def _build_recents_menu(self):
        recent_group = {
            'base_group': [],
            'subgroup_quotes': [],
            'subgroup_exchanges': []
        }

        for i in range(0,5):
            if i > len(self.coin.settings.get('recent'))-1:
                base_item = self.create_base_item(None, recent_group, hidden = True)
            else:
                base = self.coin.settings.get('recent')[i]
                base_item = self.create_base_item(base, recent_group)
            
            yield base_item

        self.recent_group = recent_group

    def _menu_bases(self):
        base_list_menu = Gtk.Menu()

        # these are to keep track of all the option groups across menus
        all_group = {
            'base_group': [],
            'subgroup_quotes': [],
            'subgroup_exchanges': []
        }

        # build recents menu atop the assets
        for item in self._build_recents_menu():
            base_list_menu.append(item)

        base_list_menu.append(Gtk.SeparatorMenuItem())

        # sorting magic
        bases = []
        for base in self.coin.bases:
            bases.append(base)
        bases.sort()

        # add all other assets, sorted
        for base in bases:
            base_item = self.create_base_item(base, all_group)
            base_list_menu.append(base_item)

        self.base_list_menu = base_list_menu

        return base_list_menu

    def create_base_item(self, base, group, hidden = False):
        if hidden:
            base_item = Gtk.RadioMenuItem.new_with_label(group.get('base_group'), 'hidden')
            base_item.hide()
        else:
            base_item = Gtk.RadioMenuItem.new_with_label(group.get('base_group'), base)
            base_item.set_submenu(self._menu_quotes(base, group.get('subgroup_quotes'), group.get('subgroup_exchanges')))
        
        group.get('base_group').append(base_item)

        if self.exchange.asset_pair.get('base') == base:
            base_item.set_active(True)

        base_item.connect('toggled', self._handle_toggle, base)

        return base_item

    def _menu_quotes(self, base, subgroup_quotes, subgroup_exchanges):
        quote_list_menu = Gtk.Menu()

        # sorting magic
        quotes = []
        for quote in self.coin.bases[base]:
            quotes.append(quote)
        quotes.sort()

        for quote in quotes:
            quote_item = Gtk.RadioMenuItem.new_with_label(subgroup_quotes, quote)
            quote_item.set_submenu(self._menu_exchanges(base, quote, subgroup_exchanges))
            subgroup_quotes.append(quote_item)
            quote_list_menu.append(quote_item)

            if (self.exchange.asset_pair.get('quote') == quote) and (self.exchange.asset_pair.get('base') == base):
                quote_item.set_active(True)

            quote_item.connect('toggled', self._handle_toggle, base, quote)

        return quote_list_menu

    def _menu_exchanges(self, base, quote, subgroup_exchanges):
        exchange_list_menu = Gtk.Menu()

        # some sorting magic
        exchanges = []
        for exchange in self.coin.bases[base][quote]:
            exchanges.append(exchange)        
        exchanges = sorted(exchanges, key=lambda k: k['name'])

        for exchange in exchanges:
            exchange_item = Gtk.RadioMenuItem.new_with_label(subgroup_exchanges, exchange.get('name'))
            subgroup_exchanges.append(exchange_item)
            exchange_list_menu.append(exchange_item)

            if (self.exchange.get_code() == exchange.get('code')) and (self.exchange.asset_pair.get('quote') == quote) and (self.exchange.asset_pair.get('base') == base):
                exchange_item.set_active(True)

            exchange_item.connect('activate', self._change_assets, base, quote, exchange.get('code'))

        return exchange_list_menu

    # this eliminates the strange side-effect that an item stays active
    # when you hover over it and then mouse out
    def _handle_toggle(self, widget, base=None, quote=None):
        if base == None:
            base = self.exchange.asset_pair.get('base')
        if quote == None:
            quote = self.exchange.asset_pair.get('quote')

        if (self.exchange.asset_pair.get('quote') == quote) and (self.exchange.asset_pair.get('base') == base):
            widget.set_active(True)
        else:
            widget.set_active(False)

    # if the asset pairs change
    def _change_assets(self, widget, base, quote, exchangeCode):
        if widget.get_active():
            # save for later
            previous_base = self.exchange.asset_pair.get('base')

            # stop the current exchange
            self.exchange.stop()

            # There must be an easier way to set the parent menu item active
            widget.get_parent().get_attach_widget().set_active(True)
            widget.get_parent().get_attach_widget().get_parent().get_attach_widget().set_active(True)

            # change the exchange class if needed. This needs a factory by the way.
            if self.exchange.get_code() is not exchangeCode:
                exchange_class = self.coin.find_exchange_by_code(exchangeCode).get('class')
                self.exchange = exchange_class(self)

            # change exchange's asset pair
            self.exchange.set_asset_pair(base, quote)

            # add item to recents menu, recents menu will be rebuilt too
            if previous_base is not base:
                self.coin.add_new_recent_base(base)

            self.coin.save_settings()
            self._start_exchange()

    def _remove(self, widget):
        self.coin.remove_ticker(self)

    def _alarm_settings(self, widget):
        AlarmSettingsWindow(self)
コード例 #34
0
 def test_check_normal_temp_doesnt_sounds_alarm(self):
     alarm = Alarm(sensor=TestSensor(20))
     alarm.check()
     self.assertFalse(alarm.is_alarm_on)
コード例 #35
0
 def test_check_too_low_pressure_sounds_alarm(self):
     alarm = Alarm(sensor=TestSensor(15))
     alarm.check()
     self.assertTrue(alarm.is_alarm_on)
コード例 #36
0
ファイル: test_alarm.py プロジェクト: copyleftdev/Plural
 def test_check_too_high_pressure_sounds_alarm(self):
     alarm = Alarm(sensor=TestSensor(22))
     alarm.check()
     self.assertTrue(alarm.is_alarm_on)
コード例 #37
0
 def test_check_with_pressure_ok_with_mock_fw(self):
     test_sensor = Mock(Sensor)
     test_sensor.sample_pressure.return_value = 18
     alarm = Alarm(test_sensor)
     alarm.check()
     self.assertFalse(alarm.is_alarm_on)
コード例 #38
0
class Indicator(object):
    def __init__(self, coin, unique_id, exchange, asset_pair, refresh,
                 default_label):
        self.coin = coin  # reference to main object
        self.unique_id = unique_id
        self.alarm = Alarm(self)  # alarm
        self.exchange = self.coin.find_exchange_by_code(exchange)(self)
        self.exchange.set_asset_pair_from_code(asset_pair)
        self.refresh_frequency = refresh
        self.default_label = default_label
        self.asset_selection_window = None
        self.alarm_settings_window = None

        self.prices = {}
        self.latest_response = 0  # helps with discarding outdated responses

    # initialisation and start of indicator and exchanges
    def start(self):
        icon = self.coin.config.get(
            'project_root') + '/resources/icon_32px.png'
        self.indicator_widget = AppIndicator.Indicator.new(
            "CoinPriceIndicator_" + str(self.unique_id), icon,
            AppIndicator.IndicatorCategory.APPLICATION_STATUS)
        self.indicator_widget.set_status(AppIndicator.IndicatorStatus.ACTIVE)
        self.indicator_widget.set_ordering_index(0)
        self.indicator_widget.set_menu(self._menu())
        self._start_exchange()

    # updates GUI menus with data stored in the object
    def update_gui(self):
        logging.debug('Updating GUI, last response was: ' +
                      str(self.latest_response))

        self.symbol = self.exchange.get_symbol()
        self.volumecurrency = self.exchange.get_volume_currency()

        if self.prices.get(self.default_label):
            label = self.symbol + self.prices.get(self.default_label)
        else:
            label = 'select default label'

        self.indicator_widget.set_label(label, label)

        for item, name in CATEGORIES:
            price_menu_item = self.price_menu_items.get(item)  # get menu item

            # assigns prices to the corresponding menu items
            # if such a price value is returned from the exchange
            if self.prices.get(item):
                if item == self.default_label:
                    price_menu_item.set_active(True)
                    if self.alarm.active:
                        if self.alarm.check(float(self.prices.get(item))):
                            self.alarm.deactivate()

                price_menu_item.set_label(name + self.symbol +
                                          self.prices.get(item))
                price_menu_item.show()
            # if no such price value is returned, hide the menu item
            else:
                price_menu_item.hide()

        # slightly different behaviour for volume menu item
        if self.prices.get('vol'):
            self.volume_item.set_label('Vol (' + self.volumecurrency + '):\t' +
                                       self.prices.get('vol'))
            self.volume_item.show()
        else:
            self.volume_item.hide()

    # (re)starts the exchange logic and its timer
    def _start_exchange(self):
        logging.info("Loading " + self.exchange.asset_pair.get('pair') +
                     " from " + self.exchange.get_name() + " (" +
                     str(self.refresh_frequency) + "s)")

        # don't show any data until first response is in
        GLib.idle_add(self.indicator_widget.set_label, 'loading', 'loading')
        for item in self.price_group:
            GLib.idle_add(item.set_active, False)
            GLib.idle_add(item.set_label, 'loading')

        self.volume_item.set_label('loading')

        # set icon for asset if it exists
        currency = self.exchange.asset_pair.get('base').lower()

        if isfile(
                self.coin.config.get('project_root') + '/resources/' +
                currency + '.png'):
            self.indicator_widget.set_icon(
                self.coin.config.get('project_root') + '/resources/' +
                currency + '.png')
        else:
            self.indicator_widget.set_icon(
                self.coin.config.get('project_root') +
                '/resources/unknown-coin.png')

        self._make_default_label(self.default_label)

        # start the timers and logic
        self.exchange.start()

    # promotes a price value to the main label position
    def _menu_make_label(self, widget, label):
        if widget.get_active():
            self._make_default_label(label)
            self.coin.save_settings()

    def _make_default_label(self, label):
        self.default_label = label
        if self.price_menu_items.get(self.default_label):
            new_label = self.prices.get(label)
            if new_label:
                self.indicator_widget.set_label(self.symbol + new_label,
                                                new_label)

    def _menu(self):
        menu = Gtk.Menu()
        self.price_group = [
        ]  # so that a radio button can be set on the active one

        # hacky way to get every price item on the menu and filled
        self.price_menu_items = {}
        for price_type, name in CATEGORIES:
            self.price_menu_items[
                price_type] = Gtk.RadioMenuItem.new_with_label(
                    self.price_group, 'loading...')
            self.price_menu_items[price_type].connect('toggled',
                                                      self._menu_make_label,
                                                      price_type)
            self.price_group.append(self.price_menu_items.get(price_type))
            menu.append(self.price_menu_items.get(price_type))

        # trading volume display
        self.volume_item = Gtk.MenuItem('loading...')
        menu.append(self.volume_item)

        menu.append(Gtk.SeparatorMenuItem())

        # settings menu
        self.settings_menu = Gtk.MenuItem("Select Asset" + u"\u2026")
        self.settings_menu.connect("activate", self._settings)
        menu.append(self.settings_menu)

        # refresh rate choice menu
        self.refresh_menu = Gtk.MenuItem("Refresh")
        self.refresh_menu.set_submenu(self._menu_refresh())
        menu.append(self.refresh_menu)

        # alert menu
        self.alarm_menu = Gtk.MenuItem("Set Alert" + u"\u2026")
        self.alarm_menu.connect("activate", self._alarm_settings)
        menu.append(self.alarm_menu)

        menu.append(Gtk.SeparatorMenuItem())

        # menu to remove current indicator from app
        remove_item = Gtk.MenuItem("Remove Ticker")
        remove_item.connect("activate", self._remove)
        menu.append(remove_item)

        menu.show_all()

        return menu

    def _menu_refresh(self):
        refresh_menu = Gtk.Menu()

        group = []
        for ri in REFRESH_TIMES:
            item = Gtk.RadioMenuItem.new_with_label(group, str(ri) + ' sec')
            group.append(item)
            refresh_menu.append(item)

            if self.refresh_frequency == ri:
                item.set_active(True)
            item.connect('activate', self._menu_refresh_change, ri)

        return refresh_menu

    def _menu_refresh_change(self, widget, ri):
        if widget.get_active():
            self.refresh_frequency = ri
            self.coin.save_settings()
            self.exchange.stop().start()

    def change_assets(self, base, quote, exchange_code):
        self.exchange.stop()

        if self.exchange.get_code() is not exchange_code:
            exchange_class = self.coin.find_exchange_by_code(exchange_code)
            self.exchange = exchange_class(self)

        self.exchange.set_asset_pair(base, quote)

        self.coin.save_settings()
        self._start_exchange()

    def _remove(self, widget):
        self.coin.remove_ticker(self)

    def _alarm_settings(self, widget):
        self.alarm_settings_window = AlarmSettingsWindow(
            self, self.prices.get(self.default_label))

    def _settings(self, widget):
        for indicator in self.coin.instances:
            if indicator.asset_selection_window:
                indicator.asset_selection_window.destroy()

        self.asset_selection_window = AssetSelectionWindow(self)
コード例 #39
0
 def test_normal_pressure_sounds_alarm(self):
     alarm = Alarm(sensor=TestSensor(20))
     alarm.check()
     self.assertFalse(alarm.is_alarm_on)
コード例 #40
0
ファイル: test_alarm.py プロジェクト: copyleftdev/Plural
 def test_check_with_pressure_ok_with_mock_fw(self):
     test_sensor = Mock(Sensor)
     test_sensor.sample_pressure.return_value = 18
     alarm = Alarm(test_sensor)
     alarm.check()
     self.assertFalse(alarm.is_alarm_on)
コード例 #41
0
def test_check_normal_pressure_doesnt_sound_alarm(normal_sensor):
    alarm = Alarm(normal_sensor)
    alarm.check()
    assert not alarm.is_alarm_on
コード例 #42
0
 def test_check_too_low_temp_sounds_alarm(self):
     alarm = Alarm(sensor=TestSensor(2))  # arrange
     alarm.check()                        # act
     self.assertTrue(alarm.is_alarm_on)   # assert