diff --git a/Doc/glossary.rst b/Doc/glossary.rst index f93fc72d361d66..dad745348f9b4b 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -1219,8 +1219,8 @@ Glossary attribute, or a function parameter or return value. Type hints are optional and are not enforced by Python but - they are useful to :term:`static type checkers `, - and aid IDEs with code completion and refactoring. + they are useful to :term:`static type checkers `. + They can also aid IDEs with code completion and refactoring. Type hints of global variables, class attributes, and functions, but not local variables, can be accessed using diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst index 6c30a0dd7d6bcc..501b16d82d4d6f 100644 --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -39,7 +39,8 @@ are: #. Once your dependencies are no longer blocking you, use continuous integration to make sure you stay compatible with Python 2 and 3 (tox_ can help test against multiple versions of Python; ``python -m pip install tox``) -#. Consider using optional static type checking to make sure your type usage +#. Consider using optional :term:`static type checking ` + to make sure your type usage works in both Python 2 and 3 (e.g. use mypy_ to check your typing under both Python 2 and Python 3; ``python -m pip install mypy``). @@ -395,7 +396,7 @@ comparisons occur, making the mistake much easier to track down. Consider using optional static type checking -------------------------------------------- -Another way to help port your code is to use a static type checker like +Another way to help port your code is to use a :term:`static type checker` like mypy_ or pytype_ on your code. These tools can be used to analyze your code as if it's being run under Python 2, then you can run the tool a second time as if your code is running under Python 3. By running a static type checker twice like diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 0b9d42f32e3bd6..1bab1fb9bd9464 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -38,7 +38,8 @@ on efficient attribute extraction for output formatting and manipulation. Third-party library with expanded time zone and parsing support. Package `DateType `_ - Third-party library that introduces distinct static types to e.g. allow static type checkers + Third-party library that introduces distinct static types to e.g. allow + :term:`static type checkers ` to differentiate between naive and aware datetimes. .. _datetime-naive-aware: diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index a4767d222d0af7..ba2845eb17ddcc 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -18,8 +18,8 @@ .. note:: The Python runtime does not enforce function and variable type annotations. - They can be used by third party tools such as type checkers, IDEs, linters, - etc. + They can be used by third party tools such as :term:`type checkers `, + IDEs, linters, etc. -------------- diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 5cfe8b1d00325a..bd5a401adf11bf 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -81,15 +81,15 @@ #define _FOR_ITER 353 #define _ITER_CHECK_LIST 354 #define _ITER_JUMP_LIST 355 -#define _IS_ITER_EXHAUSTED_LIST 356 +#define _GUARD_NOT_EXHAUSTED_LIST 356 #define _ITER_NEXT_LIST 357 #define _ITER_CHECK_TUPLE 358 #define _ITER_JUMP_TUPLE 359 -#define _IS_ITER_EXHAUSTED_TUPLE 360 +#define _GUARD_NOT_EXHAUSTED_TUPLE 360 #define _ITER_NEXT_TUPLE 361 #define _ITER_CHECK_RANGE 362 #define _ITER_JUMP_RANGE 363 -#define _IS_ITER_EXHAUSTED_RANGE 364 +#define _GUARD_NOT_EXHAUSTED_RANGE 364 #define _ITER_NEXT_RANGE 365 #define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 366 #define _GUARD_KEYS_VERSION 367 @@ -542,7 +542,7 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 1; case _ITER_JUMP_LIST: return 1; - case _IS_ITER_EXHAUSTED_LIST: + case _GUARD_NOT_EXHAUSTED_LIST: return 1; case _ITER_NEXT_LIST: return 1; @@ -552,7 +552,7 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 1; case _ITER_JUMP_TUPLE: return 1; - case _IS_ITER_EXHAUSTED_TUPLE: + case _GUARD_NOT_EXHAUSTED_TUPLE: return 1; case _ITER_NEXT_TUPLE: return 1; @@ -562,7 +562,7 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 1; case _ITER_JUMP_RANGE: return 1; - case _IS_ITER_EXHAUSTED_RANGE: + case _GUARD_NOT_EXHAUSTED_RANGE: return 1; case _ITER_NEXT_RANGE: return 1; @@ -1170,8 +1170,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 1; case _ITER_JUMP_LIST: return 1; - case _IS_ITER_EXHAUSTED_LIST: - return 2; + case _GUARD_NOT_EXHAUSTED_LIST: + return 1; case _ITER_NEXT_LIST: return 2; case FOR_ITER_LIST: @@ -1180,8 +1180,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 1; case _ITER_JUMP_TUPLE: return 1; - case _IS_ITER_EXHAUSTED_TUPLE: - return 2; + case _GUARD_NOT_EXHAUSTED_TUPLE: + return 1; case _ITER_NEXT_TUPLE: return 2; case FOR_ITER_TUPLE: @@ -1190,8 +1190,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 1; case _ITER_JUMP_RANGE: return 1; - case _IS_ITER_EXHAUSTED_RANGE: - return 2; + case _GUARD_NOT_EXHAUSTED_RANGE: + return 1; case _ITER_NEXT_RANGE: return 2; case FOR_ITER_RANGE: @@ -1651,17 +1651,17 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG }, [_ITER_CHECK_LIST] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [_ITER_JUMP_LIST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [_IS_ITER_EXHAUSTED_LIST] = { true, INSTR_FMT_IX, 0 }, + [_GUARD_NOT_EXHAUSTED_LIST] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [_ITER_NEXT_LIST] = { true, INSTR_FMT_IX, 0 }, [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG }, [_ITER_CHECK_TUPLE] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [_ITER_JUMP_TUPLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [_IS_ITER_EXHAUSTED_TUPLE] = { true, INSTR_FMT_IX, 0 }, + [_GUARD_NOT_EXHAUSTED_TUPLE] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [_ITER_NEXT_TUPLE] = { true, INSTR_FMT_IX, 0 }, [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG }, [_ITER_CHECK_RANGE] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [_ITER_JUMP_RANGE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [_IS_ITER_EXHAUSTED_RANGE] = { true, INSTR_FMT_IX, 0 }, + [_GUARD_NOT_EXHAUSTED_RANGE] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [_ITER_NEXT_RANGE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG }, [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, @@ -1870,6 +1870,9 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN [MATCH_KEYS] = { .nuops = 1, .uops = { { MATCH_KEYS, 0, 0 } } }, [GET_ITER] = { .nuops = 1, .uops = { { GET_ITER, 0, 0 } } }, [GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { GET_YIELD_FROM_ITER, 0, 0 } } }, + [FOR_ITER_LIST] = { .nuops = 3, .uops = { { _ITER_CHECK_LIST, 0, 0 }, { _ITER_JUMP_LIST, 0, 0 }, { _ITER_NEXT_LIST, 0, 0 } } }, + [FOR_ITER_TUPLE] = { .nuops = 3, .uops = { { _ITER_CHECK_TUPLE, 0, 0 }, { _ITER_JUMP_TUPLE, 0, 0 }, { _ITER_NEXT_TUPLE, 0, 0 } } }, + [FOR_ITER_RANGE] = { .nuops = 3, .uops = { { _ITER_CHECK_RANGE, 0, 0 }, { _ITER_JUMP_RANGE, 0, 0 }, { _ITER_NEXT_RANGE, 0, 0 } } }, [BEFORE_ASYNC_WITH] = { .nuops = 1, .uops = { { BEFORE_ASYNC_WITH, 0, 0 } } }, [BEFORE_WITH] = { .nuops = 1, .uops = { { BEFORE_WITH, 0, 0 } } }, [WITH_EXCEPT_START] = { .nuops = 1, .uops = { { WITH_EXCEPT_START, 0, 0 } } }, @@ -1966,15 +1969,15 @@ const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = { [_FOR_ITER] = "_FOR_ITER", [_ITER_CHECK_LIST] = "_ITER_CHECK_LIST", [_ITER_JUMP_LIST] = "_ITER_JUMP_LIST", - [_IS_ITER_EXHAUSTED_LIST] = "_IS_ITER_EXHAUSTED_LIST", + [_GUARD_NOT_EXHAUSTED_LIST] = "_GUARD_NOT_EXHAUSTED_LIST", [_ITER_NEXT_LIST] = "_ITER_NEXT_LIST", [_ITER_CHECK_TUPLE] = "_ITER_CHECK_TUPLE", [_ITER_JUMP_TUPLE] = "_ITER_JUMP_TUPLE", - [_IS_ITER_EXHAUSTED_TUPLE] = "_IS_ITER_EXHAUSTED_TUPLE", + [_GUARD_NOT_EXHAUSTED_TUPLE] = "_GUARD_NOT_EXHAUSTED_TUPLE", [_ITER_NEXT_TUPLE] = "_ITER_NEXT_TUPLE", [_ITER_CHECK_RANGE] = "_ITER_CHECK_RANGE", [_ITER_JUMP_RANGE] = "_ITER_JUMP_RANGE", - [_IS_ITER_EXHAUSTED_RANGE] = "_IS_ITER_EXHAUSTED_RANGE", + [_GUARD_NOT_EXHAUSTED_RANGE] = "_GUARD_NOT_EXHAUSTED_RANGE", [_ITER_NEXT_RANGE] = "_ITER_NEXT_RANGE", [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = "_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT", [_GUARD_KEYS_VERSION] = "_GUARD_KEYS_VERSION", diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 11dec031d3d79f..d526bbf62dda0b 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -2712,7 +2712,7 @@ def testfunc(n): # for i, (opname, oparg) in enumerate(ex): # print(f"{i:4d}: {opname:<20s} {oparg:3d}") uops = {opname for opname, _, _ in ex} - self.assertIn("_IS_ITER_EXHAUSTED_RANGE", uops) + self.assertIn("_GUARD_NOT_EXHAUSTED_RANGE", uops) # Verification that the jump goes past END_FOR # is done by manual inspection of the output @@ -2734,7 +2734,7 @@ def testfunc(a): # for i, (opname, oparg) in enumerate(ex): # print(f"{i:4d}: {opname:<20s} {oparg:3d}") uops = {opname for opname, _, _ in ex} - self.assertIn("_IS_ITER_EXHAUSTED_LIST", uops) + self.assertIn("_GUARD_NOT_EXHAUSTED_LIST", uops) # Verification that the jump goes past END_FOR # is done by manual inspection of the output @@ -2756,7 +2756,7 @@ def testfunc(a): # for i, (opname, oparg) in enumerate(ex): # print(f"{i:4d}: {opname:<20s} {oparg:3d}") uops = {opname for opname, _, _ in ex} - self.assertIn("_IS_ITER_EXHAUSTED_TUPLE", uops) + self.assertIn("_GUARD_NOT_EXHAUSTED_TUPLE", uops) # Verification that the jump goes past END_FOR # is done by manual inspection of the output diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py index 8f0a998e1f3dc1..9c325bc595f585 100644 --- a/Lib/test/test_type_aliases.py +++ b/Lib/test/test_type_aliases.py @@ -2,7 +2,7 @@ import types import unittest from test.support import check_syntax_error, run_code -from test import mod_generics_cache +from test.typinganndata import mod_generics_cache from typing import Callable, TypeAliasType, TypeVar, get_args diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 6ff79e8eeed9aa..1e812e1d525a81 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -45,8 +45,7 @@ import types from test.support import captured_stderr, cpython_only, infinite_recursion -from test import mod_generics_cache -from test import _typed_dict_helper +from test.typinganndata import mod_generics_cache, _typed_dict_helper CANNOT_SUBCLASS_TYPE = 'Cannot subclass special typing classes' diff --git a/Lib/test/_typed_dict_helper.py b/Lib/test/typinganndata/_typed_dict_helper.py similarity index 100% rename from Lib/test/_typed_dict_helper.py rename to Lib/test/typinganndata/_typed_dict_helper.py diff --git a/Lib/test/mod_generics_cache.py b/Lib/test/typinganndata/mod_generics_cache.py similarity index 100% rename from Lib/test/mod_generics_cache.py rename to Lib/test/typinganndata/mod_generics_cache.py diff --git a/Modules/clinic/socketmodule.c.h b/Modules/clinic/socketmodule.c.h index b6c74b1e9befd2..35019e7a167119 100644 --- a/Modules/clinic/socketmodule.c.h +++ b/Modules/clinic/socketmodule.c.h @@ -91,4 +91,167 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=c85517815c2d69cf input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_socket_socket_ntohs__doc__, +"ntohs($self, x, /)\n" +"--\n" +"\n" +"Convert a 16-bit unsigned integer from network to host byte order."); + +#define _SOCKET_SOCKET_NTOHS_METHODDEF \ + {"ntohs", (PyCFunction)_socket_socket_ntohs, METH_O, _socket_socket_ntohs__doc__}, + +static PyObject * +_socket_socket_ntohs_impl(PySocketSockObject *self, int x); + +static PyObject * +_socket_socket_ntohs(PySocketSockObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int x; + + x = PyLong_AsInt(arg); + if (x == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _socket_socket_ntohs_impl(self, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_socket_socket_htons__doc__, +"htons($self, x, /)\n" +"--\n" +"\n" +"Convert a 16-bit unsigned integer from host to network byte order."); + +#define _SOCKET_SOCKET_HTONS_METHODDEF \ + {"htons", (PyCFunction)_socket_socket_htons, METH_O, _socket_socket_htons__doc__}, + +static PyObject * +_socket_socket_htons_impl(PySocketSockObject *self, int x); + +static PyObject * +_socket_socket_htons(PySocketSockObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int x; + + x = PyLong_AsInt(arg); + if (x == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _socket_socket_htons_impl(self, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_socket_socket_inet_aton__doc__, +"inet_aton($self, ip_addr, /)\n" +"--\n" +"\n" +"Convert an IP address in string format (123.45.67.89) to the 32-bit packed binary format used in low-level network functions."); + +#define _SOCKET_SOCKET_INET_ATON_METHODDEF \ + {"inet_aton", (PyCFunction)_socket_socket_inet_aton, METH_O, _socket_socket_inet_aton__doc__}, + +static PyObject * +_socket_socket_inet_aton_impl(PySocketSockObject *self, const char *ip_addr); + +static PyObject * +_socket_socket_inet_aton(PySocketSockObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *ip_addr; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("inet_aton", "argument", "str", arg); + goto exit; + } + ip_addr = PyUnicode_AsUTF8(arg); + if (ip_addr == NULL) { + goto exit; + } + return_value = _socket_socket_inet_aton_impl(self, ip_addr); + +exit: + return return_value; +} + +#if defined(HAVE_INET_NTOA) + +PyDoc_STRVAR(_socket_socket_inet_ntoa__doc__, +"inet_ntoa($self, packed_ip, /)\n" +"--\n" +"\n" +"Convert an IP address from 32-bit packed binary format to string format."); + +#define _SOCKET_SOCKET_INET_NTOA_METHODDEF \ + {"inet_ntoa", (PyCFunction)_socket_socket_inet_ntoa, METH_O, _socket_socket_inet_ntoa__doc__}, + +static PyObject * +_socket_socket_inet_ntoa_impl(PySocketSockObject *self, Py_buffer *packed_ip); + +static PyObject * +_socket_socket_inet_ntoa(PySocketSockObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_buffer packed_ip = {NULL, NULL}; + + if (PyObject_GetBuffer(arg, &packed_ip, PyBUF_SIMPLE) != 0) { + goto exit; + } + return_value = _socket_socket_inet_ntoa_impl(self, &packed_ip); + +exit: + /* Cleanup for packed_ip */ + if (packed_ip.obj) { + PyBuffer_Release(&packed_ip); + } + + return return_value; +} + +#endif /* defined(HAVE_INET_NTOA) */ + +#if (defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)) + +PyDoc_STRVAR(_socket_socket_if_nametoindex__doc__, +"if_nametoindex($self, oname, /)\n" +"--\n" +"\n" +"Returns the interface index corresponding to the interface name if_name."); + +#define _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF \ + {"if_nametoindex", (PyCFunction)_socket_socket_if_nametoindex, METH_O, _socket_socket_if_nametoindex__doc__}, + +static PyObject * +_socket_socket_if_nametoindex_impl(PySocketSockObject *self, PyObject *oname); + +static PyObject * +_socket_socket_if_nametoindex(PySocketSockObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *oname; + + if (!PyUnicode_FSConverter(arg, &oname)) { + goto exit; + } + return_value = _socket_socket_if_nametoindex_impl(self, oname); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)) */ + +#ifndef _SOCKET_SOCKET_INET_NTOA_METHODDEF + #define _SOCKET_SOCKET_INET_NTOA_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_INET_NTOA_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF + #define _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF) */ +/*[clinic end generated code: output=a6621b09bcb88f6b input=a9049054013a1b77]*/ diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 1cf6fa4a8936e9..97f4d174666750 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -6332,14 +6332,18 @@ AF_UNIX if defined on the platform; otherwise, the default is AF_INET."); #endif /* HAVE_SOCKETPAIR */ +/*[clinic input] +_socket.socket.ntohs + x: int + / + +Convert a 16-bit unsigned integer from network to host byte order. +[clinic start generated code]*/ + static PyObject * -socket_ntohs(PyObject *self, PyObject *args) +_socket_socket_ntohs_impl(PySocketSockObject *self, int x) +/*[clinic end generated code: output=a828a61a9fb205b2 input=9a79cb3a71652147]*/ { - int x; - - if (!PyArg_ParseTuple(args, "i:ntohs", &x)) { - return NULL; - } if (x < 0) { PyErr_SetString(PyExc_OverflowError, "ntohs: can't convert negative Python int to C " @@ -6355,11 +6359,6 @@ socket_ntohs(PyObject *self, PyObject *args) return PyLong_FromUnsignedLong(ntohs((unsigned short)x)); } -PyDoc_STRVAR(ntohs_doc, -"ntohs(integer) -> integer\n\ -\n\ -Convert a 16-bit unsigned integer from network to host byte order."); - static PyObject * socket_ntohl(PyObject *self, PyObject *arg) @@ -6395,14 +6394,18 @@ PyDoc_STRVAR(ntohl_doc, Convert a 32-bit integer from network to host byte order."); +/*[clinic input] +_socket.socket.htons + x: int + / + +Convert a 16-bit unsigned integer from host to network byte order. +[clinic start generated code]*/ + static PyObject * -socket_htons(PyObject *self, PyObject *args) +_socket_socket_htons_impl(PySocketSockObject *self, int x) +/*[clinic end generated code: output=d785ee692312da47 input=053252d8416f4337]*/ { - int x; - - if (!PyArg_ParseTuple(args, "i:htons", &x)) { - return NULL; - } if (x < 0) { PyErr_SetString(PyExc_OverflowError, "htons: can't convert negative Python int to C " @@ -6418,11 +6421,6 @@ socket_htons(PyObject *self, PyObject *args) return PyLong_FromUnsignedLong(htons((unsigned short)x)); } -PyDoc_STRVAR(htons_doc, -"htons(integer) -> integer\n\ -\n\ -Convert a 16-bit unsigned integer from host to network byte order."); - static PyObject * socket_htonl(PyObject *self, PyObject *arg) @@ -6459,14 +6457,17 @@ Convert a 32-bit integer from host to network byte order."); /* socket.inet_aton() and socket.inet_ntoa() functions. */ -PyDoc_STRVAR(inet_aton_doc, -"inet_aton(string) -> bytes giving packed 32-bit IP representation\n\ -\n\ -Convert an IP address in string format (123.45.67.89) to the 32-bit packed\n\ -binary format used in low-level network functions."); +/*[clinic input] +_socket.socket.inet_aton + ip_addr: str + / -static PyObject* -socket_inet_aton(PyObject *self, PyObject *args) +Convert an IP address in string format (123.45.67.89) to the 32-bit packed binary format used in low-level network functions. +[clinic start generated code]*/ + +static PyObject * +_socket_socket_inet_aton_impl(PySocketSockObject *self, const char *ip_addr) +/*[clinic end generated code: output=5bfe11a255423d8c input=a120e20cb52b9488]*/ { #ifdef HAVE_INET_ATON struct in_addr buf; @@ -6479,11 +6480,6 @@ socket_inet_aton(PyObject *self, PyObject *args) /* Have to use inet_addr() instead */ unsigned int packed_addr; #endif - const char *ip_addr; - - if (!PyArg_ParseTuple(args, "s:inet_aton", &ip_addr)) - return NULL; - #ifdef HAVE_INET_ATON @@ -6532,30 +6528,29 @@ socket_inet_aton(PyObject *self, PyObject *args) } #ifdef HAVE_INET_NTOA -PyDoc_STRVAR(inet_ntoa_doc, -"inet_ntoa(packed_ip) -> ip_address_string\n\ -\n\ -Convert an IP address from 32-bit packed binary format to string format"); +/*[clinic input] +_socket.socket.inet_ntoa + packed_ip: Py_buffer + / -static PyObject* -socket_inet_ntoa(PyObject *self, PyObject *args) +Convert an IP address from 32-bit packed binary format to string format. +[clinic start generated code]*/ + +static PyObject * +_socket_socket_inet_ntoa_impl(PySocketSockObject *self, Py_buffer *packed_ip) +/*[clinic end generated code: output=b671880a3f62461b input=95c2c4a1b2ee957c]*/ { - Py_buffer packed_ip; struct in_addr packed_addr; - if (!PyArg_ParseTuple(args, "y*:inet_ntoa", &packed_ip)) { - return NULL; - } - - if (packed_ip.len != sizeof(packed_addr)) { + if (packed_ip->len != sizeof(packed_addr)) { PyErr_SetString(PyExc_OSError, "packed IP wrong length for inet_ntoa"); - PyBuffer_Release(&packed_ip); + PyBuffer_Release(packed_ip); return NULL; } - memcpy(&packed_addr, packed_ip.buf, packed_ip.len); - PyBuffer_Release(&packed_ip); + memcpy(&packed_addr, packed_ip->buf, packed_ip->len); + PyBuffer_Release(packed_ip); SUPPRESS_DEPRECATED_CALL return PyUnicode_FromString(inet_ntoa(packed_addr)); @@ -7049,18 +7044,23 @@ PyDoc_STRVAR(if_nameindex_doc, \n\ Returns a list of network interface information (index, name) tuples."); +/*[clinic input] +_socket.socket.if_nametoindex + oname: object(converter="PyUnicode_FSConverter") + / + +Returns the interface index corresponding to the interface name if_name. +[clinic start generated code]*/ + static PyObject * -socket_if_nametoindex(PyObject *self, PyObject *args) +_socket_socket_if_nametoindex_impl(PySocketSockObject *self, PyObject *oname) +/*[clinic end generated code: output=f7fc00511a309a8e input=662688054482cd46]*/ { - PyObject *oname; #ifdef MS_WINDOWS NET_IFINDEX index; #else unsigned long index; #endif - if (!PyArg_ParseTuple(args, "O&:if_nametoindex", - PyUnicode_FSConverter, &oname)) - return NULL; index = if_nametoindex(PyBytes_AS_STRING(oname)); Py_DECREF(oname); @@ -7073,10 +7073,6 @@ socket_if_nametoindex(PyObject *self, PyObject *args) return PyLong_FromUnsignedLong(index); } -PyDoc_STRVAR(if_nametoindex_doc, -"if_nametoindex(if_name)\n\ -\n\ -Returns the interface index corresponding to the interface name if_name."); static PyObject * socket_if_indextoname(PyObject *self, PyObject *arg) @@ -7215,19 +7211,15 @@ static PyMethodDef socket_methods[] = { {"socketpair", socket_socketpair, METH_VARARGS, socketpair_doc}, #endif - {"ntohs", socket_ntohs, - METH_VARARGS, ntohs_doc}, + _SOCKET_SOCKET_NTOHS_METHODDEF {"ntohl", socket_ntohl, METH_O, ntohl_doc}, - {"htons", socket_htons, - METH_VARARGS, htons_doc}, + _SOCKET_SOCKET_HTONS_METHODDEF {"htonl", socket_htonl, METH_O, htonl_doc}, - {"inet_aton", socket_inet_aton, - METH_VARARGS, inet_aton_doc}, + _SOCKET_SOCKET_INET_ATON_METHODDEF #ifdef HAVE_INET_NTOA - {"inet_ntoa", socket_inet_ntoa, - METH_VARARGS, inet_ntoa_doc}, + _SOCKET_SOCKET_INET_NTOA_METHODDEF #endif #ifdef HAVE_INET_PTON {"inet_pton", socket_inet_pton, @@ -7250,8 +7242,7 @@ static PyMethodDef socket_methods[] = { #if defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS) {"if_nameindex", socket_if_nameindex, METH_NOARGS, if_nameindex_doc}, - {"if_nametoindex", socket_if_nametoindex, - METH_VARARGS, if_nametoindex_doc}, + _SOCKET_SOCKET_IF_NAMETOINDEX_METHODDEF {"if_indextoname", socket_if_indextoname, METH_O, if_indextoname_doc}, #endif diff --git a/Python/abstract_interp_cases.c.h b/Python/abstract_interp_cases.c.h index c6ebea024c3cd2..384a11212b3a2c 100644 --- a/Python/abstract_interp_cases.c.h +++ b/Python/abstract_interp_cases.c.h @@ -628,9 +628,7 @@ break; } - case _IS_ITER_EXHAUSTED_LIST: { - STACK_GROW(1); - PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true); + case _GUARD_NOT_EXHAUSTED_LIST: { break; } @@ -644,9 +642,7 @@ break; } - case _IS_ITER_EXHAUSTED_TUPLE: { - STACK_GROW(1); - PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true); + case _GUARD_NOT_EXHAUSTED_TUPLE: { break; } @@ -660,9 +656,7 @@ break; } - case _IS_ITER_EXHAUSTED_RANGE: { - STACK_GROW(1); - PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true); + case _GUARD_NOT_EXHAUSTED_RANGE: { break; } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 8e1d318f195936..f879ea5850aede 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2580,7 +2580,7 @@ dummy_func( DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type); } - op(_ITER_JUMP_LIST, (iter -- iter)) { + replaced op(_ITER_JUMP_LIST, (iter -- iter)) { _PyListIterObject *it = (_PyListIterObject *)iter; assert(Py_TYPE(iter) == &PyListIter_Type); STAT_INC(FOR_ITER, hit); @@ -2599,21 +2599,12 @@ dummy_func( } // Only used by Tier 2 - op(_IS_ITER_EXHAUSTED_LIST, (iter -- iter, exhausted)) { + op(_GUARD_NOT_EXHAUSTED_LIST, (iter -- iter)) { _PyListIterObject *it = (_PyListIterObject *)iter; assert(Py_TYPE(iter) == &PyListIter_Type); PyListObject *seq = it->it_seq; - if (seq == NULL) { - exhausted = Py_True; - } - else if (it->it_index >= PyList_GET_SIZE(seq)) { - Py_DECREF(seq); - it->it_seq = NULL; - exhausted = Py_True; - } - else { - exhausted = Py_False; - } + DEOPT_IF(seq == NULL); + DEOPT_IF(it->it_index >= PyList_GET_SIZE(seq)); } op(_ITER_NEXT_LIST, (iter -- iter, next)) { @@ -2635,7 +2626,7 @@ dummy_func( DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type); } - op(_ITER_JUMP_TUPLE, (iter -- iter)) { + replaced op(_ITER_JUMP_TUPLE, (iter -- iter)) { _PyTupleIterObject *it = (_PyTupleIterObject *)iter; assert(Py_TYPE(iter) == &PyTupleIter_Type); STAT_INC(FOR_ITER, hit); @@ -2654,21 +2645,12 @@ dummy_func( } // Only used by Tier 2 - op(_IS_ITER_EXHAUSTED_TUPLE, (iter -- iter, exhausted)) { + op(_GUARD_NOT_EXHAUSTED_TUPLE, (iter -- iter)) { _PyTupleIterObject *it = (_PyTupleIterObject *)iter; assert(Py_TYPE(iter) == &PyTupleIter_Type); PyTupleObject *seq = it->it_seq; - if (seq == NULL) { - exhausted = Py_True; - } - else if (it->it_index >= PyTuple_GET_SIZE(seq)) { - Py_DECREF(seq); - it->it_seq = NULL; - exhausted = Py_True; - } - else { - exhausted = Py_False; - } + DEOPT_IF(seq == NULL); + DEOPT_IF(it->it_index >= PyTuple_GET_SIZE(seq)); } op(_ITER_NEXT_TUPLE, (iter -- iter, next)) { @@ -2691,7 +2673,7 @@ dummy_func( DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type); } - op(_ITER_JUMP_RANGE, (iter -- iter)) { + replaced op(_ITER_JUMP_RANGE, (iter -- iter)) { _PyRangeIterObject *r = (_PyRangeIterObject *)iter; assert(Py_TYPE(r) == &PyRangeIter_Type); STAT_INC(FOR_ITER, hit); @@ -2705,10 +2687,10 @@ dummy_func( } // Only used by Tier 2 - op(_IS_ITER_EXHAUSTED_RANGE, (iter -- iter, exhausted)) { + op(_GUARD_NOT_EXHAUSTED_RANGE, (iter -- iter)) { _PyRangeIterObject *r = (_PyRangeIterObject *)iter; assert(Py_TYPE(r) == &PyRangeIter_Type); - exhausted = r->len <= 0 ? Py_True : Py_False; + DEOPT_IF(r->len <= 0); } op(_ITER_NEXT_RANGE, (iter -- iter, next)) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index d9e9ad133de508..d94a7cc4be0052 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -2138,26 +2138,14 @@ break; } - case _IS_ITER_EXHAUSTED_LIST: { + case _GUARD_NOT_EXHAUSTED_LIST: { PyObject *iter; - PyObject *exhausted; iter = stack_pointer[-1]; _PyListIterObject *it = (_PyListIterObject *)iter; assert(Py_TYPE(iter) == &PyListIter_Type); PyListObject *seq = it->it_seq; - if (seq == NULL) { - exhausted = Py_True; - } - else if (it->it_index >= PyList_GET_SIZE(seq)) { - Py_DECREF(seq); - it->it_seq = NULL; - exhausted = Py_True; - } - else { - exhausted = Py_False; - } - STACK_GROW(1); - stack_pointer[-1] = exhausted; + DEOPT_IF(seq == NULL, _GUARD_NOT_EXHAUSTED_LIST); + DEOPT_IF(it->it_index >= PyList_GET_SIZE(seq), _GUARD_NOT_EXHAUSTED_LIST); break; } @@ -2183,26 +2171,14 @@ break; } - case _IS_ITER_EXHAUSTED_TUPLE: { + case _GUARD_NOT_EXHAUSTED_TUPLE: { PyObject *iter; - PyObject *exhausted; iter = stack_pointer[-1]; _PyTupleIterObject *it = (_PyTupleIterObject *)iter; assert(Py_TYPE(iter) == &PyTupleIter_Type); PyTupleObject *seq = it->it_seq; - if (seq == NULL) { - exhausted = Py_True; - } - else if (it->it_index >= PyTuple_GET_SIZE(seq)) { - Py_DECREF(seq); - it->it_seq = NULL; - exhausted = Py_True; - } - else { - exhausted = Py_False; - } - STACK_GROW(1); - stack_pointer[-1] = exhausted; + DEOPT_IF(seq == NULL, _GUARD_NOT_EXHAUSTED_TUPLE); + DEOPT_IF(it->it_index >= PyTuple_GET_SIZE(seq), _GUARD_NOT_EXHAUSTED_TUPLE); break; } @@ -2229,15 +2205,12 @@ break; } - case _IS_ITER_EXHAUSTED_RANGE: { + case _GUARD_NOT_EXHAUSTED_RANGE: { PyObject *iter; - PyObject *exhausted; iter = stack_pointer[-1]; _PyRangeIterObject *r = (_PyRangeIterObject *)iter; assert(Py_TYPE(r) == &PyRangeIter_Type); - exhausted = r->len <= 0 ? Py_True : Py_False; - STACK_GROW(1); - stack_pointer[-1] = exhausted; + DEOPT_IF(r->len <= 0, _GUARD_NOT_EXHAUSTED_RANGE); break; } diff --git a/Python/optimizer.c b/Python/optimizer.c index a332fd1c89582c..065e1274671993 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -384,6 +384,14 @@ PyTypeObject _PyUOpExecutor_Type = { .tp_methods = executor_methods, }; +/* TO DO -- Generate this table */ +static const uint16_t +_PyUop_Replacements[OPCODE_METADATA_SIZE] = { + [_ITER_JUMP_RANGE] = _GUARD_NOT_EXHAUSTED_RANGE, + [_ITER_JUMP_LIST] = _GUARD_NOT_EXHAUSTED_LIST, + [_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE, +}; + #define TRACE_STACK_SIZE 5 /* Returns 1 on success, @@ -586,46 +594,6 @@ translate_bytecode_to_trace( break; } - case FOR_ITER_LIST: - case FOR_ITER_TUPLE: - case FOR_ITER_RANGE: - { - RESERVE(4, 3); - int check_op, exhausted_op, next_op; - switch (opcode) { - case FOR_ITER_LIST: - check_op = _ITER_CHECK_LIST; - exhausted_op = _IS_ITER_EXHAUSTED_LIST; - next_op = _ITER_NEXT_LIST; - break; - case FOR_ITER_TUPLE: - check_op = _ITER_CHECK_TUPLE; - exhausted_op = _IS_ITER_EXHAUSTED_TUPLE; - next_op = _ITER_NEXT_TUPLE; - break; - case FOR_ITER_RANGE: - check_op = _ITER_CHECK_RANGE; - exhausted_op = _IS_ITER_EXHAUSTED_RANGE; - next_op = _ITER_NEXT_RANGE; - break; - default: - Py_UNREACHABLE(); - } - // Assume jump unlikely (can a for-loop exit be likely?) - _Py_CODEUNIT *target_instr = // +1 at the end skips over END_FOR - instr + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + oparg + 1; - max_length -= 3; // Really the start of the stubs - ADD_TO_TRACE(check_op, 0, 0); - ADD_TO_TRACE(exhausted_op, 0, 0); - ADD_TO_TRACE(_POP_JUMP_IF_TRUE, max_length, 0); - ADD_TO_TRACE(next_op, 0, 0); - - ADD_TO_STUB(max_length + 0, POP_TOP, 0, 0); - ADD_TO_STUB(max_length + 1, _SET_IP, INSTR_IP(target_instr, code), 0); - ADD_TO_STUB(max_length + 2, _EXIT_TRACE, 0, 0); - break; - } - default: { const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode]; @@ -661,6 +629,9 @@ translate_bytecode_to_trace( oparg += extras; } } + if (_PyUop_Replacements[uop]) { + uop = _PyUop_Replacements[uop]; + } break; case OPARG_CACHE_1: operand = read_u16(&instr[offset].cache); diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py index a3313b4929afc4..d1dbfeae8d74f6 100644 --- a/Tools/cases_generator/generate_cases.py +++ b/Tools/cases_generator/generate_cases.py @@ -655,7 +655,7 @@ def write_macro_expansions( if "specializing" in part.instr.annotations: continue # All other component instructions must be viable uops - if not part.instr.is_viable_uop(): + if not part.instr.is_viable_uop() and "replaced" not in part.instr.annotations: # This note just reminds us about macros that cannot # be expanded to Tier 2 uops. It is not an error. # It is sometimes emitted for macros that have a diff --git a/Tools/cases_generator/lexer.py b/Tools/cases_generator/lexer.py index 4c5403dc1d1fa8..1185c855785939 100644 --- a/Tools/cases_generator/lexer.py +++ b/Tools/cases_generator/lexer.py @@ -216,7 +216,7 @@ def choice(*opts: str) -> str: keywords = {name.lower(): name for name in kwds} ANNOTATION = "ANNOTATION" -annotations = {"specializing", "guard", "override", "register"} +annotations = {"specializing", "guard", "override", "register", "replaced"} __all__ = [] __all__.extend(kwds)