use PyOS_double_to_string to prevent locale-specific behavior (#4982)

* use PyOS_double_to_string to prevent locale-specific behavior

* update

---------
This commit is contained in:
mdehoon
2025-03-26 17:58:08 +09:00
committed by GitHub
parent 180d8a6e69
commit 32b9648617
2 changed files with 99 additions and 35 deletions

View File

@ -1961,11 +1961,12 @@ Aligner_str(Aligner* self)
{
char text[1024];
char* p = text;
char* value;
PyObject* substitution_matrix = self->substitution_matrix.obj;
void* args[3];
int n = 0;
PyObject* wildcard = NULL;
PyObject* s;
PyObject* s = NULL;
p += sprintf(p, "Pairwise sequence aligner with parameters\n");
if (substitution_matrix) {
@ -1983,44 +1984,88 @@ Aligner_str(Aligner* self)
p += sprintf(p, " wildcard: '%%U'\n");
args[n++] = wildcard;
}
p += sprintf(p, " match_score: %f\n", self->match);
p += sprintf(p, " mismatch_score: %f\n", self->mismatch);
/* Use PyOS_double_to_string to ensure that the locale does
* not change the decimal point into a comma.
*/
value = PyOS_double_to_string(self->match, 'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " match_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->mismatch, 'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " mismatch_score: %s\n", value);
PyMem_Free(value);
}
if (self->insertion_score_function) {
p += sprintf(p, " insertion_score_function: %%R\n");
args[n++] = self->insertion_score_function;
}
else {
p += sprintf(p, " open_internal_insertion_score: %f\n",
self->open_internal_insertion_score);
p += sprintf(p, " extend_internal_insertion_score: %f\n",
self->extend_internal_insertion_score);
p += sprintf(p, " open_left_insertion_score: %f\n",
self->open_left_insertion_score);
p += sprintf(p, " extend_left_insertion_score: %f\n",
self->extend_left_insertion_score);
p += sprintf(p, " open_right_insertion_score: %f\n",
self->open_right_insertion_score);
p += sprintf(p, " extend_right_insertion_score: %f\n",
self->extend_right_insertion_score);
value = PyOS_double_to_string(self->open_internal_insertion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " open_internal_insertion_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->extend_internal_insertion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " extend_internal_insertion_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->open_left_insertion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " open_left_insertion_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->extend_left_insertion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " extend_left_insertion_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->open_right_insertion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " open_right_insertion_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->extend_right_insertion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " extend_right_insertion_score: %s\n", value);
PyMem_Free(value);
}
if (self->deletion_score_function) {
p += sprintf(p, " deletion_score_function: %%R\n");
args[n++] = self->deletion_score_function;
}
else {
p += sprintf(p, " open_internal_deletion_score: %f\n",
self->open_internal_deletion_score);
p += sprintf(p, " extend_internal_deletion_score: %f\n",
self->extend_internal_deletion_score);
p += sprintf(p, " open_left_deletion_score: %f\n",
self->open_left_deletion_score);
p += sprintf(p, " extend_left_deletion_score: %f\n",
self->extend_left_deletion_score);
p += sprintf(p, " open_right_deletion_score: %f\n",
self->open_right_deletion_score);
p += sprintf(p, " extend_right_deletion_score: %f\n",
self->extend_right_deletion_score);
value = PyOS_double_to_string(self->open_internal_deletion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " open_internal_deletion_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->extend_internal_deletion_score,
'f', 6, 0, NULL);
p += sprintf(p, " extend_internal_deletion_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->open_left_deletion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " open_left_deletion_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->extend_left_deletion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " extend_left_deletion_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->open_right_deletion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " open_right_deletion_score: %s\n", value);
PyMem_Free(value);
value = PyOS_double_to_string(self->extend_right_deletion_score,
'f', 6, 0, NULL);
if (!value) goto exit;
p += sprintf(p, " extend_right_deletion_score: %s\n", value);
PyMem_Free(value);
}
switch (self->mode) {
case Global: sprintf(p, " mode: global\n"); break;
@ -2031,6 +2076,8 @@ Aligner_str(Aligner* self)
return NULL;
}
s = PyUnicode_FromFormat(text, args[0], args[1], args[2]);
exit:
Py_XDECREF(wildcard);
return s;
}

View File

@ -682,8 +682,15 @@ PyNode_repr(PyNode* self)
{
char string[64];
sprintf(string, "(%d, %d): %g",
self->node.left, self->node.right, self->node.distance);
/* Use PyOS_double_to_string to ensure that the locale does
* not change the decimal point into a comma.
*/
char* value = PyOS_double_to_string(self->node.distance, 'g', 6, 0, NULL);
if (!value) return NULL;
sprintf(string, "(%d, %d): %s", self->node.left, self->node.right, value);
PyMem_Free(value);
return PyUnicode_FromString(string);
}
@ -928,15 +935,27 @@ PyTree_str(PyTree* self)
int i;
const int n = self->n;
char string[128];
char* distance;
Node node;
PyObject* line;
PyObject* output;
PyObject* temp;
output = PyUnicode_FromString("");
if (!output) return NULL;
for (i = 0; i < n; i++) {
node = self->nodes[i];
sprintf(string, "(%d, %d): %g", node.left, node.right, node.distance);
distance = PyOS_double_to_string(node.distance, 'g', 6, 0, NULL);
if (!distance) {
Py_DECREF(output);
return NULL;
}
/* Use PyOS_double_to_string to ensure that the locale does
* not change the decimal point into a comma.
*/
sprintf(string, "(%d, %d): %s", node.left, node.right, distance);
PyMem_Free(distance);
if (i < n-1) strcat(string, "\n");
line = PyUnicode_FromString(string);
if (!line) {
@ -944,11 +963,9 @@ PyTree_str(PyTree* self)
return NULL;
}
temp = PyUnicode_Concat(output, line);
if (!temp) {
Py_DECREF(output);
Py_DECREF(line);
return NULL;
}
Py_DECREF(line);
Py_DECREF(output);
if (!temp) return NULL;
output = temp;
}
return output;