fix(vlan): do not apply strip offload
[csit.git] / resources / libraries / python / OptionString.py
index 7c8b2d0..35988c4 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# Copyright (c) 2021 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:
 """Utility function for handling options without doubled or trailing spaces."""
 
 
-class OptionString(object):
+class OptionString:
     """Class serving as a builder for option strings.
 
-    Motivation: Both manual contatenation and .join() methods
+    Motivation: Both manual concatenation and .join() methods
     are prone to leaving superfluous spaces if some parts of options
     are optional (missing, empty).
 
@@ -36,19 +36,21 @@ class OptionString(object):
     the best fitting one, without much logic near the call site.
     """
 
-    def __init__(self, prefix="", *args):
+    def __init__(self, parts=tuple(), prefix=u""):
         """Create instance with listed strings as parts to use.
 
         Prefix will be converted to string and stripped.
         The typical (nonempty) prefix values are "-" and "--".
 
-        :param prefix: Subtring to prepend to every parameter (not value).
-        :param args: List of positional arguments to become parts.
+        TODO: Support users calling with parts being a string?
+
+        :param parts: List of stringifiable objects to become parts.
+        :param prefix: Substring to prepend to every parameter (not value).
+        :type parts: Iterable of object
         :type prefix: object
-        :type args: list of object
         """
+        self.parts = [str(part) for part in parts]
         self.prefix = str(prefix).strip()  # Not worth to call change_prefix.
-        self.parts = list(args)
 
     def __repr__(self):
         """Return string executable as Python constructor call.
@@ -56,12 +58,10 @@ class OptionString(object):
         :returns: Executable constructor call as string.
         :rtype: str
         """
-        return "".join([
-            "OptionString(prefix=", repr(self.prefix), ",",
-            repr(self.parts)[1:-1], ")"])
+        return f"OptionString(parts={self.parts!r},prefix={self.prefix!r})"
 
     # TODO: Would we ever need a copy() method?
-    # Currently, supersting "master" is mutable but unique,
+    # Currently, superstring "master" is mutable but unique,
     # substring "slave" can be used to extend, but does not need to be mutated.
 
     def change_prefix(self, prefix):
@@ -92,12 +92,17 @@ class OptionString(object):
         self.parts.extend(other.parts)
         return self
 
-    def _check_and_add(self, part, prefixed):
+    def check_and_add(self, part, prefixed):
         """Convert to string, strip, conditionally add prefixed if non-empty.
 
         Value of None is converted to empty string.
         Emptiness is tested before adding prefix.
 
+        This could be a protected method (name starting with underscore),
+        but then pylint does not understand add_equals and add_with_value
+        are allowed to call this on the temp instance.
+        TODO: Is there a way to make pylint understand?
+
         :param part: Unchecked part to add to list of parts.
         :param prefixed: Whether to add prefix when adding.
         :type part: object
@@ -105,7 +110,7 @@ class OptionString(object):
         :returns: The converted part without prefix, empty means not added.
         :rtype: str
         """
-        part = "" if part is None else str(part).strip()
+        part = u"" if part is None else str(part).strip()
         if part:
             prefixed_part = self.prefix + part if prefixed else part
             self.parts.append(prefixed_part)
@@ -119,11 +124,11 @@ class OptionString(object):
         Parameter is prefixed before adding.
 
         :param parameter: Parameter object, usually a word starting with dash.
-        :type variable: object
+        :type parameter: object
         :returns: Self, to enable method chaining.
         :rtype: OptionString
         """
-        self._check_and_add(parameter, prefixed=True)
+        self.check_and_add(parameter, prefixed=True)
         return self
 
     def add_if(self, parameter, condition):
@@ -136,7 +141,7 @@ class OptionString(object):
 
         :param parameter: Parameter object, usually a word starting with dash.
         :param condition: Do not add if truth value of this is false.
-        :type variable: object
+        :type parameter: object
         :type condition: object
         :returns: Self, to enable method chaining.
         :rtype: OptionString
@@ -154,17 +159,14 @@ class OptionString(object):
 
         :param parameter: Parameter object, usually a word starting with dash.
         :param value: Value object. Prefix is never added.
-        :type variable: object
+        :type parameter: object
         :type value: object
         :returns: Self, to enable method chaining.
         :rtype: OptionString
         """
         temp = OptionString(prefix=self.prefix)
