<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def set_value(self, value):
 """ Sets the user value of the symbol. Equal in effect to assigning the value to the symbol within a .config file. For bool and tristate symbols, use the 'assignable' attribute to check which values can currently be assigned. Setting values outside 'assignable' will cause Symbol.user_value to differ from Symbol.str/tri_value (be truncated down or up). Setting a choice symbol to 2 (y) sets Choice.user_selection to the choice symbol in addition to setting Symbol.user_value. Choice.user_selection is considered when the choice is in y mode (the "normal" mode). Other symbols that depend (possibly indirectly) on this symbol are automatically recalculated to reflect the assigned value. value: The user value to give to the symbol. For bool and tristate symbols, n/m/y can be specified either as 0/1/2 (the usual format for tristate values in Kconfiglib) or as one of the strings "n"/"m"/"y". For other symbol types, pass a string. Values that are invalid for the type (such as "foo" or 1 (m) for a BOOL or "0x123" for an INT) are ignored and won't be stored in Symbol.user_value. Kconfiglib will print a warning by default for invalid assignments, and set_value() will return False. Returns True if the value is valid for the type of the symbol, and False otherwise. This only looks at the form of the value. For BOOL and TRISTATE symbols, check the Symbol.assignable attribute to see what values are currently in range and would actually be reflected in the value of the symbol. For other symbol types, check whether the visibility is non-n. """

        # If the new user value matches the old, nothing changes, and we can
        # save some work.
        #
        # This optimization is skipped for choice symbols: Setting a choice
        # symbol's user value to y might change the state of the choice, so it
        # wouldn't be safe (symbol user values always match the values set in a
        # .config file or via set_value(), and are never implicitly updated).
        if value == self.user_value and not self.choice:
            self._was_set = True
            return True

        # Check if the value is valid for our type
        if not (self.orig_type is BOOL     and value in (2, 0, "y", "n")         or
                self.orig_type is TRISTATE and value in (2, 1, 0, "y", "m", "n") or
                (value.__class__ is str    and
                 (self.orig_type is STRING                        or
                  self.orig_type is INT and _is_base_n(value, 10) or
                  self.orig_type is HEX and _is_base_n(value, 16)
                                        and int(value, 16) >= 0))):

            # Display tristate values as n, m, y in the warning
            self.kconfig._warn(
                "the value {} is invalid for {}, which has type {} -- "
                "assignment ignored"
                .format(TRI_TO_STR[value] if value in (0, 1, 2) else
                            "'{}'".format(value),
                        _name_and_loc(self), TYPE_TO_STR[self.orig_type]))

            return False

        if self.orig_type in _BOOL_TRISTATE and value in ("y", "m", "n"):
            value = STR_TO_TRI[value]

        self.user_value = value
        self._was_set = True

        if self.choice and value == 2:
            # Setting a choice symbol to y makes it the user selection of the
            # choice. Like for symbol user values, the user selection is not
            # guaranteed to match the actual selection of the choice, as
            # dependencies come into play.
            self.choice.user_selection = self
            self.choice._was_set = True
            self.choice._rec_invalidate()
        else:
            self._rec_invalidate_if_has_prompt()

        return True