예제 #1
0
    def getGlobalAutoUpdateValue(cls, key, defaultValue, writeDefault):
        """Global version of getAutoUpdateValue. This function will not initialize
        NetworkTables.
        
        :param key: the full NT path of the value (must start with /)
        :type key: str
        :param defaultValue: The default value to return if the key doesn't exist
        :type defaultValue: any
        :param writeDefault: If True, force the value to the specified default
        :type writeDefault: bool
        
        .. versionadded:: 2015.3.0
        
        .. seealso:: :func:`.ntproperty` is a read-write alternative to this
        """
        assert key.startswith("/")

        # Use raw NT api to avoid having to initialize networktables
        value = None
        valuefn = None  # optimization for ntproperty

        if not writeDefault:
            value = cls._api.getEntryValue(key)

        if value is None:
            valuefn = Value.getFactory(defaultValue)
            cls._api.setEntryValue(key, valuefn(defaultValue))
            value = defaultValue
        else:
            valuefn = Value.getFactory(value)

        return cls._api.createAutoValue(key, AutoUpdateValue(key, value, valuefn))
 def putValue(self, key, value):
     """Put a value in the table, trying to autodetect the NT type of
     the value. Refer to this table to determine the type mapping:
     
     ======= ============================ =================================
     PyType  NT Type                       Notes
     ======= ============================ =================================
     bool    :attr:`.EntryTypes.BOOLEAN`
     int     :attr:`.EntryTypes.DOUBLE`
     float   :attr:`.EntryTypes.DOUBLE`
     str     :attr:`.EntryTypes.STRING`
     bytes   :attr:`.EntryTypes.RAW`      Doesn't work in Python 2.7
     list    Error                        Use `putXXXArray` methods instead
     tuple   Error                        Use `putXXXArray` methods instead
     ======= ============================ =================================
     
     :param key: the key to be assigned to
     :type key: str
     :param value: the value that will be assigned
     :type value: bool, int, float, str, bytes
     
     :returns: False if the table key already exists with a different type
     :rtype: bool
     
     .. versionadded:: 2017.0.0
     """
     value = Value.getFactory(value)(value)
     path = self._path + key
     return self._api.setEntryValue(path, value)
예제 #3
0
 def putValue(self, key, value):
     """Put a value in the table, trying to autodetect the NT type of
     the value. Refer to this table to determine the type mapping:
     
     ======= ============================ =================================
     PyType  NT Type                       Notes
     ======= ============================ =================================
     bool    :attr:`.EntryTypes.BOOLEAN`
     int     :attr:`.EntryTypes.DOUBLE`
     float   :attr:`.EntryTypes.DOUBLE`
     str     :attr:`.EntryTypes.STRING`
     bytes   :attr:`.EntryTypes.RAW`      Doesn't work in Python 2.7
     list    Error                        Use `putXXXArray` methods instead
     tuple   Error                        Use `putXXXArray` methods instead
     ======= ============================ =================================
     
     :param key: the key to be assigned to
     :type key: str
     :param value: the value that will be assigned
     :type value: bool, int, float, str, bytes
     
     :returns: False if the table key already exists with a different type
     :rtype: bool
     
     .. versionadded:: 2017.0.0
     """
     value = Value.getFactory(value)(value)
     path = self._path + key
     return self._api.setEntryValue(path, value)
예제 #4
0
    def set_safe(self, name: str, value: NT_TYPES) -> None:
        entry = self._get_entry(name)

        # Calculated using Python type (bool, str, float)
        try:
            create_value_func: Callable[..., Value] = Value.getFactory(value)
        except ValueError as e:  # getFactory raises ValueError when it should be raising TypeError
            raise TypeError(*e.args)

        if entry is not None:
            # Calculated using NT type (NT_BOOLEAN, NT_STRING, NT_DOUBLE)
            if Value.getFactoryByType(entry.type) != create_value_func:
                # The factories don't match, which means the types don't match
                # Do not allow implicit type conversion
                raise TypeError("Existing type {} does not match: {}".format(
                    entry.type, type(value)))

        # Convert Python type into NT type
        nt_value: Value = create_value_func(value)

        # Returns False on error (type mismatch)
        successful = self.api.setEntryValue(self._get_path(name), nt_value)

        if not successful:
            raise TypeError("Existing type {} does not match: {}".format(
                entry.type, type(value)))