-        # TODO: Is pylint really that ignorant?
-        # How could it not understand temp is of type of this class?
-        # pylint: disable=protected-access
-        if temp._check_and_add(parameter, prefixed=True):
-            if temp._check_and_add(value, prefixed=False):
+        if temp.check_and_add(parameter, prefixed=True):
+            if temp.check_and_add(value, prefixed=False):
                 self.extend(temp)
         return self
 
@@ -177,16 +179,15 @@ class OptionString(object):
 
         :param parameter: Parameter object, usually a word starting with dash.
         :param value: Value object. Prefix is never added.
-        :type variable: object
+        :type parameter: object
         :type value: object
         :returns: Self, to enable method chaining.
         :rtype: OptionString
         """
         temp = OptionString(prefix=self.prefix)
-        # pylint: disable=protected-access
-        if temp._check_and_add(parameter, prefixed=True):
-            if temp._check_and_add(value, prefixed=False):
-                self.parts.append("=".join(temp.parts))
+        if temp.check_and_add(parameter, prefixed=True):
+            if temp.check_and_add(value, prefixed=False):
+                self.parts.append(u"=".join(temp.parts))
         return self
 
     def add_with_value_if(self, parameter, value, condition):
@@ -200,7 +201,7 @@ class OptionString(object):
         :param parameter: Parameter object, usually a word starting with dash.
         :param value: Value object. Prefix is never added.
         :param condition: Do not add if truth value of this is false.
-        :type variable: object
+        :type parameter: object
         :type value: object
         :type condition: object
         :returns: Self, to enable method chaining.
@@ -221,7 +222,7 @@ class OptionString(object):
         :param parameter: Parameter object, usually a word starting with dash.
         :param value: Value object. Prefix is never added.
         :param condition: Do not add if truth value of this is false.
-        :type variable: object
+        :type parameter: object
         :type value: object
         :type condition: object
         :returns: Self, to enable method chaining.
@@ -231,7 +232,7 @@ class OptionString(object):
             self.add_equals(parameter, value)
         return self
 
-    def add_with_value_from_dict(self, parameter, key, mapping, default=""):
+    def add_with_value_from_dict(self, parameter, key, mapping, default=u""):
         """Add parameter with value from dict under key, or default.
 
         If key is missing, default is used as value.
@@ -253,7 +254,7 @@ class OptionString(object):
         value = mapping.get(key, default)
         return self.add_with_value(parameter, value)
 
-    def add_equals_from_dict(self, parameter, key, mapping, default=""):
+    def add_equals_from_dict(self, parameter, key, mapping, default=u""):
         """Add parameter=value to options where value is from dict.
 
         If key is missing, default is used as value.
@@ -275,7 +276,7 @@ class OptionString(object):
         value = mapping.get(key, default)
         return self.add_equals(parameter, value)
 
-    def add_if_from_dict(self, parameter, key, mapping, default="False"):
+    def add_if_from_dict(self, parameter, key, mapping, default=u"False"):
         """Add parameter based on if the condition in dict is true.
 
         If key is missing, default is used as condition.
@@ -299,7 +300,7 @@ class OptionString(object):
         return self.add_if(parameter, condition)
 
     def add_with_value_if_from_dict(
-            self, parameter, value, key, mapping, default="False"):
+            self, parameter, value, key, mapping, default=u"False"):
         """Add parameter and value based on condition in dict.
 
         If key is missing, default is used as condition.
@@ -325,7 +326,7 @@ class OptionString(object):
         return self.add_with_value_if(parameter, value, condition)
 
     def add_equals_if_from_dict(
-            self, parameter, value, key, mapping, default="False"):
+            self, parameter, value, key, mapping, default=u"False"):
         """Add parameter=value based on condition in dict.
 
         If key is missing, default is used as condition.
@@ -360,4 +361,4 @@ class OptionString(object):
         :returns: Space separated string of options.
         :rtype: str
         """
-        return " ".join(self.parts)
+        return u" ".join(self.parts)