community.docker/plugins/module_utils/_socket_helper.py
Felix Fontein cad22de628
Python code modernization, 4/n (#1162)
* Address attribute-defined-outside-init.

* Address broad-exception-raised.

* Address broad-exception-caught.

* Address consider-iterating-dictionary.

* Address consider-using-dict-comprehension.

* Address consider-using-f-string.

* Address consider-using-in.

* Address consider-using-max-builtin.

* Address some consider-using-with.

* Address invalid-name.

* Address keyword-arg-before-vararg.

* Address line-too-long.

* Address no-else-continue.

* Address no-else-raise.

* Address no-else-return.

* Remove broken dead code.

* Make consider-using-f-string changes compatible with older Python versions.

* Python 3.11 and earlier apparently do not like multi-line f-strings.
2025-10-11 23:06:50 +02:00

73 lines
2.4 KiB
Python

# Copyright (c) 2019-2021, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Note that this module util is **PRIVATE** to the collection. It can have breaking changes at any time.
# Do not use this from other collections or standalone plugins/modules!
from __future__ import annotations
import fcntl
import os
import os.path
import socket as pysocket
def make_file_unblocking(file):
fcntl.fcntl(
file.fileno(),
fcntl.F_SETFL,
fcntl.fcntl(file.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK,
)
def make_file_blocking(file):
fcntl.fcntl(
file.fileno(),
fcntl.F_SETFL,
fcntl.fcntl(file.fileno(), fcntl.F_GETFL) & ~os.O_NONBLOCK,
)
def make_unblocking(sock):
if hasattr(sock, "_sock"):
sock._sock.setblocking(0)
elif hasattr(sock, "setblocking"):
sock.setblocking(0)
else:
make_file_unblocking(sock)
def _empty_writer(msg):
pass
def shutdown_writing(sock, log=_empty_writer):
# FIXME: This does **not work with SSLSocket**! Apparently SSLSocket does not allow to send
# a close_notify TLS alert without completely shutting down the connection.
# Calling sock.shutdown(pysocket.SHUT_WR) simply turns of TLS encryption and from that
# point on the raw encrypted data is returned when sock.recv() is called. :-(
if hasattr(sock, "shutdown_write"):
sock.shutdown_write()
elif hasattr(sock, "shutdown"):
try:
sock.shutdown(pysocket.SHUT_WR)
except TypeError as e:
# probably: "TypeError: shutdown() takes 1 positional argument but 2 were given"
log(f"Shutting down for writing not possible; trying shutdown instead: {e}")
sock.shutdown()
elif isinstance(sock, getattr(pysocket, "SocketIO")):
sock._sock.shutdown(pysocket.SHUT_WR)
else:
log("No idea how to signal end of writing")
def write_to_socket(sock, data):
if hasattr(sock, "_send_until_done"):
# WrappedSocket (urllib3/contrib/pyopenssl) does not have `send`, but
# only `sendall`, which uses `_send_until_done` under the hood.
return sock._send_until_done(data)
if hasattr(sock, "send"):
return sock.send(data)
return os.write(sock.fileno(), data)