1#!/usr/bin/env python3
2
3r"""
4Define the var_stack class.
5"""
6
7import collections
8import copy
9import sys
10
11try:
12    from robot.utils import DotDict
13except ImportError:
14    pass
15
16import gen_print as gp
17
18
19class var_stack:
20    r"""
21    Define the variable stack class.
22
23    An object of this class can be used to push variable name/variable value pairs which may be popped off
24    the stack at a later time.  The most obvious use for this is for saving variables that are to be restored
25    later.
26
27    Example code:
28
29    save_stack = var_stack('save_stack')
30    var1 = "johnson"
31    save_stack.push(var1)
32    var1 = "smith"
33    ...
34    var1 = save_stack.pop('var1')
35    # var1 has now been restored to the value "johnson".
36
37
38    Example use:
39
40    var1 = "mike"
41    save_stack.push(var1)
42    var1 = "james"
43    save_stack.push(var1)
44    save_stack.print_obj()
45
46    # The print-out of the object would then look like this:
47
48    save_stack:
49      stack_dict:
50        [var1]:
51          [var1][0]:  mike
52          [var1][1]:  james
53
54    # Continuing with this code...
55
56    var1 = save_stack.pop('var1')
57    save_stack.print_obj()
58
59    # The print-out of the object would then look like this:
60
61    save_stack:
62      stack_dict:
63        [var1]:
64          [var1][0]:  mike
65    """
66
67    def __init__(self, obj_name="var_stack"):
68        r"""
69        Initialize a new object of this class type.
70
71        Description of argument(s):
72        obj_name                    The name of the object.  This is useful for printing out the object.
73        """
74
75        self.__obj_name = obj_name
76        # Create a stack dictionary.
77        try:
78            self.__stack_dict = collections.OrderedDict()
79        except AttributeError:
80            self.__stack_dict = DotDict()
81
82    def sprint_obj(self):
83        r"""
84        sprint the fields of this object.  This would normally be for debug purposes.
85        """
86
87        buffer = ""
88
89        buffer += self.__obj_name + ":\n"
90        indent = 2
91        buffer += gp.sprint_varx("stack_dict", self.__stack_dict, indent)
92
93        return buffer
94
95    def print_obj(self):
96        r"""
97        print the fields of this object to stdout.  This would normally be for debug purposes.
98        """
99
100        sys.stdout.write(self.sprint_obj())
101
102    def push(self, var_value, var_name=""):
103        r"""
104        push the var_name/var_value pair onto the stack.
105
106        Description of argument(s):
107        var_value                   The value being pushed.
108        var_name                    The name of the variable containing the value to be pushed.  This
109                                    parameter is normally unnecessary as this function can figure out the
110                                    var_name.  This is provided for Robot callers.  In this scenario, we are
111                                    unable to get the variable name ourselves.
112        """
113
114        if var_name == "":
115            # The caller has not passed a var_name so we will try to figure it out.
116            stack_frame_ix = 2
117            var_name = gp.get_arg_name(0, 1, stack_frame_ix)
118        if var_name in self.__stack_dict:
119            self.__stack_dict[var_name].append(var_value)
120        else:
121            self.__stack_dict[var_name] = copy.deepcopy([var_value])
122
123    def pop(self, var_name=""):
124        r"""
125        Pop the value for the given var_name from the stack and return it.
126
127        Description of argument(s):
128        var_name                    The name of the variable whose value is to be popped.
129        """
130
131        return self.__stack_dict[var_name].pop()
132