Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions 4 Include/internal/pycore_fileutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
extern "C" {
#endif

#ifndef Py_BUILD_CORE
# error "Py_BUILD_CORE must be defined to include this header"
#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN)
# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN defined"
#endif

#include <locale.h> /* struct lconv */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
The :mod:`decimal` module now supports formatting number to the "n" type
when the ``LC_NUMERIC`` locale uses a different encoding than the
``LC_CTYPE`` locale. It now sets temporarily the ``LC_CTYPE`` locale to the
``LC_NUMERIC`` locale to decode ``decimal_point`` and ``thousands_sep`` byte
strings if they are non-ASCII or longer than 1 byte, and the ``LC_NUMERIC``
locale is different than the ``LC_CTYPE`` locale. This temporary change
affects other threads.
73 changes: 30 additions & 43 deletions 73 Modules/_decimal/_decimal.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
#include "structmember.h"
#include "complexobject.h"
#include "mpdecimal.h"
#include "pycore_fileutils.h"

#include <locale.h>
#include <stdlib.h>

#include "docstrings.h"
Expand Down Expand Up @@ -3013,32 +3015,6 @@ dec_replace_fillchar(char *dest)
}
}

/* Convert decimal_point or thousands_sep, which may be multibyte or in
the range [128, 255], to a UTF8 string. */
static PyObject *
dotsep_as_utf8(const char *s)
{
PyObject *utf8;
PyObject *tmp;
wchar_t buf[2];
size_t n;

n = mbstowcs(buf, s, 2);
if (n != 1) { /* Issue #7442 */
PyErr_SetString(PyExc_ValueError,
"invalid decimal point or unsupported "
"combination of LC_CTYPE and LC_NUMERIC");
return NULL;
}
tmp = PyUnicode_FromWideChar(buf, n);
if (tmp == NULL) {
return NULL;
}
utf8 = PyUnicode_AsUTF8String(tmp);
Py_DECREF(tmp);
return utf8;
}

/* Formatted representation of a PyDecObject. */
static PyObject *
dec_format(PyObject *dec, PyObject *args)
Expand All @@ -3048,6 +3024,7 @@ dec_format(PyObject *dec, PyObject *args)
PyObject *dot = NULL;
PyObject *sep = NULL;
PyObject *grouping = NULL;
char *grouping_buffer = NULL;
PyObject *fmtarg;
PyObject *context;
mpd_spec_t spec;
Expand Down Expand Up @@ -3133,24 +3110,33 @@ dec_format(PyObject *dec, PyObject *args)
goto finish;
}
}
else {
size_t n = strlen(spec.dot);
if (n > 1 || (n == 1 && !isascii((uchar)spec.dot[0]))) {
/* fix locale dependent non-ascii characters */
dot = dotsep_as_utf8(spec.dot);
if (dot == NULL) {
goto finish;
}
spec.dot = PyBytes_AS_STRING(dot);
else if (spec.locale) {
struct lconv *lc = localeconv();
if (_Py_GetLocaleconvNumeric(lc, &dot, &sep) < 0) {
goto finish;
}
n = strlen(spec.sep);
if (n > 1 || (n == 1 && !isascii((uchar)spec.sep[0]))) {
/* fix locale dependent non-ascii characters */
sep = dotsep_as_utf8(spec.sep);
if (sep == NULL) {
goto finish;
}
spec.sep = PyBytes_AS_STRING(sep);

grouping_buffer = _PyMem_Strdup(lc->grouping);
if (grouping_buffer == NULL) {
PyErr_NoMemory();
goto finish;
}
spec.grouping = grouping_buffer;

spec.dot = PyUnicode_AsUTF8(dot);
if (spec.dot == NULL) {
goto finish;
}

spec.sep = PyUnicode_AsUTF8(sep);
if (spec.sep == NULL) {
goto finish;
}

if (mpd_validate_lconv(&spec) < 0) {
PyErr_SetString(PyExc_ValueError,
"invalid localeconv()");
goto finish;
}
}

Expand All @@ -3176,6 +3162,7 @@ dec_format(PyObject *dec, PyObject *args)

finish:
Py_XDECREF(grouping);
PyMem_Free(grouping_buffer);
Py_XDECREF(sep);
Py_XDECREF(dot);
if (replace_fillchar) PyMem_Free(fmt);
Expand Down
2 changes: 2 additions & 0 deletions 2 Modules/_decimal/libmpdec/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@ mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps)
spec->dot = "";
spec->sep = "";
spec->grouping = "";
spec->locale = 0;


/* presume that the first character is a UTF-8 fill character */
Expand Down Expand Up @@ -871,6 +872,7 @@ mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps)
if (*spec->sep) {
return 0;
}
spec->locale = 1;
spec->type = *cp++;
spec->type = (spec->type == 'N') ? 'G' : 'g';
lc = localeconv();
Expand Down
1 change: 1 addition & 0 deletions 1 Modules/_decimal/libmpdec/mpdecimal.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ typedef struct mpd_spec_t {
const char *dot; /* decimal point */
const char *sep; /* thousands separator */
const char *grouping; /* grouping of digits */
int locale; /* use localeconv() */
} mpd_spec_t;

/* output to a string */
Expand Down
2 changes: 1 addition & 1 deletion 2 PCbuild/_decimal.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MASM;Py_BUILD_CORE_BUILTIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Platform)' == 'Win32'">CONFIG_32;PPRO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Platform)' == 'x64'">CONFIG_64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\Modules\_decimal;..\Modules\_decimal\libmpdec;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
Expand Down
2 changes: 1 addition & 1 deletion 2 setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2002,7 +2002,7 @@ def detect_ctypes(self, inc_dirs, lib_dirs):
ext.libraries.append('dl')

def _decimal_ext(self):
extra_compile_args = []
extra_compile_args = ['-DPy_BUILD_CORE_BUILTIN']
undef_macros = []
if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"):
include_dirs = []
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.