Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
numeric.py214 linesDownload Raw Back to fields
1import decimal2 3from wtforms import widgets4from wtforms.fields.core import Field5from wtforms.utils import unset_value6 7__all__ = (8    "IntegerField",9    "DecimalField",10    "FloatField",11    "IntegerRangeField",12    "DecimalRangeField",13)14 15 16class LocaleAwareNumberField(Field):17    """18    Base class for implementing locale-aware number parsing.19 20    Locale-aware numbers require the 'babel' package to be present.21    """22 23    def __init__(24        self,25        label=None,26        validators=None,27        use_locale=False,28        number_format=None,29        **kwargs,30    ):31        super().__init__(label, validators, **kwargs)32        self.use_locale = use_locale33        if use_locale:34            self.number_format = number_format35            self.locale = kwargs["_form"].meta.locales[0]36            self._init_babel()37 38    def _init_babel(self):39        try:40            from babel import numbers41 42            self.babel_numbers = numbers43        except ImportError as exc:44            raise ImportError(45                "Using locale-aware decimals requires the babel library."46            ) from exc47 48    def _parse_decimal(self, value):49        return self.babel_numbers.parse_decimal(value, self.locale)50 51    def _format_decimal(self, value):52        return self.babel_numbers.format_decimal(value, self.number_format, self.locale)53 54 55class IntegerField(Field):56    """57    A text field, except all input is coerced to an integer.  Erroneous input58    is ignored and will not be accepted as a value.59    """60 61    widget = widgets.NumberInput()62 63    def __init__(self, label=None, validators=None, **kwargs):64        super().__init__(label, validators, **kwargs)65 66    def _value(self):67        if self.raw_data:68            return self.raw_data[0]69        if self.data is not None:70            return str(self.data)71        return ""72 73    def process_data(self, value):74        if value is None or value is unset_value:75            self.data = None76            return77 78        try:79            self.data = int(value)80        except (ValueError, TypeError) as exc:81            self.data = None82            raise ValueError(self.gettext("Not a valid integer value.")) from exc83 84    def process_formdata(self, valuelist):85        if not valuelist:86            return87 88        try:89            self.data = int(valuelist[0])90        except ValueError as exc:91            self.data = None92            raise ValueError(self.gettext("Not a valid integer value.")) from exc93 94 95class DecimalField(LocaleAwareNumberField):96    """97    A text field which displays and coerces data of the `decimal.Decimal` type.98 99    :param places:100        How many decimal places to quantize the value to for display on form.101        If unset, use 2 decimal places.102        If explicitely set to `None`, does not quantize value.103    :param rounding:104        How to round the value during quantize, for example105        `decimal.ROUND_UP`. If unset, uses the rounding value from the106        current thread's context.107    :param use_locale:108        If True, use locale-based number formatting. Locale-based number109        formatting requires the 'babel' package.110    :param number_format:111        Optional number format for locale. If omitted, use the default decimal112        format for the locale.113    """114 115    widget = widgets.NumberInput(step="any")116 117    def __init__(118        self, label=None, validators=None, places=unset_value, rounding=None, **kwargs119    ):120        super().__init__(label, validators, **kwargs)121        if self.use_locale and (places is not unset_value or rounding is not None):122            raise TypeError(123                "When using locale-aware numbers, 'places' and 'rounding' are ignored."124            )125 126        if places is unset_value:127            places = 2128        self.places = places129        self.rounding = rounding130 131    def _value(self):132        if self.raw_data:133            return self.raw_data[0]134 135        if self.data is None:136            return ""137 138        if self.use_locale:139            return str(self._format_decimal(self.data))140 141        if self.places is None:142            return str(self.data)143 144        if not hasattr(self.data, "quantize"):145            # If for some reason, data is a float or int, then format146            # as we would for floats using string formatting.147            format = "%%0.%df" % self.places148            return format % self.data149 150        exp = decimal.Decimal(".1") ** self.places151        if self.rounding is None:152            quantized = self.data.quantize(exp)153        else:154            quantized = self.data.quantize(exp, rounding=self.rounding)155        return str(quantized)156 157    def process_formdata(self, valuelist):158        if not valuelist:159            return160 161        try:162            if self.use_locale:163                self.data = self._parse_decimal(valuelist[0])164            else:165                self.data = decimal.Decimal(valuelist[0])166        except (decimal.InvalidOperation, ValueError) as exc:167            self.data = None168            raise ValueError(self.gettext("Not a valid decimal value.")) from exc169 170 171class FloatField(Field):172    """173    A text field, except all input is coerced to an float.  Erroneous input174    is ignored and will not be accepted as a value.175    """176 177    widget = widgets.TextInput()178 179    def __init__(self, label=None, validators=None, **kwargs):180        super().__init__(label, validators, **kwargs)181 182    def _value(self):183        if self.raw_data:184            return self.raw_data[0]185        if self.data is not None:186            return str(self.data)187        return ""188 189    def process_formdata(self, valuelist):190        if not valuelist:191            return192 193        try:194            self.data = float(valuelist[0])195        except ValueError as exc:196            self.data = None197            raise ValueError(self.gettext("Not a valid float value.")) from exc198 199 200class IntegerRangeField(IntegerField):201    """202    Represents an ``<input type="range">``.203    """204 205    widget = widgets.RangeInput()206 207 208class DecimalRangeField(DecimalField):209    """210    Represents an ``<input type="range">``.211    """212 213    widget = widgets.RangeInput(step="any")214 
codekingpro/portable-devtools · Team Ai