Skip to content

Commit 684a31a

Browse files
committed
Simplify conv_confname
1 parent 2544159 commit 684a31a

File tree

6 files changed

+65
-98
lines changed

6 files changed

+65
-98
lines changed

Lib/test/support/os_helper.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -632,8 +632,7 @@ def fd_count():
632632
if hasattr(os, 'sysconf'):
633633
try:
634634
MAXFD = os.sysconf("SC_OPEN_MAX")
635-
except (OSError, ValueError):
636-
# gh-118201: ValueError is raised intermittently on iOS
635+
except OSError:
637636
pass
638637

639638
old_modes = None

Lib/test/test_os.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2447,8 +2447,8 @@ def test_fchown(self):
24472447
support.is_emscripten or support.is_wasi,
24482448
"musl libc issue on Emscripten/WASI, bpo-46390"
24492449
)
2450-
@unittest.skipIf(support.is_apple_mobile, "gh-118201: Test is flaky on iOS")
24512450
def test_fpathconf(self):
2451+
self.assertIn("PC_NAME_MAX", os.pathconf_names)
24522452
self.check(os.pathconf, "PC_NAME_MAX")
24532453
self.check(os.fpathconf, "PC_NAME_MAX")
24542454
self.check_bool(os.pathconf, "PC_NAME_MAX")

Lib/test/test_posix.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -566,10 +566,38 @@ def test_dup(self):
566566

567567
@unittest.skipUnless(hasattr(posix, 'confstr'),
568568
'test needs posix.confstr()')
569-
@unittest.skipIf(support.is_apple_mobile, "gh-118201: Test is flaky on iOS")
570569
def test_confstr(self):
571-
self.assertRaises(ValueError, posix.confstr, "CS_garbage")
572-
self.assertEqual(len(posix.confstr("CS_PATH")) > 0, True)
570+
with self.assertRaisesRegex(
571+
ValueError, "unrecognized configuration name"
572+
):
573+
posix.confstr("CS_garbage")
574+
575+
with self.assertRaisesRegex(
576+
TypeError, "configuration names must be strings or integers"
577+
):
578+
posix.confstr(1.23)
579+
580+
path = posix.confstr("CS_PATH")
581+
self.assertGreater(len(path), 0)
582+
self.assertEqual(posix.confstr(posix.confstr_names["CS_PATH"]), path)
583+
584+
@unittest.skipUnless(hasattr(posix, 'sysconf'),
585+
'test needs posix.sysconf()')
586+
def test_sysconf(self):
587+
with self.assertRaisesRegex(
588+
ValueError, "unrecognized configuration name"
589+
):
590+
posix.sysconf("SC_garbage")
591+
592+
with self.assertRaisesRegex(
593+
TypeError, "configuration names must be strings or integers"
594+
):
595+
posix.sysconf(1.23)
596+
597+
open_max = posix.sysconf("SC_OPEN_MAX")
598+
self.assertGreater(open_max, 0)
599+
self.assertEqual(
600+
posix.sysconf(posix.sysconf_names["SC_OPEN_MAX"]), open_max)
573601

574602
@unittest.skipUnless(hasattr(posix, 'dup2'),
575603
'test needs posix.dup2()')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed intermittent failures of :any:`os.confstr`, :any:`os.pathconf` and
2+
:any:`os.sysconf` on iOS and Android.

Modules/clinic/posixmodule.c.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/posixmodule.c

Lines changed: 26 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -13535,46 +13535,33 @@ struct constdef {
1353513535
};
1353613536

