From 195e4bda54d8fd49936213a8f28349b96fb5acd2 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Fri, 8 Apr 2016 22:34:20 +0300 Subject: added filters.py ToggleFilter functionality, and its test file --- .../trex_control_plane/common/filters.py | 86 ++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 scripts/automation/trex_control_plane/common/filters.py (limited to 'scripts/automation/trex_control_plane') diff --git a/scripts/automation/trex_control_plane/common/filters.py b/scripts/automation/trex_control_plane/common/filters.py new file mode 100644 index 00000000..3a05f4d1 --- /dev/null +++ b/scripts/automation/trex_control_plane/common/filters.py @@ -0,0 +1,86 @@ + +def shallow_copy(x): + return type(x)(x) + + +class ToggleFilter(object): + """ + This class provides a "sticky" filter, that works by "toggling" items of the original database on and off. + """ + def __init__(self, db_ref, show_by_default=True): + self._data = db_ref + self._toggle_db = set() + self._filter_method = filter + self.__set_initial_state(show_by_default) + + def toggle_item(self, item_key): + if item_key in self._toggle_db: + self._toggle_db.remove(item_key) + return False + elif item_key in self._data: + self._toggle_db.add(item_key) + return True + else: + raise KeyError("Provided item key isn't a key of the referenced data structure.") + + def filter_items(self): + """ + Filters the pointed database by showing only the items mapped at toggle_db set. + + :returns: + Filtered data of the original object. + + """ + return self._filter_method(self.__toggle_filter, self._data) + + # private methods + + def __set_initial_state(self, show_by_default): + try: + _ = (x for x in self._data) + if isinstance(self._data, dict): + self._filter_method = ToggleFilter.dict_filter + if show_by_default: + self._toggle_db = self._data.keys() + return + elif isinstance(self._data, list): + self._filter_method = ToggleFilter.list_filter + elif isinstance(self._data, set): + self._filter_method = ToggleFilter.set_filter + elif isinstance(self._data, tuple): + self._filter_method = ToggleFilter.tuple_filter + if show_by_default: + self._toggle_db = set(shallow_copy(self._data)) # assuming all relevant data with unique identifier + return + except TypeError: + raise TypeError("provided data object is not iterable") + + def __toggle_filter(self, x): + return (x in self._toggle_db) + + # static utility methods + + @staticmethod + def dict_filter(function, iterable): + assert isinstance(iterable, dict) + return {k: v + for k,v in iterable.iteritems() + if function(k, v)} + + @staticmethod + def list_filter(function, iterable): + return filter(function, iterable) + + @staticmethod + def set_filter(function, iterable): + return {x + for x in iterable + if function(x)} + + @staticmethod + def tuple_filter(function, iterable): + return tuple(filter(function, iterable)) + + +if __name__ == "__main__": + pass -- cgit From 9e63f57a80722751221e18ae1e42a7f7ac4983ab Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Sat, 9 Apr 2016 01:08:51 +0300 Subject: added multiple toggle option all test passed! --- scripts/automation/trex_control_plane/common/filters.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'scripts/automation/trex_control_plane') diff --git a/scripts/automation/trex_control_plane/common/filters.py b/scripts/automation/trex_control_plane/common/filters.py index 3a05f4d1..d2ca7b16 100644 --- a/scripts/automation/trex_control_plane/common/filters.py +++ b/scripts/automation/trex_control_plane/common/filters.py @@ -23,6 +23,9 @@ class ToggleFilter(object): else: raise KeyError("Provided item key isn't a key of the referenced data structure.") + def toggle_items(self, *args): + return all(map(self.toggle_item, args)) + def filter_items(self): """ Filters the pointed database by showing only the items mapped at toggle_db set. @@ -41,7 +44,7 @@ class ToggleFilter(object): if isinstance(self._data, dict): self._filter_method = ToggleFilter.dict_filter if show_by_default: - self._toggle_db = self._data.keys() + self._toggle_db = set(self._data.keys()) return elif isinstance(self._data, list): self._filter_method = ToggleFilter.list_filter @@ -65,7 +68,7 @@ class ToggleFilter(object): assert isinstance(iterable, dict) return {k: v for k,v in iterable.iteritems() - if function(k, v)} + if function(k)} @staticmethod def list_filter(function, iterable): -- cgit From 330cf8f7950027efe7b4bbc96a7ee1af3ee0b10a Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Sat, 9 Apr 2016 13:34:35 +0300 Subject: basic modifications for TRex tui to support toggle filtering on ports --- .../trex_control_plane/stl/console/trex_tui.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'scripts/automation/trex_control_plane') diff --git a/scripts/automation/trex_control_plane/stl/console/trex_tui.py b/scripts/automation/trex_control_plane/stl/console/trex_tui.py index 88c53d10..975017a5 100644 --- a/scripts/automation/trex_control_plane/stl/console/trex_tui.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_tui.py @@ -13,6 +13,8 @@ else: from trex_stl_lib.utils.text_opts import * from trex_stl_lib.utils import text_tables from trex_stl_lib import trex_stl_stats +import trex_root_path +from common.filters import ToggleFilter # for STL exceptions from trex_stl_lib.api import * @@ -65,10 +67,10 @@ class TrexTUIDashBoard(TrexTUIPanel): self.key_actions['-'] = {'action': self.action_lower, 'legend': 'low 5%', 'show': True} self.ports = self.stateless_client.get_all_ports() - + self.toggle_filter = ToggleFilter(self.ports) def show (self): - stats = self.stateless_client._get_formatted_stats(self.ports) + stats = self.stateless_client._get_formatted_stats(self.toggle_filter.filter_items()) # print stats to screen for stat_type, stat_data in stats.items(): text_tables.print_table_with_header(stat_data.text_table, stat_type) @@ -289,7 +291,7 @@ class TrexTUIPanelManager(): self.key_actions['s'] = {'action': self.action_show_sstats, 'legend': 'streams stats', 'show': True} for port_id in self.ports: - self.key_actions[str(port_id)] = {'action': self.action_show_port(port_id), 'legend': 'port {0}'.format(port_id), 'show': False} + self.key_actions[str(port_id)] = {'action': self.action_toggle_port(port_id), 'legend': 'port {0}'.format(port_id), 'show': False} self.panels['port {0}'.format(port_id)] = TrexTUIPort(self, port_id) # start with dashboard @@ -387,6 +389,15 @@ class TrexTUIPanelManager(): return action_show_port_x + def action_toggle_port(self, port_id): + def action_toggle_port_x(): + self.panels['dashboard'].toggle_filter.toggle_item(port_id) + self.init() + return "" + + return action_toggle_port_x + + def action_show_sstats (self): self.main_panel = self.panels['sstats'] -- cgit From 3bafb0394c07ef2abb4ce34c7fb4ec01eb09f2df Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Tue, 19 Apr 2016 01:44:04 +0300 Subject: All unit tests passes with both python 2 and python 3. Added more documentation to the ToggleFilter class. --- .../trex_control_plane/common/filters.py | 54 ++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) (limited to 'scripts/automation/trex_control_plane') diff --git a/scripts/automation/trex_control_plane/common/filters.py b/scripts/automation/trex_control_plane/common/filters.py index d2ca7b16..bf04a775 100644 --- a/scripts/automation/trex_control_plane/common/filters.py +++ b/scripts/automation/trex_control_plane/common/filters.py @@ -8,12 +8,43 @@ class ToggleFilter(object): This class provides a "sticky" filter, that works by "toggling" items of the original database on and off. """ def __init__(self, db_ref, show_by_default=True): + """ + Instantiate a ToggleFilter object + + :parameters: + db_ref : iterable + an iterable object (i.e. list, set etc) that would serve as the reference db of the instance. + Changes in that object will affect the output of ToggleFilter instance. + + show_by_default: bool + decide if by default all the items are "on", i.e. these items will be presented if no other + toggling occurred. + + default value : **True** + + """ self._data = db_ref self._toggle_db = set() self._filter_method = filter self.__set_initial_state(show_by_default) def toggle_item(self, item_key): + """ + Toggle a single item in/out. + + :parameters: + item_key : + an item the by its value the filter can decide to toggle or not. + Example: int, str and so on. + + :return: + + **True** if item toggled **into** the filtered items + + **False** if item toggled **out from** the filtered items + + :raises: + + KeyError, in case if item key is not part of the toggled list and not part of the referenced db. + + """ if item_key in self._toggle_db: self._toggle_db.remove(item_key) return False @@ -24,7 +55,23 @@ class ToggleFilter(object): raise KeyError("Provided item key isn't a key of the referenced data structure.") def toggle_items(self, *args): - return all(map(self.toggle_item, args)) + """ + Toggle multiple items in/out with a single call. Each item will be ha. + + :parameters: + args : iterable + an iterable object containing all item keys to be toggled in/out + + :return: + + **True** if all toggled items were toggled **into** the filtered items + + **False** if at least one of the items was toggled **out from** the filtered items + + :raises: + + KeyError, in case if ont of the item keys was not part of the toggled list and not part of the referenced db. + + """ + # in python 3, 'map' returns an iterator, so wrapping with 'list' call creates same effect for both python 2 and 3 + return all(list(map(self.toggle_item, args))) def filter_items(self): """ @@ -67,12 +114,13 @@ class ToggleFilter(object): def dict_filter(function, iterable): assert isinstance(iterable, dict) return {k: v - for k,v in iterable.iteritems() + for k,v in iterable.items() if function(k)} @staticmethod def list_filter(function, iterable): - return filter(function, iterable) + # in python 3, filter returns an iterator, so wrapping with list creates same effect for both python 2 and 3 + return list(filter(function, iterable)) @staticmethod def set_filter(function, iterable): -- cgit