예제 #5
0
 def forceSetValue(self, value):
     """Sets the entry's value
     
     :param value: the value that will be assigned
     
     .. warning:: Empty lists will fail
     """
     value = Value.getFactory(value)(value)
     return self.__api.setEntryTypeValueById(self._local_id, value)
예제 #6
0
 def forceSetValue(self, value):
     """Sets the entry's value
     
     :param value: the value that will be assigned
     
     .. warning:: Empty lists will fail
     """
     value = Value.getFactory(value)(value)
     return self.__api.setEntryTypeValueById(self._local_id, value)
예제 #7
0
 def setValue(self, value):
     """Sets the entry's value
     
     :param value: the value that will be assigned
     :returns: False if the table key already exists with a different type
     
     .. warning:: Empty lists will fail
     """
     value = Value.getFactory(value)(value)
     return self.__api.setEntryValueById(self._local_id, value)
예제 #8
0
 def setDefaultValue(self, defaultValue):
     """Sets the entry's value if it does not exist.
     
     :param defaultValue: the default value to set
     :returns: False if the entry exists with a different type
     
     .. warning:: Do not set an empty list, it will fail
     """
     value = Value.getFactory(defaultValue)(defaultValue)
     return self.__api.setDefaultEntryValueById(self._local_id, value)
예제 #9
0
 def setValue(self, value):
     """Sets the entry's value
     
     :param value: the value that will be assigned
     :returns: False if the table key already exists with a different type
     
     .. warning:: Empty lists will fail
     """
     value = Value.getFactory(value)(value)
     return self.__api.setEntryValueById(self._local_id, value)
예제 #10
0
 def setDefaultValue(self, defaultValue):
     """Sets the entry's value if it does not exist.
     
     :param defaultValue: the default value to set
     :returns: False if the entry exists with a different type
     
     .. warning:: Do not set an empty list, it will fail
     """
     value = Value.getFactory(defaultValue)(defaultValue)
     return self.__api.setDefaultEntryValueById(self._local_id, value)
예제 #11
0
    def set(self, name: str, value: NT_TYPES) -> None:
        # Calculated using Python type (bool, str, float)
        try:
            create_value_func: Callable[..., Value] = Value.getFactory(value)
        except ValueError as e:  # getFactory raises ValueError when it should be raising TypeError
            raise TypeError(*e.args)

        nt_value: Value = create_value_func(value)

        self.api.setEntryTypeValue(self._get_path(name), nt_value)
예제 #12
0
 def getGlobalAutoUpdateValue(cls, key, defaultValue, writeDefault):
     '''Global version of getAutoUpdateValue. This function will not initialize
     NetworkTables.
     
     :param key: the full NT path of the value (must start with /)
     :type key: str
     :param defaultValue: The default value to return if the key doesn't exist
     :type defaultValue: any
     :param writeDefault: If True, force the value to the specified default
     :type writeDefault: bool
     
     .. versionadded:: 2015.3.0
     
     .. seealso:: :func:`.ntproperty` is a read-write alternative to this
     '''
     assert key.startswith('/')
     
     # Use raw NT api to avoid having to initialize networktables
     value = None
     valuefn = None # optimization for ntproperty
     
     if not writeDefault:
         value = cls._api.getEntryValue(key)
         
     if value is None:
         valuefn = Value.getFactory(defaultValue)
         cls._api.setEntryValue(key, valuefn(defaultValue))
         value = defaultValue
     elif not writeDefault:
         value = value.value
         valuefn = Value.getFactory(value)
     else:
         valuefn = Value.getFactory(value)
     
     return cls._api.createAutoValue(key,
                                     AutoUpdateValue(key, value, valuefn))
 def setDefaultValue(self, key, defaultValue):
     """If the key doesn't currently exist, then the specified value will
     be assigned to the key.
     
     :param key: the key to be assigned to
     :type key: str
     :param defaultValue: the default value to set if key doesn't exist.
     :type defaultValue: bool, int, float, str, bytes
     
     :returns: False if the table key exists with a different type
     
     .. versionadded:: 2017.0.0
     
     .. seealso:: :meth:`.putValue`
     """
     defaultValue = Value.getFactory(defaultValue)(defaultValue)
     path = self._path + key
     return self._api.setDefaultEntryValue(path, defaultValue)
