def _get_locale(self, tp): if tp == "n": dec, thousands, grouping = rlocale.numeric_formatting() elif self._thousands_sep: dec = "." thousands = "," grouping = "\3" else: dec = "." thousands = "" grouping = "\xFF" # special value to mean 'stop' if self.is_unicode: self._loc_dec = rutf8.decode_latin_1(dec) self._loc_thousands = rutf8.decode_latin_1(thousands) else: self._loc_dec = dec self._loc_thousands = thousands self._loc_grouping = grouping
def _long_to_base(self, base, value): prefix = "" if base == 2: prefix = "0b" elif base == 8: prefix = "0o" elif base == 16: prefix = "0x" as_str = value.format(LONG_DIGITS[:base], prefix) if self.is_unicode: return rutf8.decode_latin_1(as_str) return as_str
def _format_float(self, w_float): """helper for format_float""" space = self.space flags = 0 default_precision = 6 if self._alternate: raise oefmt(space.w_ValueError, "Alternate form (#) not allowed in float formats") tp = self._type self._get_locale(tp) if tp == "\0": tp = "g" default_precision = 12 flags |= rfloat.DTSF_ADD_DOT_0 elif tp == "n": tp = "g" value = space.float_w(w_float) if tp == "%": tp = "f" value *= 100 add_pct = True else: add_pct = False if self._precision == -1: self._precision = default_precision result, special = rfloat.double_to_string(value, tp, self._precision, flags) if add_pct: result += "%" n_digits = len(result) if result[0] == "-": sign = "-" to_number = 1 n_digits -= 1 else: sign = "\0" to_number = 0 have_dec_point, to_remainder = self._parse_number( result, to_number) n_remainder = len(result) - to_remainder if self.is_unicode: digits = rutf8.decode_latin_1(result) else: digits = result spec = self._calc_num_width(0, sign, to_number, n_digits, n_remainder, have_dec_point, digits) fill = self._fill_char return self.wrap( self._fill_number(spec, digits, to_number, 0, fill, to_remainder, False))
def _int_to_base(self, base, value): if base == 10: s = str(value) if self.is_unicode: return rutf8.decode_latin_1(s) return s # This part is slow. negative = value < 0 base = r_uint(base) value = r_uint(value) if negative: # change the sign on the unsigned number: otherwise, value = -value # we'd risk overflow if value==-sys.maxint-1 # buf = ["\0"] * (8 * 8 + 6) # Too much on 32 bit, but who cares? i = len(buf) - 1 while True: div = value // base # unsigned mod = value - div * base # unsigned, always in range(0,base) digit = intmask(mod) digit += ord("0") if digit < 10 else ord("a") - 10 buf[i] = chr(digit) value = div # unsigned i -= 1 if not value: break if base == r_uint(2): buf[i] = "b" buf[i - 1] = "0" elif base == r_uint(8): buf[i] = "o" buf[i - 1] = "0" elif base == r_uint(16): buf[i] = "x" buf[i - 1] = "0" else: buf[i] = "#" buf[i - 1] = chr(ord("0") + intmask(base % r_uint(10))) if base > r_uint(10): buf[i - 2] = chr(ord("0") + intmask(base // r_uint(10))) i -= 1 i -= 1 if negative: i -= 1 buf[i] = "-" assert i >= 0 return "".join(buf[i:])
def _format_complex(self, w_complex): space = self.space tp = self._type self._get_locale(tp) default_precision = 6 if self._align == "=": # '=' alignment is invalid raise oefmt( space.w_ValueError, "'=' alignment flag is not allowed in complex " "format specifier") if self._fill_char == "0": # zero padding is invalid raise oefmt( space.w_ValueError, "Zero padding is not allowed in complex format " "specifier") if self._alternate: # alternate is invalid raise oefmt( space.w_ValueError, "Alternate form (#) not allowed in complex format " "specifier") skip_re = 0 add_parens = 0 if tp == "\0": #should mirror str() output tp = "g" default_precision = 12 #test if real part is non-zero if (w_complex.realval == 0 and math.copysign(1., w_complex.realval) == 1.): skip_re = 1 else: add_parens = 1 if tp == "n": #same as 'g' except for locale, taken care of later tp = "g" #check if precision not set if self._precision == -1: self._precision = default_precision #might want to switch to double_to_string from formatd #in CPython it's named 're' - clashes with re module re_num = formatd(w_complex.realval, tp, self._precision) im_num = formatd(w_complex.imagval, tp, self._precision) n_re_digits = len(re_num) n_im_digits = len(im_num) to_real_number = 0 to_imag_number = 0 re_sign = im_sign = '' #if a sign character is in the output, remember it and skip if re_num[0] == "-": re_sign = "-" to_real_number = 1 n_re_digits -= 1 if im_num[0] == "-": im_sign = "-" to_imag_number = 1 n_im_digits -= 1 #turn off padding - do it after number composition #calc_num_width uses self._width, so assign to temporary variable, #calculate width of real and imag parts, then reassign padding, align tmp_fill_char = self._fill_char tmp_align = self._align tmp_width = self._width self._fill_char = "\0" self._align = "<" self._width = -1 #determine if we have remainder, might include dec or exponent or both re_have_dec, re_remainder_ptr = self._parse_number( re_num, to_real_number) im_have_dec, im_remainder_ptr = self._parse_number( im_num, to_imag_number) if self.is_unicode: re_num = rutf8.decode_latin_1(re_num) im_num = rutf8.decode_latin_1(im_num) #set remainder, in CPython _parse_number sets this #using n_re_digits causes tests to fail re_n_remainder = len(re_num) - re_remainder_ptr im_n_remainder = len(im_num) - im_remainder_ptr re_spec = self._calc_num_width(0, re_sign, to_real_number, n_re_digits, re_n_remainder, re_have_dec, re_num) #capture grouped digits b/c _fill_number reads from self._grouped_digits #self._grouped_digits will get overwritten in imaginary calc_num_width re_grouped_digits = self._grouped_digits if not skip_re: self._sign = "+" im_spec = self._calc_num_width(0, im_sign, to_imag_number, n_im_digits, im_n_remainder, im_have_dec, im_num) im_grouped_digits = self._grouped_digits if skip_re: re_spec.n_total = 0 #reassign width, alignment, fill character self._align = tmp_align self._width = tmp_width self._fill_char = tmp_fill_char #compute L and R padding - stored in self._left_pad and self._right_pad self._calc_padding( "", re_spec.n_total + im_spec.n_total + 1 + add_parens * 2) out = self._builder() fill = self._fill_char #compose the string #add left padding out.append_multiple_char(fill, self._left_pad) if add_parens: out.append(self._lit('(')[0]) #if the no. has a real component, add it if not skip_re: out.append( self._fill_number(re_spec, re_num, to_real_number, 0, fill, re_remainder_ptr, False, re_grouped_digits)) #add imaginary component out.append( self._fill_number(im_spec, im_num, to_imag_number, 0, fill, im_remainder_ptr, False, im_grouped_digits)) #add 'j' character out.append(self._lit('j')[0]) if add_parens: out.append(self._lit(')')[0]) #add right padding out.append_multiple_char(fill, self._right_pad) return self.wrap(out.build())