mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	gh-118201: Simplify conv_confname (#126089)
This commit is contained in:
		
							parent
							
								
									5fcc3a4cee
								
							
						
					
					
						commit
						c5c9286804
					
				
					 6 changed files with 89 additions and 113 deletions
				
			
		|  | @ -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 @@ def test_fchown(self): | ||||||
|         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 @@ def test_dup(self): | ||||||
| 
 | 
 | ||||||
|     @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. | ||||||
							
								
								
									
										10
									
								
								Modules/clinic/posixmodule.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								Modules/clinic/posixmodule.c.h
									
										
									
										generated
									
									
									
								
							|  | @ -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)) { | ||||||
|         int value = PyLong_AsInt(arg); |         PyObject *table = PyObject_GetAttrString(module, tablename); | ||||||
|         if (value == -1 && PyErr_Occurred()) |         if (table == NULL) { | ||||||
|             return 0; |             return 0; | ||||||
|         *valuep = value; |  | ||||||
|         return 1; |  | ||||||
|         } |         } | ||||||
|     else { | 
 | ||||||
|         /* look up the value in the table using a binary search */ |         arg = PyObject_GetItem(table, arg); | ||||||
|         size_t lo = 0; |         Py_DECREF(table); | ||||||
|         size_t mid; |         if (arg == NULL) { | ||||||
|         size_t hi = tablesize; |             PyErr_SetString( | ||||||
|         int cmp; |                 PyExc_ValueError, "unrecognized configuration name"); | ||||||
|         const char *confname; |             return 0; | ||||||
|         if (!PyUnicode_Check(arg)) { |         } | ||||||
|  |     } else { | ||||||
|  |         Py_INCREF(arg);  // Match the Py_DECREF below.
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int success = 0; | ||||||
|  |     if (!PyLong_Check(arg)) { | ||||||
|         PyErr_SetString(PyExc_TypeError, |         PyErr_SetString(PyExc_TypeError, | ||||||
|             "configuration names must be strings or integers"); |             "configuration names must be strings or integers"); | ||||||
|             return 0; |     } else { | ||||||
|         } |         int value = PyLong_AsInt(arg); | ||||||
|         confname = PyUnicode_AsUTF8(arg); |         if (!(value == -1 && PyErr_Occurred())) { | ||||||
|         if (confname == NULL) |             *valuep = value; | ||||||
|             return 0; |             success = 1; | ||||||
|         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"); |     Py_DECREF(arg); | ||||||
|         return 0; |     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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Malcolm Smith
						Malcolm Smith