mirror of https://github.com/python/cpython
gh-118201: Simplify conv_confname (#126089)
This commit is contained in:
parent
5fcc3a4cee
commit
c5c9286804
|
@ -632,8 +632,7 @@ def fd_count():
|
||||||
if hasattr(os, 'sysconf'):
|
if hasattr(os, 'sysconf'):
|
||||||
try:
|
try:
|
||||||
MAXFD = os.sysconf("SC_OPEN_MAX")
|
MAXFD = os.sysconf("SC_OPEN_MAX")
|
||||||
except (OSError, ValueError):
|
except OSError:
|
||||||
# gh-118201: ValueError is raised intermittently on iOS
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
old_modes = None
|
old_modes = None
|
||||||
|
|
|
@ -2447,8 +2447,8 @@ class TestInvalidFD(unittest.TestCase):
|
||||||
support.is_emscripten or support.is_wasi,
|
support.is_emscripten or support.is_wasi,
|
||||||
"musl libc issue on Emscripten/WASI, bpo-46390"
|
"musl libc issue on Emscripten/WASI, bpo-46390"
|
||||||
)
|
)
|
||||||
@unittest.skipIf(support.is_apple_mobile, "gh-118201: Test is flaky on iOS")
|
|
||||||
def test_fpathconf(self):
|
def test_fpathconf(self):
|
||||||
|
self.assertIn("PC_NAME_MAX", os.pathconf_names)
|
||||||
self.check(os.pathconf, "PC_NAME_MAX")
|
self.check(os.pathconf, "PC_NAME_MAX")
|
||||||
self.check(os.fpathconf, "PC_NAME_MAX")
|
self.check(os.fpathconf, "PC_NAME_MAX")
|
||||||
self.check_bool(os.pathconf, "PC_NAME_MAX")
|
self.check_bool(os.pathconf, "PC_NAME_MAX")
|
||||||
|
|
|
@ -568,10 +568,38 @@ class PosixTester(unittest.TestCase):
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(posix, 'confstr'),
|
@unittest.skipUnless(hasattr(posix, 'confstr'),
|
||||||
'test needs posix.confstr()')
|
'test needs posix.confstr()')
|
||||||
@unittest.skipIf(support.is_apple_mobile, "gh-118201: Test is flaky on iOS")
|
|
||||||
def test_confstr(self):
|
def test_confstr(self):
|
||||||
self.assertRaises(ValueError, posix.confstr, "CS_garbage")
|
with self.assertRaisesRegex(
|
||||||
self.assertEqual(len(posix.confstr("CS_PATH")) > 0, True)
|
ValueError, "unrecognized configuration name"
|
||||||
|
):
|
||||||
|
posix.confstr("CS_garbage")
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
TypeError, "configuration names must be strings or integers"
|
||||||
|
):
|
||||||
|
posix.confstr(1.23)
|
||||||
|
|
||||||
|
path = posix.confstr("CS_PATH")
|
||||||
|
self.assertGreater(len(path), 0)
|
||||||
|
self.assertEqual(posix.confstr(posix.confstr_names["CS_PATH"]), path)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(posix, 'sysconf'),
|
||||||
|
'test needs posix.sysconf()')
|
||||||
|
def test_sysconf(self):
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
ValueError, "unrecognized configuration name"
|
||||||
|
):
|
||||||
|
posix.sysconf("SC_garbage")
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
TypeError, "configuration names must be strings or integers"
|
||||||
|
):
|
||||||
|
posix.sysconf(1.23)
|
||||||
|
|
||||||
|
arg_max = posix.sysconf("SC_ARG_MAX")
|
||||||
|
self.assertGreater(arg_max, 0)
|
||||||
|
self.assertEqual(
|
||||||
|
posix.sysconf(posix.sysconf_names["SC_ARG_MAX"]), arg_max)
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(posix, 'dup2'),
|
@unittest.skipUnless(hasattr(posix, 'dup2'),
|
||||||
'test needs posix.dup2()')
|
'test needs posix.dup2()')
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fixed intermittent failures of :any:`os.confstr`, :any:`os.pathconf` and
|
||||||
|
:any:`os.sysconf` on iOS and Android.
|
|
@ -10128,7 +10128,7 @@ os_fpathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (!conv_path_confname(args[1], &name)) {
|
if (!conv_confname(module, args[1], &name, "pathconf_names")) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
_return_value = os_fpathconf_impl(module, fd, name);
|
_return_value = os_fpathconf_impl(module, fd, name);
|
||||||
|
@ -10203,7 +10203,7 @@ os_pathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
|
||||||
if (!path_converter(args[0], &path)) {
|
if (!path_converter(args[0], &path)) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (!conv_path_confname(args[1], &name)) {
|
if (!conv_confname(module, args[1], &name, "pathconf_names")) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
_return_value = os_pathconf_impl(module, &path, name);
|
_return_value = os_pathconf_impl(module, &path, name);
|
||||||
|
@ -10241,7 +10241,7 @@ os_confstr(PyObject *module, PyObject *arg)
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
int name;
|
int name;
|
||||||
|
|
||||||
if (!conv_confstr_confname(arg, &name)) {
|
if (!conv_confname(module, arg, &name, "confstr_names")) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
return_value = os_confstr_impl(module, name);
|
return_value = os_confstr_impl(module, name);
|
||||||
|
@ -10273,7 +10273,7 @@ os_sysconf(PyObject *module, PyObject *arg)
|
||||||
int name;
|
int name;
|
||||||
long _return_value;
|
long _return_value;
|
||||||
|
|
||||||
if (!conv_sysconf_confname(arg, &name)) {
|
if (!conv_confname(module, arg, &name, "sysconf_names")) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
_return_value = os_sysconf_impl(module, name);
|
_return_value = os_sysconf_impl(module, name);
|
||||||
|
@ -13114,4 +13114,4 @@ os__create_environ(PyObject *module, PyObject *Py_UNUSED(ignored))
|
||||||
#ifndef OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
|
#ifndef OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
|
||||||
#define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
|
#define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
|
||||||
#endif /* !defined(OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF) */
|
#endif /* !defined(OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF) */
|
||||||
/*[clinic end generated code: output=5358a13b4ce6148b input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=7ee14f5e880092f5 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -3113,18 +3113,22 @@ class Py_off_t_return_converter(long_return_converter):
|
||||||
type = 'Py_off_t'
|
type = 'Py_off_t'
|
||||||
conversion_fn = 'PyLong_FromPy_off_t'
|
conversion_fn = 'PyLong_FromPy_off_t'
|
||||||
|
|
||||||
class path_confname_converter(CConverter):
|
class confname_converter(CConverter):
|
||||||
type="int"
|
type="int"
|
||||||
converter="conv_path_confname"
|
converter="conv_confname"
|
||||||
|
|
||||||
class confstr_confname_converter(path_confname_converter):
|
def converter_init(self, *, table):
|
||||||
converter='conv_confstr_confname'
|
self.table = table
|
||||||
|
|
||||||
class sysconf_confname_converter(path_confname_converter):
|
def parse_arg(self, argname, displayname, *, limited_capi):
|
||||||
converter="conv_sysconf_confname"
|
return self.format_code("""
|
||||||
|
if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
|
||||||
|
goto exit;
|
||||||
|
}}}}
|
||||||
|
""", argname=argname, converter=self.converter, table=self.table)
|
||||||
|
|
||||||
[python start generated code]*/
|
[python start generated code]*/
|
||||||
/*[python end generated code: output=da39a3ee5e6b4b0d input=1860d32584c2a539]*/
|
/*[python end generated code: output=da39a3ee5e6b4b0d input=8189d5ae78244626]*/
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
|
||||||
|
@ -13547,46 +13551,38 @@ struct constdef {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
conv_confname(PyObject *arg, int *valuep, struct constdef *table,
|
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
|
||||||
size_t tablesize)
|
|
||||||
{
|
{
|
||||||
if (PyLong_Check(arg)) {
|
if (PyUnicode_Check(arg)) {
|
||||||
|
PyObject *table = PyObject_GetAttrString(module, tablename);
|
||||||
|
if (table == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = PyObject_GetItem(table, arg);
|
||||||
|
Py_DECREF(table);
|
||||||
|
if (arg == NULL) {
|
||||||
|
PyErr_SetString(
|
||||||
|
PyExc_ValueError, "unrecognized configuration name");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Py_INCREF(arg); // Match the Py_DECREF below.
|
||||||
|
}
|
||||||
|
|
||||||
|
int success = 0;
|
||||||
|
if (!PyLong_Check(arg)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"configuration names must be strings or integers");
|
||||||
|
} else {
|
||||||
int value = PyLong_AsInt(arg);
|
int value = PyLong_AsInt(arg);
|
||||||
if (value == -1 && PyErr_Occurred())
|
if (!(value == -1 && PyErr_Occurred())) {
|
||||||
return 0;
|
*valuep = value;
|
||||||
*valuep = value;
|
success = 1;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* look up the value in the table using a binary search */
|
|
||||||
size_t lo = 0;
|
|
||||||
size_t mid;
|
|
||||||
size_t hi = tablesize;
|
|
||||||
int cmp;
|
|
||||||
const char *confname;
|
|
||||||
if (!PyUnicode_Check(arg)) {
|
|
||||||
PyErr_SetString(PyExc_TypeError,
|
|
||||||
"configuration names must be strings or integers");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
confname = PyUnicode_AsUTF8(arg);
|
|
||||||
if (confname == NULL)
|
|
||||||
return 0;
|
|
||||||
while (lo < hi) {
|
|
||||||
mid = (lo + hi) / 2;
|
|
||||||
cmp = strcmp(confname, table[mid].name);
|
|
||||||
if (cmp < 0)
|
|
||||||
hi = mid;
|
|
||||||
else if (cmp > 0)
|
|
||||||
lo = mid + 1;
|
|
||||||
else {
|
|
||||||
*valuep = table[mid].value;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
Py_DECREF(arg);
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -13677,14 +13673,6 @@ static struct constdef posix_constants_pathconf[] = {
|
||||||
{"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
|
{"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
|
||||||
conv_path_confname(PyObject *arg, int *valuep)
|
|
||||||
{
|
|
||||||
return conv_confname(arg, valuep, posix_constants_pathconf,
|
|
||||||
sizeof(posix_constants_pathconf)
|
|
||||||
/ sizeof(struct constdef));
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -13693,7 +13681,7 @@ conv_path_confname(PyObject *arg, int *valuep)
|
||||||
os.fpathconf -> long
|
os.fpathconf -> long
|
||||||
|
|
||||||
fd: fildes
|
fd: fildes
|
||||||
name: path_confname
|
name: confname(table="pathconf_names")
|
||||||
/
|
/
|
||||||
|
|
||||||
Return the configuration limit name for the file descriptor fd.
|
Return the configuration limit name for the file descriptor fd.
|
||||||
|
@ -13703,7 +13691,7 @@ If there is no limit, return -1.
|
||||||
|
|
||||||
static long
|
static long
|
||||||
os_fpathconf_impl(PyObject *module, int fd, int name)
|
os_fpathconf_impl(PyObject *module, int fd, int name)
|
||||||
/*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
|
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
|
||||||
{
|
{
|
||||||
long limit;
|
long limit;
|
||||||
|
|
||||||
|
@ -13721,7 +13709,7 @@ os_fpathconf_impl(PyObject *module, int fd, int name)
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
os.pathconf -> long
|
os.pathconf -> long
|
||||||
path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
|
path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
|
||||||
name: path_confname
|
name: confname(table="pathconf_names")
|
||||||
|
|
||||||
Return the configuration limit name for the file or directory path.
|
Return the configuration limit name for the file or directory path.
|
||||||
|
|
||||||
|
@ -13732,7 +13720,7 @@ On some platforms, path may also be specified as an open file descriptor.
|
||||||
|
|
||||||
static long
|
static long
|
||||||
os_pathconf_impl(PyObject *module, path_t *path, int name)
|
os_pathconf_impl(PyObject *module, path_t *path, int name)
|
||||||
/*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
|
/*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/
|
||||||
{
|
{
|
||||||
long limit;
|
long limit;
|
||||||
|
|
||||||
|
@ -13909,19 +13897,11 @@ static struct constdef posix_constants_confstr[] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
|
||||||
conv_confstr_confname(PyObject *arg, int *valuep)
|
|
||||||
{
|
|
||||||
return conv_confname(arg, valuep, posix_constants_confstr,
|
|
||||||
sizeof(posix_constants_confstr)
|
|
||||||
/ sizeof(struct constdef));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
os.confstr
|
os.confstr
|
||||||
|
|
||||||
name: confstr_confname
|
name: confname(table="confstr_names")
|
||||||
/
|
/
|
||||||
|
|
||||||
Return a string-valued system configuration variable.
|
Return a string-valued system configuration variable.
|
||||||
|
@ -13929,7 +13909,7 @@ Return a string-valued system configuration variable.
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
os_confstr_impl(PyObject *module, int name)
|
os_confstr_impl(PyObject *module, int name)
|
||||||
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
|
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
|
||||||
{
|
{
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
char buffer[255];
|
char buffer[255];
|
||||||
|
@ -14466,18 +14446,10 @@ static struct constdef posix_constants_sysconf[] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
|
||||||
conv_sysconf_confname(PyObject *arg, int *valuep)
|
|
||||||
{
|
|
||||||
return conv_confname(arg, valuep, posix_constants_sysconf,
|
|
||||||
sizeof(posix_constants_sysconf)
|
|
||||||
/ sizeof(struct constdef));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
os.sysconf -> long
|
os.sysconf -> long
|
||||||
name: sysconf_confname
|
name: confname(table="sysconf_names")
|
||||||
/
|
/
|
||||||
|
|
||||||
Return an integer-valued system configuration variable.
|
Return an integer-valued system configuration variable.
|
||||||
|
@ -14485,7 +14457,7 @@ Return an integer-valued system configuration variable.
|
||||||
|
|
||||||
static long
|
static long
|
||||||
os_sysconf_impl(PyObject *module, int name)
|
os_sysconf_impl(PyObject *module, int name)
|
||||||
/*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
|
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
|
||||||
{
|
{
|
||||||
long value;
|
long value;
|
||||||
|
|
||||||
|
@ -14498,40 +14470,15 @@ os_sysconf_impl(PyObject *module, int name)
|
||||||
#endif /* HAVE_SYSCONF */
|
#endif /* HAVE_SYSCONF */
|
||||||
|
|
||||||
|
|
||||||
/* This code is used to ensure that the tables of configuration value names
|
|
||||||
* are in sorted order as required by conv_confname(), and also to build
|
|
||||||
* the exported dictionaries that are used to publish information about the
|
|
||||||
* names available on the host platform.
|
|
||||||
*
|
|
||||||
* Sorting the table at runtime ensures that the table is properly ordered
|
|
||||||
* when used, even for platforms we're not able to test on. It also makes
|
|
||||||
* it easier to add additional entries to the tables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
cmp_constdefs(const void *v1, const void *v2)
|
|
||||||
{
|
|
||||||
const struct constdef *c1 =
|
|
||||||
(const struct constdef *) v1;
|
|
||||||
const struct constdef *c2 =
|
|
||||||
(const struct constdef *) v2;
|
|
||||||
|
|
||||||
return strcmp(c1->name, c2->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
setup_confname_table(struct constdef *table, size_t tablesize,
|
setup_confname_table(struct constdef *table, size_t tablesize,
|
||||||
const char *tablename, PyObject *module)
|
const char *tablename, PyObject *module)
|
||||||
{
|
{
|
||||||
PyObject *d = NULL;
|
PyObject *d = PyDict_New();
|
||||||
size_t i;
|
|
||||||
|
|
||||||
qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
|
|
||||||
d = PyDict_New();
|
|
||||||
if (d == NULL)
|
if (d == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (i=0; i < tablesize; ++i) {
|
for (size_t i=0; i < tablesize; ++i) {
|
||||||
PyObject *o = PyLong_FromLong(table[i].value);
|
PyObject *o = PyLong_FromLong(table[i].value);
|
||||||
if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
|
if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
|
||||||
Py_XDECREF(o);
|
Py_XDECREF(o);
|
||||||
|
|
Loading…
Reference in New Issue