8000 gh-118201: Simplify conv_confname (#126089) · python/cpython@c5c9286 · GitHub
[go: up one dir, main page]

Skip to content

Commit c5c9286

Browse files
authored
gh-118201: Simplify conv_confname (#126089)
1 parent 5fcc3a4 commit c5c9286

File tree

6 files changed

+87
-111
lines changed

6 files changed

+87
-111
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
@@ -568,10 +568,38 @@ def test_dup(self):
568568

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

576604
@unittest.skipUnless(hasattr(posix, 'dup2'),
577605
'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: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/posixmodule.c

Lines changed: 47 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -3113,18 +3113,22 @@ class Py_off_t_return_converter(long_return_converter):
31133113
type = 'Py_off_t'
31143114
conversion_fn = 'PyLong_FromPy_off_t'
31153115
3116-
class path_confname_converter(CConverter):
3116+
class confname_converter(CConverter):
31173117
type="int"
3118-
converter="conv_path_confname"
3118+
converter="conv_confname"
31193119
3120-
class confstr_confname_converter(path_confname_converter):
3121-
converter='conv_confstr_confname'
3120+
def converter_init(self, *, table):
3121+
self.table = table
31223122
3123-
class sysconf_confname_converter(path_confname_converter):
3124-
converter="conv_sysconf_confname"
3123+
def parse_arg(self, argname, displayname, *, limited_capi):
3124+
return self.format_code("""
3125+
if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3126+
goto exit;
3127+
}}}}
3128+
""", argname=argname, converter=self.converter, table=self.table)
31253129
31263130
[python start generated code]*/
3127-
/*[python end generated code: output=da39a3ee5e6b4b0d input=1860d32584c2a539]*/
3131+
/*[python end generated code: output=da39a3ee5e6b4b0d input=8189d5ae78244626]*/
31283132

31293133
/*[clinic input]
31303134
@@ -13547,46 +13551,38 @@ struct constdef {
1354713551
};
1354813552

1354913553
static int
13550-
conv_confname(PyObject *arg, int *valuep, struct constdef *table,
13551-
size_t tablesize)
13554+
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
1355213555
{
13553-
if (PyLong_Check(arg)) {
13554-
int value = PyLong_AsInt(arg);
13555-
if (value == -1 && PyErr_Occurred())
13556-
return 0;
13557-
*valuep = value;
13558-
return 1;
13559-
}
13560-
else {
13561-
/* look up the value in the table using a binary search */
13562-
size_t lo = 0;
13563-
size_t mid;
13564-
size_t hi = tablesize;
13565-
int cmp;
13566-
const char *confname;
13567-
if (!PyUnicode_Check(arg)) {
13568-
PyErr_SetString(PyExc_TypeError,
13569-
"config 10000 uration names must be strings or integers");
13556+
if (PyUnicode_Check(arg)) {
13557+
PyObject *table = PyObject_GetAttrString(module, tablename);
13558+
if (table == NULL) {
1357013559
return 0;
1357113560
}
13572-
confname = PyUnicode_AsUTF8(arg);
13573-
if (confname == NULL)
13561+
13562+
arg = PyObject_GetItem(table, arg);
13563+
Py_DECREF(table);
13564+
if (arg == NULL) {
13565+
PyErr_SetString(
13566+
PyExc_ValueError, "unrecognized configuration name");
1357413567
return 0;
13575-
while (lo < hi) {
13576-
mid = (lo + hi) / 2;
13577-
cmp = strcmp(confname, table[mid].name);
13578-
if (cmp < 0)
13579-
hi = mid;
13580-
else if (cmp > 0)
13581-
lo = mid + 1;
13582-
else {
13583-
*valuep = table[mid].value;
13584-
return 1;
13585-
}
1358613568
}
13587-
PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
13588-
return 0;
13569+
} else {
13570+
Py_INCREF(arg); // Match the Py_DECREF below.
1358913571
}
13572+
13573+
int success = 0;
13574+
if (!PyLong_Check(arg)) {
13575+
PyErr_SetString(PyExc_TypeError,
13576+
"configuration names must be strings or integers");
13577+
} else {
13578+
int value = PyLong_AsInt(arg);
13579+
if (!(value == -1 && PyErr_Occurred())) {
13580+
*valuep = value;
13581+
success = 1;
13582+
}
13583+
}
13584+
Py_DECREF(arg);
13585+
return success;
1359013586
}
1359113587

1359213588

@@ -13677,14 +13673,6 @@ static struct constdef posix_constants_pathconf[] = {
1367713673
{"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
1367813674
#endif
1367913675
};
13680-
13681-
static int
13682-
conv_path_confname(PyObject *arg, int *valuep)
13683-
{
13684-
return conv_confname(arg, valuep, posix_constants_pathconf,
13685-
sizeof(posix_constants_pathconf)
13686-
/ sizeof(struct constdef));
13687-
}
1368813676
#endif
1368913677

1369013678

@@ -13693,7 +13681,7 @@ conv_path_confname(PyObject *arg, int *valuep)
1369313681
os.fpathconf -> long
1369413682
1369513683
fd: fildes
13696-
name: path_confname
13684+
name: confname(table="pathconf_names")
1369713685
/
1369813686
1369913687
Return the configuration limit name for the file descriptor fd.
@@ -13703,7 +13691,7 @@ If there is no limit, return -1.
1370313691

1370413692
static long
1370513693
os_fpathconf_impl(PyObject *module, int fd, int name)
13706-
/*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
13694+
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
1370713695
{
1370813696
long limit;
1370913697

@@ -13721,7 +13709,7 @@ os_fpathconf_impl(PyObject *module, int fd, int name)
1372113709
/*[clinic input]
1372213710
os.pathconf -> long
1372313711
path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
13724-
name: path_confname
13712+
name: confname(table="pathconf_names")
1372513713
1372613714
Return the configuration limit name for the file or directory path.
1372713715
@@ -13732,7 +13720,7 @@ On some platforms, path may also be specified as an open file descriptor.
1373213720

1373313721
static long
1373413722
os_pathconf_impl(PyObject *module, path_t *path, int name)
13735-
/*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
13723+
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
1373613724
{
1373713725
long limit;
1373813726

@@ -13909,27 +13897,19 @@ static struct constdef posix_constants_confstr[] = {
1390913897
#endif
1391013898
};
1391113899

13912-
static int
13913-
conv_confstr_confname(PyObject *arg, int *valuep)
13914-
{
13915-
return conv_confname(arg, valuep, posix_constants_confstr,
13916-
sizeof(posix_constants_confstr)
13917-
/ sizeof(struct constdef));
13918-
}
13919-
1392013900

1392113901
/*[clinic input]
1392213902
os.confstr
1392313903
13924-
name: confstr_confname
13904+
name: confname(table="confstr_names")
1392513905
/
1392613906
1392713907
Return a string-valued system configuration variable.
1392813908
[clinic start generated code]*/
1392913909

1393013910
static PyObject *
1393113911
os_confstr_impl(PyObject *module, int name)
13932-
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
13912+
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
1393313913
{
1393413914
PyObject *result = NULL;
1393513915
char buffer[255];
@@ -14466,26 +14446,18 @@ static struct constdef posix_constants_sysconf[] = {
1446614446
#endif
1446714447
};
1446814448

14469-
static int
14470-
conv_sysconf_confname(PyObject *arg, int *valuep)
14471-
{
14472-
return conv_confname(arg, valuep, posix_constants_sysconf,
14473-
sizeof(posix_constants_sysconf)
14474-
/ sizeof(struct constdef));
14475-
}
14476-
1447714449

1447814450
/*[clinic input]
1447914451
os.sysconf -> long
14480-
name: sysconf_confname
14452+
name: confname(table="sysconf_names")
1448114453
/
1448214454
1448314455
Return an integer-valued system configuration variable.
1448414456
[clinic start generated code]*/
1448514457

1448614458
static long
1448714459
os_sysconf_impl(PyObject *module, int name)
14488-
/*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
14460+
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
1448914461
{
1449014462
long value;
1449114463

@@ -14498,40 +14470,15 @@ os_sysconf_impl(PyObject *module, int name)
1449814470
#endif /* HAVE_SYSCONF */
1449914471

1450014472

14501-
/* This code is used to ensure that the tables of configuration value names
14502-
* are in sorted order as required by conv_confname(), and also to build
14503-
* the exported dictionaries that are used to publish information about the
14504-
* names available on the host platform.
14505-
*
14506-
* Sorting the table at runtime ensures that the table is properly ordered
14507-
* when used, even for platforms we're not able to test on. It also makes
14508-
* it easier to add additional entries to the tables.
14509-
*/
14510-
14511-
static int
14512-
cmp_constdefs(const void *v1, const void *v2)
14513-
{
14514-
const struct constdef *c1 =
14515-
(const struct constdef *) v1;
14516-
const struct constdef *c2 =
14517-
(const struct constdef *) v2;
14518-
14519-
return strcmp(c1->name, c2->name);
14520-
}
14521-
1452214473
static int
1452314474
setup_confname_table(struct constdef *table, size_t tablesize,
1452414475
const char *tablename, PyObject *module)
1452514476
{
14526-
PyObject *d = NULL;
14527-
size_t i;
14528-
14529-
qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
14530-
d = PyDict_New();
14477+
PyObject *d = PyDict_New();
1453114478
if (d == NULL)
1453214479
return -1;
1453314480

14534-
for (i=0; i < tablesize; ++i) {
14481+
for (size_t i=0; i < tablesize; ++i) {
1453514482
PyObject *o = PyLong_FromLong(table[i].value);
1453614483
if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
1453714484
Py_XDECREF(o);

0 commit comments

Comments
 (0)
0