From 702f47731b0724110afe37ecc3eea01659d1ee55 Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Sat, 25 Jan 2025 12:21:13 +0100 Subject: [PATCH 01/15] gh-129288: Add optional bdaddr_type in BTPROTO_L2CAP socket address tuple To be able to connect L2CAP sockets to Bluetooth LE devices, the l2_bdaddr_type must be set to BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM. This change adds support for providing the l2_bdaddr_type as an optional, traliing element in the address tuple passed to connect() --- Modules/socketmodule.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 5e81253ca4a591..3aa2a9d83778fd 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1493,9 +1493,17 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) PyObject *addrobj = makebdaddr(&_BT_L2_MEMB(a, bdaddr)); PyObject *ret = NULL; if (addrobj) { - ret = Py_BuildValue("Oi", - addrobj, - _BT_L2_MEMB(a, psm)); + // Retain old format for non-LE address + if (_BT_L2_MEMB(a, bdaddr_type) == BDADDR_BREDR) { + ret = Py_BuildValue("Oi", + addrobj, + _BT_L2_MEMB(a, psm)); + } else { + ret = Py_BuildValue("OiB", + addrobj, + _BT_L2_MEMB(a, psm), + _BT_L2_MEMB(a, bdaddr_type)); + } Py_DECREF(addrobj); } return ret; @@ -2045,8 +2053,10 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, struct sockaddr_l2 *addr = &addrbuf->bt_l2; memset(addr, 0, sizeof(struct sockaddr_l2)); _BT_L2_MEMB(addr, family) = AF_BLUETOOTH; - if (!PyArg_ParseTuple(args, "si", &straddr, - &_BT_L2_MEMB(addr, psm))) { + _BT_L2_MEMB(addr, bdaddr_type) = BDADDR_BREDR; + if (!PyArg_ParseTuple(args, "si|B", &straddr, + &_BT_L2_MEMB(addr, psm), + &_BT_L2_MEMB(addr, bdaddr_type))) { PyErr_Format(PyExc_OSError, "%s(): wrong format", caller); return 0; @@ -7743,6 +7753,9 @@ socket_exec(PyObject *m) #ifdef BTPROTO_SCO ADD_INT_MACRO(m, BTPROTO_SCO); #endif /* BTPROTO_SCO */ + ADD_INT_MACRO(m, BDADDR_BREDR); + ADD_INT_MACRO(m, BDADDR_LE_PUBLIC); + ADD_INT_MACRO(m, BDADDR_LE_RANDOM); #endif /* USE_BLUETOOTH */ #ifdef AF_CAN From d45523c852c6d3674a256248bf1fd785da1a1f5f Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Sat, 25 Jan 2025 13:25:59 +0100 Subject: [PATCH 02/15] gh-129288: Expose socket.BDADDR_BREDR, socket.BDADDR_LE_PUBLIC, socket.BDADDR_RANDOM only if defined for target Add check that BDADDR_BREDR is defined as Windows build may set USE_BLUETOOTH but not BDADDR_* --- Modules/socketmodule.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 3aa2a9d83778fd..2d4fcf3b955584 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -7750,12 +7750,14 @@ socket_exec(PyObject *m) #endif /* BTPROTO_RFCOMM */ ADD_STR_CONST(m, "BDADDR_ANY", "00:00:00:00:00:00"); ADD_STR_CONST(m, "BDADDR_LOCAL", "00:00:00:FF:FF:FF"); -#ifdef BTPROTO_SCO - ADD_INT_MACRO(m, BTPROTO_SCO); -#endif /* BTPROTO_SCO */ +#ifdef BDADDR_BREDR ADD_INT_MACRO(m, BDADDR_BREDR); ADD_INT_MACRO(m, BDADDR_LE_PUBLIC); ADD_INT_MACRO(m, BDADDR_LE_RANDOM); +#endif /* BDADDR_BREDR */ +#ifdef BTPROTO_SCO + ADD_INT_MACRO(m, BTPROTO_SCO); +#endif /* BTPROTO_SCO */ #endif /* USE_BLUETOOTH */ #ifdef AF_CAN From e9b2a54052e8fbe5877145cd6da1c4ebe40b942e Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Sun, 26 Jan 2025 13:26:02 +0100 Subject: [PATCH 03/15] gh-129288: Add optional CID field in BTPROTO_L2CAP socket address tuple This change adds support for the CID field in the socket address tuple. This allows e.g raw LE ATT connections. --- Modules/socketmodule.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 2d4fcf3b955584..3370574bfd1997 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1493,15 +1493,16 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) PyObject *addrobj = makebdaddr(&_BT_L2_MEMB(a, bdaddr)); PyObject *ret = NULL; if (addrobj) { - // Retain old format for non-LE address + /* Retain old format for non-LE address */ if (_BT_L2_MEMB(a, bdaddr_type) == BDADDR_BREDR) { ret = Py_BuildValue("Oi", addrobj, _BT_L2_MEMB(a, psm)); } else { - ret = Py_BuildValue("OiB", + ret = Py_BuildValue("OiiB", addrobj, _BT_L2_MEMB(a, psm), + _BT_L2_MEMB(a, cid), _BT_L2_MEMB(a, bdaddr_type)); } Py_DECREF(addrobj); @@ -2054,8 +2055,9 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, memset(addr, 0, sizeof(struct sockaddr_l2)); _BT_L2_MEMB(addr, family) = AF_BLUETOOTH; _BT_L2_MEMB(addr, bdaddr_type) = BDADDR_BREDR; - if (!PyArg_ParseTuple(args, "si|B", &straddr, + if (!PyArg_ParseTuple(args, "si|iB", &straddr, &_BT_L2_MEMB(addr, psm), + &_BT_L2_MEMB(addr, cid), &_BT_L2_MEMB(addr, bdaddr_type))) { PyErr_Format(PyExc_OSError, "%s(): wrong format", caller); From 117ccd46f5654417a07d43c505fe1b0871ad01ad Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 26 Jan 2025 15:35:54 +0000 Subject: [PATCH 04/15] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2025-01-26-15-35-53.gh-issue-129288.wB3uxU.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2025-01-26-15-35-53.gh-issue-129288.wB3uxU.rst diff --git a/Misc/NEWS.d/next/Library/2025-01-26-15-35-53.gh-issue-129288.wB3uxU.rst b/Misc/NEWS.d/next/Library/2025-01-26-15-35-53.gh-issue-129288.wB3uxU.rst new file mode 100644 index 00000000000000..3a990b799d4b8f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-26-15-35-53.gh-issue-129288.wB3uxU.rst @@ -0,0 +1 @@ +Add optional `l2_cid` and `l2_bdaddr_type` fields to :mod:`socket` `BTPROTO_L2CAP` sockaddr tuple. From 4c123f6a532adf8988e1018a5ef71ad32821beb9 Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Sun, 26 Jan 2025 16:38:57 +0100 Subject: [PATCH 05/15] gh-129288: Fix NEWS blurb formatting --- .../next/Library/2025-01-26-15-35-53.gh-issue-129288.wB3uxU.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-01-26-15-35-53.gh-issue-129288.wB3uxU.rst b/Misc/NEWS.d/next/Library/2025-01-26-15-35-53.gh-issue-129288.wB3uxU.rst index 3a990b799d4b8f..e23cb735a5b046 100644 --- a/Misc/NEWS.d/next/Library/2025-01-26-15-35-53.gh-issue-129288.wB3uxU.rst +++ b/Misc/NEWS.d/next/Library/2025-01-26-15-35-53.gh-issue-129288.wB3uxU.rst @@ -1 +1 @@ -Add optional `l2_cid` and `l2_bdaddr_type` fields to :mod:`socket` `BTPROTO_L2CAP` sockaddr tuple. +Add optional ``l2_cid`` and ``l2_bdaddr_type`` fields to :mod:`socket` ``BTPROTO_L2CAP`` sockaddr tuple. From d771afb836020f233d3b382600f11c386eeb64ca Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Sun, 23 Feb 2025 10:47:01 +0100 Subject: [PATCH 06/15] gh-129288: Update docs for socket to include new BTPROTO_L2CAP address fields Update documentation to mention the new cid and bdaddr_type fields for BTPROTO_L2CAP connections. --- Doc/library/socket.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index b36acad29ecb00..baf33730c16d75 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -137,8 +137,9 @@ created. Socket addresses are represented as follows: - :const:`AF_BLUETOOTH` supports the following protocols and address formats: - - :const:`BTPROTO_L2CAP` accepts ``(bdaddr, psm)`` where ``bdaddr`` is - the Bluetooth address as a string and ``psm`` is an integer. + - :const:`BTPROTO_L2CAP` accepts ``(bdaddr, psm, cid, bdaddr_type)`` where ``bdaddr`` is + the Bluetooth address as a string and ``psm``, ``cid`` and ``bdaddr_type`` are integers. + ``cid`` and ``bdaddr_type`` are optional. - :const:`BTPROTO_RFCOMM` accepts ``(bdaddr, channel)`` where ``bdaddr`` is the Bluetooth address as a string and ``channel`` is an integer. From 60abd6e398752bf24b720348798db44b829536be Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Tue, 25 Feb 2025 06:31:03 +0100 Subject: [PATCH 07/15] gh-129288: Improve docs for socket on BTPROTO_L2CAP, BDADDR_BREDR et al --- Doc/library/socket.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index b7ba9fd88f7726..ea905d4c64e1e5 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -139,7 +139,11 @@ created. Socket addresses are represented as follows: - :const:`BTPROTO_L2CAP` accepts ``(bdaddr, psm, cid, bdaddr_type)`` where ``bdaddr`` is the Bluetooth address as a string and ``psm``, ``cid`` and ``bdaddr_type`` are integers. - ``cid`` and ``bdaddr_type`` are optional. + ``cid`` and ``bdaddr_type`` are optional. ``bdaddr_type`` should be one of :const:`BDADDR_BREDR`, + :const:`BDADDR_LE_PUBLIC`, :const:`BDADDR_LE_RANDOM`. + + .. versionchanged:: next + Added ``cid`` and ``bdaddr_type`` fields. - :const:`BTPROTO_RFCOMM` accepts ``(bdaddr, channel)`` where ``bdaddr`` is the Bluetooth address as a string and ``channel`` is an integer. @@ -635,6 +639,14 @@ Constants any address when specifying the binding socket with :const:`BTPROTO_RFCOMM`. +.. data:: BDADDR_BREDR + BDADDR_LE_PUBLIC + BDADDR_LE_RANDOM + + These constants describe the Bluetooth address type when binding or connecting a :const:`BTPROTO_L2CAP` socket. + + .. versionadded:: next + .. data:: HCI_FILTER HCI_TIME_STAMP HCI_DATA_DIR From 2c537ba7f5394357ae9f457af7b2787af0971155 Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Tue, 25 Feb 2025 08:12:15 +0100 Subject: [PATCH 08/15] gh-129288: Move BDADDR_BREDR et al macros to use BTPROTO_L2CAP guard --- Modules/socketmodule.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 3080c87864a160..5ef43e32f4212b 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -7794,6 +7794,9 @@ socket_exec(PyObject *m) ADD_INT_MACRO(m, AF_BLUETOOTH); #ifdef BTPROTO_L2CAP ADD_INT_MACRO(m, BTPROTO_L2CAP); + ADD_INT_MACRO(m, BDADDR_BREDR); + ADD_INT_MACRO(m, BDADDR_LE_PUBLIC); + ADD_INT_MACRO(m, BDADDR_LE_RANDOM); #endif /* BTPROTO_L2CAP */ #ifdef BTPROTO_HCI ADD_INT_MACRO(m, BTPROTO_HCI); @@ -7811,11 +7814,6 @@ socket_exec(PyObject *m) #endif /* BTPROTO_RFCOMM */ ADD_STR_CONST(m, "BDADDR_ANY", "00:00:00:00:00:00"); ADD_STR_CONST(m, "BDADDR_LOCAL", "00:00:00:FF:FF:FF"); -#ifdef BDADDR_BREDR - ADD_INT_MACRO(m, BDADDR_BREDR); - ADD_INT_MACRO(m, BDADDR_LE_PUBLIC); - ADD_INT_MACRO(m, BDADDR_LE_RANDOM); -#endif /* BDADDR_BREDR */ #ifdef BTPROTO_SCO ADD_INT_MACRO(m, BTPROTO_SCO); #endif /* BTPROTO_SCO */ From fe0b9935230e2ebaf09441266a5517abe0e85d0b Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 25 Feb 2025 11:39:01 +0100 Subject: [PATCH 09/15] Expand the docs & provide link targets for the constants --- Doc/library/socket.rst | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index ea905d4c64e1e5..1d715f32e63b13 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -137,10 +137,16 @@ created. Socket addresses are represented as follows: - :const:`AF_BLUETOOTH` supports the following protocols and address formats: - - :const:`BTPROTO_L2CAP` accepts ``(bdaddr, psm, cid, bdaddr_type)`` where ``bdaddr`` is - the Bluetooth address as a string and ``psm``, ``cid`` and ``bdaddr_type`` are integers. - ``cid`` and ``bdaddr_type`` are optional. ``bdaddr_type`` should be one of :const:`BDADDR_BREDR`, - :const:`BDADDR_LE_PUBLIC`, :const:`BDADDR_LE_RANDOM`. + - :const:`BTPROTO_L2CAP` accepts a tuple + ``(bdaddr, psm[, cid[, bdaddr_type]])`` where: + + - ``bdaddr``: String specifying the Bluetooth address. + - ``psm`` Integer specifying the Protocol/Service Multiplexer. + - ``cid`` Optional integer specifying the Channel Identifier. If not given, + defaults to zero. + - ``bdaddr_type`` Optional integer specifying the address type; + one of :const:`BDADDR_BREDR` (default), :const:`BDADDR_LE_PUBLIC`, + :const:`BDADDR_LE_RANDOM`. .. versionchanged:: next Added ``cid`` and ``bdaddr_type`` fields. @@ -631,6 +637,14 @@ Constants This constant contains a boolean value which indicates if IPv6 is supported on this platform. +.. data:: AF_BLUETOOTH + BTPROTO_L2CAP + BTPROTO_RFCOMM + BTPROTO_HCI + BTPROTO_SCO + + Integer constants for use with Bluetooth addresses. + .. data:: BDADDR_ANY BDADDR_LOCAL @@ -643,7 +657,8 @@ Constants BDADDR_LE_PUBLIC BDADDR_LE_RANDOM - These constants describe the Bluetooth address type when binding or connecting a :const:`BTPROTO_L2CAP` socket. + These constants describe the Bluetooth address type when binding or + connecting a :const:`BTPROTO_L2CAP` socket. .. versionadded:: next From b25005ea05ed82f6c4ee211cd27a79c6b4afff3b Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Tue, 25 Feb 2025 12:22:23 +0100 Subject: [PATCH 10/15] gh-129288: Update comment re discarding cid for BR/EDR L2CAP socket --- Modules/socketmodule.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 5ef43e32f4212b..916ad35623e94d 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1495,7 +1495,9 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) PyObject *addrobj = makebdaddr(&_BT_L2_MEMB(a, bdaddr)); PyObject *ret = NULL; if (addrobj) { - /* Retain old format for non-LE address */ + /* Retain old format for non-LE address. + (cid may be set for BR/EDR, but we're discarding it for now) + */ if (_BT_L2_MEMB(a, bdaddr_type) == BDADDR_BREDR) { ret = Py_BuildValue("Oi", addrobj, From 8532c5bac929976b5ae449f8b366958102712722 Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Tue, 25 Feb 2025 20:39:20 +0100 Subject: [PATCH 11/15] gh-129288: Add tests for BTPROTO_L2CAP socket --- Lib/test/test_socket.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index b77fa3cb21512a..e21454bee253c0 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -2608,6 +2608,33 @@ def testCreateScoSocket(self): with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_SCO) as s: pass + @unittest.skipIf(sys.platform != "linux", "expecting full L2CAP support on linux only") + def testBindLeAttL2capSocket(self): + with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) as f: + # ATT is the only CID allowed in userspace by the Linux kernel + CID_ATT = 4 + f.bind((socket.BDADDR_ANY, 0, CID_ATT, socket.BDADDR_LE_PUBLIC)) + addr = f.getsockname() + self.assertEqual(addr, (socket.BDADDR_ANY, 0, CID_ATT, socket.BDADDR_LE_PUBLIC)) + + @unittest.skipIf(sys.platform != "linux", "expecting full L2CAP support on linux only") + def testBindLePsmL2capSocket(self): + with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) as f: + # First user PSM in LE L2CAP + psm = 0x80 + f.bind((socket.BDADDR_ANY, psm, 0, socket.BDADDR_LE_RANDOM)) + addr = f.getsockname() + self.assertEqual(addr, (socket.BDADDR_ANY, psm, 0, socket.BDADDR_LE_RANDOM)) + + @unittest.skipIf(sys.platform != "linux", "expecting full L2CAP support on linux only") + def testBindBrEdrL2capSocket(self): + with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) as f: + # First user PSM in BR/EDR L2CAP + psm = 0x1001 + f.bind((socket.BDADDR_ANY, psm)) + addr = f.getsockname() + self.assertEqual(addr, (socket.BDADDR_ANY, psm)) + @unittest.skipUnless(HAVE_SOCKET_HYPERV, 'Hyper-V sockets required for this test.') From 1af3e88632f86b7fb9e3b54b0f3a07a0c82a97b7 Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Wed, 26 Feb 2025 12:46:35 +0100 Subject: [PATCH 12/15] gh-129288: Add HAVE_SOCKET_BLUETOOTH_L2CAP to socket tests --- Lib/test/test_socket.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index e21454bee253c0..8bc6f6af1c786d 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -177,6 +177,17 @@ def _have_socket_bluetooth(): return True +def _have_socket_bluetooth_l2cap(): + """Check whether BTPROTO_L2CAP sockets are supported on this host.""" + try: + s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) + except (AttributeError, OSError): + return False + else: + s.close() + return True + + def _have_socket_hyperv(): """Check whether AF_HYPERV sockets are supported on this host.""" try: @@ -219,6 +230,8 @@ def socket_setdefaulttimeout(timeout): HAVE_SOCKET_BLUETOOTH = _have_socket_bluetooth() +HAVE_SOCKET_BLUETOOTH_L2CAP = _have_socket_bluetooth_l2cap() + HAVE_SOCKET_HYPERV = _have_socket_hyperv() # Size in bytes of the int type @@ -2592,7 +2605,7 @@ def testCreateRfcommSocket(self): with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM) as s: pass - @unittest.skipIf(sys.platform == "win32", "windows does not support L2CAP sockets") + @unittest.skipUnless(HAVE_SOCKET_BLUETOOTH_L2CAP, 'Bluetooth L2CAP sockets required for this test') def testCreateL2capSocket(self): with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) as s: pass @@ -2608,7 +2621,7 @@ def testCreateScoSocket(self): with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_SCO) as s: pass - @unittest.skipIf(sys.platform != "linux", "expecting full L2CAP support on linux only") + @unittest.skipUnless(HAVE_SOCKET_BLUETOOTH_L2CAP, 'Bluetooth L2CAP sockets required for this test') def testBindLeAttL2capSocket(self): with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) as f: # ATT is the only CID allowed in userspace by the Linux kernel @@ -2617,7 +2630,7 @@ def testBindLeAttL2capSocket(self): addr = f.getsockname() self.assertEqual(addr, (socket.BDADDR_ANY, 0, CID_ATT, socket.BDADDR_LE_PUBLIC)) - @unittest.skipIf(sys.platform != "linux", "expecting full L2CAP support on linux only") + @unittest.skipUnless(HAVE_SOCKET_BLUETOOTH_L2CAP, 'Bluetooth L2CAP sockets required for this test') def testBindLePsmL2capSocket(self): with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) as f: # First user PSM in LE L2CAP @@ -2626,7 +2639,7 @@ def testBindLePsmL2capSocket(self): addr = f.getsockname() self.assertEqual(addr, (socket.BDADDR_ANY, psm, 0, socket.BDADDR_LE_RANDOM)) - @unittest.skipIf(sys.platform != "linux", "expecting full L2CAP support on linux only") + @unittest.skipUnless(HAVE_SOCKET_BLUETOOTH_L2CAP, 'Bluetooth L2CAP sockets required for this test') def testBindBrEdrL2capSocket(self): with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) as f: # First user PSM in BR/EDR L2CAP From 5a1eaa31d5e52edf637781dbc715904de1864d38 Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Wed, 26 Feb 2025 12:48:44 +0100 Subject: [PATCH 13/15] gh-129288 Revert skip criteria for testCreateL2capSocket --- Lib/test/test_socket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 8bc6f6af1c786d..fc6e8593ae30bb 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -2605,7 +2605,7 @@ def testCreateRfcommSocket(self): with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM) as s: pass - @unittest.skipUnless(HAVE_SOCKET_BLUETOOTH_L2CAP, 'Bluetooth L2CAP sockets required for this test') + @unittest.skipIf(sys.platform == "win32", "windows does not support L2CAP sockets") def testCreateL2capSocket(self): with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) as s: pass From 38e32a7cbfe7d08aefd5432a74c93adb5c2fed27 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 27 Feb 2025 13:25:55 +0100 Subject: [PATCH 14/15] Update Doc/library/socket.rst --- Doc/library/socket.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 1d715f32e63b13..846022acf258ac 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -140,11 +140,11 @@ created. Socket addresses are represented as follows: - :const:`BTPROTO_L2CAP` accepts a tuple ``(bdaddr, psm[, cid[, bdaddr_type]])`` where: - - ``bdaddr``: String specifying the Bluetooth address. - - ``psm`` Integer specifying the Protocol/Service Multiplexer. - - ``cid`` Optional integer specifying the Channel Identifier. If not given, - defaults to zero. - - ``bdaddr_type`` Optional integer specifying the address type; + - ``bdaddr`` is a string specifying the Bluetooth address. + - ``psm`` is an integer specifying the Protocol/Service Multiplexer. + - ``cid`` is an optional integer specifying the Channel Identifier. + If not given, defaults to zero. + - ``bdaddr_type``is an optional integer specifying the address type; one of :const:`BDADDR_BREDR` (default), :const:`BDADDR_LE_PUBLIC`, :const:`BDADDR_LE_RANDOM`. From b731ae7b851018905a9415631a1cf1393e5c337b Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 27 Feb 2025 13:27:48 +0100 Subject: [PATCH 15/15] Never commit from GitHub UI, right? --- Doc/library/socket.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 846022acf258ac..67f3074e63c3c6 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -144,7 +144,7 @@ created. Socket addresses are represented as follows: - ``psm`` is an integer specifying the Protocol/Service Multiplexer. - ``cid`` is an optional integer specifying the Channel Identifier. If not given, defaults to zero. - - ``bdaddr_type``is an optional integer specifying the address type; + - ``bdaddr_type`` is an optional integer specifying the address type; one of :const:`BDADDR_BREDR` (default), :const:`BDADDR_LE_PUBLIC`, :const:`BDADDR_LE_RANDOM`.