diff options
Diffstat (limited to 'resources/libraries/python/MLRsearch')
6 files changed, 141 insertions, 123 deletions
diff --git a/resources/libraries/python/MLRsearch/AbstractMeasurer.py b/resources/libraries/python/MLRsearch/AbstractMeasurer.py index c9b5987124..622b8fdba6 100644 --- a/resources/libraries/python/MLRsearch/AbstractMeasurer.py +++ b/resources/libraries/python/MLRsearch/AbstractMeasurer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Cisco and/or its affiliates. +# Copyright (c) 2019 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -16,11 +16,9 @@ from abc import ABCMeta, abstractmethod -class AbstractMeasurer(object): +class AbstractMeasurer(metaclass=ABCMeta): """Abstract class defining common API for measurement providers.""" - __metaclass__ = ABCMeta - @abstractmethod def measure(self, duration, transmit_rate): """Perform trial measurement and return the result. @@ -32,4 +30,3 @@ class AbstractMeasurer(object): :returns: Structure containing the result of the measurement. :rtype: ReceiveRateMeasurement.ReceiveRateMeasurement """ - pass diff --git a/resources/libraries/python/MLRsearch/AbstractSearchAlgorithm.py b/resources/libraries/python/MLRsearch/AbstractSearchAlgorithm.py index 08f8b7e0a9..f4f2d3f096 100644 --- a/resources/libraries/python/MLRsearch/AbstractSearchAlgorithm.py +++ b/resources/libraries/python/MLRsearch/AbstractSearchAlgorithm.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Cisco and/or its affiliates. +# Copyright (c) 2019 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -16,11 +16,9 @@ from abc import ABCMeta, abstractmethod -class AbstractSearchAlgorithm(object): +class AbstractSearchAlgorithm(metaclass=ABCMeta): """Abstract class defining common API for search algorithms.""" - __metaclass__ = ABCMeta - def __init__(self, measurer): """Store the rate provider. @@ -48,4 +46,3 @@ class AbstractSearchAlgorithm(object): :rtype: NdrPdrResult.NdrPdrResult """ # TODO: Do we agree on arguments related to precision or trial duration? - pass diff --git a/resources/libraries/python/MLRsearch/MultipleLossRatioSearch.py b/resources/libraries/python/MLRsearch/MultipleLossRatioSearch.py index 1ecd42e7dd..29b72505de 100644 --- a/resources/libraries/python/MLRsearch/MultipleLossRatioSearch.py +++ b/resources/libraries/python/MLRsearch/MultipleLossRatioSearch.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Cisco and/or its affiliates. +# Copyright (c) 2019 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -79,7 +79,7 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): TODO: Support configurable number of Packet Loss Ratios. """ - class ProgressState(object): + class ProgressState: """Structure containing data to be passed around in recursion.""" def __init__( @@ -113,9 +113,10 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): self.minimum_transmit_rate = float(minimum_transmit_rate) self.maximum_transmit_rate = float(maximum_transmit_rate) - def __init__(self, measurer, final_relative_width=0.005, - final_trial_duration=30.0, initial_trial_duration=1.0, - number_of_intermediate_phases=2, timeout=600.0, doublings=1): + def __init__( + self, measurer, final_relative_width=0.005, + final_trial_duration=30.0, initial_trial_duration=1.0, + number_of_intermediate_phases=2, timeout=600.0, doublings=1): """Store the measurer object and additional arguments. :param measurer: Rate provider to use by this search object. @@ -147,7 +148,6 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): self.timeout = float(timeout) self.doublings = int(doublings) - @staticmethod def double_relative_width(relative_width): """Return relative width corresponding to double logarithmic width. @@ -173,8 +173,8 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): :rtype: float """ return current_bound * ( - 1.0 - MultipleLossRatioSearch.double_relative_width( - relative_width)) + 1.0 - MultipleLossRatioSearch.double_relative_width(relative_width) + ) @staticmethod def expand_down(relative_width, doublings, current_bound): @@ -191,7 +191,8 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): """ for _ in range(doublings): relative_width = MultipleLossRatioSearch.double_relative_width( - relative_width) + relative_width + ) return current_bound * (1.0 - relative_width) @staticmethod @@ -206,8 +207,8 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): :rtype: float """ return current_bound / ( - 1.0 - MultipleLossRatioSearch.double_relative_width( - relative_width)) + 1.0 - MultipleLossRatioSearch.double_relative_width(relative_width) + ) @staticmethod def expand_up(relative_width, doublings, current_bound): @@ -224,7 +225,8 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): """ for _ in range(doublings): relative_width = MultipleLossRatioSearch.double_relative_width( - relative_width) + relative_width + ) return current_bound / (1.0 - relative_width) @staticmethod @@ -250,7 +252,8 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): :rtype: float """ return current_bound / ( - 1.0 - MultipleLossRatioSearch.half_relative_width(relative_width)) + 1.0 - MultipleLossRatioSearch.half_relative_width(relative_width) + ) def narrow_down_ndr_and_pdr( self, minimum_transmit_rate, maximum_transmit_rate, @@ -278,31 +281,32 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): initial_width_goal = self.double_relative_width(initial_width_goal) max_lo = maximum_transmit_rate * (1.0 - initial_width_goal) mrr = max( - minimum_transmit_rate, - min(max_lo, line_measurement.receive_rate)) + minimum_transmit_rate, min(max_lo, line_measurement.receive_rate) + ) mrr_measurement = self.measurer.measure( - self.initial_trial_duration, mrr) + self.initial_trial_duration, mrr + ) # Attempt to get narrower width. if mrr_measurement.loss_fraction > 0.0: max2_lo = mrr * (1.0 - initial_width_goal) mrr2 = min(max2_lo, mrr_measurement.receive_rate) else: mrr2 = mrr / (1.0 - initial_width_goal) - if mrr2 > minimum_transmit_rate and mrr2 < maximum_transmit_rate: + if minimum_transmit_rate < mrr2 < maximum_transmit_rate: line_measurement = mrr_measurement mrr_measurement = self.measurer.measure( self.initial_trial_duration, mrr2) if mrr2 > mrr: - buf = line_measurement - line_measurement = mrr_measurement - mrr_measurement = buf + line_measurement, mrr_measurement = \ + (mrr_measurement, line_measurement) starting_interval = ReceiveRateInterval( mrr_measurement, line_measurement) starting_result = NdrPdrResult(starting_interval, starting_interval) state = self.ProgressState( starting_result, self.number_of_intermediate_phases, self.final_trial_duration, self.final_relative_width, - packet_loss_ratio, minimum_transmit_rate, maximum_transmit_rate) + packet_loss_ratio, minimum_transmit_rate, maximum_transmit_rate + ) state = self.ndrpdr(state) return state.result @@ -318,15 +322,18 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): """ # TODO: Implement https://stackoverflow.com/a/24683360 # to avoid the string manipulation if log verbosity is too low. - logging.info("result before update: %s", state.result) + logging.info(f"result before update: {state.result}") logging.debug( - "relative widths in goals: %s", state.result.width_in_goals( - self.final_relative_width)) + f"relative widths in goals: " + f"{state.result.width_in_goals(self.final_relative_width)}" + ) measurement = self.measurer.measure(state.duration, transmit_rate) ndr_interval = self._new_interval( - state.result.ndr_interval, measurement, 0.0) + state.result.ndr_interval, measurement, 0.0 + ) pdr_interval = self._new_interval( - state.result.pdr_interval, measurement, state.packet_loss_ratio) + state.result.pdr_interval, measurement, state.packet_loss_ratio + ) state.result = NdrPdrResult(ndr_interval, pdr_interval) return state @@ -387,11 +394,13 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): # "invalid upper bound at maximal rate" case. new_lo = measurement - return ReceiveRateInterval(old_lo if new_lo is None else new_lo, - old_hi if new_hi is None else new_hi) + return ReceiveRateInterval( + old_lo if new_lo is None else new_lo, + old_hi if new_hi is None else new_hi + ) def ndrpdr(self, state): - """Pefrom trials for this phase. Return the new state when done. + """Perform trials for this phase. Return the new state when done. :param state: State before this phase. :type state: ProgressState @@ -409,7 +418,8 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): duration_multiplier = state.duration / self.initial_trial_duration phase_exponent = float(state.phases) / saved_phases state.duration = self.initial_trial_duration * math.pow( - duration_multiplier, phase_exponent) + duration_multiplier, phase_exponent + ) # Shorter durations do not need that narrow widths. saved_width = state.width_goal state.width_goal = self.double_relative_width(state.width_goal) @@ -421,11 +431,12 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): state.phases = saved_phases # Not needed, but just in case. logging.info( - "starting iterations with duration %s and relative width goal %s", - state.duration, state.width_goal) + f"starting iterations with duration {state.duration} and relative " + f"width goal {state.width_goal}" + ) while 1: if time.time() > start_time + self.timeout: - raise RuntimeError("Optimized search takes too long.") + raise RuntimeError(u"Optimized search takes too long.") # Order of priorities: invalid bounds (nl, pl, nh, ph), # then narrowing relative Tr widths. # Durations are not priorities yet, @@ -435,14 +446,17 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): pdr_lo = state.result.pdr_interval.measured_low pdr_hi = state.result.pdr_interval.measured_high ndr_rel_width = max( - state.width_goal, state.result.ndr_interval.rel_tr_width) + state.width_goal, state.result.ndr_interval.rel_tr_width + ) pdr_rel_width = max( - state.width_goal, state.result.pdr_interval.rel_tr_width) + state.width_goal, state.result.pdr_interval.rel_tr_width + ) # If we are hitting maximal or minimal rate, we cannot shift, # but we can re-measure. - new_tr = self._ndrpdr_loss_fraction(state, - ndr_lo, ndr_hi, pdr_lo, pdr_hi, - ndr_rel_width, pdr_rel_width) + new_tr = self._ndrpdr_loss_fraction( + state, ndr_lo, ndr_hi, pdr_lo, pdr_hi, ndr_rel_width, + pdr_rel_width + ) if new_tr is not None: state = self._measure_and_update_state(state, new_tr) @@ -461,8 +475,9 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): and pdr_lo.loss_fraction > state.packet_loss_ratio): pdr_rel_width = 0.0 - new_tr = self._ndrpdr_width_goal(state, ndr_lo, pdr_lo, - ndr_rel_width, pdr_rel_width) + new_tr = self._ndrpdr_width_goal( + state, ndr_lo, pdr_lo, ndr_rel_width, pdr_rel_width + ) if new_tr is not None: state = self._measure_and_update_state(state, new_tr) @@ -470,9 +485,10 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): # We do not need to improve width, but there still might be # some measurements with smaller duration. - new_tr = self._ndrpdr_duration(state, - ndr_lo, ndr_hi, pdr_lo, pdr_hi, - ndr_rel_width, pdr_rel_width) + new_tr = self._ndrpdr_duration( + state, ndr_lo, ndr_hi, pdr_lo, pdr_hi, ndr_rel_width, + pdr_rel_width + ) if new_tr is not None: state = self._measure_and_update_state(state, new_tr) @@ -480,12 +496,13 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): # Widths are narrow (or lower bound minimal), bound measurements # are long enough, we can return. - logging.info("phase done") + logging.info(u"phase done") break return state - def _ndrpdr_loss_fraction(self, state, ndr_lo, ndr_hi, pdr_lo, pdr_hi, - ndr_rel_width, pdr_rel_width): + def _ndrpdr_loss_fraction( + self, state, ndr_lo, ndr_hi, pdr_lo, pdr_hi, ndr_rel_width, + pdr_rel_width): """Perform loss_fraction-based trials within a ndrpdr phase :param state: current state @@ -509,50 +526,54 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): if ndr_lo.loss_fraction > 0.0: if ndr_lo.target_tr > state.minimum_transmit_rate: result = max( - state.minimum_transmit_rate, - self.expand_down( - ndr_rel_width, self.doublings, ndr_lo.target_tr)) - logging.info("ndr lo external %s", result) + state.minimum_transmit_rate, self.expand_down( + ndr_rel_width, self.doublings, ndr_lo.target_tr + ) + ) + logging.info(f"ndr lo external {result}") elif ndr_lo.duration < state.duration: result = state.minimum_transmit_rate - logging.info("ndr lo minimal re-measure") + logging.info(u"ndr lo minimal re-measure") if result is None and pdr_lo.loss_fraction > state.packet_loss_ratio: if pdr_lo.target_tr > state.minimum_transmit_rate: result = max( - state.minimum_transmit_rate, - self.expand_down( - pdr_rel_width, self.doublings, pdr_lo.target_tr)) - logging.info("pdr lo external %s", result) + state.minimum_transmit_rate, self.expand_down( + pdr_rel_width, self.doublings, pdr_lo.target_tr + ) + ) + logging.info(f"pdr lo external {result}") elif pdr_lo.duration < state.duration: result = state.minimum_transmit_rate - logging.info("pdr lo minimal re-measure") + logging.info(u"pdr lo minimal re-measure") if result is None and ndr_hi.loss_fraction <= 0.0: if ndr_hi.target_tr < state.maximum_transmit_rate: result = min( - state.maximum_transmit_rate, - self.expand_up( - ndr_rel_width, self.doublings, ndr_hi.target_tr)) - logging.info("ndr hi external %s", result) + state.maximum_transmit_rate, self.expand_up( + ndr_rel_width, self.doublings, ndr_hi.target_tr + ) + ) + logging.info(f"ndr hi external {result}") elif ndr_hi.duration < state.duration: result = state.maximum_transmit_rate - logging.info("ndr hi maximal re-measure") + logging.info(u"ndr hi maximal re-measure") if result is None and pdr_hi.loss_fraction <= state.packet_loss_ratio: if pdr_hi.target_tr < state.maximum_transmit_rate: result = min( - state.maximum_transmit_rate, - self.expand_up( - pdr_rel_width, self.doublings, pdr_hi.target_tr)) - logging.info("pdr hi external %s", result) + state.maximum_transmit_rate, self.expand_up( + pdr_rel_width, self.doublings, pdr_hi.target_tr + ) + ) + logging.info(f"pdr hi external {result}") elif pdr_hi.duration < state.duration: result = state.maximum_transmit_rate - logging.info("ndr hi maximal re-measure") + logging.info(u"ndr hi maximal re-measure") return result - def _ndrpdr_width_goal(self, state, ndr_lo, pdr_lo, - ndr_rel_width, pdr_rel_width): + def _ndrpdr_width_goal( + self, state, ndr_lo, pdr_lo, ndr_rel_width, pdr_rel_width): """Perform width_goal-based trials within a ndrpdr phase :param state: current state @@ -573,18 +594,19 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): # We have to narrow NDR width first, as NDR internal search # can invalidate PDR (but not vice versa). result = self.half_step_up(ndr_rel_width, ndr_lo.target_tr) - logging.info("Bisecting for NDR at %s", result) + logging.info(f"Bisecting for NDR at {result}") elif pdr_rel_width > state.width_goal: - # PDR iternal search. + # PDR internal search. result = self.half_step_up(pdr_rel_width, pdr_lo.target_tr) - logging.info("Bisecting for PDR at %s", result) + logging.info(f"Bisecting for PDR at {result}") else: result = None return result @staticmethod - def _ndrpdr_duration(state, ndr_lo, pdr_lo, ndr_hi, pdr_hi, - ndr_rel_width, pdr_rel_width): + def _ndrpdr_duration( + state, ndr_lo, pdr_lo, ndr_hi, pdr_hi, ndr_rel_width, + pdr_rel_width): """Perform duration-based trials within a ndrpdr phase :param state: current state @@ -608,18 +630,18 @@ class MultipleLossRatioSearch(AbstractSearchAlgorithm): # creating invalid bounds to resolve (thus broadening width). if ndr_lo.duration < state.duration: result = ndr_lo.target_tr - logging.info("re-measuring NDR lower bound") + logging.info(u"re-measuring NDR lower bound") elif pdr_lo.duration < state.duration: result = pdr_lo.target_tr - logging.info("re-measuring PDR lower bound") + logging.info(u"re-measuring PDR lower bound") # Except when lower bounds have high loss fraction, in that case # we do not need to re-measure _upper_ bounds. elif ndr_hi.duration < state.duration and ndr_rel_width > 0.0: result = ndr_hi.target_tr - logging.info("re-measuring NDR upper bound") + logging.info(u"re-measuring NDR upper bound") elif pdr_hi.duration < state.duration and pdr_rel_width > 0.0: result = pdr_hi.target_tr - logging.info("re-measuring PDR upper bound") + logging.info(u"re-measuring PDR upper bound") else: result = None return result diff --git a/resources/libraries/python/MLRsearch/NdrPdrResult.py b/resources/libraries/python/MLRsearch/NdrPdrResult.py index 7b8cfd6449..3454ef1957 100644 --- a/resources/libraries/python/MLRsearch/NdrPdrResult.py +++ b/resources/libraries/python/MLRsearch/NdrPdrResult.py @@ -13,11 +13,10 @@ """Module defining NdrPdrResult class.""" -from resources.libraries.python.MLRsearch.ReceiveRateInterval \ - import ReceiveRateInterval +from .ReceiveRateInterval import ReceiveRateInterval -class NdrPdrResult(object): +class NdrPdrResult: """Two measurement intervals, return value of search algorithms. Partial fraction is NOT part of the result. Pdr interval should be valid @@ -34,11 +33,13 @@ class NdrPdrResult(object): # TODO: Type checking is not very pythonic, # perhaps users can fix wrong usage without it? if not isinstance(ndr_interval, ReceiveRateInterval): - raise TypeError("ndr_interval, is not a ReceiveRateInterval: " - "{ndr!r}".format(ndr=ndr_interval)) + raise TypeError( + f"ndr_interval, is not a ReceiveRateInterval: {ndr_interval!r}" + ) if not isinstance(pdr_interval, ReceiveRateInterval): - raise TypeError("pdr_interval, is not a ReceiveRateInterval: " - "{pdr!r}".format(pdr=pdr_interval)) + raise TypeError( + f"pdr_interval, is not a ReceiveRateInterval: {pdr_interval!r}" + ) self.ndr_interval = ndr_interval self.pdr_interval = pdr_interval @@ -51,16 +52,14 @@ class NdrPdrResult(object): :returns: Message containing NDR and PDR widths in goals. :rtype: str """ - return "ndr {ndr_in_goals}; pdr {pdr_in_goals}".format( - ndr_in_goals=self.ndr_interval.width_in_goals(relative_width_goal), - pdr_in_goals=self.pdr_interval.width_in_goals(relative_width_goal)) + return f"ndr {self.ndr_interval.width_in_goals(relative_width_goal)};" \ + f" pdr {self.pdr_interval.width_in_goals(relative_width_goal)}" def __str__(self): """Return string as tuple of named values.""" - return "NDR={ndr!s};PDR={pdr!s}".format( - ndr=self.ndr_interval, pdr=self.pdr_interval) + return f"NDR={self.ndr_interval!s};PDR={self.pdr_interval!s}" def __repr__(self): """Return string evaluable as a constructor call.""" - return "NdrPdrResult(ndr_interval={ndr!r},pdr_interval={pdr!r})".format( - ndr=self.ndr_interval, pdr=self.pdr_interval) + return f"NdrPdrResult(ndr_interval={self.ndr_interval!r}," \ + f"pdr_interval={self.pdr_interval!r})" diff --git a/resources/libraries/python/MLRsearch/ReceiveRateInterval.py b/resources/libraries/python/MLRsearch/ReceiveRateInterval.py index ec3cbb7462..eff23e8bcc 100644 --- a/resources/libraries/python/MLRsearch/ReceiveRateInterval.py +++ b/resources/libraries/python/MLRsearch/ReceiveRateInterval.py @@ -15,11 +15,10 @@ import math -from resources.libraries.python.MLRsearch.ReceiveRateMeasurement \ - import ReceiveRateMeasurement +from .ReceiveRateMeasurement import ReceiveRateMeasurement -class ReceiveRateInterval(object): +class ReceiveRateInterval: """Structure defining two Rr measurements, and their relation.""" def __init__(self, measured_low, measured_high): @@ -33,11 +32,15 @@ class ReceiveRateInterval(object): # TODO: Type checking is not very pythonic, # perhaps users can fix wrong usage without it? if not isinstance(measured_low, ReceiveRateMeasurement): - raise TypeError("measured_low is not a ReceiveRateMeasurement: " - "{low!r}".format(low=measured_low)) + raise TypeError( + f"measured_low is not a ReceiveRateMeasurement: " + f"{measured_low!r}" + ) if not isinstance(measured_high, ReceiveRateMeasurement): - raise TypeError("measured_high is not a ReceiveRateMeasurement: " - "{high!r}".format(high=measured_high)) + raise TypeError( + f"measured_high is not a ReceiveRateMeasurement: " + f"{measured_high!r}" + ) self.measured_low = measured_low self.measured_high = measured_high # Declare secondary quantities to appease pylint. @@ -51,9 +54,11 @@ class ReceiveRateInterval(object): """Sort bounds by target Tr, compute secondary quantities.""" if self.measured_low.target_tr > self.measured_high.target_tr: self.measured_low, self.measured_high = ( - self.measured_high, self.measured_low) + self.measured_high, self.measured_low + ) self.abs_tr_width = ( - self.measured_high.target_tr - self.measured_low.target_tr) + self.measured_high.target_tr - self.measured_low.target_tr + ) self.rel_tr_width = self.abs_tr_width / self.measured_high.target_tr def width_in_goals(self, relative_width_goal): @@ -75,11 +80,9 @@ class ReceiveRateInterval(object): def __str__(self): """Return string as half-open interval.""" - return "[{low!s};{high!s})".format( - low=self.measured_low, high=self.measured_high) + return f"[{self.measured_low!s};{self.measured_high!s})" def __repr__(self): """Return string evaluable as a constructor call.""" - return ("ReceiveRateInterval(measured_low={low!r}" - ",measured_high={high!r})".format( - low=self.measured_low, high=self.measured_high)) + return f"ReceiveRateInterval(measured_low={self.measured_low!r}," \ + f"measured_high={self.measured_high!r})" diff --git a/resources/libraries/python/MLRsearch/ReceiveRateMeasurement.py b/resources/libraries/python/MLRsearch/ReceiveRateMeasurement.py index d052ebd3bf..31a6f8202e 100644 --- a/resources/libraries/python/MLRsearch/ReceiveRateMeasurement.py +++ b/resources/libraries/python/MLRsearch/ReceiveRateMeasurement.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Cisco and/or its affiliates. +# Copyright (c) 2019 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -14,7 +14,7 @@ """Module defining ReceiveRateMeasurement class.""" -class ReceiveRateMeasurement(object): +class ReceiveRateMeasurement: """Structure defining the result of single Rr measurement.""" def __init__(self, duration, target_tr, transmit_count, loss_count): @@ -43,12 +43,12 @@ class ReceiveRateMeasurement(object): def __str__(self): """Return string reporting input and loss fraction.""" - return "d={dur!s},Tr={rate!s},Df={frac!s}".format( - dur=self.duration, rate=self.target_tr, frac=self.loss_fraction) + return f"d={self.duration!s},Tr={self.target_tr!s}," \ + f"Df={self.loss_fraction!s}" def __repr__(self): """Return string evaluable as a constructor call.""" - return ("ReceiveRateMeasurement(duration={dur!r},target_tr={rate!r}" - ",transmit_count={trans!r},loss_count={loss!r})".format( - dur=self.duration, rate=self.target_tr, - trans=self.transmit_count, loss=self.loss_count)) + return f"ReceiveRateMeasurement(duration={self.duration!r}," \ + f"target_tr={self.target_tr!r}," \ + f"transmit_count={self.transmit_count!r}," \ + f"loss_count={self.loss_count!r})" |