def _currencyfmt(self, value): if not self.currency_enabled: return () if not isinstance(value, (float, decimal.Decimal)): if self.currency_float_only: return () value = decimal.Decimal(value) if self.currency_from_system: value_to_api = str(float(value)) try: # use the GetCurrencyFormatEx windows api to format the value GetCurrencyFormatEx = kpwt.declare_func( kpwt.kernel32, "GetCurrencyFormatEx", ret=kpwt.ct.c_int, arg=[kpwt.LPCWSTR, kpwt.DWORD, kpwt.LPCWSTR, kpwt.LPVOID, kpwt.PWSTR, kpwt.ct.c_int]) buf = kpwt.ct.create_unicode_buffer(128) res = GetCurrencyFormatEx( None, 0, value_to_api, None, buf, len(buf)) if res > 0 and len(buf.value) > 0: return (buf.value,) except: traceback.print_exc() self.info( "Failed to ask system to currency format value \"{}\". " + "Falling back to manual method.".format(value_to_api)) # manual mode # note that this code block may be used as a fallback method in case the # above code failed to ask windows api to format the value formatted_value = self._currencyfmt_impl( value, places=self.currency_places, sep=self.currency_thousandsep, dp=self.currency_decsep) return (formatted_value,)
def get_separators(self): # [main] decimal_separator decimal_separator = "." thousand_separator = "" transmap_output = str.maketrans("", "", ",") config_decsep = self.settings.get_enum("decimal_separator", "main", fallback="dot", enum=["dot", "comma", "auto"]) if config_decsep == "auto": thousand_separator = " " try: # use the GetLocaleInfoEx windows api to get the decimal and # thousand separators configured by system's user GetLocaleInfoEx = kpwt.declare_func( kpwt.kernel32, "GetLocaleInfoEx", ret=kpwt.ct.c_int, args=[kpwt.LPCWSTR, kpwt.DWORD, kpwt.PWSTR, kpwt.ct.c_int]) LOCALE_SDECIMAL = 0x0000000E LOCALE_STHOUSAND = 0x0000000F # decimal separator buf = kpwt.ct.create_unicode_buffer(10) res = GetLocaleInfoEx(None, LOCALE_SDECIMAL, buf, len(buf)) if res == 2 and len(buf.value) == res - 1 and buf.value == ",": decimal_separator = "," # thousand separator # quite awful to have a try block here but we take advantage of # having GetLocaleInfoEx already defined try: buf = kpwt.ct.create_unicode_buffer(10) res = GetLocaleInfoEx(None, LOCALE_STHOUSAND, buf, len(buf)) if res == 2 and len(buf.value) == res - 1: thousand_separator = buf.value except Exception: traceback.print_exc() transmap_output = str.maketrans( ".,", f"{decimal_separator}{thousand_separator}") except Exception: self.warn( "Failed to get system user decimal and thousand separators. " + # noqa "Falling back to default (" + config_decsep + ")...") traceback.print_exc() self.info(f'Using "{decimal_separator}" as a decimal separator') if config_decsep == "comma": decimal_separator = "," thousand_separator = " " transmap_output = str.maketrans( ".,", f"{decimal_separator}{thousand_separator}") return (decimal_separator, thousand_separator, transmap_output)
def _currencyfmt(self, value): if not self.currency_enabled: return () if not isinstance(value, (float, Number)): if self.currency_float_only: return () value = Number(value) if self.currency_from_system: value_to_api = str(float(value)) try: # use the GetCurrencyFormatEx windows api to format the value GetCurrencyFormatEx = kpwt.declare_func( kpwt.kernel32, "GetCurrencyFormatEx", ret=kpwt.ct.c_int, args=[ kpwt.LPCWSTR, kpwt.DWORD, kpwt.LPCWSTR, kpwt.LPVOID, kpwt.PWSTR, kpwt.ct.c_int ]) buf = kpwt.ct.create_unicode_buffer(128) res = GetCurrencyFormatEx(None, 0, value_to_api, None, buf, len(buf)) if res > 0 and len(buf.value) > 0: return (buf.value, ) except: traceback.print_exc() self.info('Failed to ask system to currency format value "' + str(value_to_api) + '". ' + 'Falling back to manual method.') # manual mode # note that this code block may be used as a fallback method in case the # above code failed to ask windows api to format the value formatted_value = self._currencyfmt_impl(value, places=self.currency_places, sep=self.currency_thousandsep, dp=self.currency_decsep) if self.currency_decsep in formatted_value: formatted_value = formatted_value.rstrip("0").rstrip( self.currency_decsep) if not len(formatted_value): formatted_value = "0" return (formatted_value, )
def _read_config(self): settings = self.load_settings() # [main] always_evaluate self.always_evaluate = settings.get_bool("always_evaluate", "main", self.DEFAULT_ALWAYS_EVALUATE) # [main] decimal_separator DEFAULT_DECIMAL_SEPARATOR = "dot" self.decimal_separator = "." self.thousand_separator = "," config_decsep = settings.get_enum("decimal_separator", "main", fallback=DEFAULT_DECIMAL_SEPARATOR, enum=["dot", "comma", "auto"]) if config_decsep == "auto": config_decsep = DEFAULT_DECIMAL_SEPARATOR try: # use the GetLocaleInfoEx windows api to get the decimal and # thousand separators configured by system's user GetLocaleInfoEx = kpwt.declare_func( kpwt.kernel32, "GetLocaleInfoEx", ret=kpwt.ct.c_int, args=[kpwt.LPCWSTR, kpwt.DWORD, kpwt.PWSTR, kpwt.ct.c_int]) LOCALE_SDECIMAL = 0x0000000E LOCALE_STHOUSAND = 0x0000000F # decimal separator buf = kpwt.ct.create_unicode_buffer(10) res = GetLocaleInfoEx(None, LOCALE_SDECIMAL, buf, len(buf)) if res == 2 and len(buf.value) == res - 1 and buf.value == ",": config_decsep = "comma" # thousand separator # quite awful to have a try block here but we take advantage of # having GetLocaleInfoEx already defined try: buf = kpwt.ct.create_unicode_buffer(10) res = GetLocaleInfoEx(None, LOCALE_STHOUSAND, buf, len(buf)) if res > 0: self.thousand_separator = buf except: traceback.print_exc() except: self.warn( "Failed to get system user decimal and thousand separators. " + "Falling back to default (" + config_decsep + ")...") traceback.print_exc() self.info( "Using \"{}\" as a decimal separator".format(config_decsep)) if config_decsep == "comma": self.decimal_separator = "," self.thousand_separator = " " self.transmap_input = str.maketrans(",;", ".,") self.transmap_output = str.maketrans(".", ",") else: self.decimal_separator = "." self.thousand_separator = "," self.transmap_input = "" self.transmap_output = "" # [main] base conversion self.base_conversion = settings.get_bool("base_conversion", "main", self.DEFAULT_BASE_CONVERSION) # [main] rounding_precision if not settings.has("rounding_precision", "main"): self.rounding_precision = self.DEFAULT_ROUNDING_PRECISION elif None == settings.get_stripped("rounding_precision", "main", fallback=None): self.rounding_precision = None # None means "feature disabled" else: self.rounding_precision = settings.get_int( "rounding_precision", "main", fallback=self.DEFAULT_ROUNDING_PRECISION, min=0, max=16) self.rounding_precision += 1 # [currency] mode cfgval = settings.get_enum("mode", "currency", fallback=self.DEFAULT_CURRENCY_MODE, enum=["on", "float", "off"]) if cfgval == "off": self.currency_enabled = False self.currency_float_only = True else: self.currency_enabled = True self.currency_float_only = True if cfgval == "float" else False # [currency] format cfgval = settings.get_enum("format", "currency", fallback=self.DEFAULT_CURRENCY_FORMAT, enum=["system", "manual"]) self.currency_from_system = False if cfgval == "manual" else True # [currency] decimal_separator self.currency_decsep = settings.get_stripped( "decimal_separator", "currency", fallback=self.DEFAULT_CURRENCY_DECIMALSEP) if len(self.currency_decsep) == 0 or len(self.currency_decsep) > 4: self.currency_decsep = self.DEFAULT_CURRENCY_DECIMALSEP # [currency] thousand_separator self.currency_thousandsep = settings.get( "thousand_separator", "currency", fallback=self.DEFAULT_CURRENCY_THOUSANDSEP, unquote=True) if len(self.currency_thousandsep) > 4: self.currency_thousandsep = self.DEFAULT_CURRENCY_THOUSANDSEP # [currency] places self.currency_places = settings.get_int( "places", "currency", fallback=self.DEFAULT_CURRENCY_PLACES, min=0, max=5)
def _read_config(self): settings = self.load_settings() # [main] always_evaluate self.always_evaluate = settings.get_bool("always_evaluate", "main", self.DEFAULT_ALWAYS_EVALUATE) # [main] decimal_separator DEFAULT_DECIMAL_SEPARATOR = "dot" decimal_separator = settings.get_enum( "decimal_separator", "main", fallback=DEFAULT_DECIMAL_SEPARATOR, enum=["dot", "comma", "auto"]) if decimal_separator == "auto": decimal_separator = DEFAULT_DECIMAL_SEPARATOR try: # use the GetLocaleInfoEx windows api to get the decimal # separator configured by system's user GetLocaleInfoEx = kpwt.declare_func( kpwt.kernel32, "GetLocaleInfoEx", ret=kpwt.ct.c_int, arg=[kpwt.LPCWSTR, kpwt.DWORD, kpwt.PWSTR, kpwt.ct.c_int]) LOCALE_SDECIMAL = 0x0000000E buf = kpwt.ct.create_unicode_buffer(10) res = GetLocaleInfoEx(None, LOCALE_SDECIMAL, buf, len(buf)) if res == 2 and len(buf.value) == res - 1 and buf.value == ",": decimal_separator = "comma" except: self.warn( "Failed to get system user decimal separator value. " + "Falling back to default (" + decimal_separator + ")...") traceback.print_exc() self.info("Using \"{}\" as a decimal separator".format( decimal_separator)) if decimal_separator == "comma": self.transmap_input = str.maketrans(",;", ".,") self.transmap_output = str.maketrans(".", ",") else: self.transmap_input = "" self.transmap_output = "" # [currency] mode cfgval = settings.get_enum("mode", "currency", fallback=self.DEFAULT_CURRENCY_MODE, enum=["on", "float", "off"]) if cfgval == "off": self.currency_enabled = False self.currency_float_only = True else: self.currency_enabled = True self.currency_float_only = True if cfgval == "float" else False # [currency] format cfgval = settings.get_enum("format", "currency", fallback=self.DEFAULT_CURRENCY_FORMAT, enum=["system", "manual"]) self.currency_from_system = False if cfgval == "manual" else True # [currency] decimal_separator self.currency_decsep = settings.get_stripped( "decimal_separator", "currency", fallback=self.DEFAULT_CURRENCY_DECIMALSEP) if len(self.currency_decsep) == 0 or len(self.currency_decsep) > 4: self.currency_decsep = self.DEFAULT_CURRENCY_DECIMALSEP # [currency] thousand_separator self.currency_thousandsep = settings.get( "thousand_separator", "currency", fallback=self.DEFAULT_CURRENCY_THOUSANDSEP, unquote=True) if len(self.currency_thousandsep) > 4: self.currency_thousandsep = self.DEFAULT_CURRENCY_THOUSANDSEP # [currency] places self.currency_places = settings.get_int( "places", "currency", fallback=self.DEFAULT_CURRENCY_PLACES, min=0, max=5)
def _read_config(self): settings = self.load_settings() # [main] always_evaluate self.always_evaluate = settings.get_bool( "always_evaluate", "main", self.DEFAULT_ALWAYS_EVALUATE) # [main] decimal_separator DEFAULT_DECIMAL_SEPARATOR = "dot" decimal_separator = settings.get_enum( "decimal_separator", "main", fallback=DEFAULT_DECIMAL_SEPARATOR, enum=["dot", "comma", "auto"]) if decimal_separator == "auto": decimal_separator = DEFAULT_DECIMAL_SEPARATOR try: # use the GetLocaleInfoEx windows api to get the decimal # separator configured by system's user GetLocaleInfoEx = kpwt.declare_func( kpwt.kernel32, "GetLocaleInfoEx", ret=kpwt.ct.c_int, arg=[kpwt.LPCWSTR, kpwt.DWORD, kpwt.PWSTR, kpwt.ct.c_int]) LOCALE_SDECIMAL = 0x0000000E buf = kpwt.ct.create_unicode_buffer(10) res = GetLocaleInfoEx(None, LOCALE_SDECIMAL, buf, len(buf)) if res == 2 and len(buf.value) == res - 1 and buf.value == ",": decimal_separator = "comma" except: self.warn( "Failed to get system user decimal separator value. " + "Falling back to default (" + decimal_separator + ")...") traceback.print_exc() self.info("Using \"{}\" as a decimal separator".format(decimal_separator)) if decimal_separator == "comma": self.transmap_input = str.maketrans(",;", ".,") self.transmap_output = str.maketrans(".", ",") else: self.transmap_input = "" self.transmap_output = "" # [currency] mode cfgval = settings.get_enum( "mode", "currency", fallback=self.DEFAULT_CURRENCY_MODE, enum=["on", "float", "off"]) if cfgval == "off": self.currency_enabled = False self.currency_float_only = True else: self.currency_enabled = True self.currency_float_only = True if cfgval == "float" else False # [currency] format cfgval = settings.get_enum( "format", "currency", fallback=self.DEFAULT_CURRENCY_FORMAT, enum=["system", "manual"]) self.currency_from_system = False if cfgval == "manual" else True # [currency] decimal_separator self.currency_decsep = settings.get_stripped( "decimal_separator", "currency", fallback=self.DEFAULT_CURRENCY_DECIMALSEP) if len(self.currency_decsep) == 0 or len(self.currency_decsep) > 4: self.currency_decsep = self.DEFAULT_CURRENCY_DECIMALSEP # [currency] thousand_separator self.currency_thousandsep = settings.get( "thousand_separator", "currency", fallback=self.DEFAULT_CURRENCY_THOUSANDSEP, unquote=True) if len(self.currency_thousandsep) > 4: self.currency_thousandsep = self.DEFAULT_CURRENCY_THOUSANDSEP # [currency] places self.currency_places = settings.get_int( "places", "currency", fallback=self.DEFAULT_CURRENCY_PLACES, min=0, max=5)