static PyObject * contextvar_tp_repr(PyContextVar *self) { _PyUnicodeWriter writer; _PyUnicodeWriter_Init(&writer); if (_PyUnicodeWriter_WriteASCIIString( &writer, "<ContextVar name=", 17) < 0) { goto error; } PyObject *name = PyObject_Repr(self->var_name); if (name == NULL) { goto error; } if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) { Py_DECREF(name); goto error; } Py_DECREF(name); if (self->var_default != NULL) { if (_PyUnicodeWriter_WriteASCIIString(&writer, " default=", 9) < 0) { goto error; } PyObject *def = PyObject_Repr(self->var_default); if (def == NULL) { goto error; } if (_PyUnicodeWriter_WriteStr(&writer, def) < 0) { Py_DECREF(def); goto error; } Py_DECREF(def); } PyObject *addr = PyUnicode_FromFormat(" at %p>", self); if (addr == NULL) { goto error; } if (_PyUnicodeWriter_WriteStr(&writer, addr) < 0) { Py_DECREF(addr); goto error; } Py_DECREF(addr); return _PyUnicodeWriter_Finish(&writer); error: _PyUnicodeWriter_Dealloc(&writer); return NULL; }
int _PyUnicode_FormatAdvancedWriter(_PyUnicodeWriter *writer, PyObject *obj, PyObject *format_spec, Py_ssize_t start, Py_ssize_t end) { InternalFormatSpec format; assert(PyUnicode_Check(obj)); /* check for the special case of zero length format spec, make it equivalent to str(obj) */ if (start == end) { if (PyUnicode_CheckExact(obj)) return _PyUnicodeWriter_WriteStr(writer, obj); else return format_obj(obj, writer); } /* parse the format_spec */ if (!parse_internal_render_format_spec(format_spec, start, end, &format, 's', '<')) return -1; /* type conversion? */ switch (format.type) { case 's': /* no type conversion needed, already a string. do the formatting */ return format_string_internal(obj, &format, writer); default: /* unknown */ unknown_presentation_type(format.type, obj->ob_type->tp_name); return -1; } }
static PyObject * token_tp_repr(PyContextToken *self) { _PyUnicodeWriter writer; _PyUnicodeWriter_Init(&writer); if (_PyUnicodeWriter_WriteASCIIString(&writer, "<Token", 6) < 0) { goto error; } if (self->tok_used) { if (_PyUnicodeWriter_WriteASCIIString(&writer, " used", 5) < 0) { goto error; } } if (_PyUnicodeWriter_WriteASCIIString(&writer, " var=", 5) < 0) { goto error; } PyObject *var = PyObject_Repr((PyObject *)self->tok_var); if (var == NULL) { goto error; } if (_PyUnicodeWriter_WriteStr(&writer, var) < 0) { Py_DECREF(var); goto error; } Py_DECREF(var); PyObject *addr = PyUnicode_FromFormat(" at %p>", self); if (addr == NULL) { goto error; } if (_PyUnicodeWriter_WriteStr(&writer, addr) < 0) { Py_DECREF(addr); goto error; } Py_DECREF(addr); return _PyUnicodeWriter_Finish(&writer); error: _PyUnicodeWriter_Dealloc(&writer); return NULL; }
static int format_obj(PyObject *obj, _PyUnicodeWriter *writer) { PyObject *str; int err; str = PyObject_Str(obj); if (str == NULL) return -1; err = _PyUnicodeWriter_WriteStr(writer, str); Py_DECREF(str); return err; }
static int format_string_internal(PyObject *value, const InternalFormatSpec *format, _PyUnicodeWriter *writer) { Py_ssize_t lpad; Py_ssize_t rpad; Py_ssize_t total; Py_ssize_t len; int result = -1; Py_UCS4 maxchar; assert(PyUnicode_IS_READY(value)); len = PyUnicode_GET_LENGTH(value); /* sign is not allowed on strings */ if (format->sign != '\0') { PyErr_SetString(PyExc_ValueError, "Sign not allowed in string format specifier"); goto done; } /* alternate is not allowed on strings */ if (format->alternate) { PyErr_SetString(PyExc_ValueError, "Alternate form (#) not allowed in string format " "specifier"); goto done; } /* '=' alignment not allowed on strings */ if (format->align == '=') { PyErr_SetString(PyExc_ValueError, "'=' alignment not allowed " "in string format specifier"); goto done; } if ((format->width == -1 || format->width <= len) && (format->precision == -1 || format->precision >= len)) { /* Fast path */ return _PyUnicodeWriter_WriteStr(writer, value); } /* if precision is specified, output no more that format.precision characters */ if (format->precision >= 0 && len >= format->precision) { len = format->precision; } calc_padding(len, format->width, format->align, &lpad, &rpad, &total); maxchar = writer->maxchar; if (lpad != 0 || rpad != 0) maxchar = Py_MAX(maxchar, format->fill_char); if (PyUnicode_MAX_CHAR_VALUE(value) > maxchar) { Py_UCS4 valmaxchar = _PyUnicode_FindMaxChar(value, 0, len); maxchar = Py_MAX(maxchar, valmaxchar); } /* allocate the resulting string */ if (_PyUnicodeWriter_Prepare(writer, total, maxchar) == -1) goto done; /* Write into that space. First the padding. */ result = fill_padding(writer, len, format->fill_char, lpad, rpad); if (result == -1) goto done; /* Then the source string. */ if (len) { _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos, value, 0, len); } writer->pos += (len + rpad); result = 0; done: return result; }
/* much of this is taken from unicodeobject.c */ static int format_float_internal(PyObject *value, const InternalFormatSpec *format, _PyUnicodeWriter *writer) { char *buf = NULL; /* buffer returned from PyOS_double_to_string */ Py_ssize_t n_digits; Py_ssize_t n_remainder; Py_ssize_t n_total; int has_decimal; double val; Py_ssize_t precision; Py_ssize_t default_precision = 6; Py_UCS4 type = format->type; int add_pct = 0; Py_ssize_t index; NumberFieldWidths spec; int flags = 0; int result = -1; Py_UCS4 maxchar = 127; Py_UCS4 sign_char = '\0'; int float_type; /* Used to see if we have a nan, inf, or regular float. */ PyObject *unicode_tmp = NULL; /* Locale settings, either from the actual locale or from a hard-code pseudo-locale */ LocaleInfo locale = STATIC_LOCALE_INFO_INIT; if (format->precision > INT_MAX) { PyErr_SetString(PyExc_ValueError, "precision too big"); goto done; } precision = (int)format->precision; if (format->alternate) flags |= Py_DTSF_ALT; if (type == '\0') { /* Omitted type specifier. Behaves in the same way as repr(x) and str(x) if no precision is given, else like 'g', but with at least one digit after the decimal point. */ flags |= Py_DTSF_ADD_DOT_0; type = 'r'; default_precision = 0; } if (type == 'n') /* 'n' is the same as 'g', except for the locale used to format the result. We take care of that later. */ type = 'g'; val = PyFloat_AsDouble(value); if (val == -1.0 && PyErr_Occurred()) goto done; if (type == '%') { type = 'f'; val *= 100; add_pct = 1; } if (precision < 0) precision = default_precision; else if (type == 'r') type = 'g'; /* Cast "type", because if we're in unicode we need to pass a 8-bit char. This is safe, because we've restricted what "type" can be. */ buf = PyOS_double_to_string(val, (char)type, precision, flags, &float_type); if (buf == NULL) goto done; n_digits = strlen(buf); if (add_pct) { /* We know that buf has a trailing zero (since we just called strlen() on it), and we don't use that fact any more. So we can just write over the trailing zero. */ buf[n_digits] = '%'; n_digits += 1; } /* Since there is no unicode version of PyOS_double_to_string, just use the 8 bit version and then convert to unicode. */ unicode_tmp = _PyUnicode_FromASCII(buf, n_digits); PyMem_Free(buf); if (unicode_tmp == NULL) goto done; if (format->sign != '+' && format->sign != ' ' && format->width == -1 && format->type != 'n' && !format->thousands_separators) { /* Fast path */ result = _PyUnicodeWriter_WriteStr(writer, unicode_tmp); Py_DECREF(unicode_tmp); return result; } /* Is a sign character present in the output? If so, remember it and skip it */ index = 0; if (PyUnicode_READ_CHAR(unicode_tmp, index) == '-') { sign_char = '-'; ++index; --n_digits; } /* Determine if we have any "remainder" (after the digits, might include decimal or exponent or both (or neither)) */ parse_number(unicode_tmp, index, index + n_digits, &n_remainder, &has_decimal); /* Determine the grouping, separator, and decimal point, if any. */ if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : (format->thousands_separators ? LT_DEFAULT_LOCALE : LT_NO_LOCALE), &locale) == -1) goto done; /* Calculate how much memory we'll need. */ n_total = calc_number_widths(&spec, 0, sign_char, unicode_tmp, index, index + n_digits, n_remainder, has_decimal, &locale, format, &maxchar); /* Allocate the memory. */ if (_PyUnicodeWriter_Prepare(writer, n_total, maxchar) == -1) goto done; /* Populate the memory. */ result = fill_number(writer, &spec, unicode_tmp, index, index + n_digits, NULL, 0, format->fill_char == '\0' ? ' ' : format->fill_char, &locale, 0); done: Py_XDECREF(unicode_tmp); free_locale_info(&locale); return result; }
static PyObject * record_repr(ApgRecordObject *v) { Py_ssize_t i, n; PyObject *keys_iter; _PyUnicodeWriter writer; n = Py_SIZE(v); assert(n > 0); keys_iter = PyObject_GetIter(v->mapping); if (keys_iter == NULL) { return NULL; } i = Py_ReprEnter((PyObject *)v); if (i != 0) { Py_DECREF(keys_iter); return i > 0 ? PyUnicode_FromString("<Record ...>") : NULL; } _PyUnicodeWriter_Init(&writer); writer.overallocate = 1; writer.min_length = 12; /* <Record a=1> */ if (_PyUnicodeWriter_WriteASCIIString(&writer, "<Record ", 8) < 0) { goto error; } for (i = 0; i < n; ++i) { PyObject *key; PyObject *key_repr; PyObject *val_repr; if (i > 0) { if (_PyUnicodeWriter_WriteChar(&writer, ' ') < 0) { goto error; } } if (Py_EnterRecursiveCall(" while getting the repr of a record")) { goto error; } val_repr = PyObject_Repr(v->ob_item[i]); Py_LeaveRecursiveCall(); if (val_repr == NULL) { goto error; } key = PyIter_Next(keys_iter); if (key == NULL) { Py_DECREF(val_repr); PyErr_SetString(PyExc_RuntimeError, "invalid record mapping"); goto error; } key_repr = PyObject_Str(key); Py_DECREF(key); if (key_repr == NULL) { Py_DECREF(val_repr); goto error; } if (_PyUnicodeWriter_WriteStr(&writer, key_repr) < 0) { Py_DECREF(key_repr); Py_DECREF(val_repr); goto error; } Py_DECREF(key_repr); if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) { Py_DECREF(val_repr); goto error; } if (_PyUnicodeWriter_WriteStr(&writer, val_repr) < 0) { Py_DECREF(val_repr); goto error; } Py_DECREF(val_repr); } writer.overallocate = 0; if (_PyUnicodeWriter_WriteChar(&writer, '>') < 0) { goto error; } Py_DECREF(keys_iter); Py_ReprLeave((PyObject *)v); return _PyUnicodeWriter_Finish(&writer); error: Py_DECREF(keys_iter); _PyUnicodeWriter_Dealloc(&writer); Py_ReprLeave((PyObject *)v); return NULL; }
static PyObject * tuplerepr(PyTupleObject *v) { Py_ssize_t i, n; _PyUnicodeWriter writer; n = Py_SIZE(v); if (n == 0) return PyUnicode_FromString("()"); /* While not mutable, it is still possible to end up with a cycle in a tuple through an object that stores itself within a tuple (and thus infinitely asks for the repr of itself). This should only be possible within a type. */ i = Py_ReprEnter((PyObject *)v); if (i != 0) { return i > 0 ? PyUnicode_FromString("(...)") : NULL; } _PyUnicodeWriter_Init(&writer); writer.overallocate = 1; if (Py_SIZE(v) > 1) { /* "(" + "1" + ", 2" * (len - 1) + ")" */ writer.min_length = 1 + 1 + (2 + 1) * (Py_SIZE(v) - 1) + 1; } else { /* "(1,)" */ writer.min_length = 4; } if (_PyUnicodeWriter_WriteChar(&writer, '(') < 0) goto error; /* Do repr() on each element. */ for (i = 0; i < n; ++i) { PyObject *s; if (i > 0) { if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) goto error; } if (Py_EnterRecursiveCall(" while getting the repr of a tuple")) goto error; s = PyObject_Repr(v->ob_item[i]); Py_LeaveRecursiveCall(); if (s == NULL) goto error; if (_PyUnicodeWriter_WriteStr(&writer, s) < 0) { Py_DECREF(s); goto error; } Py_DECREF(s); } writer.overallocate = 0; if (n > 1) { if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) goto error; } else { if (_PyUnicodeWriter_WriteASCIIString(&writer, ",)", 2) < 0) goto error; } Py_ReprLeave((PyObject *)v); return _PyUnicodeWriter_Finish(&writer); error: _PyUnicodeWriter_Dealloc(&writer); Py_ReprLeave((PyObject *)v); return NULL; }