def str_to_value(text, va): """ Attempt to fit the given text as a value for the given VA text (str): "Free-form" entry from a user va (Vigilant Attribute): the VA that would receive the value return (value): a value that might fit the VA raise ValueError: if cannot convert """ logging.debug("Parsing free text value %s", text) va_val = va.value # Try to find a good corresponding value inside the string if isinstance(va_val, collections.Iterable) and text.endswith(va.unit): _, str_si, _ = decompose_si_prefix("1" + text[-(len(va.unit) + 1):], unit=va.unit) str_val = text else: str_val, str_si, _ = decompose_si_prefix(text, unit=va.unit) new_val = reproduce_typed_value(va_val, str_val) # In case of list, be lenient by dropping the extra values if it's too many if isinstance(new_val, collections.Iterable): new_val = new_val[:len(va_val)] if new_val and isinstance(new_val[0], numbers.Real): new_val = tuple(si_scale_val(v, str_si) for v in new_val) else: # If an SI prefix was found, scale the new value if isinstance(new_val, numbers.Real): new_val = si_scale_val(new_val, str_si) return new_val
def cb_get(ctrl=value_ctrl, va=va, u=unit): ctrl_value = ctrl.GetValue() # Try to use the predefined value if it's available i = ctrl.GetSelection() # Warning: if the text contains an unknown value, GetSelection will # not return wx.NOT_FOUND (as expected), but the last selection value if i != wx.NOT_FOUND and ctrl.Items[i] == ctrl_value: logging.debug("Getting item value %s from combobox control", ctrl.GetClientData(i)) return ctrl.GetClientData(i) else: logging.debug("Parsing combobox free text value %s", ctrl_value) va_val = va.value # Try to find a good corresponding value inside the string # Try and find an SI prefix str_val, str_si, _ = decompose_si_prefix(ctrl_value, unit=u) new_val = reproduce_typed_value(va_val, str_val) if isinstance(new_val, collections.Iterable): # be less picky, by shortening the number of values if it's too many new_val = new_val[:len(va_val)] # If an SI prefix was found, scale the new value new_val = si_scale_val(new_val, str_si) # if it ends up being the same value as before the combobox will not update, so # force it now if va_val == new_val: cb_set(va_val) return new_val
def cb_get(ctrl=value_ctrl, va=va, u=unit): ctrl_value = ctrl.GetValue() # Try to use the predefined value if it's available i = ctrl.GetSelection() # Warning: if the text contains an unknown value, GetSelection will # not return wx.NOT_FOUND (as expected), but the last selection value if i != wx.NOT_FOUND and ctrl.Items[i] == ctrl_value: logging.debug("Getting item value %s from combobox control", ctrl.GetClientData(i)) return ctrl.GetClientData(i) else: logging.debug("Parsing combobox free text value %s", ctrl_value) va_val = va.value # Try to find a good corresponding value inside the string str_val, str_si, _ = decompose_si_prefix(ctrl_value, unit=u) try: new_val = reproduce_typed_value(va_val, str_val) except (ValueError, TypeError): logging.warning("Value %s couldn't be understood", str_val, exc_info=True) new_val = va_val # To force going back to last value # In case of list, be lenient by dropping the extra values if it's too many if isinstance(new_val, collections.Iterable): new_val = new_val[:len(va_val)] # If an SI prefix was found, scale the new value new_val = si_scale_val(new_val, str_si) # if it ends up being the same value as before the combobox will # not update, so force it now if va_val == new_val: cb_set(va_val) return new_val
def _cast(self, str_val): """ Cast the string value to an integer and return it Args: str_val (str): A string representing a number value Returns: (int) Raises: ValueError: When the string cannot be parsed correctly """ if self.unit and str_val.endswith(self.unit): # Help it to find the right unit (important for complicated ones like 'px') str_val, si_prefix, unit = decompose_si_prefix(str_val, self.unit) else: str_val, si_prefix, unit = decompose_si_prefix(str_val) return int(si_scale_val(float(str_val), si_prefix))
def test_decompose_si_prefix_explicit_unit(self): values = [ (("-12 nm", "m"), ("-12", "n", "m")), (("-12 nm", "s"), ("-12 nm", None, None)), (("12 u", "s"), ("12", u"µ", None)), (("12 m", "s"), ("12", "m", None)), (("0.12 rad", "s"), ("0.12 rad", None, None)), (("0.12 rad", "rad"), ("0.12", None, "rad")), ] for args_in, exp_out in values: self.assertEqual(units.decompose_si_prefix(*args_in), exp_out)
def test_decompose_si_prefix(self): values = [ ("-12 nm", ("-12", "n", "m")), ("12 um", ("12", u"µ", "m")), ("12 um ", ("12", u"µ", "m")), ("12 um Hallo!", ("12 um Hallo!", None, None)), ("3.2 Grap", ("3.2", "G", "rap")), ("-13.223 mm", ("-13.223", "m", "m")), ("-13.323 pm", ("-13.323", "p", "m")), ("-156.41e-9kN", ("-156.41e-9", "k", "N")), ("-156.41e-9 GN", ("-156.41e-9", "G", "N")), ("-156.41e-9 GN", ("-156.41e-9", "G", "N")), ("100.2", ("100.2", None, None)), ("100 m", ("100", None, "m")), ("banaan", ("banaan", None, None)), ("2 x 2 px", ("2 x 2 px", None, None)), ("2 x 2", ("2 x 2", None, None)), ("[3.0, 4.5]", ("[3.0, 4.5]", None, None)), ] for str_in, tuple_out in values: self.assertEqual(units.decompose_si_prefix(str_in), tuple_out)
def str_to_value(text, va): """ Attempt to fit the given text as a value for the given VA text (str): "Free-form" entry from a user va (Vigilant Attribute): the VA that would receive the value return (value): a value that might fit the VA raise ValueError: if cannot convert """ logging.debug("Parsing free text value %s", text) va_val = va.value # Try to find a good corresponding value inside the string str_val, str_si, _ = decompose_si_prefix(text, unit=va.unit) new_val = reproduce_typed_value(va_val, str_val) # In case of list, be lenient by dropping the extra values if it's too many if isinstance(new_val, collections.Iterable): new_val = new_val[:len(va_val)] # If an SI prefix was found, scale the new value # TODO: support iterables too if isinstance(new_val, numbers.Real): new_val = si_scale_val(new_val, str_si) return new_val