1353713537
static int
13538-
conv_confname(PyObject *arg, int *valuep, struct constdef *table,
13539-
size_t tablesize)
13540-
{
13541-
if (PyLong_Check(arg)) {
13542-
int value = PyLong_AsInt(arg);
13543-
if (value == -1 && PyErr_Occurred())
13544-
return 0;
13545-
*valuep = value;
13546-
return 1;
13547-
}
13548-
else {
13549-
/* look up the value in the table using a binary search */
13550-
size_t lo = 0;
13551-
size_t mid;
13552-
size_t hi = tablesize;
13553-
int cmp;
13554-
const char *confname;
13555-
if (!PyUnicode_Check(arg)) {
13556-
PyErr_SetString(PyExc_TypeError,
13557-
"configuration names must be strings or integers");
13558-
return 0;
13559-
}
13560-
confname = PyUnicode_AsUTF8(arg);
13561-
if (confname == NULL)
13562-
return 0;
13563-
while (lo < hi) {
13564-
mid = (lo + hi) / 2;
13565-
cmp = strcmp(confname, table[mid].name);
13566-
if (cmp < 0)
13567-
hi = mid;
13568-
else if (cmp > 0)
13569-
lo = mid + 1;
13570-
else {
13571-
*valuep = table[mid].value;
13572-
return 1;
13538+
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
13539+
{
13540+
if (PyUnicode_Check(arg)) {
13541+
PyObject *table = PyObject_GetAttrString(module, tablename);
13542+
if (table != NULL) {
13543+
arg = PyObject_GetItem(table, arg);
13544+
if (arg == NULL) {
13545+
PyErr_SetString(
13546+
PyExc_ValueError, "unrecognized configuration name");
1357313547
}
13548+
Py_DECREF(table);
1357413549
}
13575-
PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
13576-
return 0;
13550+
if (PyErr_Occurred())
13551+
return 0;
13552+
} else {
13553+
Py_INCREF(arg);
13554+
}
13555+
13556+
if (PyLong_Check(arg)) {
13557+
*valuep = PyLong_AsInt(arg);
13558+
} else {
13559+
PyErr_SetString(PyExc_TypeError,
13560+
"configuration names must be strings or integers");
1357713561
}
13562+
13563+
Py_DECREF(arg);
13564+
return !PyErr_Occurred();
1357813565
}
1357913566

1358013567

@@ -13665,14 +13652,6 @@ static struct constdef posix_constants_pathconf[] = {
1366513652
{"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
1366613653
#endif
1366713654
};
13668-
13669-
static int
13670-
conv_path_confname(PyObject *arg, int *valuep)
13671-
{
13672-
return conv_confname(arg, valuep, posix_constants_pathconf,
13673-
sizeof(posix_constants_pathconf)
13674-
/ sizeof(struct constdef));
13675-
}
1367613655
#endif
1367713656

1367813657

@@ -13897,14 +13876,6 @@ static struct constdef posix_constants_confstr[] = {
1389713876
#endif
1389813877
};
1389913878

13900-
static int
13901-
conv_confstr_confname(PyObject *arg, int *valuep)
13902-
{
13903-
return conv_confname(arg, valuep, posix_constants_confstr,
13904-
sizeof(posix_constants_confstr)
13905-
/ sizeof(struct constdef));
13906-
}
13907-
1390813879

1390913880
/*[clinic input]
1391013881
os.confstr
@@ -14454,14 +14425,6 @@ static struct constdef posix_constants_sysconf[] = {
1445414425
#endif
1445514426
};
1445614427

14457-
static int
14458-
conv_sysconf_confname(PyObject *arg, int *valuep)
14459-
{
14460-
return conv_confname(arg, valuep, posix_constants_sysconf,
14461-
sizeof(posix_constants_sysconf)
14462-
/ sizeof(struct constdef));
14463-
}
14464-
1446514428

1446614429
/*[clinic input]
1446714430
os.sysconf -> long
@@ -14486,40 +14449,15 @@ os_sysconf_impl(PyObject *module, int name)
1448614449
#endif /* HAVE_SYSCONF */
1448714450

1448814451

14489-
/* This code is used to ensure that the tables of configuration value names
14490-
* are in sorted order as required by conv_confname(), and also to build
14491-
* the exported dictionaries that are used to publish information about the
14492-
* names available on the host platform.
14493-
*
14494-
* Sorting the table at runtime ensures that the table is properly ordered
14495-
* when used, even for platforms we're not able to test on. It also makes
14496-
* it easier to add additional entries to the tables.
14497-
*/
14498-
14499-
static int
14500-
cmp_constdefs(const void *v1, const void *v2)
14501-
{
14502-
const struct constdef *c1 =
14503-
(const struct constdef *) v1;
14504-
const struct constdef *c2 =
14505-
(const struct constdef *) v2;
14506-
14507-
return strcmp(c1->name, c2->name);
14508-
}
14509-
1451014452
static int
1451114453
setup_confname_table(struct constdef *table, size_t tablesize,
1451214454
const char *tablename, PyObject *module)
1451314455
{
14514-
PyObject *d = NULL;
14515-
size_t i;
14516-
14517-
qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
14518-
d = PyDict_New();
14456+
PyObject *d = PyDict_New();
1451914457
if (d == NULL)
1452014458
return -1;
1452114459

14522-
for (i=0; i < tablesize; ++i) {
14460+
for (size_t i=0; i < tablesize; ++i) {
1452314461
PyObject *o = PyLong_FromLong(table[i].value);
1452414462
if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
1452514463
Py_XDECREF(o);

0 commit comments

Comments
 (0)