예제 #14
0
 def setDefaultValue(self, key, defaultValue):
     """If the key doesn't currently exist, then the specified value will
     be assigned to the key.
     
     :param key: the key to be assigned to
     :type key: str
     :param defaultValue: the default value to set if key doesn't exist.
     :type defaultValue: bool, int, float, str, bytes
     
     :returns: False if the table key exists with a different type
     
     .. versionadded:: 2017.0.0
     
     .. seealso:: :meth:`.putValue`
     """
     defaultValue = Value.getFactory(defaultValue)(defaultValue)
     path = self._path + key
     return self._api.setDefaultEntryValue(path, defaultValue)
예제 #15
0
    def __init__(
        self,
        default: V,
        *,
        writeDefault: bool = True,
        subtable: Optional[str] = None,
        doc=None
    ) -> None:
        if doc is not None:
            warnings.warn("tunable no longer uses the doc argument", stacklevel=2)

        self._ntdefault = default
        self._ntsubtable = subtable
        self._ntwritedefault = writeDefault
        # self.__doc__ = doc

        self._mkv = Value.getFactory(default)
        self._nt = NetworkTables
예제 #16
0
def tunable(default, *, writeDefault=True, subtable=None, doc=None):
    """
        This allows you to define simple properties that allow you to easily
        communicate with other programs via NetworkTables.
    
        The following example will define a NetworkTable variable at
        ``/components/my_component/foo``::
        
            class MyRobot(magicbot.MagicRobot):
            
                my_component = MyComponent
        
            ... 
            
            from magicbot import tunable
        
            class MyComponent:
        
                # define the tunable property
                foo = tunable(True)
    
    
                def execute(self):
                
                    # set the variable
                    self.foo = True
                    
                    # get the variable
                    foo = self.foo

        The key of the NetworkTables variable will vary based on what kind of
        object the decorated method belongs to:

        * A component: ``/components/COMPONENTNAME/VARNAME``
        * An autonomous mode: ``/autonomous/MODENAME/VARNAME``
        * Your main robot class: ``/robot/VARNAME``
                    
        .. note:: When executing unit tests on objects that create tunables,
                  you will want to use setup_tunables to set the object up.
                  In normal usage, MagicRobot does this for you, so you don't
                  have to do anything special.
    """

    # the way this works is we use a special class to indicate that it
    # is a tunable, and MagicRobot adds _ntattr and _global_table variables
    # to the class property

    # The tricky bit is that you need to do late binding on these, because
    # the networktables key is not known when the object is created. Instead,
    # the name of the key is related to the name of the variable name in the
    # robot class

    nt = NetworkTables
    mkv = Value.getFactory(default)

    def _get(self):
        return getattr(self, prop._ntattr).value

    def _set(self, value):
        v = getattr(self, prop._ntattr)
        nt._api.setEntryValueById(v._local_id, mkv(value))

    prop = _TunableProperty(fget=_get, fset=_set, doc=doc)
    prop._ntdefault = default
    prop._ntsubtable = subtable
    prop._ntwritedefault = writeDefault

    return prop