Table of Contents
Test Report
View CI Run 2704 | Commit c8b8f24 ✅ Pytest completed successfully
All tests were collected and executed properly. See the details below.
📋 Short test summary info
=========================== short test summary info ============================
FAILED tests/test_utils_debug.py::test_short_repr[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-10-'aaaaaaaaaa...] - assert "'aaaaaaaaa..." == "'aaaaaaaaaa..."
- 'aaaaaaaaaa...
? -
+ 'aaaaaaaaa...
FAILED tests/test_utils_debug.py::test_short_repr[value5-20-Obj(xxxxxxxxxxxxxxxxx...] - AssertionError: assert 'Obj(xxxxxxxxxxxxxxxx...' == 'Obj(xxxxxxxxxxxxxxxxx...'
- Obj(xxxxxxxxxxxxxxxxx...
? -
+ Obj(xxxxxxxxxxxxxxxx...
FAILED tests/test_utils_elog.py::test_get_default_elog_instance_with_direct_password_and_real_check - Failed: elog.post() raised an unexpected exception: No response from the logbook server.
Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused'))
FAILED tests/test_utils_elog.py::test_get_default_elog_instance_asks_password_and_opens - Failed: elog.post() raised an unexpected exception: No response from the logbook server.
Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused'))
FAILED tests/test_utils_elog.py::test_get_default_elog_with_path_home - Failed: elog.post() raised an unexpected exception: No response from the logbook server.
Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused'))
FAILED tests/test_utils_elog.py::test_screenshot - elog.logbook_exceptions.LogbookServerProblem: No response from the logbook server.
Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused'))
FAILED tests/test_utils_get_adj.py::test_get_adjs_filter - AssertionError: assert {'contrast', ...mid_contrast'} == {'brightness'...mid_contrast'}
Extra items in the right set:
'brightness'
Full diff:
{
- 'brightness',
'contrast',
'mid_brightness',
'mid_contrast',
}
FAILED tests/test_utils_logcfg.py::test_import_logging_once_per_module - AssertionError: Expected 1 import log for 'math', found 0
assert 0 == 1
FAILED tests/test_utils_shortcut.py::TestShortcutsSingleton::test_registration - assert 3 == 2
+ where 3 = len({'<lambda>': Shortcut "<lambda>", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB"})
+ where {'<lambda>': Shortcut "<lambda>", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB"} = _get()
+ where _get = <lambda>: Shortcut "<lambda>"\nFuncA: Shortcut "FuncA"\nFuncB: Shortcut "FuncB"\n._get
FAILED tests/test_utils_shortcut.py::TestFullIntegration::test_multiple_shortcuts - assert 5 == 2
+ where 5 = len({'<lambda>': Shortcut "<lambda>", 'First': Shortcut "First", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB", ...})
+ where {'<lambda>': Shortcut "<lambda>", 'First': Shortcut "First", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB", ...} = _get()
+ where _get = <lambda>: Shortcut "<lambda>"\nFirst: Shortcut "First"\nFuncA: Shortcut "FuncA"\nFuncB: Shortcut "FuncB"\nSecond: Shortcut "Second"\n._get
FAILED tests/test_utils_tqdm_mod.py::test_float_alignment_in_bar - assert 3 == 1
+ where 3 = len({50, 64, 65})
+ where {50, 64, 65} = set([50, 64, 64, 65, 65])
============ 11 failed, 518 passed, 2 warnings in 161.11s (0:02:41) ============
]0;TerminalERROR conda.cli.main_run:execute(125): `conda run pytest . --continue-on-collection-errors --cov=slic --json-report --json-report-file=markdown/pytest-report.json` failed. (See above for error)
🪵 Full raw pytest log
============================= test session starts ==============================
platform linux -- Python 3.8.20, pytest-8.3.5, pluggy-1.5.0
rootdir: /workspace/tligui_y/slic
plugins: time-machine-2.15.0, metadata-3.1.1, cov-5.0.0, json-report-1.5.0
collected 529 items
morbidissimo/morbidissimo/morioc/test_infer_type.py .................... [ 3%]
............ [ 6%]
tests/test_utils_argfwd.py ............................ [ 11%]
tests/test_utils_ask_yes_no.py ........................................ [ 18%]
tests/test_utils_channels.py . [ 19%]
tests/test_utils_config.py .. [ 19%]
tests/test_utils_cpint.py ........................ [ 24%]
tests/test_utils_dbusnotify.py ....... [ 25%]
tests/test_utils_debug.py ......F...F [ 27%]
tests/test_utils_dictext.py ................. [ 30%]
tests/test_utils_dotdir.py ... [ 31%]
tests/test_utils_duo.py ........... [ 33%]
tests/test_utils_elog.py F.FFF [ 34%]
tests/test_utils_eval.py ...................................... [ 41%]
tests/test_utils_exceptions.py .......... [ 43%]
tests/test_utils_get_adj.py ...F [ 44%]
tests/test_utils_ipy.py . [ 44%]
tests/test_utils_jsonext.py ........ [ 45%]
tests/test_utils_lazypv.py . [ 45%]
tests/test_utils_logcfg.py ..F [ 46%]
tests/test_utils_logign.py ..... [ 47%]
tests/test_utils_marker.py ............. [ 49%]
tests/test_utils_metaclasses.py .. [ 50%]
tests/test_utils_namespace.py . [ 50%]
tests/test_utils_npy.py ................................................ [ 59%]
...... [ 60%]
tests/test_utils_path.py ..... [ 61%]
tests/test_utils_picklio.py ....... [ 62%]
tests/test_utils_printing.py ....................................... [ 70%]
tests/test_utils_rangebar.py ................. [ 73%]
tests/test_utils_readable.py ........................ [ 78%]
tests/test_utils_registry.py ........ [ 79%]
tests/test_utils_richcfg.py ╭─ user = <test_utils_richcfg.User object at 0x7feb09898850> ─╮
│ Represents a user in the system. │
│ │
│ ╭─────────────────────────────────────────────────────────╮ │
│ │ <test_utils_richcfg.User object at 0x7feb09898850> │ │
│ ╰─────────────────────────────────────────────────────────╯ │
│ │
│ age = 30 │
│ name = 'Alice' │
│ role = 'admin' │
│ greet = def greet(): Returns a welcome message. │
╰─────────────────────────────────────────────────────────────╯
Type: User
String form: <test_utils_richcfg.User object at 0x7feb09512e80>
File: /workspace/tligui_y/slic/tests/test_utils_richcfg.py
Source:
class User:
"""Represents a user in the system."""
role = "admin"
def __init__(self, name: str, age: int):
self.name = name
self.age = age
def greet(self):
"""Returns a welcome message."""
return f"Welcome, {self.name}!"
. [ 79%]
tests/test_utils_run_later.py .................. [ 83%]
tests/test_utils_sendmail.py .. [ 83%]
tests/test_utils_sendsms.py . [ 83%]
tests/test_utils_shortcut.py ..........F....F. [ 86%]
tests/test_utils_snapshot.py ........ [ 88%]
tests/test_utils_termtitle.py . [ 88%]
tests/test_utils_tqdm_mod.py ...F... [ 89%]
tests/test_utils_trinary.py ... [ 90%]
tests/test_utils_typecast.py ......... [ 92%]
tests/test_utils_utils.py .................................. [ 98%]
tests/test_utils_xrange.py ....... [100%]
=================================== FAILURES ===================================
_ test_short_repr[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-10-'aaaaaaaaaa...] _
value = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
cutoff = 10, expected = "'aaaaaaaaaa..."
@pytest.mark.parametrize(
"value, cutoff, expected",
[
("abc", 10, "'abc'"),
("a" * 100, 10, "'aaaaaaaaaa..."),
(12345, 10, "12345"),
([0]*100, 15, str(repr([0]*100))[:15] + "..."),
(None, 10, "None"),
(type("Obj", (), {"__repr__": lambda self: "Obj(" + "x"*50 + ")"})(), 20, "Obj(xxxxxxxxxxxxxxxxx..."),
]
)
def test_short_repr(value, cutoff, expected):
> assert short_repr(value, cutoff) == expected
E assert "'aaaaaaaaa..." == "'aaaaaaaaaa..."
E
E - 'aaaaaaaaaa...
E ? -
E + 'aaaaaaaaa...
tests/test_utils_debug.py:66: AssertionError
_____________ test_short_repr[value5-20-Obj(xxxxxxxxxxxxxxxxx...] ______________
value = Obj(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx), cutoff = 20
expected = 'Obj(xxxxxxxxxxxxxxxxx...'
@pytest.mark.parametrize(
"value, cutoff, expected",
[
("abc", 10, "'abc'"),
("a" * 100, 10, "'aaaaaaaaaa..."),
(12345, 10, "12345"),
([0]*100, 15, str(repr([0]*100))[:15] + "..."),
(None, 10, "None"),
(type("Obj", (), {"__repr__": lambda self: "Obj(" + "x"*50 + ")"})(), 20, "Obj(xxxxxxxxxxxxxxxxx..."),
]
)
def test_short_repr(value, cutoff, expected):
> assert short_repr(value, cutoff) == expected
E AssertionError: assert 'Obj(xxxxxxxxxxxxxxxx...' == 'Obj(xxxxxxxxxxxxxxxxx...'
E
E - Obj(xxxxxxxxxxxxxxxxx...
E ? -
E + Obj(xxxxxxxxxxxxxxxx...
tests/test_utils_debug.py:66: AssertionError
______ test_get_default_elog_instance_with_direct_password_and_real_check ______
self = <urllib3.connection.HTTPConnection object at 0x7feb09b79310>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection
raise err
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
address = ('localhost', 8080), timeout = None, source_address = None
socket_options = [(6, 1, 1)]
def create_connection(
address: tuple[str, int],
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
source_address: tuple[str, int] | None = None,
socket_options: _TYPE_SOCKET_OPTIONS | None = None,
) -> socket.socket:
"""Connect to *address* and return the socket object.
Convenience function. Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object. Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect. If no *timeout* is supplied, the
global default timeout setting returned by :func:`socket.getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default.
"""
host, port = address
if host.startswith("["):
host = host.strip("[]")
err = None
# Using the value from allowed_gai_family() in the context of getaddrinfo lets
# us select whether to work with IPv4 DNS records, IPv6 records, or both.
# The original create_connection function always returns all records.
family = allowed_gai_family()
try:
host.encode("idna")
except UnicodeError:
raise LocationParseError(f"'{host}', label empty or too long") from None
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
# If provided, set socket level options before connecting.
_set_socket_options(sock, socket_options)
if timeout is not _DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
> sock.connect(sa)
E ConnectionRefusedError: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError
The above exception was the direct cause of the following exception:
self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b79910>
method = 'POST', url = '/demo/'
body = b'--06a2aba8224344deb19cc358b997508b\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--06a2aba8224344...Disposition: form-data; name="Text"; filename=""\r\n\r\nThis is a message1\r\n--06a2aba8224344deb19cc358b997508b--\r\n'
headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=06a2aba8224344deb19cc358b997508b'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None)
redirect = False, assert_same_host = False
timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False
decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None)
destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False
def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.
.. note::
More commonly, it's appropriate to use a convenience method
such as :meth:`request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.
:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.
:param bool preload_content:
If True, the response's body will be preloaded into memory.
:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.
:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme
if headers is None:
headers = self.headers
if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)
if release_conn is None:
release_conn = preload_content
# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)
# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)
conn = None
# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn
http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)
# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]
# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None
# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False
# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)
try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)
conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]
# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise
# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None
# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request
conn.request(
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request
self.endheaders()
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output
self.send(msg)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send
self.connect()
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect
self.sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connection.HTTPConnection object at 0x7feb09b79310>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
raise NameResolutionError(self.host, self, e) from e
except SocketTimeout as e:
raise ConnectTimeoutError(
self,
f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
) from e
except OSError as e:
> raise NewConnectionError(
self, f"Failed to establish a new connection: {e}"
) from e
E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb09b79310>: Failed to establish a new connection: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError
The above exception was the direct cause of the following exception:
self = <requests.adapters.HTTPAdapter object at 0x7feb09b79730>
request = <PreparedRequest [POST]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = Retry(total=0, connect=None, read=False, redirect=None, status=None)
method = 'POST', url = '/demo/', response = None
error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b79310>: Failed to establish a new connection: [Errno 111] Connection refused')
_pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b79910>
_stacktrace = <traceback object at 0x7feb09b744c0>
def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.
:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.
:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)
total = self.total
if total is not None:
total -= 1
connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None
if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1
elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1
elif error:
# Other retry?
if other is not None:
other -= 1
elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status
else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status
history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)
new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)
if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b79310>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError
During handling of the above exception, another exception occurred:
self = <elog.logbook.Logbook object at 0x7feb09b79e80>
message = 'This is a message1', msg_id = None, reply = False
attributes = {'Author': 'robot', 'When': 1756376001, 'cmd': 'Submit', 'exp': 'demo', ...}
attachments = [], suppress_email_notification = False, encoding = None
timeout = None, kwargs = {'Author': 'robot'}
new_attachment_list = [('Text', ('', b'This is a message1'))]
objects_to_close = []
attributes_to_edit = {'Author': b'robot', 'When': 1756376001, 'cmd': b'Submit', 'exp': b'demo', ...}
def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None,
suppress_email_notification=False, encoding=None, timeout=None, **kwargs):
"""
Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing
message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id
of the newly created message.
:param message: string with message text
:param msg_id: ID number of message to edit or reply. If not specified new message is created.
:param reply: If 'True' reply to existing message is created instead of editing it
:param attributes: Dictionary of attributes. Following attributes are used internally by the elog and will be
ignored: Text, Date, Encoding, Reply to, In reply to, Locked by, Attachment
:param attachments: list of:
- file like objects which read() will return bytes (if file_like_object.name is not
defined, default name "attachment<i>" will be used.
- paths to the files
All items will be appended as attachment to the elog entry. In case of unknown
attachment an exception LogbookInvalidAttachment will be raised.
:param suppress_email_notification: If set to True or 1, E-Mail notification will be suppressed, defaults to False.
:param encoding: Defines encoding of the message. Can be: 'plain' -> plain text, 'html'->html-text,
'ELCode' --> elog formatting syntax
:param timeout: Define the timeout to be used by the post request. Its value is directly passed to the requests
post. Use None to disable the request timeout.
:param kwargs: Anything in the kwargs will be interpreted as attribute. e.g.: logbook.post('Test text',
Author='Rok Vintar), "Author" will be sent as an attribute. If named same as one of the
attributes defined in "attributes", kwargs will have priority.
:return: msg_id
"""
attributes = attributes or {}
attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority
attachments = attachments or []
if encoding is not None:
if encoding not in ['plain', 'HTML', 'ELCode']:
raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.')
attributes['Encoding'] = encoding
if suppress_email_notification:
attributes["suppress"] = 1
# THE ATTACHMENT STRATEGY WHEN DEALING WITH POST MODIFICATION
#
# 1. Does the message on the server have already attachments?
# 1.1 - We read the message getting the existing attachment list.
# 1.2 - Add to the attributes dictionary one line for each attachment like this:
# attributes['attachmentN'] = timestamped_filename_name
#
# 2. Do we have new attachments?
# 2.1 - Those are in the new_attachment_list. This is a list of this type:
# [ ('attfileN', ('filename', fileobject)) ]
# 2.2 - We need to loop over all the new attachments:
# 2.2.1 - Does a file already on the server with the same name exist?
# 2.2.1.1 - No: OK. Then we go ahead with the next attachment.
# 2.2.1.2 - Yes:
# 2.2.1.2.1 - Are the two files identical?
# 2.2.1.2.1.1 - Yes: then we remove this current entry from the new_attachment_list and we leave the one
# already on server.
# 2.2.1.2.1.2 - No:
# 2.2.1.2.1.2.1 - Then the file has been update.
# 2.2.1.2.1.2.2 - We need to remove the file on server first (using special post)
# 2.2.1.2.1.2.3 - We have to remove the old attachment from the attributes dictionary.
#
if attachments:
# here we accomplish point 2.1.
# new_attachment_list is something like [ ('attfileN', ('filename', fileobject)) ]
new_attachment_list, objects_to_close = self._prepare_attachments(attachments)
else:
objects_to_close = list()
new_attachment_list = list()
attributes_to_edit = dict()
if msg_id:
# Message exists, we can continue
if reply:
# Verify that there is a message on the server, otherwise do not reply to it!
self._check_if_message_on_server(msg_id) # raises exception in case of none existing message
attributes['reply_to'] = str(msg_id)
else: # Edit existing
attributes['edit_id'] = str(msg_id)
attributes['skiplock'] = '1'
# here we accomplish point 1.1.
# existing_attachments_list is something like:
# [ 'https://elog.url.com/logbook/timestamped_filename' ]
msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id)
for attribute, data in attributes.items():
new_data = attributes.get(attribute)
if new_data is not None:
attributes_to_edit[attribute] = new_data
i = 0
existing_attachments_filename_list = list()
for attachment in existing_attachments_list:
# here we accomplish point 1.2. We strip the timestamped_filename from the whole URL.
attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)
existing_attachments_filename_list.append(os.path.basename(attachment)[14:])
i += 1
# let's accomplish 2.2. Loop over all new attachment
duplicate_attachment_list = list()
for new_attachment in new_attachment_list:
# the new_attachment_list is something like:
# [ ('attfileN', ('filename', fileobject)) ]
new_attachment_filename = new_attachment[1][0]
if new_attachment_filename in existing_attachments_filename_list:
# a file with the same name existing already on the server.
# we need to check if the two files are the same.
# read the content of the new file
new_attachment_content = new_attachment[1][1].read()
# don't forget to reset the fileobj to the beginning of the file
new_attachment[1][1].seek(0)
# get the existing attachment content
attachment_index = existing_attachments_filename_list.index(new_attachment_filename)
existing_attachment_content = self.download_attachment(
url=existing_attachments_list[attachment_index],
timeout=timeout
)
# check if the two contents are the same
if new_attachment_content == existing_attachment_content:
# yes. then we don't upload a second copy. we remove the current entry from the list
duplicate_attachment_list.append(new_attachment)
else:
# no. they are not the same file. we will replace the existing file with the new one
# first: we need to remove the attachment from the server using the dedicated method
self.delete_attachment(msg_id, attributes=attributes_to_edit,
attachment_id=attachment_index,
timeout=timeout, text=msg_to_edit)
# now we can remove this attachment from the auxiliary lists.
existing_attachments_filename_list.pop(attachment_index)
existing_attachments_list.pop(attachment_index)
# now we need to rebuild the attributes dictionary for the part concerning the attachments.
# we remove all of them first
keys_to_be_removed = list()
for key in attributes_to_edit.keys():
if key.startswith('attachment'):
keys_to_be_removed.append(key)
if key.startswith('delatt'):
keys_to_be_removed.append(key)
for key in keys_to_be_removed:
del attributes_to_edit[key]
# now we rebuild it
for i, attachment in enumerate(existing_attachments_list):
attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)
# remove all duplicate attachments from the new_attachment_list
for attach in duplicate_attachment_list:
new_attachment_list.remove(attach)
else:
# As we create a new message, specify creation time if not already specified in attributes
if 'When' not in attributes:
attributes['When'] = int(datetime.now().timestamp())
if not attributes_to_edit:
attributes_to_edit = attributes
# Remove any attributes that should not be sent
_remove_reserved_attributes(attributes_to_edit)
# Make requests module think that Text is a "file". This is the only way to force requests to send data as
# multipart/form-data even if there are no attachments. Elog understands only multipart/form-data
new_attachment_list.append(('Text', ('', message.encode('iso-8859-1'))))
# Base attributes are common to all messages
self._add_base_msg_attributes(attributes_to_edit)
# Keys in attributes cannot have certain characters like whitespaces or dashes for the http request
attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit)
# All string values in the attributes must be encoded in latin1
attributes_to_edit = _encode_values(attributes_to_edit)
try:
> response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list,
allow_redirects=False, verify=False, timeout=timeout)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:288:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <requests.adapters.HTTPAdapter object at 0x7feb09b79730>
request = <PreparedRequest [POST]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)
except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)
if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)
if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)
if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)
> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b79310>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError
During handling of the above exception, another exception occurred:
self = <urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection
raise err
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
address = ('localhost', 8080), timeout = None, source_address = None
socket_options = [(6, 1, 1)]
def create_connection(
address: tuple[str, int],
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
source_address: tuple[str, int] | None = None,
socket_options: _TYPE_SOCKET_OPTIONS | None = None,
) -> socket.socket:
"""Connect to *address* and return the socket object.
Convenience function. Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object. Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect. If no *timeout* is supplied, the
global default timeout setting returned by :func:`socket.getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default.
"""
host, port = address
if host.startswith("["):
host = host.strip("[]")
err = None
# Using the value from allowed_gai_family() in the context of getaddrinfo lets
# us select whether to work with IPv4 DNS records, IPv6 records, or both.
# The original create_connection function always returns all records.
family = allowed_gai_family()
try:
host.encode("idna")
except UnicodeError:
raise LocationParseError(f"'{host}', label empty or too long") from None
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
# If provided, set socket level options before connecting.
_set_socket_options(sock, socket_options)
if timeout is not _DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
> sock.connect(sa)
E ConnectionRefusedError: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError
The above exception was the direct cause of the following exception:
self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b7e820>
method = 'GET', url = '/demo/None', body = None
headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None)
redirect = False, assert_same_host = False
timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False
decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None)
destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False
def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.
.. note::
More commonly, it's appropriate to use a convenience method
such as :meth:`request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.
:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.
:param bool preload_content:
If True, the response's body will be preloaded into memory.
:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.
:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme
if headers is None:
headers = self.headers
if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)
if release_conn is None:
release_conn = preload_content
# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)
# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)
conn = None
# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn
http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)
# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]
# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None
# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False
# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)
try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)
conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]
# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise
# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None
# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request
conn.request(
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request
self.endheaders()
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output
self.send(msg)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send
self.connect()
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect
self.sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
raise NameResolutionError(self.host, self, e) from e
except SocketTimeout as e:
raise ConnectTimeoutError(
self,
f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
) from e
except OSError as e:
> raise NewConnectionError(
self, f"Failed to establish a new connection: {e}"
) from e
E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError
The above exception was the direct cause of the following exception:
self = <requests.adapters.HTTPAdapter object at 0x7feb09b7ea00>
request = <PreparedRequest [GET]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = Retry(total=0, connect=None, read=False, redirect=None, status=None)
method = 'GET', url = '/demo/None', response = None
error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused')
_pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b7e820>
_stacktrace = <traceback object at 0x7feb09bbad40>
def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.
:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.
:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)
total = self.total
if total is not None:
total -= 1
connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None
if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1
elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1
elif error:
# Other retry?
if other is not None:
other -= 1
elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status
else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status
history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)
new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)
if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError
During handling of the above exception, another exception occurred:
self = <elog.logbook.Logbook object at 0x7feb09b79e80>, msg_id = None
timeout = None
def _check_if_message_on_server(self, msg_id, timeout=None):
"""Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no
such message.
:param msg_id: ID of message to be checked
:params timeout: The value of timeout to be passed to the get request
:return:
"""
request_headers = dict()
if self._user or self._password:
request_headers['Cookie'] = self._make_user_and_pswd_cookie()
try:
> response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,
verify=False, timeout=timeout)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:581:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:73: in get
return request("get", url, params=params, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <requests.adapters.HTTPAdapter object at 0x7feb09b7ea00>
request = <PreparedRequest [GET]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)
except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)
if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)
if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)
if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)
> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError
During handling of the above exception, another exception occurred:
def test_get_default_elog_instance_with_direct_password_and_real_check():
url = "http://localhost:8080/demo"
user = "robot"
password = "testpassword"
text = "This is a message1"
elog = Elog("http://localhost:8080/demo", user=user, password=password)
try:
> msg_id = elog.post(text)
tests/test_utils_elog.py:22:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
slic/utils/elog.py:16: in post
return self._log.post(*args, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:307: in post
self._check_if_message_on_server(msg_id) # raises exceptions if no message or no response from server
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <elog.logbook.Logbook object at 0x7feb09b79e80>, msg_id = None
timeout = None
def _check_if_message_on_server(self, msg_id, timeout=None):
"""Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no
such message.
:param msg_id: ID of message to be checked
:params timeout: The value of timeout to be passed to the get request
:return:
"""
request_headers = dict()
if self._user or self._password:
request_headers['Cookie'] = self._make_user_and_pswd_cookie()
try:
response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,
verify=False, timeout=timeout)
# If there is no message code 200 will be returned (OK) and _validate_response will not recognise it
# but there will be some error in the html code.
resp_message, resp_headers, resp_msg_id = _validate_response(response)
# If there is no message, code 200 will be returned (OK) but there will be some error indication in
# the html code.
if re.findall('<td.*?class="errormsg".*?>.*?</td>',
resp_message.decode('utf-8', 'ignore'),
flags=re.DOTALL):
raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.')
except requests.Timeout as e:
# Catch here a timeout o the post request.
# Raise the logbook exception and let the user handle it
raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\n' +
'{1}'.format(sys._getframe().f_code.co_name, e))
except requests.RequestException as e:
> raise LogbookServerProblem('No response from the logbook server.\nDetails: ' + '{0}'.format(e))
E elog.logbook_exceptions.LogbookServerProblem: No response from the logbook server.
E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:601: LogbookServerProblem
During handling of the above exception, another exception occurred:
def test_get_default_elog_instance_with_direct_password_and_real_check():
url = "http://localhost:8080/demo"
user = "robot"
password = "testpassword"
text = "This is a message1"
elog = Elog("http://localhost:8080/demo", user=user, password=password)
try:
msg_id = elog.post(text)
except Exception as e:
> pytest.fail(f"elog.post() raised an unexpected exception: {e}")
E Failed: elog.post() raised an unexpected exception: No response from the logbook server.
E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused'))
tests/test_utils_elog.py:24: Failed
____________ test_get_default_elog_instance_asks_password_and_opens ____________
self = <urllib3.connection.HTTPConnection object at 0x7feb09830f40>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection
raise err
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
address = ('localhost', 8080), timeout = None, source_address = None
socket_options = [(6, 1, 1)]
def create_connection(
address: tuple[str, int],
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
source_address: tuple[str, int] | None = None,
socket_options: _TYPE_SOCKET_OPTIONS | None = None,
) -> socket.socket:
"""Connect to *address* and return the socket object.
Convenience function. Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object. Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect. If no *timeout* is supplied, the
global default timeout setting returned by :func:`socket.getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default.
"""
host, port = address
if host.startswith("["):
host = host.strip("[]")
err = None
# Using the value from allowed_gai_family() in the context of getaddrinfo lets
# us select whether to work with IPv4 DNS records, IPv6 records, or both.
# The original create_connection function always returns all records.
family = allowed_gai_family()
try:
host.encode("idna")
except UnicodeError:
raise LocationParseError(f"'{host}', label empty or too long") from None
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
# If provided, set socket level options before connecting.
_set_socket_options(sock, socket_options)
if timeout is not _DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
> sock.connect(sa)
E ConnectionRefusedError: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError
The above exception was the direct cause of the following exception:
self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09830bb0>
method = 'POST', url = '/demo/'
body = b'--aa75161c22b288663152f49dada5f35f\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--aa75161c22b288...Disposition: form-data; name="Text"; filename=""\r\n\r\nThis is a message2\r\n--aa75161c22b288663152f49dada5f35f--\r\n'
headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=aa75161c22b288663152f49dada5f35f'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None)
redirect = False, assert_same_host = False
timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False
decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None)
destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False
def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.
.. note::
More commonly, it's appropriate to use a convenience method
such as :meth:`request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.
:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.
:param bool preload_content:
If True, the response's body will be preloaded into memory.
:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.
:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme
if headers is None:
headers = self.headers
if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)
if release_conn is None:
release_conn = preload_content
# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)
# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)
conn = None
# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn
http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)
# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]
# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None
# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False
# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)
try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)
conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]
# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise
# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None
# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request
conn.request(
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request
self.endheaders()
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output
self.send(msg)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send
self.connect()
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect
self.sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connection.HTTPConnection object at 0x7feb09830f40>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
raise NameResolutionError(self.host, self, e) from e
except SocketTimeout as e:
raise ConnectTimeoutError(
self,
f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
) from e
except OSError as e:
> raise NewConnectionError(
self, f"Failed to establish a new connection: {e}"
) from e
E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb09830f40>: Failed to establish a new connection: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError
The above exception was the direct cause of the following exception:
self = <requests.adapters.HTTPAdapter object at 0x7feb0522b790>
request = <PreparedRequest [POST]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = Retry(total=0, connect=None, read=False, redirect=None, status=None)
method = 'POST', url = '/demo/', response = None
error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09830f40>: Failed to establish a new connection: [Errno 111] Connection refused')
_pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09830bb0>
_stacktrace = <traceback object at 0x7feb09590040>
def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.
:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.
:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)
total = self.total
if total is not None:
total -= 1
connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None
if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1
elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1
elif error:
# Other retry?
if other is not None:
other -= 1
elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status
else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status
history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)
new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)
if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09830f40>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError
During handling of the above exception, another exception occurred:
self = <elog.logbook.Logbook object at 0x7feb05e26fd0>
message = 'This is a message2', msg_id = None, reply = False
attributes = {'Author': 'robot', 'When': 1756376002, 'cmd': 'Submit', 'exp': 'demo', ...}
attachments = [], suppress_email_notification = False, encoding = None
timeout = None, kwargs = {'Author': 'robot'}
new_attachment_list = [('Text', ('', b'This is a message2'))]
objects_to_close = []
attributes_to_edit = {'Author': b'robot', 'When': 1756376002, 'cmd': b'Submit', 'exp': b'demo', ...}
def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None,
suppress_email_notification=False, encoding=None, timeout=None, **kwargs):
"""
Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing
message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id
of the newly created message.
:param message: string with message text
:param msg_id: ID number of message to edit or reply. If not specified new message is created.
:param reply: If 'True' reply to existing message is created instead of editing it
:param attributes: Dictionary of attributes. Following attributes are used internally by the elog and will be
ignored: Text, Date, Encoding, Reply to, In reply to, Locked by, Attachment
:param attachments: list of:
- file like objects which read() will return bytes (if file_like_object.name is not
defined, default name "attachment<i>" will be used.
- paths to the files
All items will be appended as attachment to the elog entry. In case of unknown
attachment an exception LogbookInvalidAttachment will be raised.
:param suppress_email_notification: If set to True or 1, E-Mail notification will be suppressed, defaults to False.
:param encoding: Defines encoding of the message. Can be: 'plain' -> plain text, 'html'->html-text,
'ELCode' --> elog formatting syntax
:param timeout: Define the timeout to be used by the post request. Its value is directly passed to the requests
post. Use None to disable the request timeout.
:param kwargs: Anything in the kwargs will be interpreted as attribute. e.g.: logbook.post('Test text',
Author='Rok Vintar), "Author" will be sent as an attribute. If named same as one of the
attributes defined in "attributes", kwargs will have priority.
:return: msg_id
"""
attributes = attributes or {}
attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority
attachments = attachments or []
if encoding is not None:
if encoding not in ['plain', 'HTML', 'ELCode']:
raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.')
attributes['Encoding'] = encoding
if suppress_email_notification:
attributes["suppress"] = 1
# THE ATTACHMENT STRATEGY WHEN DEALING WITH POST MODIFICATION
#
# 1. Does the message on the server have already attachments?
# 1.1 - We read the message getting the existing attachment list.
# 1.2 - Add to the attributes dictionary one line for each attachment like this:
# attributes['attachmentN'] = timestamped_filename_name
#
# 2. Do we have new attachments?
# 2.1 - Those are in the new_attachment_list. This is a list of this type:
# [ ('attfileN', ('filename', fileobject)) ]
# 2.2 - We need to loop over all the new attachments:
# 2.2.1 - Does a file already on the server with the same name exist?
# 2.2.1.1 - No: OK. Then we go ahead with the next attachment.
# 2.2.1.2 - Yes:
# 2.2.1.2.1 - Are the two files identical?
# 2.2.1.2.1.1 - Yes: then we remove this current entry from the new_attachment_list and we leave the one
# already on server.
# 2.2.1.2.1.2 - No:
# 2.2.1.2.1.2.1 - Then the file has been update.
# 2.2.1.2.1.2.2 - We need to remove the file on server first (using special post)
# 2.2.1.2.1.2.3 - We have to remove the old attachment from the attributes dictionary.
#
if attachments:
# here we accomplish point 2.1.
# new_attachment_list is something like [ ('attfileN', ('filename', fileobject)) ]
new_attachment_list, objects_to_close = self._prepare_attachments(attachments)
else:
objects_to_close = list()
new_attachment_list = list()
attributes_to_edit = dict()
if msg_id:
# Message exists, we can continue
if reply:
# Verify that there is a message on the server, otherwise do not reply to it!
self._check_if_message_on_server(msg_id) # raises exception in case of none existing message
attributes['reply_to'] = str(msg_id)
else: # Edit existing
attributes['edit_id'] = str(msg_id)
attributes['skiplock'] = '1'
# here we accomplish point 1.1.
# existing_attachments_list is something like:
# [ 'https://elog.url.com/logbook/timestamped_filename' ]
msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id)
for attribute, data in attributes.items():
new_data = attributes.get(attribute)
if new_data is not None:
attributes_to_edit[attribute] = new_data
i = 0
existing_attachments_filename_list = list()
for attachment in existing_attachments_list:
# here we accomplish point 1.2. We strip the timestamped_filename from the whole URL.
attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)
existing_attachments_filename_list.append(os.path.basename(attachment)[14:])
i += 1
# let's accomplish 2.2. Loop over all new attachment
duplicate_attachment_list = list()
for new_attachment in new_attachment_list:
# the new_attachment_list is something like:
# [ ('attfileN', ('filename', fileobject)) ]
new_attachment_filename = new_attachment[1][0]
if new_attachment_filename in existing_attachments_filename_list:
# a file with the same name existing already on the server.
# we need to check if the two files are the same.
# read the content of the new file
new_attachment_content = new_attachment[1][1].read()
# don't forget to reset the fileobj to the beginning of the file
new_attachment[1][1].seek(0)
# get the existing attachment content
attachment_index = existing_attachments_filename_list.index(new_attachment_filename)
existing_attachment_content = self.download_attachment(
url=existing_attachments_list[attachment_index],
timeout=timeout
)
# check if the two contents are the same
if new_attachment_content == existing_attachment_content:
# yes. then we don't upload a second copy. we remove the current entry from the list
duplicate_attachment_list.append(new_attachment)
else:
# no. they are not the same file. we will replace the existing file with the new one
# first: we need to remove the attachment from the server using the dedicated method
self.delete_attachment(msg_id, attributes=attributes_to_edit,
attachment_id=attachment_index,
timeout=timeout, text=msg_to_edit)
# now we can remove this attachment from the auxiliary lists.
existing_attachments_filename_list.pop(attachment_index)
existing_attachments_list.pop(attachment_index)
# now we need to rebuild the attributes dictionary for the part concerning the attachments.
# we remove all of them first
keys_to_be_removed = list()
for key in attributes_to_edit.keys():
if key.startswith('attachment'):
keys_to_be_removed.append(key)
if key.startswith('delatt'):
keys_to_be_removed.append(key)
for key in keys_to_be_removed:
del attributes_to_edit[key]
# now we rebuild it
for i, attachment in enumerate(existing_attachments_list):
attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)
# remove all duplicate attachments from the new_attachment_list
for attach in duplicate_attachment_list:
new_attachment_list.remove(attach)
else:
# As we create a new message, specify creation time if not already specified in attributes
if 'When' not in attributes:
attributes['When'] = int(datetime.now().timestamp())
if not attributes_to_edit:
attributes_to_edit = attributes
# Remove any attributes that should not be sent
_remove_reserved_attributes(attributes_to_edit)
# Make requests module think that Text is a "file". This is the only way to force requests to send data as
# multipart/form-data even if there are no attachments. Elog understands only multipart/form-data
new_attachment_list.append(('Text', ('', message.encode('iso-8859-1'))))
# Base attributes are common to all messages
self._add_base_msg_attributes(attributes_to_edit)
# Keys in attributes cannot have certain characters like whitespaces or dashes for the http request
attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit)
# All string values in the attributes must be encoded in latin1
attributes_to_edit = _encode_values(attributes_to_edit)
try:
> response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list,
allow_redirects=False, verify=False, timeout=timeout)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:288:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <requests.adapters.HTTPAdapter object at 0x7feb0522b790>
request = <PreparedRequest [POST]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)
except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)
if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)
if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)
if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)
> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09830f40>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError
During handling of the above exception, another exception occurred:
self = <urllib3.connection.HTTPConnection object at 0x7feb098025b0>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection
raise err
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
address = ('localhost', 8080), timeout = None, source_address = None
socket_options = [(6, 1, 1)]
def create_connection(
address: tuple[str, int],
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
source_address: tuple[str, int] | None = None,
socket_options: _TYPE_SOCKET_OPTIONS | None = None,
) -> socket.socket:
"""Connect to *address* and return the socket object.
Convenience function. Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object. Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect. If no *timeout* is supplied, the
global default timeout setting returned by :func:`socket.getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default.
"""
host, port = address
if host.startswith("["):
host = host.strip("[]")
err = None
# Using the value from allowed_gai_family() in the context of getaddrinfo lets
# us select whether to work with IPv4 DNS records, IPv6 records, or both.
# The original create_connection function always returns all records.
family = allowed_gai_family()
try:
host.encode("idna")
except UnicodeError:
raise LocationParseError(f"'{host}', label empty or too long") from None
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
# If provided, set socket level options before connecting.
_set_socket_options(sock, socket_options)
if timeout is not _DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
> sock.connect(sa)
E ConnectionRefusedError: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError
The above exception was the direct cause of the following exception:
self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09830640>
method = 'GET', url = '/demo/None', body = None
headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None)
redirect = False, assert_same_host = False
timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False
decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None)
destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False
def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.
.. note::
More commonly, it's appropriate to use a convenience method
such as :meth:`request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.
:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.
:param bool preload_content:
If True, the response's body will be preloaded into memory.
:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.
:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme
if headers is None:
headers = self.headers
if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)
if release_conn is None:
release_conn = preload_content
# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)
# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)
conn = None
# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn
http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)
# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]
# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None
# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False
# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)
try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)
conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]
# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise
# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None
# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request
conn.request(
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request
self.endheaders()
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output
self.send(msg)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send
self.connect()
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect
self.sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connection.HTTPConnection object at 0x7feb098025b0>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
raise NameResolutionError(self.host, self, e) from e
except SocketTimeout as e:
raise ConnectTimeoutError(
self,
f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
) from e
except OSError as e:
> raise NewConnectionError(
self, f"Failed to establish a new connection: {e}"
) from e
E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError
The above exception was the direct cause of the following exception:
self = <requests.adapters.HTTPAdapter object at 0x7feb098307f0>
request = <PreparedRequest [GET]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = Retry(total=0, connect=None, read=False, redirect=None, status=None)
method = 'GET', url = '/demo/None', response = None
error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused')
_pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09830640>
_stacktrace = <traceback object at 0x7feb09803440>
def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.
:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.
:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)
total = self.total
if total is not None:
total -= 1
connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None
if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1
elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1
elif error:
# Other retry?
if other is not None:
other -= 1
elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status
else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status
history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)
new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)
if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError
During handling of the above exception, another exception occurred:
self = <elog.logbook.Logbook object at 0x7feb05e26fd0>, msg_id = None
timeout = None
def _check_if_message_on_server(self, msg_id, timeout=None):
"""Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no
such message.
:param msg_id: ID of message to be checked
:params timeout: The value of timeout to be passed to the get request
:return:
"""
request_headers = dict()
if self._user or self._password:
request_headers['Cookie'] = self._make_user_and_pswd_cookie()
try:
> response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,
verify=False, timeout=timeout)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:581:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:73: in get
return request("get", url, params=params, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <requests.adapters.HTTPAdapter object at 0x7feb098307f0>
request = <PreparedRequest [GET]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)
except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)
if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)
if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)
if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)
> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError
During handling of the above exception, another exception occurred:
mock_home = <MagicMock name='home' id='140647452478240'>
mock_getpass = <MagicMock name='getpass' id='140647452477088'>
@patch("slic.utils.elog.getpass")
@patch("slic.utils.elog.Path.home")
def test_get_default_elog_instance_asks_password_and_opens(mock_home, mock_getpass):
mock_home.return_value = Path("/does/not/exist") # Fausse home → lecture échoue
mock_getpass.return_value = "testpassword"
user = "robot"
text = "This is a message2"
url = "http://localhost:8080/demo"
elog = Elog("http://localhost:8080/demo", user=user)
try:
> msd_id = elog.post(text)
tests/test_utils_elog.py:55:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
slic/utils/elog.py:16: in post
return self._log.post(*args, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:307: in post
self._check_if_message_on_server(msg_id) # raises exceptions if no message or no response from server
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <elog.logbook.Logbook object at 0x7feb05e26fd0>, msg_id = None
timeout = None
def _check_if_message_on_server(self, msg_id, timeout=None):
"""Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no
such message.
:param msg_id: ID of message to be checked
:params timeout: The value of timeout to be passed to the get request
:return:
"""
request_headers = dict()
if self._user or self._password:
request_headers['Cookie'] = self._make_user_and_pswd_cookie()
try:
response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,
verify=False, timeout=timeout)
# If there is no message code 200 will be returned (OK) and _validate_response will not recognise it
# but there will be some error in the html code.
resp_message, resp_headers, resp_msg_id = _validate_response(response)
# If there is no message, code 200 will be returned (OK) but there will be some error indication in
# the html code.
if re.findall('<td.*?class="errormsg".*?>.*?</td>',
resp_message.decode('utf-8', 'ignore'),
flags=re.DOTALL):
raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.')
except requests.Timeout as e:
# Catch here a timeout o the post request.
# Raise the logbook exception and let the user handle it
raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\n' +
'{1}'.format(sys._getframe().f_code.co_name, e))
except requests.RequestException as e:
> raise LogbookServerProblem('No response from the logbook server.\nDetails: ' + '{0}'.format(e))
E elog.logbook_exceptions.LogbookServerProblem: No response from the logbook server.
E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:601: LogbookServerProblem
During handling of the above exception, another exception occurred:
mock_home = <MagicMock name='home' id='140647452478240'>
mock_getpass = <MagicMock name='getpass' id='140647452477088'>
@patch("slic.utils.elog.getpass")
@patch("slic.utils.elog.Path.home")
def test_get_default_elog_instance_asks_password_and_opens(mock_home, mock_getpass):
mock_home.return_value = Path("/does/not/exist") # Fausse home → lecture échoue
mock_getpass.return_value = "testpassword"
user = "robot"
text = "This is a message2"
url = "http://localhost:8080/demo"
elog = Elog("http://localhost:8080/demo", user=user)
try:
msd_id = elog.post(text)
except Exception as e:
> pytest.fail(f"elog.post() raised an unexpected exception: {e}")
E Failed: elog.post() raised an unexpected exception: No response from the logbook server.
E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused'))
tests/test_utils_elog.py:57: Failed
----------------------------- Captured stdout call -----------------------------
Enter elog password for user: robot
_____________________ test_get_default_elog_with_path_home _____________________
self = <urllib3.connection.HTTPConnection object at 0x7feb09937130>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection
raise err
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
address = ('localhost', 8080), timeout = None, source_address = None
socket_options = [(6, 1, 1)]
def create_connection(
address: tuple[str, int],
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
source_address: tuple[str, int] | None = None,
socket_options: _TYPE_SOCKET_OPTIONS | None = None,
) -> socket.socket:
"""Connect to *address* and return the socket object.
Convenience function. Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object. Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect. If no *timeout* is supplied, the
global default timeout setting returned by :func:`socket.getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default.
"""
host, port = address
if host.startswith("["):
host = host.strip("[]")
err = None
# Using the value from allowed_gai_family() in the context of getaddrinfo lets
# us select whether to work with IPv4 DNS records, IPv6 records, or both.
# The original create_connection function always returns all records.
family = allowed_gai_family()
try:
host.encode("idna")
except UnicodeError:
raise LocationParseError(f"'{host}', label empty or too long") from None
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
# If provided, set socket level options before connecting.
_set_socket_options(sock, socket_options)
if timeout is not _DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
> sock.connect(sa)
E ConnectionRefusedError: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError
The above exception was the direct cause of the following exception:
self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09937670>
method = 'POST', url = '/demo/'
body = b'--e76de29c11540daf53cb0ad4febce9b6\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--e76de29c11540d...Disposition: form-data; name="Text"; filename=""\r\n\r\nThis is a message3\r\n--e76de29c11540daf53cb0ad4febce9b6--\r\n'
headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=e76de29c11540daf53cb0ad4febce9b6'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None)
redirect = False, assert_same_host = False
timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False
decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None)
destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False
def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.
.. note::
More commonly, it's appropriate to use a convenience method
such as :meth:`request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.
:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.
:param bool preload_content:
If True, the response's body will be preloaded into memory.
:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.
:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme
if headers is None:
headers = self.headers
if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)
if release_conn is None:
release_conn = preload_content
# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)
# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)
conn = None
# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn
http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)
# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]
# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None
# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False
# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)
try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)
conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]
# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise
# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None
# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request
conn.request(
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request
self.endheaders()
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output
self.send(msg)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send
self.connect()
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect
self.sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connection.HTTPConnection object at 0x7feb09937130>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
raise NameResolutionError(self.host, self, e) from e
except SocketTimeout as e:
raise ConnectTimeoutError(
self,
f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
) from e
except OSError as e:
> raise NewConnectionError(
self, f"Failed to establish a new connection: {e}"
) from e
E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb09937130>: Failed to establish a new connection: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError
The above exception was the direct cause of the following exception:
self = <requests.adapters.HTTPAdapter object at 0x7feb09937850>
request = <PreparedRequest [POST]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = Retry(total=0, connect=None, read=False, redirect=None, status=None)
method = 'POST', url = '/demo/', response = None
error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09937130>: Failed to establish a new connection: [Errno 111] Connection refused')
_pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09937670>
_stacktrace = <traceback object at 0x7feb0965e740>
def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.
:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.
:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)
total = self.total
if total is not None:
total -= 1
connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None
if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1
elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1
elif error:
# Other retry?
if other is not None:
other -= 1
elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status
else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status
history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)
new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)
if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09937130>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError
During handling of the above exception, another exception occurred:
self = <elog.logbook.Logbook object at 0x7feb09937280>
message = 'This is a message3', msg_id = None, reply = False
attributes = {'Author': 'robot', 'When': 1756376002, 'cmd': 'Submit', 'exp': 'demo', ...}
attachments = [], suppress_email_notification = False, encoding = None
timeout = None, kwargs = {'Author': 'robot'}
new_attachment_list = [('Text', ('', b'This is a message3'))]
objects_to_close = []
attributes_to_edit = {'Author': b'robot', 'When': 1756376002, 'cmd': b'Submit', 'exp': b'demo', ...}
def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None,
suppress_email_notification=False, encoding=None, timeout=None, **kwargs):
"""
Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing
message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id
of the newly created message.
:param message: string with message text
:param msg_id: ID number of message to edit or reply. If not specified new message is created.
:param reply: If 'True' reply to existing message is created instead of editing it
:param attributes: Dictionary of attributes. Following attributes are used internally by the elog and will be
ignored: Text, Date, Encoding, Reply to, In reply to, Locked by, Attachment
:param attachments: list of:
- file like objects which read() will return bytes (if file_like_object.name is not
defined, default name "attachment<i>" will be used.
- paths to the files
All items will be appended as attachment to the elog entry. In case of unknown
attachment an exception LogbookInvalidAttachment will be raised.
:param suppress_email_notification: If set to True or 1, E-Mail notification will be suppressed, defaults to False.
:param encoding: Defines encoding of the message. Can be: 'plain' -> plain text, 'html'->html-text,
'ELCode' --> elog formatting syntax
:param timeout: Define the timeout to be used by the post request. Its value is directly passed to the requests
post. Use None to disable the request timeout.
:param kwargs: Anything in the kwargs will be interpreted as attribute. e.g.: logbook.post('Test text',
Author='Rok Vintar), "Author" will be sent as an attribute. If named same as one of the
attributes defined in "attributes", kwargs will have priority.
:return: msg_id
"""
attributes = attributes or {}
attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority
attachments = attachments or []
if encoding is not None:
if encoding not in ['plain', 'HTML', 'ELCode']:
raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.')
attributes['Encoding'] = encoding
if suppress_email_notification:
attributes["suppress"] = 1
# THE ATTACHMENT STRATEGY WHEN DEALING WITH POST MODIFICATION
#
# 1. Does the message on the server have already attachments?
# 1.1 - We read the message getting the existing attachment list.
# 1.2 - Add to the attributes dictionary one line for each attachment like this:
# attributes['attachmentN'] = timestamped_filename_name
#
# 2. Do we have new attachments?
# 2.1 - Those are in the new_attachment_list. This is a list of this type:
# [ ('attfileN', ('filename', fileobject)) ]
# 2.2 - We need to loop over all the new attachments:
# 2.2.1 - Does a file already on the server with the same name exist?
# 2.2.1.1 - No: OK. Then we go ahead with the next attachment.
# 2.2.1.2 - Yes:
# 2.2.1.2.1 - Are the two files identical?
# 2.2.1.2.1.1 - Yes: then we remove this current entry from the new_attachment_list and we leave the one
# already on server.
# 2.2.1.2.1.2 - No:
# 2.2.1.2.1.2.1 - Then the file has been update.
# 2.2.1.2.1.2.2 - We need to remove the file on server first (using special post)
# 2.2.1.2.1.2.3 - We have to remove the old attachment from the attributes dictionary.
#
if attachments:
# here we accomplish point 2.1.
# new_attachment_list is something like [ ('attfileN', ('filename', fileobject)) ]
new_attachment_list, objects_to_close = self._prepare_attachments(attachments)
else:
objects_to_close = list()
new_attachment_list = list()
attributes_to_edit = dict()
if msg_id:
# Message exists, we can continue
if reply:
# Verify that there is a message on the server, otherwise do not reply to it!
self._check_if_message_on_server(msg_id) # raises exception in case of none existing message
attributes['reply_to'] = str(msg_id)
else: # Edit existing
attributes['edit_id'] = str(msg_id)
attributes['skiplock'] = '1'
# here we accomplish point 1.1.
# existing_attachments_list is something like:
# [ 'https://elog.url.com/logbook/timestamped_filename' ]
msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id)
for attribute, data in attributes.items():
new_data = attributes.get(attribute)
if new_data is not None:
attributes_to_edit[attribute] = new_data
i = 0
existing_attachments_filename_list = list()
for attachment in existing_attachments_list:
# here we accomplish point 1.2. We strip the timestamped_filename from the whole URL.
attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)
existing_attachments_filename_list.append(os.path.basename(attachment)[14:])
i += 1
# let's accomplish 2.2. Loop over all new attachment
duplicate_attachment_list = list()
for new_attachment in new_attachment_list:
# the new_attachment_list is something like:
# [ ('attfileN', ('filename', fileobject)) ]
new_attachment_filename = new_attachment[1][0]
if new_attachment_filename in existing_attachments_filename_list:
# a file with the same name existing already on the server.
# we need to check if the two files are the same.
# read the content of the new file
new_attachment_content = new_attachment[1][1].read()
# don't forget to reset the fileobj to the beginning of the file
new_attachment[1][1].seek(0)
# get the existing attachment content
attachment_index = existing_attachments_filename_list.index(new_attachment_filename)
existing_attachment_content = self.download_attachment(
url=existing_attachments_list[attachment_index],
timeout=timeout
)
# check if the two contents are the same
if new_attachment_content == existing_attachment_content:
# yes. then we don't upload a second copy. we remove the current entry from the list
duplicate_attachment_list.append(new_attachment)
else:
# no. they are not the same file. we will replace the existing file with the new one
# first: we need to remove the attachment from the server using the dedicated method
self.delete_attachment(msg_id, attributes=attributes_to_edit,
attachment_id=attachment_index,
timeout=timeout, text=msg_to_edit)
# now we can remove this attachment from the auxiliary lists.
existing_attachments_filename_list.pop(attachment_index)
existing_attachments_list.pop(attachment_index)
# now we need to rebuild the attributes dictionary for the part concerning the attachments.
# we remove all of them first
keys_to_be_removed = list()
for key in attributes_to_edit.keys():
if key.startswith('attachment'):
keys_to_be_removed.append(key)
if key.startswith('delatt'):
keys_to_be_removed.append(key)
for key in keys_to_be_removed:
del attributes_to_edit[key]
# now we rebuild it
for i, attachment in enumerate(existing_attachments_list):
attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)
# remove all duplicate attachments from the new_attachment_list
for attach in duplicate_attachment_list:
new_attachment_list.remove(attach)
else:
# As we create a new message, specify creation time if not already specified in attributes
if 'When' not in attributes:
attributes['When'] = int(datetime.now().timestamp())
if not attributes_to_edit:
attributes_to_edit = attributes
# Remove any attributes that should not be sent
_remove_reserved_attributes(attributes_to_edit)
# Make requests module think that Text is a "file". This is the only way to force requests to send data as
# multipart/form-data even if there are no attachments. Elog understands only multipart/form-data
new_attachment_list.append(('Text', ('', message.encode('iso-8859-1'))))
# Base attributes are common to all messages
self._add_base_msg_attributes(attributes_to_edit)
# Keys in attributes cannot have certain characters like whitespaces or dashes for the http request
attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit)
# All string values in the attributes must be encoded in latin1
attributes_to_edit = _encode_values(attributes_to_edit)
try:
> response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list,
allow_redirects=False, verify=False, timeout=timeout)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:288:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <requests.adapters.HTTPAdapter object at 0x7feb09937850>
request = <PreparedRequest [POST]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)
except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)
if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)
if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)
if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)
> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09937130>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError
During handling of the above exception, another exception occurred:
self = <urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection
raise err
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
address = ('localhost', 8080), timeout = None, source_address = None
socket_options = [(6, 1, 1)]
def create_connection(
address: tuple[str, int],
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
source_address: tuple[str, int] | None = None,
socket_options: _TYPE_SOCKET_OPTIONS | None = None,
) -> socket.socket:
"""Connect to *address* and return the socket object.
Convenience function. Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object. Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect. If no *timeout* is supplied, the
global default timeout setting returned by :func:`socket.getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default.
"""
host, port = address
if host.startswith("["):
host = host.strip("[]")
err = None
# Using the value from allowed_gai_family() in the context of getaddrinfo lets
# us select whether to work with IPv4 DNS records, IPv6 records, or both.
# The original create_connection function always returns all records.
family = allowed_gai_family()
try:
host.encode("idna")
except UnicodeError:
raise LocationParseError(f"'{host}', label empty or too long") from None
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
# If provided, set socket level options before connecting.
_set_socket_options(sock, socket_options)
if timeout is not _DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
> sock.connect(sa)
E ConnectionRefusedError: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError
The above exception was the direct cause of the following exception:
self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb098b2730>
method = 'GET', url = '/demo/None', body = None
headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None)
redirect = False, assert_same_host = False
timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False
decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None)
destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False
def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.
.. note::
More commonly, it's appropriate to use a convenience method
such as :meth:`request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.
:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.
:param bool preload_content:
If True, the response's body will be preloaded into memory.
:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.
:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme
if headers is None:
headers = self.headers
if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)
if release_conn is None:
release_conn = preload_content
# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)
# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)
conn = None
# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn
http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)
# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]
# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None
# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False
# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)
try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)
conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]
# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise
# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None
# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request
conn.request(
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request
self.endheaders()
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output
self.send(msg)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send
self.connect()
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect
self.sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
raise NameResolutionError(self.host, self, e) from e
except SocketTimeout as e:
raise ConnectTimeoutError(
self,
f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
) from e
except OSError as e:
> raise NewConnectionError(
self, f"Failed to establish a new connection: {e}"
) from e
E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError
The above exception was the direct cause of the following exception:
self = <requests.adapters.HTTPAdapter object at 0x7feb098b25b0>
request = <PreparedRequest [GET]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = Retry(total=0, connect=None, read=False, redirect=None, status=None)
method = 'GET', url = '/demo/None', response = None
error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused')
_pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb098b2730>
_stacktrace = <traceback object at 0x7feb097c29c0>
def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.
:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.
:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)
total = self.total
if total is not None:
total -= 1
connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None
if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1
elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1
elif error:
# Other retry?
if other is not None:
other -= 1
elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status
else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status
history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)
new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)
if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError
During handling of the above exception, another exception occurred:
self = <elog.logbook.Logbook object at 0x7feb09937280>, msg_id = None
timeout = None
def _check_if_message_on_server(self, msg_id, timeout=None):
"""Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no
such message.
:param msg_id: ID of message to be checked
:params timeout: The value of timeout to be passed to the get request
:return:
"""
request_headers = dict()
if self._user or self._password:
request_headers['Cookie'] = self._make_user_and_pswd_cookie()
try:
> response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,
verify=False, timeout=timeout)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:581:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:73: in get
return request("get", url, params=params, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <requests.adapters.HTTPAdapter object at 0x7feb098b25b0>
request = <PreparedRequest [GET]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)
except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)
if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)
if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)
if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)
> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError
During handling of the above exception, another exception occurred:
mock_home = <MagicMock name='home' id='140647451303744'>
mock_getuser = <MagicMock name='getuser' id='140647451733824'>
mock_getpass = <MagicMock name='getpass' id='140647453841488'>
@patch("slic.utils.elog.getpass")
@patch("slic.utils.elog.getuser")
@patch("slic.utils.elog.Path.home")
def test_get_default_elog_with_path_home(mock_home, mock_getuser, mock_getpass):
fake_user = "robot"
fake_pw = "testpassword"
mock_getuser.return_value = fake_user
mock_getpass.return_value = fake_pw # fallback safety
text = "This is a message3"
url = "http://localhost:8080/demo"
tmp_home = Path("/tmp/fake_home_for_robot")
tmp_home.mkdir(parents=True, exist_ok=True)
pw_file = tmp_home / ".elog_psi"
pw_file.write_text(fake_pw)
mock_home.return_value = tmp_home
try:
elog = Elog("http://localhost:8080/demo")
try:
> msg_id = elog.post(text)
tests/test_utils_elog.py:90:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
slic/utils/elog.py:16: in post
return self._log.post(*args, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:307: in post
self._check_if_message_on_server(msg_id) # raises exceptions if no message or no response from server
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <elog.logbook.Logbook object at 0x7feb09937280>, msg_id = None
timeout = None
def _check_if_message_on_server(self, msg_id, timeout=None):
"""Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no
such message.
:param msg_id: ID of message to be checked
:params timeout: The value of timeout to be passed to the get request
:return:
"""
request_headers = dict()
if self._user or self._password:
request_headers['Cookie'] = self._make_user_and_pswd_cookie()
try:
response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,
verify=False, timeout=timeout)
# If there is no message code 200 will be returned (OK) and _validate_response will not recognise it
# but there will be some error in the html code.
resp_message, resp_headers, resp_msg_id = _validate_response(response)
# If there is no message, code 200 will be returned (OK) but there will be some error indication in
# the html code.
if re.findall('<td.*?class="errormsg".*?>.*?</td>',
resp_message.decode('utf-8', 'ignore'),
flags=re.DOTALL):
raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.')
except requests.Timeout as e:
# Catch here a timeout o the post request.
# Raise the logbook exception and let the user handle it
raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\n' +
'{1}'.format(sys._getframe().f_code.co_name, e))
except requests.RequestException as e:
> raise LogbookServerProblem('No response from the logbook server.\nDetails: ' + '{0}'.format(e))
E elog.logbook_exceptions.LogbookServerProblem: No response from the logbook server.
E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:601: LogbookServerProblem
During handling of the above exception, another exception occurred:
mock_home = <MagicMock name='home' id='140647451303744'>
mock_getuser = <MagicMock name='getuser' id='140647451733824'>
mock_getpass = <MagicMock name='getpass' id='140647453841488'>
@patch("slic.utils.elog.getpass")
@patch("slic.utils.elog.getuser")
@patch("slic.utils.elog.Path.home")
def test_get_default_elog_with_path_home(mock_home, mock_getuser, mock_getpass):
fake_user = "robot"
fake_pw = "testpassword"
mock_getuser.return_value = fake_user
mock_getpass.return_value = fake_pw # fallback safety
text = "This is a message3"
url = "http://localhost:8080/demo"
tmp_home = Path("/tmp/fake_home_for_robot")
tmp_home.mkdir(parents=True, exist_ok=True)
pw_file = tmp_home / ".elog_psi"
pw_file.write_text(fake_pw)
mock_home.return_value = tmp_home
try:
elog = Elog("http://localhost:8080/demo")
try:
msg_id = elog.post(text)
except Exception as e:
> pytest.fail(f"elog.post() raised an unexpected exception: {e}")
E Failed: elog.post() raised an unexpected exception: No response from the logbook server.
E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused'))
tests/test_utils_elog.py:92: Failed
_______________________________ test_screenshot ________________________________
self = <urllib3.connection.HTTPConnection object at 0x7feb0958cb20>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection
raise err
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
address = ('localhost', 8080), timeout = None, source_address = None
socket_options = [(6, 1, 1)]
def create_connection(
address: tuple[str, int],
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
source_address: tuple[str, int] | None = None,
socket_options: _TYPE_SOCKET_OPTIONS | None = None,
) -> socket.socket:
"""Connect to *address* and return the socket object.
Convenience function. Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object. Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect. If no *timeout* is supplied, the
global default timeout setting returned by :func:`socket.getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default.
"""
host, port = address
if host.startswith("["):
host = host.strip("[]")
err = None
# Using the value from allowed_gai_family() in the context of getaddrinfo lets
# us select whether to work with IPv4 DNS records, IPv6 records, or both.
# The original create_connection function always returns all records.
family = allowed_gai_family()
try:
host.encode("idna")
except UnicodeError:
raise LocationParseError(f"'{host}', label empty or too long") from None
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
# If provided, set socket level options before connecting.
_set_socket_options(sock, socket_options)
if timeout is not _DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
> sock.connect(sa)
E ConnectionRefusedError: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError
The above exception was the direct cause of the following exception:
self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb0977c0a0>
method = 'POST', url = '/demo/'
body = b'--1194c6bfc5b78a946fff64f5d06636c0\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--1194c6bfc5b78a...-data; name="Text"; filename=""\r\n\r\nSCREENSHOT_INTEGRATION_TEST_MSG_456\r\n--1194c6bfc5b78a946fff64f5d06636c0--\r\n'
headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '889', 'Content-Type': 'multipart/form-data; boundary=1194c6bfc5b78a946fff64f5d06636c0'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None)
redirect = False, assert_same_host = False
timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False
decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None)
destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False
def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.
.. note::
More commonly, it's appropriate to use a convenience method
such as :meth:`request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.
:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.
:param bool preload_content:
If True, the response's body will be preloaded into memory.
:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.
:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme
if headers is None:
headers = self.headers
if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)
if release_conn is None:
release_conn = preload_content
# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)
# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)
conn = None
# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn
http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)
# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]
# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None
# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False
# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)
try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)
conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]
# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise
# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None
# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request
conn.request(
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request
self.endheaders()
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output
self.send(msg)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send
self.connect()
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect
self.sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connection.HTTPConnection object at 0x7feb0958cb20>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
raise NameResolutionError(self.host, self, e) from e
except SocketTimeout as e:
raise ConnectTimeoutError(
self,
f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
) from e
except OSError as e:
> raise NewConnectionError(
self, f"Failed to establish a new connection: {e}"
) from e
E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb0958cb20>: Failed to establish a new connection: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError
The above exception was the direct cause of the following exception:
self = <requests.adapters.HTTPAdapter object at 0x7feb0958c490>
request = <PreparedRequest [POST]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = Retry(total=0, connect=None, read=False, redirect=None, status=None)
method = 'POST', url = '/demo/', response = None
error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb0958cb20>: Failed to establish a new connection: [Errno 111] Connection refused')
_pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb0977c0a0>
_stacktrace = <traceback object at 0x7feb09808600>
def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.
:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.
:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)
total = self.total
if total is not None:
total -= 1
connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None
if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1
elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1
elif error:
# Other retry?
if other is not None:
other -= 1
elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status
else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status
history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)
new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)
if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb0958cb20>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError
During handling of the above exception, another exception occurred:
self = <elog.logbook.Logbook object at 0x7feb0977c5b0>
message = 'SCREENSHOT_INTEGRATION_TEST_MSG_456', msg_id = None, reply = False
attributes = {'Author': 'robot', 'When': 1756376002, 'cmd': 'Submit', 'exp': 'demo', ...}
attachments = ['/tmp/fake_screenshot.png'], suppress_email_notification = False
encoding = None, timeout = None, kwargs = {'Author': 'robot'}
new_attachment_list = [('attfile0', ('fake_screenshot.png', <_io.BufferedReader name='/tmp/fake_screenshot.png'>)), ('Text', ('', b'SCREENSHOT_INTEGRATION_TEST_MSG_456'))]
objects_to_close = [<_io.BufferedReader name='/tmp/fake_screenshot.png'>]
attributes_to_edit = {'Author': b'robot', 'When': 1756376002, 'cmd': b'Submit', 'exp': b'demo', ...}
def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None,
suppress_email_notification=False, encoding=None, timeout=None, **kwargs):
"""
Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing
message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id
of the newly created message.
:param message: string with message text
:param msg_id: ID number of message to edit or reply. If not specified new message is created.
:param reply: If 'True' reply to existing message is created instead of editing it
:param attributes: Dictionary of attributes. Following attributes are used internally by the elog and will be
ignored: Text, Date, Encoding, Reply to, In reply to, Locked by, Attachment
:param attachments: list of:
- file like objects which read() will return bytes (if file_like_object.name is not
defined, default name "attachment<i>" will be used.
- paths to the files
All items will be appended as attachment to the elog entry. In case of unknown
attachment an exception LogbookInvalidAttachment will be raised.
:param suppress_email_notification: If set to True or 1, E-Mail notification will be suppressed, defaults to False.
:param encoding: Defines encoding of the message. Can be: 'plain' -> plain text, 'html'->html-text,
'ELCode' --> elog formatting syntax
:param timeout: Define the timeout to be used by the post request. Its value is directly passed to the requests
post. Use None to disable the request timeout.
:param kwargs: Anything in the kwargs will be interpreted as attribute. e.g.: logbook.post('Test text',
Author='Rok Vintar), "Author" will be sent as an attribute. If named same as one of the
attributes defined in "attributes", kwargs will have priority.
:return: msg_id
"""
attributes = attributes or {}
attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority
attachments = attachments or []
if encoding is not None:
if encoding not in ['plain', 'HTML', 'ELCode']:
raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.')
attributes['Encoding'] = encoding
if suppress_email_notification:
attributes["suppress"] = 1
# THE ATTACHMENT STRATEGY WHEN DEALING WITH POST MODIFICATION
#
# 1. Does the message on the server have already attachments?
# 1.1 - We read the message getting the existing attachment list.
# 1.2 - Add to the attributes dictionary one line for each attachment like this:
# attributes['attachmentN'] = timestamped_filename_name
#
# 2. Do we have new attachments?
# 2.1 - Those are in the new_attachment_list. This is a list of this type:
# [ ('attfileN', ('filename', fileobject)) ]
# 2.2 - We need to loop over all the new attachments:
# 2.2.1 - Does a file already on the server with the same name exist?
# 2.2.1.1 - No: OK. Then we go ahead with the next attachment.
# 2.2.1.2 - Yes:
# 2.2.1.2.1 - Are the two files identical?
# 2.2.1.2.1.1 - Yes: then we remove this current entry from the new_attachment_list and we leave the one
# already on server.
# 2.2.1.2.1.2 - No:
# 2.2.1.2.1.2.1 - Then the file has been update.
# 2.2.1.2.1.2.2 - We need to remove the file on server first (using special post)
# 2.2.1.2.1.2.3 - We have to remove the old attachment from the attributes dictionary.
#
if attachments:
# here we accomplish point 2.1.
# new_attachment_list is something like [ ('attfileN', ('filename', fileobject)) ]
new_attachment_list, objects_to_close = self._prepare_attachments(attachments)
else:
objects_to_close = list()
new_attachment_list = list()
attributes_to_edit = dict()
if msg_id:
# Message exists, we can continue
if reply:
# Verify that there is a message on the server, otherwise do not reply to it!
self._check_if_message_on_server(msg_id) # raises exception in case of none existing message
attributes['reply_to'] = str(msg_id)
else: # Edit existing
attributes['edit_id'] = str(msg_id)
attributes['skiplock'] = '1'
# here we accomplish point 1.1.
# existing_attachments_list is something like:
# [ 'https://elog.url.com/logbook/timestamped_filename' ]
msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id)
for attribute, data in attributes.items():
new_data = attributes.get(attribute)
if new_data is not None:
attributes_to_edit[attribute] = new_data
i = 0
existing_attachments_filename_list = list()
for attachment in existing_attachments_list:
# here we accomplish point 1.2. We strip the timestamped_filename from the whole URL.
attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)
existing_attachments_filename_list.append(os.path.basename(attachment)[14:])
i += 1
# let's accomplish 2.2. Loop over all new attachment
duplicate_attachment_list = list()
for new_attachment in new_attachment_list:
# the new_attachment_list is something like:
# [ ('attfileN', ('filename', fileobject)) ]
new_attachment_filename = new_attachment[1][0]
if new_attachment_filename in existing_attachments_filename_list:
# a file with the same name existing already on the server.
# we need to check if the two files are the same.
# read the content of the new file
new_attachment_content = new_attachment[1][1].read()
# don't forget to reset the fileobj to the beginning of the file
new_attachment[1][1].seek(0)
# get the existing attachment content
attachment_index = existing_attachments_filename_list.index(new_attachment_filename)
existing_attachment_content = self.download_attachment(
url=existing_attachments_list[attachment_index],
timeout=timeout
)
# check if the two contents are the same
if new_attachment_content == existing_attachment_content:
# yes. then we don't upload a second copy. we remove the current entry from the list
duplicate_attachment_list.append(new_attachment)
else:
# no. they are not the same file. we will replace the existing file with the new one
# first: we need to remove the attachment from the server using the dedicated method
self.delete_attachment(msg_id, attributes=attributes_to_edit,
attachment_id=attachment_index,
timeout=timeout, text=msg_to_edit)
# now we can remove this attachment from the auxiliary lists.
existing_attachments_filename_list.pop(attachment_index)
existing_attachments_list.pop(attachment_index)
# now we need to rebuild the attributes dictionary for the part concerning the attachments.
# we remove all of them first
keys_to_be_removed = list()
for key in attributes_to_edit.keys():
if key.startswith('attachment'):
keys_to_be_removed.append(key)
if key.startswith('delatt'):
keys_to_be_removed.append(key)
for key in keys_to_be_removed:
del attributes_to_edit[key]
# now we rebuild it
for i, attachment in enumerate(existing_attachments_list):
attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)
# remove all duplicate attachments from the new_attachment_list
for attach in duplicate_attachment_list:
new_attachment_list.remove(attach)
else:
# As we create a new message, specify creation time if not already specified in attributes
if 'When' not in attributes:
attributes['When'] = int(datetime.now().timestamp())
if not attributes_to_edit:
attributes_to_edit = attributes
# Remove any attributes that should not be sent
_remove_reserved_attributes(attributes_to_edit)
# Make requests module think that Text is a "file". This is the only way to force requests to send data as
# multipart/form-data even if there are no attachments. Elog understands only multipart/form-data
new_attachment_list.append(('Text', ('', message.encode('iso-8859-1'))))
# Base attributes are common to all messages
self._add_base_msg_attributes(attributes_to_edit)
# Keys in attributes cannot have certain characters like whitespaces or dashes for the http request
attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit)
# All string values in the attributes must be encoded in latin1
attributes_to_edit = _encode_values(attributes_to_edit)
try:
> response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list,
allow_redirects=False, verify=False, timeout=timeout)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:288:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:115: in post
return request("post", url, data=data, json=json, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <requests.adapters.HTTPAdapter object at 0x7feb0958c490>
request = <PreparedRequest [POST]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)
except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)
if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)
if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)
if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)
> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb0958cb20>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError
During handling of the above exception, another exception occurred:
self = <urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
> sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection
raise err
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
address = ('localhost', 8080), timeout = None, source_address = None
socket_options = [(6, 1, 1)]
def create_connection(
address: tuple[str, int],
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
source_address: tuple[str, int] | None = None,
socket_options: _TYPE_SOCKET_OPTIONS | None = None,
) -> socket.socket:
"""Connect to *address* and return the socket object.
Convenience function. Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object. Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect. If no *timeout* is supplied, the
global default timeout setting returned by :func:`socket.getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default.
"""
host, port = address
if host.startswith("["):
host = host.strip("[]")
err = None
# Using the value from allowed_gai_family() in the context of getaddrinfo lets
# us select whether to work with IPv4 DNS records, IPv6 records, or both.
# The original create_connection function always returns all records.
family = allowed_gai_family()
try:
host.encode("idna")
except UnicodeError:
raise LocationParseError(f"'{host}', label empty or too long") from None
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
# If provided, set socket level options before connecting.
_set_socket_options(sock, socket_options)
if timeout is not _DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
> sock.connect(sa)
E ConnectionRefusedError: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError
The above exception was the direct cause of the following exception:
self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b7e640>
method = 'GET', url = '/demo/None', body = None
headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'}
retries = Retry(total=0, connect=None, read=False, redirect=None, status=None)
redirect = False, assert_same_host = False
timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None
release_conn = False, chunked = False, body_pos = None, preload_content = False
decode_content = False, response_kw = {}
parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None)
destination_scheme = None, conn = None, release_this_conn = True
http_tunnel_required = False, err = None, clean_exit = False
def urlopen( # type: ignore[override]
self,
method: str,
url: str,
body: _TYPE_BODY | None = None,
headers: typing.Mapping[str, str] | None = None,
retries: Retry | bool | int | None = None,
redirect: bool = True,
assert_same_host: bool = True,
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
pool_timeout: int | None = None,
release_conn: bool | None = None,
chunked: bool = False,
body_pos: _TYPE_BODY_POSITION | None = None,
preload_content: bool = True,
decode_content: bool = True,
**response_kw: typing.Any,
) -> BaseHTTPResponse:
"""
Get a connection from the pool and perform an HTTP request. This is the
lowest level call for making a request, so you'll need to specify all
the raw details.
.. note::
More commonly, it's appropriate to use a convenience method
such as :meth:`request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
:param url:
The URL to perform the request on.
:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc. If None, pool headers are used. If provided,
these headers completely replace any pool-specific headers.
:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.
If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.
:param assert_same_host:
If ``True``, will make sure that the host of the pool requests is
consistent else will raise HostChangedError. When ``False``, you can
use the pool on an HTTP proxy and request foreign hosts.
:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.
:param pool_timeout:
If set and the pool is set to block=True, then this method will
block for ``pool_timeout`` seconds and raise EmptyPoolError if no
connection is available within the time period.
:param bool preload_content:
If True, the response's body will be preloaded into memory.
:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of ``preload_content``
which defaults to ``True``.
:param bool chunked:
If True, urllib3 will send the body using chunked transfer
encoding. Otherwise, urllib3 will send the body using the standard
content-length form. Defaults to False.
:param int body_pos:
Position to seek to in file-like body in the event of a retry or
redirect. Typically this won't need to be set because urllib3 will
auto-populate the value when needed.
"""
parsed_url = parse_url(url)
destination_scheme = parsed_url.scheme
if headers is None:
headers = self.headers
if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect, default=self.retries)
if release_conn is None:
release_conn = preload_content
# Check host
if assert_same_host and not self.is_same_host(url):
raise HostChangedError(self, url, retries)
# Ensure that the URL we're connecting to is properly encoded
if url.startswith("/"):
url = to_str(_encode_target(url))
else:
url = to_str(parsed_url.url)
conn = None
# Track whether `conn` needs to be released before
# returning/raising/recursing. Update this variable if necessary, and
# leave `release_conn` constant throughout the function. That way, if
# the function recurses, the original value of `release_conn` will be
# passed down into the recursive call, and its value will be respected.
#
# See issue #651 [1] for details.
#
# [1] <https://github.com/urllib3/urllib3/issues/651>
release_this_conn = release_conn
http_tunnel_required = connection_requires_http_tunnel(
self.proxy, self.proxy_config, destination_scheme
)
# Merge the proxy headers. Only done when not using HTTP CONNECT. We
# have to copy the headers dict so we can safely change it without those
# changes being reflected in anyone else's copy.
if not http_tunnel_required:
headers = headers.copy() # type: ignore[attr-defined]
headers.update(self.proxy_headers) # type: ignore[union-attr]
# Must keep the exception bound to a separate variable or else Python 3
# complains about UnboundLocalError.
err = None
# Keep track of whether we cleanly exited the except block. This
# ensures we do proper cleanup in finally.
clean_exit = False
# Rewind body position, if needed. Record current position
# for future rewinds in the event of a redirect/retry.
body_pos = set_file_position(body, body_pos)
try:
# Request a connection from the queue.
timeout_obj = self._get_timeout(timeout)
conn = self._get_conn(timeout=pool_timeout)
conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]
# Is this a closed/new connection that requires CONNECT tunnelling?
if self.proxy is not None and http_tunnel_required and conn.is_closed:
try:
self._prepare_proxy(conn)
except (BaseSSLError, OSError, SocketTimeout) as e:
self._raise_timeout(
err=e, url=self.proxy.url, timeout_value=conn.timeout
)
raise
# If we're going to release the connection in ``finally:``, then
# the response doesn't need to know about the connection. Otherwise
# it will also try to release it and we'll have a double-release
# mess.
response_conn = conn if not release_conn else None
# Make the request on the HTTPConnection object
> response = self._make_request(
conn,
method,
url,
timeout=timeout_obj,
body=body,
headers=headers,
chunked=chunked,
retries=retries,
response_conn=response_conn,
preload_content=preload_content,
decode_content=decode_content,
**response_kw,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request
conn.request(
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request
self.endheaders()
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output
self.send(msg)
/root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send
self.connect()
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect
self.sock = self._new_conn()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>
def _new_conn(self) -> socket.socket:
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
try:
sock = connection.create_connection(
(self._dns_host, self.port),
self.timeout,
source_address=self.source_address,
socket_options=self.socket_options,
)
except socket.gaierror as e:
raise NameResolutionError(self.host, self, e) from e
except SocketTimeout as e:
raise ConnectTimeoutError(
self,
f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
) from e
except OSError as e:
> raise NewConnectionError(
self, f"Failed to establish a new connection: {e}"
) from e
E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError
The above exception was the direct cause of the following exception:
self = <requests.adapters.HTTPAdapter object at 0x7feb09b7eaf0>
request = <PreparedRequest [GET]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
> resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen
retries = retries.increment(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = Retry(total=0, connect=None, read=False, redirect=None, status=None)
method = 'GET', url = '/demo/None', response = None
error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused')
_pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b7e640>
_stacktrace = <traceback object at 0x7feb09906780>
def increment(
self,
method: str | None = None,
url: str | None = None,
response: BaseHTTPResponse | None = None,
error: Exception | None = None,
_pool: ConnectionPool | None = None,
_stacktrace: TracebackType | None = None,
) -> Self:
"""Return a new Retry object with incremented retry counters.
:param response: A response object, or None, if the server did not
return a response.
:type response: :class:`~urllib3.response.BaseHTTPResponse`
:param Exception error: An error encountered during the request, or
None if the response was received successfully.
:return: A new ``Retry`` object.
"""
if self.total is False and error:
# Disabled, indicate to re-raise the error.
raise reraise(type(error), error, _stacktrace)
total = self.total
if total is not None:
total -= 1
connect = self.connect
read = self.read
redirect = self.redirect
status_count = self.status
other = self.other
cause = "unknown"
status = None
redirect_location = None
if error and self._is_connection_error(error):
# Connect retry?
if connect is False:
raise reraise(type(error), error, _stacktrace)
elif connect is not None:
connect -= 1
elif error and self._is_read_error(error):
# Read retry?
if read is False or method is None or not self._is_method_retryable(method):
raise reraise(type(error), error, _stacktrace)
elif read is not None:
read -= 1
elif error:
# Other retry?
if other is not None:
other -= 1
elif response and response.get_redirect_location():
# Redirect retry?
if redirect is not None:
redirect -= 1
cause = "too many redirects"
response_redirect_location = response.get_redirect_location()
if response_redirect_location:
redirect_location = response_redirect_location
status = response.status
else:
# Incrementing because of a server error like a 500 in
# status_forcelist and the given method is in the allowed_methods
cause = ResponseError.GENERIC_ERROR
if response and response.status:
if status_count is not None:
status_count -= 1
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
status = response.status
history = self.history + (
RequestHistory(method, url, error, status, redirect_location),
)
new_retry = self.new(
total=total,
connect=connect,
read=read,
redirect=redirect,
status=status_count,
other=other,
history=history,
)
if new_retry.is_exhausted():
reason = error or ResponseError(cause)
> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError
During handling of the above exception, another exception occurred:
self = <elog.logbook.Logbook object at 0x7feb0977c5b0>, msg_id = None
timeout = None
def _check_if_message_on_server(self, msg_id, timeout=None):
"""Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no
such message.
:param msg_id: ID of message to be checked
:params timeout: The value of timeout to be passed to the get request
:return:
"""
request_headers = dict()
if self._user or self._password:
request_headers['Cookie'] = self._make_user_and_pswd_cookie()
try:
> response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,
verify=False, timeout=timeout)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:581:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:73: in get
return request("get", url, params=params, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request
return session.request(method=method, url=url, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request
resp = self.send(prep, **send_kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <requests.adapters.HTTPAdapter object at 0x7feb09b7eaf0>
request = <PreparedRequest [GET]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = False
cert = None, proxies = OrderedDict()
def send(
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection_with_tls_context(
request, verify, proxies=proxies, cert=cert
)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(
request,
stream=stream,
timeout=timeout,
verify=verify,
cert=cert,
proxies=proxies,
)
chunked = not (request.body is None or "Content-Length" in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError:
raise ValueError(
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
f"or a single float to set both timeouts to the same value."
)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout,
chunked=chunked,
)
except (ProtocolError, OSError) as err:
raise ConnectionError(err, request=request)
except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)
if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)
if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)
if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)
> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError
During handling of the above exception, another exception occurred:
mock_screenshot_class = <MagicMock name='Screenshot' id='140647452388896'>
@patch("slic.utils.elog.Screenshot")
def test_screenshot(mock_screenshot_class):
fake_path = "/tmp/fake_screenshot.png"
with open(fake_path, "wb") as f:
f.write(b"fake image data")
mock_instance = mock_screenshot_class.return_value
mock_instance.shoot.return_value = [fake_path]
elog = Elog("http://localhost:8080/demo", user="robot", password="testpassword")
test_msg = "SCREENSHOT_INTEGRATION_TEST_MSG_456"
> msg_id = elog.screenshot(message=test_msg)
tests/test_utils_elog.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
slic/utils/elog.py:21: in screenshot
return self.post(message, **kwargs)
slic/utils/elog.py:16: in post
return self._log.post(*args, **kwargs)
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:307: in post
self._check_if_message_on_server(msg_id) # raises exceptions if no message or no response from server
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <elog.logbook.Logbook object at 0x7feb0977c5b0>, msg_id = None
timeout = None
def _check_if_message_on_server(self, msg_id, timeout=None):
"""Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no
such message.
:param msg_id: ID of message to be checked
:params timeout: The value of timeout to be passed to the get request
:return:
"""
request_headers = dict()
if self._user or self._password:
request_headers['Cookie'] = self._make_user_and_pswd_cookie()
try:
response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,
verify=False, timeout=timeout)
# If there is no message code 200 will be returned (OK) and _validate_response will not recognise it
# but there will be some error in the html code.
resp_message, resp_headers, resp_msg_id = _validate_response(response)
# If there is no message, code 200 will be returned (OK) but there will be some error indication in
# the html code.
if re.findall('<td.*?class="errormsg".*?>.*?</td>',
resp_message.decode('utf-8', 'ignore'),
flags=re.DOTALL):
raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.')
except requests.Timeout as e:
# Catch here a timeout o the post request.
# Raise the logbook exception and let the user handle it
raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\n' +
'{1}'.format(sys._getframe().f_code.co_name, e))
except requests.RequestException as e:
> raise LogbookServerProblem('No response from the logbook server.\nDetails: ' + '{0}'.format(e))
E elog.logbook_exceptions.LogbookServerProblem: No response from the logbook server.
E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused'))
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:601: LogbookServerProblem
_____________________________ test_get_adjs_filter _____________________________
def test_get_adjs_filter():
a4 = SubAdjustable("mid_brightness", units="%", limit_low=0, limit_high=100)
a5 = SubAdjustable("debug_internal", internal=True)
public = get_adjs()
> assert set(public) == {'brightness', 'contrast', 'mid_contrast', 'mid_brightness'}
E AssertionError: assert {'contrast', ...mid_contrast'} == {'brightness'...mid_contrast'}
E
E Extra items in the right set:
E 'brightness'
E
E Full diff:
E {
E - 'brightness',
E 'contrast',
E 'mid_brightness',
E 'mid_contrast',
E }
tests/test_utils_get_adj.py:42: AssertionError
_____________________ test_import_logging_once_per_module ______________________
def test_import_logging_once_per_module():
code = textwrap.dedent("""
from slic.utils.logcfg import *
import math
import io
import random
""")
with tempfile.NamedTemporaryFile("w", suffix=".py", delete=False) as tmp:
tmp.write(code)
tmp_path = tmp.name
env = os.environ.copy()
root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
env["PYTHONPATH"] = root_path + os.pathsep + env.get("PYTHONPATH", "")
result = subprocess.run([sys.executable, tmp_path], capture_output=True, text=True, env=env)
os.remove(tmp_path)
assert result.returncode == 0, f"Script failed:\n{result.stderr}"
stderr = result.stderr
print(stderr)
lines = stderr.splitlines()
for mod in ["math", "io", "random"]:
count = sum(1 for line in lines if f"importing: {mod}" in line)
> assert count == 1, f"Expected 1 import log for '{mod}', found {count}"
E AssertionError: Expected 1 import log for 'math', found 0
E assert 0 == 1
tests/test_utils_logcfg.py:78: AssertionError
----------------------------- Captured stdout call -----------------------------
[E 250828 10:15:55 tools:40] cannot assign endstation to IP 172.18.0.3 (038eaf845eac)
___________________ TestShortcutsSingleton.test_registration ___________________
self = <test_utils_shortcut.TestShortcutsSingleton object at 0x7feb09bdfee0>
def test_registration(self):
# Test automatic registration
@as_shortcut(name="FuncA")
def func_a():
pass
@as_shortcut(name="FuncB")
def func_b():
pass
> assert len(shortcuts._get()) == 2
E assert 3 == 2
E + where 3 = len({'<lambda>': Shortcut "<lambda>", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB"})
E + where {'<lambda>': Shortcut "<lambda>", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB"} = _get()
E + where _get = <lambda>: Shortcut "<lambda>"\nFuncA: Shortcut "FuncA"\nFuncB: Shortcut "FuncB"\n._get
tests/test_utils_shortcut.py:138: AssertionError
_________________ TestFullIntegration.test_multiple_shortcuts __________________
self = <test_utils_shortcut.TestFullIntegration object at 0x7feb09cdfcd0>
def test_multiple_shortcuts(self):
# Test multiple shortcuts coexistence
@as_shortcut(name="First")
def first():
return 1
@as_shortcut(name="Second")
def second():
return 2
assert shortcuts["First"].func() == 1
assert shortcuts["Second"].func() == 2
> assert len(shortcuts._get()) == 2
E assert 5 == 2
E + where 5 = len({'<lambda>': Shortcut "<lambda>", 'First': Shortcut "First", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB", ...})
E + where {'<lambda>': Shortcut "<lambda>", 'First': Shortcut "First", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB", ...} = _get()
E + where _get = <lambda>: Shortcut "<lambda>"\nFirst: Shortcut "First"\nFuncA: Shortcut "FuncA"\nFuncB: Shortcut "FuncB"\nSecond: Shortcut "Second"\n._get
tests/test_utils_shortcut.py:203: AssertionError
_________________________ test_float_alignment_in_bar __________________________
def test_float_alignment_in_bar():
# Capture the tqdm output into a string buffer
f = io.StringIO()
with redirect_stdout(f):
bar = tqdm_mod(total=100.12, desc="AlignBar", file=f, miniters=1, mininterval=0)
bar.set(1.3333)
bar.set(12.5)
bar.set(99.89)
bar.set(100.12)
bar.close()
# Extract lines containing the label
lines = extract_lines(f.getvalue(), "AlignBar")
# Expected formatted values using format_sizeof
expected_values = [
"1.3/100.1",
"12.5/100.1",
"99.9/100.1",
"100.1/100.1",
]
# Extract the actual padded float/total strings from the full lines
values = []
for line in lines:
match = re.search(r"(\d{1,3}\.\d)/100\.1", line)
if match:
values.append(match.group(0))
# Ensure raw 100.12 never appears : format_sizeof must have truncated it
assert all("100.12" not in line for line in lines), "Unrounded value '100.12' found in output!"
# Check all expected values appear rounded as expected by format_sizeof
for expected in expected_values:
assert expected in values, f"Missing expected value: {expected}"
# Check that all values are visually aligned, output with same length, to ensure that format_sizeof add the good number avec spaces
print("\n")
bar_segments = []
for line in lines:
match = re.search(r".*?\]", line)
if match:
bar_segments.append(match.group(0))
print(match.group(0))
lengths = [len(seg) for seg in bar_segments]
> assert len(set(lengths)) == 1
E assert 3 == 1
E + where 3 = len({50, 64, 65})
E + where {50, 64, 65} = set([50, 64, 64, 65, 65])
tests/test_utils_tqdm_mod.py:130: AssertionError
----------------------------- Captured stdout call -----------------------------
AlignBar: 0%| | 0/100.1 [00:00<?, ? Hz]
AlignBar: 1%|1 | 1.3/100.1 [00:00<00:00, 57652.2 Hz]
AlignBar: 12%|#2 | 12.5/100.1 [00:00<00:00, 81738.0 Hz]
AlignBar: 100%|#########9| 99.9/100.1 [00:00<00:00, 420734.0 Hz]
AlignBar: 100%|##########| 100.1/100.1 [00:00<00:00, 217807.9 Hz]
=============================== warnings summary ===============================
../../../root/mambaforge/envs/ci-env/lib/python3.8/site-packages/scipy/fft/__init__.py:97
/root/mambaforge/envs/ci-env/lib/python3.8/site-packages/scipy/fft/__init__.py:97: DeprecationWarning: The module numpy.dual is deprecated. Instead of using dual, use the functions directly from numpy or scipy.
from numpy.dual import register_func
tests/test_utils_pv.py:12
/workspace/tligui_y/slic/tests/test_utils_pv.py:12: DeprecationWarning: invalid escape sequence \[
'''
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
Generated on 2025-08-28 12:16:05 CEST
🧾 General Info
- duration: 161.07588052749634
- root: /workspace/tligui_y/slic
- environment: {}
📋 Summary
- Passed: 518
- Failed: 11
- Total: 529
- Collected: 529
🔎 Tests
✅ Passed (518)
-
📄 morbidissimo/morbidissimo/morioc/test_infer_type.py
↳ Function: test_it_type_str
-
✅ Test 1
📌 Setup phase
duration:
0.0008492115885019302outcome:
passed📌 Call phase
duration:
0.00028853677213191986outcome:
passed📌 Teardown phase
duration:
0.0002390863373875618outcome:
passed
↳ Function: test_it_type_float
-
✅ Test 2
📌 Setup phase
duration:
0.00016960874199867249outcome:
passed📌 Call phase
duration:
0.00018779374659061432outcome:
passed📌 Teardown phase
duration:
0.00014367513358592987outcome:
passed
↳ Function: test_it_type_int
-
✅ Test 3
📌 Setup phase
duration:
0.00015050452202558517outcome:
passed📌 Call phase
duration:
0.0002009579911828041outcome:
passed📌 Teardown phase
duration:
0.00015898514539003372outcome:
passed
↳ Function: test_it_value_str
-
✅ Test 4
📌 Setup phase
duration:
0.0001521427184343338outcome:
passed📌 Call phase
duration:
0.0001798029989004135outcome:
passed📌 Teardown phase
duration:
0.0001422381028532982outcome:
passed
↳ Function: test_it_value_long_str
-
✅ Test 5
📌 Setup phase
duration:
0.00014987587928771973outcome:
passed📌 Call phase
duration:
0.0001828102394938469outcome:
passed📌 Teardown phase
duration:
0.0001388099044561386outcome:
passed
↳ Function: test_it_value_float
-
✅ Test 6
📌 Setup phase
duration:
0.00014726724475622177outcome:
passed📌 Call phase
duration:
0.0002255188301205635outcome:
passed📌 Teardown phase
duration:
0.00014698971062898636outcome:
passed
↳ Function: test_it_value_int
-
✅ Test 7
📌 Setup phase
duration:
0.00017888564616441727outcome:
passed📌 Call phase
duration:
0.0002636425197124481outcome:
passed📌 Teardown phase
duration:
0.00014178454875946045outcome:
passed
↳ Function: test_it_empty_value_str
-
✅ Test 8
📌 Setup phase
duration:
0.00015732459723949432outcome:
passed📌 Call phase
duration:
0.00018253177404403687outcome:
passed📌 Teardown phase
duration:
0.00013552885502576828outcome:
passed
↳ Function: test_it_empty_value_float
-
✅ Test 9
📌 Setup phase
duration:
0.00014503486454486847outcome:
passed📌 Call phase
duration:
0.0001764744520187378outcome:
passed📌 Teardown phase
duration:
0.00013448670506477356outcome:
passed
↳ Function: test_it_empty_value_int
-
✅ Test 10
📌 Setup phase
duration:
0.0001433100551366806outcome:
passed📌 Call phase
duration:
0.00016853585839271545outcome:
passed📌 Teardown phase
duration:
0.0001297472044825554outcome:
passed
↳ Function: test_pstrue_str
-
✅ Test 11
📌 Setup phase
duration:
0.00014315545558929443outcome:
passed📌 Call phase
duration:
0.0001804698258638382outcome:
passed📌 Teardown phase
duration:
0.00014874618500471115outcome:
passed
↳ Function: test_pstrue_float
-
✅ Test 12
📌 Setup phase
duration:
0.0001861676573753357outcome:
passed📌 Call phase
duration:
0.00017831847071647644outcome:
passed📌 Teardown phase
duration:
0.00013916287571191788outcome:
passed
↳ Function: test_pstrue_int
-
✅ Test 13
📌 Setup phase
duration:
0.0001414380967617035outcome:
passed📌 Call phase
duration:
0.00017048045992851257outcome:
passed📌 Teardown phase
duration:
0.00013455841690301895outcome:
passed
↳ Function: test_psfalse_str
-
✅ Test 14
📌 Setup phase
duration:
0.00014704465866088867outcome:
passed📌 Call phase
duration:
0.0001721540465950966outcome:
passed📌 Teardown phase
duration:
0.00013556703925132751outcome:
passed
↳ Function: test_psfalse_float
-
✅ Test 15
📌 Setup phase
duration:
0.0001393575221300125outcome:
passed📌 Call phase
duration:
0.00017584767192602158outcome:
passed📌 Teardown phase
duration:
0.00013235583901405334outcome:
passed
↳ Function: test_psfalse_int
-
✅ Test 16
📌 Setup phase
duration:
0.0001479675993323326outcome:
passed📌 Call phase
duration:
0.00021432247012853622outcome:
passed📌 Teardown phase
duration:
0.00013510696589946747outcome:
passed
↳ Function: test_it_None
-
✅ Test 17
📌 Setup phase
duration:
0.00013822317123413086outcome:
passed📌 Call phase
duration:
0.00022944528609514236outcome:
passed📌 Teardown phase
duration:
0.00014167185872793198outcome:
passed
↳ Function: test_it_True
-
✅ Test 18
📌 Setup phase
duration:
0.00014280807226896286outcome:
passed📌 Call phase
duration:
0.00017523113638162613outcome:
passed📌 Teardown phase
duration:
0.00012876931577920914outcome:
passed
↳ Function: test_it_False
-
✅ Test 19
📌 Setup phase
duration:
0.0001469263806939125outcome:
passed📌 Call phase
duration:
0.0002308376133441925outcome:
passed📌 Teardown phase
duration:
0.0001902719959616661outcome:
passed
↳ Function: test_it_nan
-
✅ Test 20
📌 Setup phase
duration:
0.000439605675637722outcome:
passed📌 Call phase
duration:
0.0002726307138800621outcome:
passed📌 Teardown phase
duration:
0.00017759297043085098outcome:
passed
↳ Function: test_it_np_nan
-
✅ Test 21
📌 Setup phase
duration:
0.00022440683096647263outcome:
passed📌 Call phase
duration:
0.00018002837896347046outcome:
passed📌 Teardown phase
duration:
0.00014685280621051788outcome:
passed
↳ Function: test_it_np1D_int
-
✅ Test 22
📌 Setup phase
duration:
0.00015140417963266373outcome:
passed📌 Call phase
duration:
0.0002526352182030678outcome:
passed📌 Teardown phase
duration:
0.00014894641935825348outcome:
passed
↳ Function: test_it_np2D_int
-
✅ Test 23
📌 Setup phase
duration:
0.0001408737152814865outcome:
passed📌 Call phase
duration:
0.0002279793843626976outcome:
passed📌 Teardown phase
duration:
0.00014532171189785004outcome:
passed
↳ Function: test_it_np1D_float
-
✅ Test 24
📌 Setup phase
duration:
0.0001736050471663475outcome:
passed📌 Call phase
duration:
0.00032355543226003647outcome:
passed📌 Teardown phase
duration:
0.00013871211558580399outcome:
passed
↳ Function: test_it_np2D_float
-
✅ Test 25
📌 Setup phase
duration:
0.00015734322369098663outcome:
passed📌 Call phase
duration:
0.0002528103068470955outcome:
passed📌 Teardown phase
duration:
0.00013892445713281631outcome:
passed
↳ Function: test_it_np1D_bool
-
✅ Test 26
📌 Setup phase
duration:
0.00017307698726654053outcome:
passed📌 Call phase
duration:
0.00020481180399656296outcome:
passed📌 Teardown phase
duration:
0.00013688579201698303outcome:
passed
↳ Function: test_it_np1D_object
-
✅ Test 27
📌 Setup phase
duration:
0.000151841901242733outcome:
passed📌 Call phase
duration:
0.00019360054284334183outcome:
passed📌 Teardown phase
duration:
0.00013342685997486115outcome:
passed
↳ Function: test_it_np_scalar_int
-
✅ Test 28
📌 Setup phase
duration:
0.00014191865921020508outcome:
passed📌 Call phase
duration:
0.00021919235587120056outcome:
passed📌 Teardown phase
duration:
0.00013150274753570557outcome:
passed
↳ Function: test_it_np_scalar_float
-
✅ Test 29
📌 Setup phase
duration:
0.00014956574887037277outcome:
passed📌 Call phase
duration:
0.00021452363580465317outcome:
passed📌 Teardown phase
duration:
0.00014550518244504929outcome:
passed
↳ Function: test_it_np_scalar_bool
-
✅ Test 30
📌 Setup phase
duration:
0.00014221202582120895outcome:
passed📌 Call phase
duration:
0.00022305455058813095outcome:
passed📌 Teardown phase
duration:
0.00014491844922304153outcome:
passed
↳ Function: test_it_list
-
✅ Test 31
📌 Setup phase
duration:
0.0001393323764204979outcome:
passed📌 Call phase
duration:
0.00018355902284383774outcome:
passed📌 Teardown phase
duration:
0.00014203041791915894outcome:
passed
↳ Function: test_it_tuple
-
✅ Test 32
📌 Setup phase
duration:
0.00014260876923799515outcome:
passed📌 Call phase
duration:
0.00018188171088695526outcome:
passed📌 Teardown phase
duration:
0.0001498861238360405outcome:
passed
-
-
📄 test_utils_argfwd.py
↳ Function: test_split_at
-
✅ Test 33
params:lst=["a", "b", "c", "d"], index=2, expected=[["a", "b"], ["c", "d"]]📌 Parameters
params: lst: ["a", "b", "c", "d"] index: 2 expected: [["a", "b"], ["c", "d"]] id: "lst0-2-expected0"📌 Setup phase
duration:
0.00047350209206342697outcome:
passed📌 Call phase
duration:
0.00019927509129047394outcome:
passed📌 Teardown phase
duration:
0.00021731015294790268outcome:
passed -
✅ Test 34
params:lst=["x", "y"], index=1, expected=[["x"], ["y"]]📌 Parameters
params: lst: ["x", "y"] index: 1 expected: [["x"], ["y"]] id: "lst1-1-expected1"📌 Setup phase
duration:
0.00032537151128053665outcome:
passed📌 Call phase
duration:
0.0001871725544333458outcome:
passed📌 Teardown phase
duration:
0.0002054646611213684outcome:
passed -
✅ Test 35
params:lst=[], index=0, expected=[[], []]📌 Parameters
params: lst: [] index: 0 expected: [[], []] id: "lst2-0-expected2"📌 Setup phase
duration:
0.00032277218997478485outcome:
passed📌 Call phase
duration:
0.00017444230616092682outcome:
passed📌 Teardown phase
duration:
0.0001965295523405075outcome:
passed
↳ Function: test_merge_lists_unique
-
✅ Test 36
params:a=["a", "b"], b=["b", "c"], expected=["a", "b", "c"]📌 Parameters
params: a: ["a", "b"] b: ["b", "c"] expected: ["a", "b", "c"] id: "a0-b0-expected0"📌 Setup phase
duration:
0.0003235694020986557outcome:
passed📌 Call phase
duration:
0.00017551425844430923outcome:
passed📌 Teardown phase
duration:
0.00021209102123975754outcome:
passed -
✅ Test 37
params:a=[], b=["x"], expected=["x"]📌 Parameters
params: a: [] b: ["x"] expected: ["x"] id: "a1-b1-expected1"📌 Setup phase
duration:
0.0003076251596212387outcome:
passed📌 Call phase
duration:
0.00018645543605089188outcome:
passed📌 Teardown phase
duration:
0.0001875096932053566outcome:
passed -
✅ Test 38
params:a=["x", "y"], b=["x", "y"], expected=["x", "y"]📌 Parameters
params: a: ["x", "y"] b: ["x", "y"] expected: ["x", "y"] id: "a2-b2-expected2"📌 Setup phase
duration:
0.00031824223697185516outcome:
passed📌 Call phase
duration:
0.00017457548528909683outcome:
passed📌 Teardown phase
duration:
0.0001897420734167099outcome:
passed
↳ Function: test_merge_dicts_unique
-
✅ Test 39
params:a={"a": 1}, b={"b": 2}, expected={"a": 1, "b": 2}📌 Parameters
params: a: {"a": 1} b: {"b": 2} expected: {"a": 1, "b": 2} id: "a0-b0-expected0"📌 Setup phase
duration:
0.0003154994919896126outcome:
passed📌 Call phase
duration:
0.00018051546066999435outcome:
passed📌 Teardown phase
duration:
0.0002170829102396965outcome:
passed -
✅ Test 40
params:a={"x": 1}, b={"x": 9, "y": 3}, expected={"x": 1, "y": 3}📌 Parameters
params: a: {"x": 1} b: {"x": 9, "y": 3} expected: {"x": 1, "y": 3} id: "a1-b1-expected1"📌 Setup phase
duration:
0.0003124549984931946outcome:
passed📌 Call phase
duration:
0.0001886766403913498outcome:
passed📌 Teardown phase
duration:
0.00018966849893331528outcome:
passed -
✅ Test 41
params:a={}, b={"k": 4}, expected={"k": 4}📌 Parameters
params: a: {} b: {"k": 4} expected: {"k": 4} id: "a2-b2-expected2"📌 Setup phase
duration:
0.00032521411776542664outcome:
passed📌 Call phase
duration:
0.00017796270549297333outcome:
passed📌 Teardown phase
duration:
0.0003001820296049118outcome:
passed
↳ Function: test_make_params_pos_basic
-
✅ Test 42
params:pos=["a", "b"], expected_names=["a", "b"]📌 Parameters
params: pos: ["a", "b"] expected_names: ["a", "b"] id: "pos0-expected_names0"📌 Setup phase
duration:
0.0002869032323360443outcome:
passed📌 Call phase
duration:
0.00021937023848295212outcome:
passed📌 Teardown phase
duration:
0.00018197577446699142outcome:
passed -
✅ Test 43
params:pos=["param1", "value_2", "Z"], expected_names=["param1", "value_2", "Z"]📌 Parameters
params: pos: ["param1", "value_2", "Z"] expected_names: ["param1", "value_2", "Z"] id: "pos1-expected_names1"📌 Setup phase
duration:
0.00026125460863113403outcome:
passed📌 Call phase
duration:
0.00021721329540014267outcome:
passed📌 Teardown phase
duration:
0.000178532674908638outcome:
passed -
✅ Test 44
params:pos=[], expected_names=[]📌 Parameters
params: pos: [] expected_names: [] id: "pos2-expected_names2"📌 Setup phase
duration:
0.000279928557574749outcome:
passed📌 Call phase
duration:
0.00018133874982595444outcome:
passed📌 Teardown phase
duration:
0.0001762276515364647outcome:
passed
↳ Function: test_make_params_kw_basic
-
✅ Test 45
params:kw={"a": 1, "b": 2}, expected_keys=["a", "b"], expected_defaults=[1, 2]📌 Parameters
params: kw: {"a": 1, "b": 2} expected_keys: ["a", "b"] expected_defaults: [1, 2] id: "kw0-expected_keys0-expected_defaults0"📌 Setup phase
duration:
0.00031310226768255234outcome:
passed📌 Call phase
duration:
0.00019277166575193405outcome:
passed📌 Teardown phase
duration:
0.00020230188965797424outcome:
passed -
✅ Test 46
params:kw={"param_x": 0}, expected_keys=["param_x"], expected_defaults=[0]📌 Parameters
params: kw: {"param_x": 0} expected_keys: ["param_x"] expected_defaults: [0] id: "kw1-expected_keys1-expected_defaults1"📌 Setup phase
duration:
0.00030715949833393097outcome:
passed📌 Call phase
duration:
0.0002019917592406273outcome:
passed📌 Teardown phase
duration:
0.00019695516675710678outcome:
passed -
✅ Test 47
params:kw={}, expected_keys=[], expected_defaults=[]📌 Parameters
params: kw: {} expected_keys: [] expected_defaults: [] id: "kw2-expected_keys2-expected_defaults2"📌 Setup phase
duration:
0.00032265298068523407outcome:
passed📌 Call phase
duration:
0.00018729642033576965outcome:
passed📌 Teardown phase
duration:
0.00020504556596279144outcome:
passed
↳ Function: test_make_signature_parametrized
-
✅ Test 48
params:pos=["x", "y"], kw={"z": 3}, expected_signature="(x, y, z=3)"📌 Parameters
params: pos: ["x", "y"] kw: {"z": 3} expected_signature: "(x, y, z=3)" id: "pos0-kw0-(x, y, z=3)"📌 Setup phase
duration:
0.0003156689926981926outcome:
passed📌 Call phase
duration:
0.00022267736494541168outcome:
passed📌 Teardown phase
duration:
0.00019366107881069183outcome:
passed -
✅ Test 49
params:pos=["a"], kw={"b": 1, "c": 2}, expected_signature="(a, b=1, c=2)"📌 Parameters
params: pos: ["a"] kw: {"b": 1, "c": 2} expected_signature: "(a, b=1, c=2)" id: "pos1-kw1-(a, b=1, c=2)"📌 Setup phase
duration:
0.0003072097897529602outcome:
passed📌 Call phase
duration:
0.00022211764007806778outcome:
passed📌 Teardown phase
duration:
0.00019348599016666412outcome:
passed -
✅ Test 50
params:pos=[], kw={"flag": false}, expected_signature="(flag=False)"📌 Parameters
params: pos: [] kw: {"flag": false} expected_signature: "(flag=False)" id: "pos2-kw2-(flag=False)"📌 Setup phase
duration:
0.0003270106390118599outcome:
passed📌 Call phase
duration:
0.0002046152949333191outcome:
passed📌 Teardown phase
duration:
0.00020399410277605057outcome:
passed
↳ Function: test_get_args_parametrized
-
✅ Test 51
params:func="<function <lambda> at 0x7feb0ab58040>", expected_pos=["a", "b"], expected_kw={"c": 3, "d": 4}📌 Parameters
params: func: "<function <lambda> at 0x7feb0ab58040>" expected_pos: ["a", "b"] expected_kw: {"c": 3, "d": 4} id: "<lambda>-expected_pos0-expected_kw0"📌 Setup phase
duration:
0.0003008134663105011outcome:
passed📌 Call phase
duration:
0.0002547306939959526outcome:
passed📌 Teardown phase
duration:
0.0002012457698583603outcome:
passed -
✅ Test 52
params:func="<function <lambda> at 0x7feb0ab58f70>", expected_pos=[], expected_kw="{'x': 1, 'y': <class 'inspect._empty'>, 'z': 0}"📌 Parameters
params: func: "<function <lambda> at 0x7feb0ab58f70>" expected_pos: [] expected_kw: "{'x': 1, 'y': <class 'inspect._empty'>, 'z': 0}" id: "<lambda>-expected_pos1-expected_kw1"📌 Setup phase
duration:
0.00031566526740789413outcome:
passed📌 Call phase
duration:
0.00022898521274328232outcome:
passed📌 Teardown phase
duration:
0.0002016201615333557outcome:
passed -
✅ Test 53
params:func="<function <lambda> at 0x7feb0ab5b0d0>", expected_pos=[], expected_kw={}📌 Parameters
params: func: "<function <lambda> at 0x7feb0ab5b0d0>" expected_pos: [] expected_kw: {} id: "<lambda>-expected_pos2-expected_kw2"📌 Setup phase
duration:
0.00031538214534521103outcome:
passed📌 Call phase
duration:
0.00020868796855211258outcome:
passed📌 Teardown phase
duration:
0.0002007409930229187outcome:
passed
↳ Function: test_signature_visible
-
✅ Test 54
params:func="<function wrap_all at 0x7feb0ab5b310>", expected_sig="(a, b, d=30, c=10)"📌 Parameters
params: func: "<function wrap_all at 0x7feb0ab5b310>" expected_sig: "(a, b, d=30, c=10)" id: "wrap_all-(a, b, d=30, c=10)"📌 Setup phase
duration:
0.0002719815820455551outcome:
passed📌 Call phase
duration:
0.00022020097821950912outcome:
passed📌 Teardown phase
duration:
0.00018278323113918304outcome:
passed -
✅ Test 55
params:func="<function wrap_skip at 0x7feb0ab5b3a0>", expected_sig="(a, b, c=10, d=20)"📌 Parameters
params: func: "<function wrap_skip at 0x7feb0ab5b3a0>" expected_sig: "(a, b, c=10, d=20)" id: "wrap_skip-(a, b, c=10, d=20)"📌 Setup phase
duration:
0.00026768632233142853outcome:
passed📌 Call phase
duration:
0.0001864023506641388outcome:
passed📌 Teardown phase
duration:
0.00018760841339826584outcome:
passed -
✅ Test 56
params:func="<function wrap_ignore_all at 0x7feb0ab5b430>", expected_sig="(x, y, c=10, d=20)"📌 Parameters
params: func: "<function wrap_ignore_all at 0x7feb0ab5b430>" expected_sig: "(x, y, c=10, d=20)" id: "wrap_ignore_all-(x, y, c=10, d=20)"📌 Setup phase
duration:
0.000266294926404953outcome:
passed📌 Call phase
duration:
0.00018823985010385513outcome:
passed📌 Teardown phase
duration:
0.00018959958106279373outcome:
passed
↳ Function: test_wrapper_behavior
-
✅ Test 57
params:func="<function wrap_all at 0x7feb0ab5b310>", args=[1, 2, 3], kwargs={}, expected_result=36📌 Parameters
params: func: "<function wrap_all at 0x7feb0ab5b310>" args: [1, 2, 3] kwargs: {} expected_result: 36 id: "wrap_all-args0-kwargs0-36"📌 Setup phase
duration:
0.0003584623336791992outcome:
passed📌 Call phase
duration:
0.00019318610429763794outcome:
passed📌 Teardown phase
duration:
0.000208328478038311outcome:
passed -
✅ Test 58
params:func="<function wrap_all at 0x7feb0ab5b310>", args=[1, 2, 3], kwargs={"d": 5}, expected_result=11📌 Parameters
params: func: "<function wrap_all at 0x7feb0ab5b310>" args: [1, 2, 3] kwargs: {"d": 5} expected_result: 11 id: "wrap_all-args1-kwargs1-11"📌 Setup phase
duration:
0.0003572562709450722outcome:
passed📌 Call phase
duration:
0.00017806701362133026outcome:
passed📌 Teardown phase
duration:
0.00021044723689556122outcome:
passed -
✅ Test 59
params:func="<function wrap_skip at 0x7feb0ab5b3a0>", args=[0, 0], kwargs={"c": 3, "d": 4}, expected_result=10📌 Parameters
params: func: "<function wrap_skip at 0x7feb0ab5b3a0>" args: [0, 0] kwargs: {"c": 3, "d": 4} expected_result: 10 id: "wrap_skip-args2-kwargs2-10"📌 Setup phase
duration:
0.0003505023196339607outcome:
passed📌 Call phase
duration:
0.0001687249168753624outcome:
passed📌 Teardown phase
duration:
0.0002217283472418785outcome:
passed -
✅ Test 60
params:func="<function wrap_ignore_all at 0x7feb0ab5b430>", args=[0, 0], kwargs={}, expected_result=10📌 Parameters
params: func: "<function wrap_ignore_all at 0x7feb0ab5b430>" args: [0, 0] kwargs: {} expected_result: 10 id: "wrap_ignore_all-args3-kwargs3-10"📌 Setup phase
duration:
0.0003528110682964325outcome:
passed📌 Call phase
duration:
0.00017293915152549744outcome:
passed📌 Teardown phase
duration:
0.00020739994943141937outcome:
passed
-
-
📄 test_utils_ask_yes_no.py
↳ Function: test_ask_yes_no
-
✅ Test 61
params:default=null, user_input="y", expected_output=true, expected_prompt="Question? [y/n] "📌 Parameters
params: default: null user_input: "y" expected_output: true expected_prompt: "Question? [y/n] " id: "None-y-True-Question? [y/n] "📌 Setup phase
duration:
0.00039163045585155487outcome:
passed📌 Call phase
duration:
0.0009704111143946648outcome:
passed📌 Teardown phase
duration:
0.0002596825361251831outcome:
passed -
✅ Test 62
params:default=null, user_input="yes", expected_output=true, expected_prompt="Question? [y/n] "📌 Parameters
params: default: null user_input: "yes" expected_output: true expected_prompt: "Question? [y/n] " id: "None-yes-True-Question? [y/n] "📌 Setup phase
duration:
0.0003703795373439789outcome:
passed📌 Call phase
duration:
0.0006387867033481598outcome:
passed📌 Teardown phase
duration:
0.00023720692843198776outcome:
passed -
✅ Test 63
params:default=null, user_input="n", expected_output=false, expected_prompt="Question? [y/n] "📌 Parameters
params: default: null user_input: "n" expected_output: false expected_prompt: "Question? [y/n] " id: "None-n-False-Question? [y/n] "📌 Setup phase
duration:
0.00036588776856660843outcome:
passed📌 Call phase
duration:
0.0005895337089896202outcome:
passed📌 Teardown phase
duration:
0.00024140626192092896outcome:
passed -
✅ Test 64
params:default=null, user_input="no", expected_output=false, expected_prompt="Question? [y/n] "📌 Parameters
params: default: null user_input: "no" expected_output: false expected_prompt: "Question? [y/n] " id: "None-no-False-Question? [y/n] "📌 Setup phase
duration:
0.00036413781344890594outcome:
passed📌 Call phase
duration:
0.0006846310570836067outcome:
passed📌 Teardown phase
duration:
0.0002493159845471382outcome:
passed -
✅ Test 65
params:default=null, user_input=["maybe", "y"], expected_output=true, expected_prompt="Question? [y/n] "📌 Parameters
params: default: null user_input: ["maybe", "y"] expected_output: true expected_prompt: "Question? [y/n] " id: "None-user_input4-True-Question? [y/n] "📌 Setup phase
duration:
0.0003711208701133728outcome:
passed📌 Call phase
duration:
0.0006335172802209854outcome:
passed📌 Teardown phase
duration:
0.00024958979338407516outcome:
passed -
✅ Test 66
params:default=null, user_input=["", "no"], expected_output=false, expected_prompt="Question? [y/n] "📌 Parameters
params: default: null user_input: ["", "no"] expected_output: false expected_prompt: "Question? [y/n] " id: "None-user_input5-False-Question? [y/n] "📌 Setup phase
duration:
0.0003680204972624779outcome:
passed📌 Call phase
duration:
0.0006720423698425293outcome:
passed📌 Teardown phase
duration:
0.0002484312281012535outcome:
passed -
✅ Test 67
params:default=null, user_input=["invalid", "", "invalid", "yes"], expected_output=true, expected_prompt="Question? [y/n] "📌 Parameters
params: default: null user_input: ["invalid", "", "invalid", "yes"] expected_output: true expected_prompt: "Question? [y/n] " id: "None-user_input6-True-Question? [y/n] "📌 Setup phase
duration:
0.00036552827805280685outcome:
passed📌 Call phase
duration:
0.0006300825625658035outcome:
passed📌 Teardown phase
duration:
0.00023937691003084183outcome:
passed -
✅ Test 68
params:default="y", user_input="y", expected_output=true, expected_prompt="Question? [Y/n] "📌 Parameters
params: default: "y" user_input: "y" expected_output: true expected_prompt: "Question? [Y/n] " id: "y-y-True-Question? [Y/n] "📌 Setup phase
duration:
0.00037391483783721924outcome:
passed📌 Call phase
duration:
0.0006918814033269882outcome:
passed📌 Teardown phase
duration:
0.00031389016658067703outcome:
passed -
✅ Test 69
params:default="y", user_input="n", expected_output=false, expected_prompt="Question? [Y/n] "📌 Parameters
params: default: "y" user_input: "n" expected_output: false expected_prompt: "Question? [Y/n] " id: "y-n-False-Question? [Y/n] "📌 Setup phase
duration:
0.0003663068637251854outcome:
passed📌 Call phase
duration:
0.0005773017182946205outcome:
passed📌 Teardown phase
duration:
0.0002341819927096367outcome:
passed -
✅ Test 70
params:default="y", user_input="", expected_output=true, expected_prompt="Question? [Y/n] "📌 Parameters
params: default: "y" user_input: "" expected_output: true expected_prompt: "Question? [Y/n] " id: "y--True-Question? [Y/n] "📌 Setup phase
duration:
0.0003656148910522461outcome:
passed📌 Call phase
duration:
0.0005584582686424255outcome:
passed📌 Teardown phase
duration:
0.00022018607705831528outcome:
passed -
✅ Test 71
params:default="n", user_input="y", expected_output=true, expected_prompt="Question? [y/N] "📌 Parameters
params: default: "n" user_input: "y" expected_output: true expected_prompt: "Question? [y/N] " id: "n-y-True-Question? [y/N] "📌 Setup phase
duration:
0.0003519579768180847outcome:
passed📌 Call phase
duration:
0.0005792174488306046outcome:
passed📌 Teardown phase
duration:
0.00024229567497968674outcome:
passed -
✅ Test 72
params:default="n", user_input="n", expected_output=false, expected_prompt="Question? [y/N] "📌 Parameters
params: default: "n" user_input: "n" expected_output: false expected_prompt: "Question? [y/N] " id: "n-n-False-Question? [y/N] "📌 Setup phase
duration:
0.0003627752885222435outcome:
passed📌 Call phase
duration:
0.000691484659910202outcome:
passed📌 Teardown phase
duration:
0.00022077281028032303outcome:
passed -
✅ Test 73
params:default="n", user_input="", expected_output=false, expected_prompt="Question? [y/N] "📌 Parameters
params: default: "n" user_input: "" expected_output: false expected_prompt: "Question? [y/N] " id: "n--False-Question? [y/N] "📌 Setup phase
duration:
0.00038279034197330475outcome:
passed📌 Call phase
duration:
0.0005721980705857277outcome:
passed📌 Teardown phase
duration:
0.0002336297184228897outcome:
passed
↳ Function: test_ask_yes_no_ctrl_c
-
✅ Test 74
params:default=null, user_input="<class 'KeyboardInterrupt'>", expected_output=false, ctrl_c="n"📌 Parameters
params: default: null user_input: "<class 'KeyboardInterrupt'>" expected_output: false ctrl_c: "n" id: "None-KeyboardInterrupt-False-n"📌 Setup phase
duration:
0.00039671268314123154outcome:
passed📌 Call phase
duration:
0.0011618370190262794outcome:
passedstdout:
📌 Teardown phase
duration:
0.000264790840446949outcome:
passed -
✅ Test 75
params:default=null, user_input="<class 'KeyboardInterrupt'>", expected_output=true, ctrl_c="y"📌 Parameters
params: default: null user_input: "<class 'KeyboardInterrupt'>" expected_output: true ctrl_c: "y" id: "None-KeyboardInterrupt-True-y"📌 Setup phase
duration:
0.0003820238634943962outcome:
passed📌 Call phase
duration:
0.0011475170031189919outcome:
passedstdout:
📌 Teardown phase
duration:
0.00023440178483724594outcome:
passed -
✅ Test 76
params:default="y", user_input="<class 'KeyboardInterrupt'>", expected_output=false, ctrl_c="n"📌 Parameters
params: default: "y" user_input: "<class 'KeyboardInterrupt'>" expected_output: false ctrl_c: "n" id: "y-KeyboardInterrupt-False-n"📌 Setup phase
duration:
0.0004116250202059746outcome:
passed📌 Call phase
duration:
0.0010054968297481537outcome:
passedstdout:
📌 Teardown phase
duration:
0.00026118941605091095outcome:
passed -
✅ Test 77
params:default="y", user_input="<class 'KeyboardInterrupt'>", expected_output=true, ctrl_c="y"📌 Parameters
params: default: "y" user_input: "<class 'KeyboardInterrupt'>" expected_output: true ctrl_c: "y" id: "y-KeyboardInterrupt-True-y"📌 Setup phase
duration:
0.0003730505704879761outcome:
passed📌 Call phase
duration:
0.0009170044213533401outcome:
passedstdout:
📌 Teardown phase
duration:
0.00024047959595918655outcome:
passed -
✅ Test 78
params:default="n", user_input="<class 'KeyboardInterrupt'>", expected_output=false, ctrl_c="n"📌 Parameters
params: default: "n" user_input: "<class 'KeyboardInterrupt'>" expected_output: false ctrl_c: "n" id: "n-KeyboardInterrupt-False-n"📌 Setup phase
duration:
0.0003815172240138054outcome:
passed📌 Call phase
duration:
0.0009303539991378784outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002467762678861618outcome:
passed -
✅ Test 79
params:default=null, user_input="['invalid', '', 'invalid', <class 'KeyboardInterrupt'>]", expected_output=false, ctrl_c="n"📌 Parameters
params: default: null user_input: "['invalid', '', 'invalid', <class 'KeyboardInterrupt'>]" expected_output: false ctrl_c: "n" id: "None-user_input5-False-n"📌 Setup phase
duration:
0.00039336737245321274outcome:
passed📌 Call phase
duration:
0.0011023785918951035outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002518966794013977outcome:
passed -
✅ Test 80
params:default=null, user_input="['invalid', '', 'invalid', <class 'KeyboardInterrupt'>]", expected_output=true, ctrl_c="y"📌 Parameters
params: default: null user_input: "['invalid', '', 'invalid', <class 'KeyboardInterrupt'>]" expected_output: true ctrl_c: "y" id: "None-user_input6-True-y"📌 Setup phase
duration:
0.00036707986146211624outcome:
passed📌 Call phase
duration:
0.00258572306483984outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002529555931687355outcome:
passed -
✅ Test 81
params:default=null, user_input="['foo', '', <class 'KeyboardInterrupt'>, '', 'invalid', <class 'KeyboardInterrupt'>, 'no']", expected_output=false, ctrl_c=null📌 Parameters
params: default: null user_input: "['foo', '', <class 'KeyboardInterrupt'>, '', 'invalid', <class 'KeyboardInterrupt'>, 'no']" expected_output: false ctrl_c: null id: "None-user_input7-False-None"📌 Setup phase
duration:
0.0003852378576993942outcome:
passed📌 Call phase
duration:
0.0010348595678806305outcome:
passedstdout:
📌 Teardown phase
duration:
0.00023961905390024185outcome:
passed -
✅ Test 82
params:default="n", user_input="[<class 'KeyboardInterrupt'>, <class 'KeyboardInterrupt'>, <class 'KeyboardInterrupt'>, '']", expected_output=false, ctrl_c=null📌 Parameters
params: default: "n" user_input: "[<class 'KeyboardInterrupt'>, <class 'KeyboardInterrupt'>, <class 'KeyboardInterrupt'>, '']" expected_output: false ctrl_c: null id: "n-user_input8-False-None"📌 Setup phase
duration:
0.00038191303610801697outcome:
passed📌 Call phase
duration:
0.0016371775418519974outcome:
passedstdout:
📌 Teardown phase
duration:
0.00024224445223808289outcome:
passed -
✅ Test 83
params:default="n", user_input="[<class 'KeyboardInterrupt'>, <class 'KeyboardInterrupt'>, <class 'KeyboardInterrupt'>, '']", expected_output=false, ctrl_c="Invalid"📌 Parameters
params: default: "n" user_input: "[<class 'KeyboardInterrupt'>, <class 'KeyboardInterrupt'>, <class 'KeyboardInterrupt'>, '']" expected_output: false ctrl_c: "Invalid" id: "n-user_input9-False-Invalid"📌 Setup phase
duration:
0.0003876863047480583outcome:
passed📌 Call phase
duration:
0.0008964315056800842outcome:
passedstdout:
📌 Teardown phase
duration:
0.00023733451962471008outcome:
passed
↳ Function: test_ask_yes_no_ctrl_d
-
✅ Test 84
params:default=null, user_input="<class 'EOFError'>", expected_output=false, ctrl_d="n"📌 Parameters
params: default: null user_input: "<class 'EOFError'>" expected_output: false ctrl_d: "n" id: "None-EOFError-False-n"📌 Setup phase
duration:
0.0003726175054907799outcome:
passed📌 Call phase
duration:
0.0008871555328369141outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002542613074183464outcome:
passed -
✅ Test 85
params:default=null, user_input="<class 'EOFError'>", expected_output=true, ctrl_d="y"📌 Parameters
params: default: null user_input: "<class 'EOFError'>" expected_output: true ctrl_d: "y" id: "None-EOFError-True-y"📌 Setup phase
duration:
0.0003627082332968712outcome:
passed📌 Call phase
duration:
0.0008972557261586189outcome:
passedstdout:
📌 Teardown phase
duration:
0.00023705698549747467outcome:
passed -
✅ Test 86
params:default="y", user_input="<class 'EOFError'>", expected_output=true, ctrl_d="y"📌 Parameters
params: default: "y" user_input: "<class 'EOFError'>" expected_output: true ctrl_d: "y" id: "y-EOFError-True-y"📌 Setup phase
duration:
0.0004184022545814514outcome:
passed📌 Call phase
duration:
0.0009787585586309433outcome:
passedstdout:
📌 Teardown phase
duration:
0.00023046694695949554outcome:
passed -
✅ Test 87
params:default="n", user_input="<class 'EOFError'>", expected_output=true, ctrl_d="y"📌 Parameters
params: default: "n" user_input: "<class 'EOFError'>" expected_output: true ctrl_d: "y" id: "n-EOFError-True-y"📌 Setup phase
duration:
0.0003843940794467926outcome:
passed📌 Call phase
duration:
0.0008781375363469124outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002259640023112297outcome:
passed -
✅ Test 88
params:default="n", user_input="<class 'EOFError'>", expected_output=false, ctrl_d="n"📌 Parameters
params: default: "n" user_input: "<class 'EOFError'>" expected_output: false ctrl_d: "n" id: "n-EOFError-False-n"📌 Setup phase
duration:
0.0003888756036758423outcome:
passed📌 Call phase
duration:
0.0008959807455539703outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002534901723265648outcome:
passed -
✅ Test 89
params:default=null, user_input="['foo', <class 'EOFError'>]", expected_output=true, ctrl_d="y"📌 Parameters
params: default: null user_input: "['foo', <class 'EOFError'>]" expected_output: true ctrl_d: "y" id: "None-user_input5-True-y"📌 Setup phase
duration:
0.0003615645691752434outcome:
passed📌 Call phase
duration:
0.000899776816368103outcome:
passedstdout:
📌 Teardown phase
duration:
0.00023662764579057693outcome:
passed -
✅ Test 90
params:default=null, user_input="['foo', <class 'EOFError'>]", expected_output=false, ctrl_d="n"📌 Parameters
params: default: null user_input: "['foo', <class 'EOFError'>]" expected_output: false ctrl_d: "n" id: "None-user_input6-False-n"📌 Setup phase
duration:
0.00041280873119831085outcome:
passed📌 Call phase
duration:
0.0009732767939567566outcome:
passedstdout:
📌 Teardown phase
duration:
0.00023824907839298248outcome:
passed -
✅ Test 91
params:default="y", user_input="<class 'EOFError'>", expected_output=true, ctrl_d=null📌 Parameters
params: default: "y" user_input: "<class 'EOFError'>" expected_output: true ctrl_d: null id: "y-EOFError-True-None"📌 Setup phase
duration:
0.0003694538027048111outcome:
passed📌 Call phase
duration:
0.0008951779454946518outcome:
passedstdout:
📌 Teardown phase
duration:
0.00024981889873743057outcome:
passed -
✅ Test 92
params:default="n", user_input="<class 'EOFError'>", expected_output=false, ctrl_d=null📌 Parameters
params: default: "n" user_input: "<class 'EOFError'>" expected_output: false ctrl_d: null id: "n-EOFError-False-None"📌 Setup phase
duration:
0.0003621745854616165outcome:
passed📌 Call phase
duration:
0.0014246618375182152outcome:
passedstdout:
📌 Teardown phase
duration:
0.00023971684277057648outcome:
passed -
✅ Test 93
params:default=null, user_input="['invalid', 'ok', '', <class 'EOFError'>, 'ok', 'y']", expected_output=true, ctrl_d=null📌 Parameters
params: default: null user_input: "['invalid', 'ok', '', <class 'EOFError'>, 'ok', 'y']" expected_output: true ctrl_d: null id: "None-user_input9-True-None"📌 Setup phase
duration:
0.0003715064376592636outcome:
passed📌 Call phase
duration:
0.001607096754014492outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002424679696559906outcome:
passed -
✅ Test 94
params:default="n", user_input="['no', <class 'EOFError'>]", expected_output=false, ctrl_d=null📌 Parameters
params: default: "n" user_input: "['no', <class 'EOFError'>]" expected_output: false ctrl_d: null id: "n-user_input10-False-None"📌 Setup phase
duration:
0.00036812759935855865outcome:
passed📌 Call phase
duration:
0.0005777738988399506outcome:
passed📌 Teardown phase
duration:
0.00023484881967306137outcome:
passed -
✅ Test 95
params:default=null, user_input="[<class 'EOFError'>, <class 'EOFError'>, <class 'EOFError'>, 'y']", expected_output=true, ctrl_d=null📌 Parameters
params: default: null user_input: "[<class 'EOFError'>, <class 'EOFError'>, <class 'EOFError'>, 'y']" expected_output: true ctrl_d: null id: "None-user_input11-True-None"📌 Setup phase
duration:
0.0003673471510410309outcome:
passed📌 Call phase
duration:
0.0009757718071341515outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002485932782292366outcome:
passed -
✅ Test 96
params:default=null, user_input="['invalid', '', 'nope', <class 'EOFError'>]", expected_output=false, ctrl_d="n"📌 Parameters
params: default: null user_input: "['invalid', '', 'nope', <class 'EOFError'>]" expected_output: false ctrl_d: "n" id: "None-user_input12-False-n"📌 Setup phase
duration:
0.00036809779703617096outcome:
passed📌 Call phase
duration:
0.0009618541225790977outcome:
passedstdout:
📌 Teardown phase
duration:
0.00023052189499139786outcome:
passed -
✅ Test 97
params:default=null, user_input="['nope', 'nope', <class 'EOFError'>]", expected_output=true, ctrl_d="y"📌 Parameters
params: default: null user_input: "['nope', 'nope', <class 'EOFError'>]" expected_output: true ctrl_d: "y" id: "None-user_input13-True-y"📌 Setup phase
duration:
0.0003831610083580017outcome:
passed📌 Call phase
duration:
0.0010563209652900696outcome:
passedstdout:
📌 Teardown phase
duration:
0.00024065840989351273outcome:
passed
↳ Function: test_ask_yes_no_mixed_sequences
-
✅ Test 98
params:default=null, ctrl_c="invalid", ctrl_d=null, user_input="['what', '', 'nope', <class 'KeyboardInterrupt'>, 'ok', <class 'EOFError'>, 'no']", expected_output=false📌 Parameters
params: default: null ctrl_c: "invalid" ctrl_d: null user_input: "['what', '', 'nope', <class 'KeyboardInterrupt'>, 'ok', <class 'EOFError'>, 'no']" expected_output: false id: "None-invalid-None-user_input0-False"📌 Setup phase
duration:
0.00041622482240200043outcome:
passed📌 Call phase
duration:
0.0010157553479075432outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002604592591524124outcome:
passed -
✅ Test 99
params:default=null, ctrl_c=null, ctrl_d="notananswer", user_input="['maybe', <class 'KeyboardInterrupt'>, 'nop', 'yep', <class 'EOFError'>, 'yes']", expected_output=true📌 Parameters
params: default: null ctrl_c: null ctrl_d: "notananswer" user_input: "['maybe', <class 'KeyboardInterrupt'>, 'nop', 'yep', <class 'EOFError'>, 'yes']" expected_output: true id: "None-None-notananswer-user_input1-True"📌 Setup phase
duration:
0.00040698330849409103outcome:
passed📌 Call phase
duration:
0.0009638303890824318outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002526436001062393outcome:
passed -
✅ Test 100
params:default=null, ctrl_c="n", ctrl_d="nop", user_input="['ok', <class 'EOFError'>, <class 'EOFError'>, 'maybe', <class 'EOFError'>, 'nah', <class 'KeyboardInterrupt'>]", expected_output=false📌 Parameters
params: default: null ctrl_c: "n" ctrl_d: "nop" user_input: "['ok', <class 'EOFError'>, <class 'EOFError'>, 'maybe', <class 'EOFError'>, 'nah', <class 'KeyboardInterrupt'>]" expected_output: false id: "None-n-nop-user_input2-False"📌 Setup phase
duration:
0.00043327175080776215outcome:
passed📌 Call phase
duration:
0.0013270247727632523outcome:
passedstdout:
📌 Teardown phase
duration:
0.0002634022384881973outcome:
passed
-
-
📄 test_utils_channels.py
↳ Function: test_load_channels_and_channels_class_with_professional_names
-
✅ Test 101
📌 Setup phase
duration:
0.00018401723355054855outcome:
passed📌 Call phase
duration:
0.0008257022127509117outcome:
passed📌 Teardown phase
duration:
0.00015549547970294952outcome:
passed
-
-
📄 test_utils_config.py
↳ Function: test_config_with_nested_and_list_data
-
✅ Test 102
📌 Setup phase
duration:
0.000216582790017128outcome:
passed📌 Call phase
duration:
0.0006183367222547531outcome:
passed📌 Teardown phase
duration:
0.00015449151396751404outcome:
passed
↳ Function: test_config_with_strange_and_edge_keys
-
✅ Test 103
📌 Setup phase
duration:
0.0001468062400817871outcome:
passed📌 Call phase
duration:
0.0007917210459709167outcome:
passed📌 Teardown phase
duration:
0.00017132610082626343outcome:
passed
-
-
📄 test_utils_cpint.py
↳ Function: test_load_color_variants_all_keys_and_types
-
✅ Test 104
params:base_color="red"📌 Parameters
params: base_color: "red" id: "red"📌 Setup phase
duration:
0.0002757906913757324outcome:
passed📌 Call phase
duration:
0.00027075596153736115outcome:
passed📌 Teardown phase
duration:
0.0001768181100487709outcome:
passed -
✅ Test 105
params:base_color="blue"📌 Parameters
params: base_color: "blue" id: "blue"📌 Setup phase
duration:
0.00024858489632606506outcome:
passed📌 Call phase
duration:
0.00019746087491512299outcome:
passed📌 Teardown phase
duration:
0.00016057025641202927outcome:
passed -
✅ Test 106
params:base_color="yellow"📌 Parameters
params: base_color: "yellow" id: "yellow"📌 Setup phase
duration:
0.0002231420949101448outcome:
passed📌 Call phase
duration:
0.00018832087516784668outcome:
passed📌 Teardown phase
duration:
0.0001714443787932396outcome:
passed -
✅ Test 107
params:base_color="green"📌 Parameters
params: base_color: "green" id: "green"📌 Setup phase
duration:
0.00021129846572875977outcome:
passed📌 Call phase
duration:
0.0001940568909049034outcome:
passed📌 Teardown phase
duration:
0.00016852375119924545outcome:
passed -
✅ Test 108
params:base_color="cyan"📌 Parameters
params: base_color: "cyan" id: "cyan"📌 Setup phase
duration:
0.00021124444901943207outcome:
passed📌 Call phase
duration:
0.00020111817866563797outcome:
passed📌 Teardown phase
duration:
0.00016603432595729828outcome:
passed -
✅ Test 109
params:base_color="magenta"📌 Parameters
params: base_color: "magenta" id: "magenta"📌 Setup phase
duration:
0.0002137674018740654outcome:
passed📌 Call phase
duration:
0.00019227247685194016outcome:
passed📌 Teardown phase
duration:
0.00016937777400016785outcome:
passed -
✅ Test 110
params:base_color="white"📌 Parameters
params: base_color: "white" id: "white"📌 Setup phase
duration:
0.00023118779063224792outcome:
passed📌 Call phase
duration:
0.00019463151693344116outcome:
passed📌 Teardown phase
duration:
0.0001563066616654396outcome:
passed -
✅ Test 111
params:base_color="black"📌 Parameters
params: base_color: "black" id: "black"📌 Setup phase
duration:
0.00021959375590085983outcome:
passed📌 Call phase
duration:
0.0002045910805463791outcome:
passed📌 Teardown phase
duration:
0.00017527956515550613outcome:
passed
↳ Function: test_cprint_all_cases_fancy
-
✅ Test 112
params:objects=[["Fancy", "list"], {"a": 7}, null], color_spec=["red", "+"], sep=" | ", expected_flatten="['Fancy', 'list'] | {'a': 7} | None", expected_error=null📌 Parameters
params: objects: [["Fancy", "list"], {"a": 7}, null] color_spec: ["red", "+"] sep: " | " expected_flatten: "['Fancy', 'list'] | {'a': 7} | None" expected_error: null id: "objects0-color_spec0- | -['Fancy', 'list'] | {'a': 7} | None-None"📌 Setup phase
duration:
0.0007306616753339767outcome:
passed📌 Call phase
duration:
0.00029857363551855087outcome:
passed📌 Teardown phase
duration:
0.00031745340675115585outcome:
passed -
✅ Test 113
params:objects=[{"k": [1, 2]}, 99, ["X", ["Y"]]], color_spec=["blue", "++"], sep=" - ", expected_flatten="{'k': [1, 2]} - 99 - ['X', ['Y']]", expected_error=null📌 Parameters
params: objects: [{"k": [1, 2]}, 99, ["X", ["Y"]]] color_spec: ["blue", "++"] sep: " - " expected_flatten: "{'k': [1, 2]} - 99 - ['X', ['Y']]" expected_error: null id: "objects1-color_spec1- - -{'k': [1, 2]} - 99 - ['X', ['Y']]-None"📌 Setup phase
duration:
0.0005028415471315384outcome:
passed📌 Call phase
duration:
0.0002788146957755089outcome:
passed📌 Teardown phase
duration:
0.0002873959019780159outcome:
passed -
✅ Test 114
params:objects=[[], {}, "End"], color_spec=["magenta", "--"], sep=" / ", expected_flatten="[] / {} / End", expected_error=null📌 Parameters
params: objects: [[], {}, "End"] color_spec: ["magenta", "--"] sep: " / " expected_flatten: "[] / {} / End" expected_error: null id: "objects2-color_spec2- / -[] / {} / End-None"📌 Setup phase
duration:
0.0005251215770840645outcome:
passed📌 Call phase
duration:
0.0002839835360646248outcome:
passed📌 Teardown phase
duration:
0.00029595382511615753outcome:
passed -
✅ Test 115
params:objects=[["", [3, 4]], "done", 0], color_spec=["green", ""], sep=";", expected_flatten="['', [3, 4]];done;0", expected_error=null📌 Parameters
params: objects: [["", [3, 4]], "done", 0] color_spec: ["green", ""] sep: ";" expected_flatten: "['', [3, 4]];done;0" expected_error: null id: "objects3-color_spec3-;-['', [3, 4]];done;0-None"📌 Setup phase
duration:
0.0005118260160088539outcome:
passed📌 Call phase
duration:
0.00026065390557050705outcome:
passed📌 Teardown phase
duration:
0.00028977636247873306outcome:
passed -
✅ Test 116
params:objects=[["alpha", null], ["beta", {}], "stop"], color_spec=["yellow", ""], sep="::", expected_flatten="['alpha', None]::['beta', {}]::stop", expected_error=null📌 Parameters
params: objects: [["alpha", null], ["beta", {}], "stop"] color_spec: ["yellow", ""] sep: "::" expected_flatten: "['alpha', None]::['beta', {}]::stop" expected_error: null id: "objects4-color_spec4-::-['alpha', None]::['beta', {}]::stop-None"📌 Setup phase
duration:
0.000518798828125outcome:
passed📌 Call phase
duration:
0.0002632616087794304outcome:
passed📌 Teardown phase
duration:
0.00033649057149887085outcome:
passed -
✅ Test 117
params:objects=[["deep", ["deeper", ["deepest"]]], "X"], color_spec=["cyan", "+"], sep=" ... ", expected_flatten="['deep', ['deeper', ['deepest']]] ... X", expected_error=null📌 Parameters
params: objects: [["deep", ["deeper", ["deepest"]]], "X"] color_spec: ["cyan", "+"] sep: " ... " expected_flatten: "['deep', ['deeper', ['deepest']]] ... X" expected_error: null id: "objects5-color_spec5- ... -['deep', ['deeper', ['deepest']]] ... X-None"📌 Setup phase
duration:
0.0005203504115343094outcome:
passed📌 Call phase
duration:
0.00025780685245990753outcome:
passed📌 Teardown phase
duration:
0.00030151475220918655outcome:
passed -
✅ Test 118
params:objects=[{"dict": {"nested": [4, 5]}}, [true, false], 6.28], color_spec=["white", "++"], sep=" // ", expected_flatten="{'dict': {'nested': [4, 5]}} // [True, False] // 6.28", expected_error=null📌 Parameters
params: objects: [{"dict": {"nested": [4, 5]}}, [true, false], 6.28] color_spec: ["white", "++"] sep: " // " expected_flatten: "{'dict': {'nested': [4, 5]}} // [True, False] // 6.28" expected_error: null id: "objects6-color_spec6- // -{'dict': {'nested': [4, 5]}} // [True, False] // 6.28-None"📌 Setup phase
duration:
0.0005175741389393806outcome:
passed📌 Call phase
duration:
0.0002792244777083397outcome:
passed📌 Teardown phase
duration:
0.0002819318324327469outcome:
passed -
✅ Test 119
params:objects=[["A", ["B"]], "string", "C"], color_spec=["red", "--"], sep="==", expected_flatten="['A', ['B']]==string==C", expected_error=null📌 Parameters
params: objects: [["A", ["B"]], "string", "C"] color_spec: ["red", "--"] sep: "==" expected_flatten: "['A', ['B']]==string==C" expected_error: null id: "objects7-color_spec7-==-['A', ['B']]==string==C-None"📌 Setup phase
duration:
0.0005251849070191383outcome:
passed📌 Call phase
duration:
0.0002711135894060135outcome:
passed📌 Teardown phase
duration:
0.00028059910982847214outcome:
passed -
✅ Test 120
params:objects=[["Test", null, []], {"v": 0}], color_spec=["green", "++"], sep=" ++ ", expected_flatten="['Test', None, []] ++ {'v': 0}", expected_error=null📌 Parameters
params: objects: [["Test", null, []], {"v": 0}] color_spec: ["green", "++"] sep: " ++ " expected_flatten: "['Test', None, []] ++ {'v': 0}" expected_error: null id: "objects8-color_spec8- ++ -['Test', None, []] ++ {'v': 0}-None"📌 Setup phase
duration:
0.0005137398838996887outcome:
passed📌 Call phase
duration:
0.0002524787560105324outcome:
passed📌 Teardown phase
duration:
0.0004157042130827904outcome:
passed -
✅ Test 121
params:objects=[["no", "color"], "plain"], color_spec=null, sep=";", expected_flatten="['no', 'color'];plain", expected_error=null📌 Parameters
params: objects: [["no", "color"], "plain"] color_spec: null sep: ";" expected_flatten: "['no', 'color'];plain" expected_error: null id: "objects9-None-;-['no', 'color'];plain-None"📌 Setup phase
duration:
0.0005211103707551956outcome:
passed📌 Call phase
duration:
0.0002501504495739937outcome:
passed📌 Teardown phase
duration:
0.00030966661870479584outcome:
passed -
✅ Test 122
params:objects=[["simple"], "", 12], color_spec=null, sep=" | ", expected_flatten="['simple'] | | 12", expected_error=null📌 Parameters
params: objects: [["simple"], "", 12] color_spec: null sep: " | " expected_flatten: "['simple'] | | 12" expected_error: null id: "objects10-None- | -['simple'] | | 12-None"📌 Setup phase
duration:
0.0005443096160888672outcome:
passed📌 Call phase
duration:
0.0002549579367041588outcome:
passed📌 Teardown phase
duration:
0.0002954360097646713outcome:
passed -
✅ Test 123
params:objects=[[["very", "deep"]], {"ok": true}], color_spec=null, sep=" : ", expected_flatten="[['very', 'deep']] : {'ok': True}", expected_error=null📌 Parameters
params: objects: [[["very", "deep"]], {"ok": true}] color_spec: null sep: " : " expected_flatten: "[['very', 'deep']] : {'ok': True}" expected_error: null id: "objects11-None- : -[['very', 'deep']] : {'ok': True}-None"📌 Setup phase
duration:
0.0004990492016077042outcome:
passed📌 Call phase
duration:
0.0002622082829475403outcome:
passed📌 Teardown phase
duration:
0.0002947114408016205outcome:
passed -
✅ Test 124
params:objects=[["fail", "color"], 123], color_spec=["green", "!!"], sep="|", expected_flatten="['fail', 'color']|123", expected_error="<class 'ValueError'>"📌 Parameters
params: objects: [["fail", "color"], 123] color_spec: ["green", "!!"] sep: "|" expected_flatten: "['fail', 'color']|123" expected_error: "<class 'ValueError'>" id: "objects12-color_spec12-|-['fail', 'color']|123-ValueError"📌 Setup phase
duration:
0.0005187559872865677outcome:
passed📌 Call phase
duration:
0.0003010965883731842outcome:
passed📌 Teardown phase
duration:
0.0003099655732512474outcome:
passed -
✅ Test 125
params:objects=[["error"], {}], color_spec=["cyan", "xxx"], sep=" * ", expected_flatten="['error'] * {}", expected_error="<class 'ValueError'>"📌 Parameters
params: objects: [["error"], {}] color_spec: ["cyan", "xxx"] sep: " * " expected_flatten: "['error'] * {}" expected_error: "<class 'ValueError'>" id: "objects13-color_spec13- * -['error'] * {}-ValueError"📌 Setup phase
duration:
0.0005266331136226654outcome:
passed📌 Call phase
duration:
0.0002756882458925247outcome:
passed📌 Teardown phase
duration:
0.0003040144219994545outcome:
passed -
✅ Test 126
params:objects=[["nope"], ["bad"]], color_spec=["magenta", "invalid"], sep="//", expected_flatten="['nope']//['bad']", expected_error="<class 'ValueError'>"📌 Parameters
params: objects: [["nope"], ["bad"]] color_spec: ["magenta", "invalid"] sep: "//" expected_flatten: "['nope']//['bad']" expected_error: "<class 'ValueError'>" id: "objects14-color_spec14-//-['nope']//['bad']-ValueError"📌 Setup phase
duration:
0.0005216943100094795outcome:
passed📌 Call phase
duration:
0.0002763299271464348outcome:
passed📌 Teardown phase
duration:
0.0003075888380408287outcome:
passed -
✅ Test 127
params:objects=["wrong", "base"], color_spec=["notacolor", ""], sep="--", expected_flatten="wrong--base", expected_error="<class 'ValueError'>"📌 Parameters
params: objects: ["wrong", "base"] color_spec: ["notacolor", ""] sep: "--" expected_flatten: "wrong--base" expected_error: "<class 'ValueError'>" id: "objects15-color_spec15----wrong--base-ValueError"📌 Setup phase
duration:
0.0005154097452759743outcome:
passed📌 Call phase
duration:
0.0002562450245022774outcome:
passed📌 Teardown phase
duration:
0.00031027384102344513outcome:
passed
-
-
📄 test_utils_dbusnotify.py
↳ Function: test_notify_create
-
✅ Test 128
📌 Setup phase
duration:
0.0006854627281427383outcome:
passed📌 Call phase
duration:
0.005087520927190781outcome:
passed📌 Teardown phase
duration:
0.00018891040235757828outcome:
passed
↳ Function: test_notify_update
-
✅ Test 129
📌 Setup phase
duration:
0.0002070050686597824outcome:
passed📌 Call phase
duration:
0.01696749124675989outcome:
passed📌 Teardown phase
duration:
0.00026872381567955017outcome:
passed
↳ Function: test_get_server_info
-
✅ Test 130
📌 Setup phase
duration:
0.00026488397270441055outcome:
passed📌 Call phase
duration:
0.000705355778336525outcome:
passed📌 Teardown phase
duration:
0.00021848082542419434outcome:
passed
↳ Function: test_get_capabilities
-
✅ Test 131
📌 Setup phase
duration:
0.0003793351352214813outcome:
passed📌 Call phase
duration:
0.0008136937394738197outcome:
passed📌 Teardown phase
duration:
0.0002942681312561035outcome:
passed
↳ Function: test_notify_and_close
-
✅ Test 132
📌 Setup phase
duration:
0.0002825409173965454outcome:
passed📌 Call phase
duration:
0.20464586652815342outcome:
passed📌 Teardown phase
duration:
0.00026594940572977066outcome:
passed
↳ Function: test_notify_invalid_value
-
✅ Test 133
📌 Setup phase
duration:
0.00023364368826150894outcome:
passed📌 Call phase
duration:
0.0005289716646075249outcome:
passedlog:
- name: dbus.connection msg: Unable to set arguments ('', 0, '', 'Invalid Test', 1234, (), {}, 0) according to signature 'susssasa{sv}i': <class 'TypeError'>: Expected a string or unicode object args: [] levelname: ERROR levelno: 40 pathname: /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/dbus/connection.py filename: connection.py module: connection exc_info: [] exc_text: [] stack_info: [] lineno: 628 funcName: call_blocking created: 1756376001.4968197 msecs: 496.81973457336426 relativeCreated: 3824.5084285736084 thread: 140648901174784 threadName: MainThread processName: MainProcess process: 2977📌 Teardown phase
duration:
0.0001817094162106514outcome:
passed
↳ Function: test_convert_dbus_strings
-
✅ Test 134
📌 Setup phase
duration:
0.00015726592391729355outcome:
passed📌 Call phase
duration:
0.00024477671831846237outcome:
passed📌 Teardown phase
duration:
0.0001427438110113144outcome:
passed
-
-
📄 test_utils_debug.py
↳ Function: test_traceable
-
✅ Test 135
params:cls="<class 'test_utils_debug.A'>", entry=[[10, 20], {}], expected="creating: A(10, 20)"📌 Parameters
params: cls: "<class 'test_utils_debug.A'>" entry: [[10, 20], {}] expected: "creating: A(10, 20)" id: "A-entry0-creating: A(10, 20)"📌 Setup phase
duration:
0.00040617678314447403outcome:
passed📌 Call phase
duration:
0.001128663308918476outcome:
passed📌 Teardown phase
duration:
0.00024067796766757965outcome:
passed -
✅ Test 136
params:cls="<class 'test_utils_debug.A'>", entry=[[10, 20], {"e": 100}], expected="creating: A(10, 20, e=100)"📌 Parameters
params: cls: "<class 'test_utils_debug.A'>" entry: [[10, 20], {"e": 100}] expected: "creating: A(10, 20, e=100)" id: "A-entry1-creating: A(10, 20, e=100)"📌 Setup phase
duration:
0.0003371266648173332outcome:
passed📌 Call phase
duration:
0.0009148353710770607outcome:
passed📌 Teardown phase
duration:
0.00022287014871835709outcome:
passed -
✅ Test 137
params:cls="<class 'test_utils_debug.A'>", entry=[["foo", [1, 2, 3]], {"flag": true, "data": {"x": 9}}], expected="creating: A('foo', [1, 2, 3], flag=True, data={'x': 9})"📌 Parameters
params: cls: "<class 'test_utils_debug.A'>" entry: [["foo", [1, 2, 3]], {"flag": true, "data": {"x": 9}}] expected: "creating: A('foo', [1, 2, 3], flag=True, data={'x': 9})" id: "A-entry2-creating: A('foo', [1, 2, 3], flag=True, data={'x': 9})"📌 Setup phase
duration:
0.000337798148393631outcome:
passed📌 Call phase
duration:
0.0009904159232974052outcome:
passed📌 Teardown phase
duration:
0.00022893212735652924outcome:
passed -
✅ Test 138
params:cls="<class 'test_utils_debug.A'>", entry="([CustomObj(big), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], {'name': 'test', 'meta': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'})", expected="creating: A(CustomObj(big), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], name='test', meta='yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy...)"📌 Parameters
params: cls: "<class 'test_utils_debug.A'>" entry: "([CustomObj(big), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], {'name': 'test', 'meta': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'})" expected: "creating: A(CustomObj(big), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], name='test', meta='yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy...)" id: "A-entry3-creating: A(CustomObj(big), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], name='test', meta='yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy...)"📌 Setup phase
duration:
0.0003446759656071663outcome:
passed📌 Call phase
duration:
0.0009119650349020958outcome:
passed📌 Teardown phase
duration:
0.0002269558608531952outcome:
passed -
✅ Test 139
params:cls="<class 'test_utils_debug.A'>", entry=[["AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", [0, 0, 0, 0, 0]], {}], expected="creating: A('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA..., [0, 0, 0, 0, 0])"📌 Parameters
params: cls: "<class 'test_utils_debug.A'>" entry: [["AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", [0, 0, 0, 0, 0]], {}] expected: "creating: A('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA..., [0, 0, 0, 0, 0])" id: "A-entry4-creating: A('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA..., [0, 0, 0, 0, 0])"📌 Setup phase
duration:
0.00033375341445207596outcome:
passed📌 Call phase
duration:
0.0009415149688720703outcome:
passed📌 Teardown phase
duration:
0.0002396106719970703outcome:
passed
↳ Function: test_short_repr
-
✅ Test 140
params:value="abc", cutoff=10, expected="'abc'"📌 Parameters
params: value: "abc" cutoff: 10 expected: "'abc'" id: "abc-10-'abc'"📌 Setup phase
duration:
0.00032036658376455307outcome:
passed📌 Call phase
duration:
0.0002113664522767067outcome:
passed📌 Teardown phase
duration:
0.0002040807157754898outcome:
passed -
✅ Test 142
params:value=12345, cutoff=10, expected="12345"📌 Parameters
params: value: 12345 cutoff: 10 expected: "12345" id: "12345-10-12345"📌 Setup phase
duration:
0.0006428128108382225outcome:
passed📌 Call phase
duration:
0.0004043998196721077outcome:
passed📌 Teardown phase
duration:
0.0003981897607445717outcome:
passed -
✅ Test 143
params:value=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], cutoff=15, expected="[0, 0, 0, 0, 0,..."📌 Parameters
params: value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] cutoff: 15 expected: "[0, 0, 0, 0, 0,..." id: "value3-15-[0, 0, 0, 0, 0,..."📌 Setup phase
duration:
0.0005013672634959221outcome:
passed📌 Call phase
duration:
0.00034567341208457947outcome:
passed📌 Teardown phase
duration:
0.0003566080704331398outcome:
passed -
✅ Test 144
params:value=null, cutoff=10, expected="None"📌 Parameters
params: value: null cutoff: 10 expected: "None" id: "None-10-None"📌 Setup phase
duration:
0.000403841957449913outcome:
passed📌 Call phase
duration:
0.00020684674382209778outcome:
passed📌 Teardown phase
duration:
0.00024171825498342514outcome:
passed
-
-
📄 test_utils_dictext.py
↳ Function: test_attrdict_getattr
-
✅ Test 146
params:data={"x": 1, "y": 2}, attr="x", expected=1📌 Parameters
params: data: {"x": 1, "y": 2} attr: "x" expected: 1 id: "data0-x-1"📌 Setup phase
duration:
0.0004962170496582985outcome:
passed📌 Call phase
duration:
0.0003164084628224373outcome:
passed📌 Teardown phase
duration:
0.000430879183113575outcome:
passed -
✅ Test 147
params:data={"world": "ok"}, attr="world", expected="ok"📌 Parameters
params: data: {"world": "ok"} attr: "world" expected: "ok" id: "data1-world-ok"📌 Setup phase
duration:
0.0005793515592813492outcome:
passed📌 Call phase
duration:
0.0003451230004429817outcome:
passed📌 Teardown phase
duration:
0.0003024907782673836outcome:
passed -
✅ Test 148
params:data={"outer": {"inner": 42}}, attr="outer", expected={"inner": 42}📌 Parameters
params: data: {"outer": {"inner": 42}} attr: "outer" expected: {"inner": 42} id: "data2-outer-expected2"📌 Setup phase
duration:
0.0004766695201396942outcome:
passed📌 Call phase
duration:
0.0002464447170495987outcome:
passed📌 Teardown phase
duration:
0.00026236195117235184outcome:
passed
↳ Function: test_attrdict_setattr
-
✅ Test 149
params:initial={}, attr="nouveau", value=123📌 Parameters
params: initial: {} attr: "nouveau" value: 123 id: "initial0-nouveau-123"📌 Setup phase
duration:
0.0003591710701584816outcome:
passed📌 Call phase
duration:
0.00021881051361560822outcome:
passed📌 Teardown phase
duration:
0.0002867523580789566outcome:
passed -
✅ Test 150
params:initial={"a": 1}, attr="b", value="valeur"📌 Parameters
params: initial: {"a": 1} attr: "b" value: "valeur" id: "initial1-b-valeur"📌 Setup phase
duration:
0.00047320034354925156outcome:
passed📌 Call phase
duration:
0.00025423895567655563outcome:
passed📌 Teardown phase
duration:
0.00023606326431035995outcome:
passed
↳ Function: test_attrdict_delattr
-
✅ Test 151
params:initial={"a": 1, "b": 2}, to_del="a", expected_keys=["b"]📌 Parameters
params: initial: {"a": 1, "b": 2} to_del: "a" expected_keys: ["b"] id: "initial0-a-expected_keys0"📌 Setup phase
duration:
0.0003133527934551239outcome:
passed📌 Call phase
duration:
0.0002696588635444641outcome:
passed📌 Teardown phase
duration:
0.0002498682588338852outcome:
passed -
✅ Test 152
params:initial={"k": "v"}, to_del="k", expected_keys=[]📌 Parameters
params: initial: {"k": "v"} to_del: "k" expected_keys: [] id: "initial1-k-expected_keys1"📌 Setup phase
duration:
0.00040162820369005203outcome:
passed📌 Call phase
duration:
0.000245068222284317outcome:
passed📌 Teardown phase
duration:
0.00020593125373125076outcome:
passed
↳ Function: test_attrdict_dir
-
✅ Test 153
params:data={"alpha": 1, "beta": 2}, expected_keys="{'beta', 'alpha'}"📌 Parameters
params: data: {"alpha": 1, "beta": 2} expected_keys: "{'beta', 'alpha'}" id: "data0-expected_keys0"📌 Setup phase
duration:
0.00036404654383659363outcome:
passed📌 Call phase
duration:
0.00032124854624271393outcome:
passed📌 Teardown phase
duration:
0.00024531129747629166outcome:
passed -
✅ Test 154
params:data={}, expected_keys="set()"📌 Parameters
params: data: {} expected_keys: "set()" id: "data1-expected_keys1"📌 Setup phase
duration:
0.0003797682002186775outcome:
passed📌 Call phase
duration:
0.00030283816158771515outcome:
passed📌 Teardown phase
duration:
0.00024407170712947845outcome:
passed
↳ Function: test_attrdict_getattr_and_missing
-
✅ Test 155
params:data={"x": 1, "y": 2}, attr="x", expect_value=1, expect_error=null📌 Parameters
params: data: {"x": 1, "y": 2} attr: "x" expect_value: 1 expect_error: null id: "data0-x-1-None"📌 Setup phase
duration:
0.0005677379667758942outcome:
passed📌 Call phase
duration:
0.0002822699025273323outcome:
passed📌 Teardown phase
duration:
0.00029976852238178253outcome:
passed -
✅ Test 156
params:data={"number": 42}, attr="missing", expect_value=null, expect_error="'MyDict' object has no attribute 'missing'"📌 Parameters
params: data: {"number": 42} attr: "missing" expect_value: null expect_error: "'MyDict' object has no attribute 'missing'" id: "data1-missing-None-'MyDict' object has no attribute 'missing'"📌 Setup phase
duration:
0.0005960464477539062outcome:
passed📌 Call phase
duration:
0.00026692822575569153outcome:
passed📌 Teardown phase
duration:
0.00041577965021133423outcome:
passed
↳ Function: test_dictupdatemixin_init_and_update
-
✅ Test 157
params:init_kwargs={"a": 1, "b": 2}, other=null, kwargs={}, expected={"a": 1, "b": 2}📌 Parameters
params: init_kwargs: {"a": 1, "b": 2} other: null kwargs: {} expected: {"a": 1, "b": 2} id: "init_kwargs0-None-kwargs0-expected0"📌 Setup phase
duration:
0.0005042180418968201outcome:
passed📌 Call phase
duration:
0.00032423995435237885outcome:
passed📌 Teardown phase
duration:
0.0002432074397802353outcome:
passed -
✅ Test 158
params:init_kwargs={}, other={"x": 10, "y": 20}, kwargs={}, expected={"x": 10, "y": 20}📌 Parameters
params: init_kwargs: {} other: {"x": 10, "y": 20} kwargs: {} expected: {"x": 10, "y": 20} id: "init_kwargs1-other1-kwargs1-expected1"📌 Setup phase
duration:
0.0004223734140396118outcome:
passed📌 Call phase
duration:
0.0002208491787314415outcome:
passed📌 Teardown phase
duration:
0.0002480205148458481outcome:
passed -
✅ Test 159
params:init_kwargs={"world": "ok"}, other={"number": 42}, kwargs={"num2": 100}, expected={"world": "ok", "number": 42, "num2": 100}📌 Parameters
params: init_kwargs: {"world": "ok"} other: {"number": 42} kwargs: {"num2": 100} expected: {"world": "ok", "number": 42, "num2": 100} id: "init_kwargs2-other2-kwargs2-expected2"📌 Setup phase
duration:
0.00042845960706472397outcome:
passed📌 Call phase
duration:
0.00021429825574159622outcome:
passed📌 Teardown phase
duration:
0.00021904334425926208outcome:
passed -
✅ Test 160
params:init_kwargs={}, other=null, kwargs={"alpha": "beta"}, expected={"alpha": "beta"}📌 Parameters
params: init_kwargs: {} other: null kwargs: {"alpha": "beta"} expected: {"alpha": "beta"} id: "init_kwargs3-None-kwargs3-expected3"📌 Setup phase
duration:
0.00041524507105350494outcome:
passed📌 Call phase
duration:
0.0002485997974872589outcome:
passed📌 Teardown phase
duration:
0.00024088844656944275outcome:
passed -
✅ Test 161
params:init_kwargs={}, other={"key": "value"}, kwargs={"extra": 1}, expected={"key": "value", "extra": 1}📌 Parameters
params: init_kwargs: {} other: {"key": "value"} kwargs: {"extra": 1} expected: {"key": "value", "extra": 1} id: "init_kwargs4-other4-kwargs4-expected4"📌 Setup phase
duration:
0.0003793109208345413outcome:
passed📌 Call phase
duration:
0.0002526538446545601outcome:
passed📌 Teardown phase
duration:
0.00023614056408405304outcome:
passed -
✅ Test 162
params:init_kwargs={}, other=[["key", "value"], ["list", [5, 6]]], kwargs={"extra": {"subkey": 123}}, expected={"key": "value", "list": [5, 6], "extra": {"subkey": 123}}📌 Parameters
params: init_kwargs: {} other: [["key", "value"], ["list", [5, 6]]] kwargs: {"extra": {"subkey": 123}} expected: {"key": "value", "list": [5, 6], "extra": {"subkey": 123}} id: "init_kwargs5-other5-kwargs5-expected5"📌 Setup phase
duration:
0.0004470245912671089outcome:
passed📌 Call phase
duration:
0.0003634681925177574outcome:
passed📌 Teardown phase
duration:
0.00026802532374858856outcome:
passed
-
-
📄 test_utils_dotdir.py
↳ Function: test_dotdir_creation_and_base_exists
-
✅ Test 163
📌 Setup phase
duration:
0.0015016142278909683outcome:
passed📌 Call phase
duration:
0.00043480284512043outcome:
passed📌 Teardown phase
duration:
0.00038635265082120895outcome:
passed
↳ Function: test_dotdir_repr_returns_path_str
-
✅ Test 164
📌 Setup phase
duration:
0.0007829107344150543outcome:
passed📌 Call phase
duration:
0.0002950131893157959outcome:
passed📌 Teardown phase
duration:
0.00031824130564928055outcome:
passed
↳ Function: test_dotdir_call
-
✅ Test 165
📌 Setup phase
duration:
0.0008252719417214394outcome:
passed📌 Call phase
duration:
0.0011571869254112244outcome:
passed📌 Teardown phase
duration:
0.00026491377502679825outcome:
passed
-
-
📄 test_utils_duo.py
↳ Function: TestPickledDictReal
-
✅ Test 166
📌 Setup phase
duration:
0.00017429422587156296outcome:
passed📌 Call phase
duration:
0.0026126131415367126outcome:
passed📌 Teardown phase
duration:
0.00017393287271261215outcome:
passed -
✅ Test 167
📌 Setup phase
duration:
0.0001611625775694847outcome:
passed📌 Call phase
duration:
0.008062758482992649outcome:
passed📌 Teardown phase
duration:
0.00026553962379693985outcome:
passed
↳ Function: TestSecrets
-
✅ Test 168
📌 Setup phase
duration:
0.0009338594973087311outcome:
passed📌 Call phase
duration:
0.012359211221337318outcome:
passed📌 Teardown phase
duration:
0.0012211808934807777outcome:
passed -
✅ Test 169
📌 Setup phase
duration:
0.0007458347827196121outcome:
passed📌 Call phase
duration:
0.0027843955904245377outcome:
passed📌 Teardown phase
duration:
0.0003632251173257828outcome:
passed -
✅ Test 170
📌 Setup phase
duration:
0.000639844685792923outcome:
passed📌 Call phase
duration:
0.001321401447057724outcome:
passedstdout:
📌 Teardown phase
duration:
0.00040127523243427277outcome:
passed
↳ Function: test_get_pgroup_raises_if_no_key
-
✅ Test 171
📌 Setup phase
duration:
0.00030512455850839615outcome:
passed📌 Call phase
duration:
0.0006421636790037155outcome:
passed📌 Teardown phase
duration:
0.0002711750566959381outcome:
passed
↳ Function: test_get_pgroup_info_with_props_same_name_and_pi
-
✅ Test 172
📌 Setup phase
duration:
0.00032791122794151306outcome:
passed📌 Call phase
duration:
0.0002810917794704437outcome:
passed📌 Teardown phase
duration:
0.000183851458132267outcome:
passed
↳ Function: test_get_pgroup_info_with_props_different_pi
-
✅ Test 173
📌 Setup phase
duration:
0.00022998079657554626outcome:
passed📌 Call phase
duration:
0.00021796301007270813outcome:
passed📌 Teardown phase
duration:
0.0001754285767674446outcome:
passed
↳ Function: test_get_pgroup_info_without_props_with_owner
-
✅ Test 174
📌 Setup phase
duration:
0.00021580327302217484outcome:
passed📌 Call phase
duration:
0.0002480586990714073outcome:
passed📌 Teardown phase
duration:
0.00016600359231233597outcome:
passed
↳ Function: test_get_pgroup_info_without_props_no_owner
-
✅ Test 175
📌 Setup phase
duration:
0.0002299286425113678outcome:
passed📌 Call phase
duration:
0.0002155369147658348outcome:
passed📌 Teardown phase
duration:
0.0001680459827184677outcome:
passed
↳ Function: test_get_pgroup_info_mock
-
✅ Test 176
📌 Setup phase
duration:
0.00021883472800254822outcome:
passed📌 Call phase
duration:
0.00020692311227321625outcome:
passed📌 Teardown phase
duration:
0.00017917994409799576outcome:
passed
-
-
📄 test_utils_elog.py
↳ Function: test_get_default_elog_instance_with_wrong_password_and_real_check
-
✅ Test 178
📌 Setup phase
duration:
0.00020082946866750717outcome:
passed📌 Call phase
duration:
0.007667813450098038outcome:
passed📌 Teardown phase
duration:
0.0002079075202345848outcome:
passed
-
-
📄 test_utils_eval.py
↳ Function: test_arithmetic_eval_valid
-
✅ Test 182
params:expr="1 + 2", expected=3📌 Parameters
params: expr: "1 + 2" expected: 3 id: "1 + 2-3"📌 Setup phase
duration:
0.00041782110929489136outcome:
passed📌 Call phase
duration:
0.0002766633406281471outcome:
passed📌 Teardown phase
duration:
0.00020018219947814941outcome:
passed -
✅ Test 183
params:expr="4 - 2", expected=2📌 Parameters
params: expr: "4 - 2" expected: 2 id: "4 - 2-2"📌 Setup phase
duration:
0.000297006219625473outcome:
passed📌 Call phase
duration:
0.00020484160631895065outcome:
passed📌 Teardown phase
duration:
0.00018071196973323822outcome:
passed -
✅ Test 184
params:expr="3 * 5", expected=15📌 Parameters
params: expr: "3 * 5" expected: 15 id: "3 * 5-15"📌 Setup phase
duration:
0.00026360154151916504outcome:
passed📌 Call phase
duration:
0.00019094441086053848outcome:
passed📌 Teardown phase
duration:
0.00019138306379318237outcome:
passed -
✅ Test 185
params:expr="10 / 2", expected=5.0📌 Parameters
params: expr: "10 / 2" expected: 5.0 id: "10 / 2-5.0"📌 Setup phase
duration:
0.00026543252170085907outcome:
passed📌 Call phase
duration:
0.0002075526863336563outcome:
passed📌 Teardown phase
duration:
0.00017395615577697754outcome:
passed -
✅ Test 186
params:expr="10 % 3", expected=1📌 Parameters
params: expr: "10 % 3" expected: 1 id: "10 % 3-1"📌 Setup phase
duration:
0.00027392245829105377outcome:
passed📌 Call phase
duration:
0.000199844129383564outcome:
passed📌 Teardown phase
duration:
0.00019279774278402328outcome:
passed -
✅ Test 187
params:expr="-5", expected=-5📌 Parameters
params: expr: "-5" expected: -5 id: "-5--5"📌 Setup phase
duration:
0.0002624206244945526outcome:
passed📌 Call phase
duration:
0.000197606161236763outcome:
passed📌 Teardown phase
duration:
0.0001937495544552803outcome:
passed -
✅ Test 188
params:expr="+7", expected=7📌 Parameters
params: expr: "+7" expected: 7 id: "+7-7"📌 Setup phase
duration:
0.0002616792917251587outcome:
passed📌 Call phase
duration:
0.00018545519560575485outcome:
passed📌 Teardown phase
duration:
0.00017793010920286179outcome:
passed -
✅ Test 189
params:expr="1 + 2 * 3", expected=7📌 Parameters
params: expr: "1 + 2 * 3" expected: 7 id: "1 + 2 * 3-7"📌 Setup phase
duration:
0.0002636881545186043outcome:
passed📌 Call phase
duration:
0.0002010529860854149outcome:
passed📌 Teardown phase
duration:
0.00017993804067373276outcome:
passed -
✅ Test 190
params:expr="(1 + 2) * 3", expected=9📌 Parameters
params: expr: "(1 + 2) * 3" expected: 9 id: "(1 + 2) * 3-9"📌 Setup phase
duration:
0.0002666302025318146outcome:
passed📌 Call phase
duration:
0.00019652768969535828outcome:
passed📌 Teardown phase
duration:
0.00018306542187929153outcome:
passed -
✅ Test 191
params:expr="-(-3)", expected=3📌 Parameters
params: expr: "-(-3)" expected: 3 id: "-(-3)-3"📌 Setup phase
duration:
0.0002659643068909645outcome:
passed📌 Call phase
duration:
0.00019340869039297104outcome:
passed📌 Teardown phase
duration:
0.0001820167526602745outcome:
passed -
✅ Test 192
params:expr="-2 + 4 * 2", expected=6📌 Parameters
params: expr: "-2 + 4 * 2" expected: 6 id: "-2 + 4 * 2-6"📌 Setup phase
duration:
0.0002614827826619148outcome:
passed📌 Call phase
duration:
0.00021327286958694458outcome:
passed📌 Teardown phase
duration:
0.00017581041902303696outcome:
passed -
✅ Test 193
params:expr="(4 + 5) * (6 - 1)", expected=45📌 Parameters
params: expr: "(4 + 5) * (6 - 1)" expected: 45 id: "(4 + 5) * (6 - 1)-45"📌 Setup phase
duration:
0.00027731992304325104outcome:
passed📌 Call phase
duration:
0.00021094270050525665outcome:
passed📌 Teardown phase
duration:
0.00017810240387916565outcome:
passed -
✅ Test 194
params:expr="(((3)))", expected=3📌 Parameters
params: expr: "(((3)))" expected: 3 id: "(((3)))-3"📌 Setup phase
duration:
0.0002632550895214081outcome:
passed📌 Call phase
duration:
0.00019176490604877472outcome:
passed📌 Teardown phase
duration:
0.0001907050609588623outcome:
passed -
✅ Test 195
params:expr="-(-(-2))", expected=-2📌 Parameters
params: expr: "-(-(-2))" expected: -2 id: "-(-(-2))--2"📌 Setup phase
duration:
0.0002546226605772972outcome:
passed📌 Call phase
duration:
0.0001939963549375534outcome:
passed📌 Teardown phase
duration:
0.00018606707453727722outcome:
passed -
✅ Test 196
params:expr="3 + +4", expected=7📌 Parameters
params: expr: "3 + +4" expected: 7 id: "3 + +4-7"📌 Setup phase
duration:
0.00026069022715091705outcome:
passed📌 Call phase
duration:
0.00024283677339553833outcome:
passed📌 Teardown phase
duration:
0.00018803030252456665outcome:
passed -
✅ Test 197
params:expr="3 + -4", expected=-1📌 Parameters
params: expr: "3 + -4" expected: -1 id: "3 + -4--1"📌 Setup phase
duration:
0.00027363933622837067outcome:
passed📌 Call phase
duration:
0.00019357912242412567outcome:
passed📌 Teardown phase
duration:
0.00018515903502702713outcome:
passed -
✅ Test 198
params:expr="True + 1", expected=2📌 Parameters
params: expr: "True + 1" expected: 2 id: "True + 1-2"📌 Setup phase
duration:
0.00027304142713546753outcome:
passed📌 Call phase
duration:
0.00019461847841739655outcome:
passed📌 Teardown phase
duration:
0.00018056295812129974outcome:
passed -
✅ Test 199
params:expr="'string'", expected="string"📌 Parameters
params: expr: "'string'" expected: "string" id: "'string'-string"📌 Setup phase
duration:
0.0002606501802802086outcome:
passed📌 Call phase
duration:
0.0002023782581090927outcome:
passed📌 Teardown phase
duration:
0.00017745234072208405outcome:
passed -
✅ Test 200
params:expr="1e1000 * 1e1000", expected=Infinity📌 Parameters
params: expr: "1e1000 * 1e1000" expected: Infinity id: "1e1000 * 1e1000-inf"📌 Setup phase
duration:
0.0002669040113687515outcome:
passed📌 Call phase
duration:
0.0001880154013633728outcome:
passed📌 Teardown phase
duration:
0.0001855362206697464outcome:
passed -
✅ Test 201
params:expr="'a' + 'b'", expected="ab"📌 Parameters
params: expr: "'a' + 'b'" expected: "ab" id: "'a' + 'b'-ab"📌 Setup phase
duration:
0.00030419696122407913outcome:
passed📌 Call phase
duration:
0.00019974540919065475outcome:
passed📌 Teardown phase
duration:
0.00019262544810771942outcome:
passed
↳ Function: test_arithmetic_eval_raises_with_message
-
✅ Test 202
params:expr="2 ** 3", expected_message="Unsupported BinOp Pow"📌 Parameters
params: expr: "2 ** 3" expected_message: "Unsupported BinOp Pow" id: "2 ** 3-Unsupported BinOp Pow"📌 Setup phase
duration:
0.00029427744448184967outcome:
passed📌 Call phase
duration:
0.00045494455844163895outcome:
passed📌 Teardown phase
duration:
0.00018509943038225174outcome:
passed -
✅ Test 203
params:expr="3 << 1", expected_message="Unsupported BinOp LShift"📌 Parameters
params: expr: "3 << 1" expected_message: "Unsupported BinOp LShift" id: "3 << 1-Unsupported BinOp LShift"📌 Setup phase
duration:
0.00027391593903303146outcome:
passed📌 Call phase
duration:
0.00039758067578077316outcome:
passed📌 Teardown phase
duration:
0.00018644332885742188outcome:
passed -
✅ Test 204
params:expr="1 < 2", expected_message="Unsupported node type Compare"📌 Parameters
params: expr: "1 < 2" expected_message: "Unsupported node type Compare" id: "1 < 2-Unsupported node type Compare"📌 Setup phase
duration:
0.0002546999603509903outcome:
passed📌 Call phase
duration:
0.0004278114065527916outcome:
passed📌 Teardown phase
duration:
0.00018517859280109406outcome:
passed -
✅ Test 205
params:expr="abs(3)", expected_message="Unsupported node type Call"📌 Parameters
params: expr: "abs(3)" expected_message: "Unsupported node type Call" id: "abs(3)-Unsupported node type Call"📌 Setup phase
duration:
0.0002696700394153595outcome:
passed📌 Call phase
duration:
0.00038123689591884613outcome:
passed📌 Teardown phase
duration:
0.00019400566816329956outcome:
passed -
✅ Test 206
params:expr="a + 2", expected_message="Unsupported node type Name"📌 Parameters
params: expr: "a + 2" expected_message: "Unsupported node type Name" id: "a + 2-Unsupported node type Name"📌 Setup phase
duration:
0.00029622670263051987outcome:
passed📌 Call phase
duration:
0.0004009092226624489outcome:
passed📌 Teardown phase
duration:
0.0001933649182319641outcome:
passed -
✅ Test 207
params:expr="string", expected_message="Unsupported node type Name"📌 Parameters
params: expr: "string" expected_message: "Unsupported node type Name" id: "string-Unsupported node type Name"📌 Setup phase
duration:
0.00027129147201776505outcome:
passed📌 Call phase
duration:
0.00022644829005002975outcome:
passed📌 Teardown phase
duration:
0.0001919679343700409outcome:
passed -
✅ Test 208
params:expr="[1, 2] + [3]", expected_message="Unsupported node type List"📌 Parameters
params: expr: "[1, 2] + [3]" expected_message: "Unsupported node type List" id: "[1, 2] + [3]-Unsupported node type List"📌 Setup phase
duration:
0.0002646055072546005outcome:
passed📌 Call phase
duration:
0.0005967067554593086outcome:
passed📌 Teardown phase
duration:
0.00020565558224916458outcome:
passed -
✅ Test 209
params:expr="{1: 2}", expected_message="Unsupported node type Dict"📌 Parameters
params: expr: "{1: 2}" expected_message: "Unsupported node type Dict" id: "{1: 2}-Unsupported node type Dict"📌 Setup phase
duration:
0.0002773404121398926outcome:
passed📌 Call phase
duration:
0.0003940919414162636outcome:
passed📌 Teardown phase
duration:
0.0001843450590968132outcome:
passed
↳ Function: test_arithmetic_eval_runtime_errors
-
✅ Test 210
params:expr="1 / 0", exception="<class 'ZeroDivisionError'>"📌 Parameters
params: expr: "1 / 0" exception: "<class 'ZeroDivisionError'>" id: "1 / 0-ZeroDivisionError"📌 Setup phase
duration:
0.0002865530550479889outcome:
passed📌 Call phase
duration:
0.00021854974329471588outcome:
passed📌 Teardown phase
duration:
0.00017940625548362732outcome:
passed -
✅ Test 211
params:expr="10 % 0", exception="<class 'ZeroDivisionError'>"📌 Parameters
params: expr: "10 % 0" exception: "<class 'ZeroDivisionError'>" id: "10 % 0-ZeroDivisionError"📌 Setup phase
duration:
0.00026124995201826096outcome:
passed📌 Call phase
duration:
0.0002084365114569664outcome:
passed📌 Teardown phase
duration:
0.00020090676844120026outcome:
passed
↳ Function: test_forgiving_eval
-
✅ Test 212
params:expr="1 + 2", expected=3📌 Parameters
params: expr: "1 + 2" expected: 3 id: "1 + 2-3"📌 Setup phase
duration:
0.00026413053274154663outcome:
passed📌 Call phase
duration:
0.0002049347385764122outcome:
passed📌 Teardown phase
duration:
0.00017539504915475845outcome:
passed -
✅ Test 213
params:expr="bad + 2", expected="bad + 2"📌 Parameters
params: expr: "bad + 2" expected: "bad + 2" id: "bad + 2-bad + 2"📌 Setup phase
duration:
0.0002605309709906578outcome:
passed📌 Call phase
duration:
0.00020782556384801865outcome:
passed📌 Teardown phase
duration:
0.0001779431477189064outcome:
passed -
✅ Test 214
params:expr="1 / 0", expected="1 / 0"📌 Parameters
params: expr: "1 / 0" expected: "1 / 0" id: "1 / 0-1 / 0"📌 Setup phase
duration:
0.0002740621566772461outcome:
passed📌 Call phase
duration:
0.00019888859242200851outcome:
passed📌 Teardown phase
duration:
0.00017656851559877396outcome:
passed -
✅ Test 215
params:expr="2 ** 10", expected="2 ** 10"📌 Parameters
params: expr: "2 ** 10" expected: "2 ** 10" id: "2 ** 10-2 ** 10"📌 Setup phase
duration:
0.00025577470660209656outcome:
passed📌 Call phase
duration:
0.00019797775894403458outcome:
passed📌 Teardown phase
duration:
0.000181589275598526outcome:
passed
↳ Function: test_defaulting_eval
-
✅ Test 216
params:expr="3 * 4", default=0, expected=12📌 Parameters
params: expr: "3 * 4" default: 0 expected: 12 id: "3 * 4-0-12"📌 Setup phase
duration:
0.00031125638633966446outcome:
passed📌 Call phase
duration:
0.00021144654601812363outcome:
passed📌 Teardown phase
duration:
0.00019667576998472214outcome:
passed -
✅ Test 217
params:expr="invalid + 1", default=99, expected=99📌 Parameters
params: expr: "invalid + 1" default: 99 expected: 99 id: "invalid + 1-99-99"📌 Setup phase
duration:
0.00031953025609254837outcome:
passed📌 Call phase
duration:
0.00020374543964862823outcome:
passed📌 Teardown phase
duration:
0.0001962948590517044outcome:
passed -
✅ Test 218
params:expr="1 / 0", default=-1, expected=-1📌 Parameters
params: expr: "1 / 0" default: -1 expected: -1 id: "1 / 0--1--1"📌 Setup phase
duration:
0.000331035815179348outcome:
passed📌 Call phase
duration:
0.0001972094178199768outcome:
passed📌 Teardown phase
duration:
0.00020135007798671722outcome:
passed -
✅ Test 219
params:expr="2 ** 10", default=42, expected=42📌 Parameters
params: expr: "2 ** 10" default: 42 expected: 42 id: "2 ** 10-42-42"📌 Setup phase
duration:
0.00030743982642889023outcome:
passed📌 Call phase
duration:
0.0001955972984433174outcome:
passed📌 Teardown phase
duration:
0.000202828086912632outcome:
passed
-
-
📄 test_utils_exceptions.py
↳ Function: test_chained_exception_various
-
✅ Test 220
params:func="<function cause_key_error at 0x7feb0aa50a60>", expected_output="High-level task failed\ncaused by KeyError: 'missing'"📌 Parameters
params: func: "<function cause_key_error at 0x7feb0aa50a60>" expected_output: "High-level task failed\ncaused by KeyError: 'missing'" id: "cause_key_error-High-level task failed\\ncaused by KeyError: 'missing'"📌 Setup phase
duration:
0.0002917833626270294outcome:
passed📌 Call phase
duration:
0.00019184034317731857outcome:
passed📌 Teardown phase
duration:
0.00018107425421476364outcome:
passed -
✅ Test 221
params:func="<function cause_index_error at 0x7feb0a40ac10>", expected_output="High-level task failed\ncaused by IndexError: list index out of range"📌 Parameters
params: func: "<function cause_index_error at 0x7feb0a40ac10>" expected_output: "High-level task failed\ncaused by IndexError: list index out of range" id: "cause_index_error-High-level task failed\\ncaused by IndexError: list index out of range"📌 Setup phase
duration:
0.0002714525908231735outcome:
passed📌 Call phase
duration:
0.00020081084221601486outcome:
passed📌 Teardown phase
duration:
0.00017896946519613266outcome:
passed -
✅ Test 222
params:func="<function cause_zero_division at 0x7feb0a40aca0>", expected_output="High-level task failed\ncaused by ZeroDivisionError: division by zero"📌 Parameters
params: func: "<function cause_zero_division at 0x7feb0a40aca0>" expected_output: "High-level task failed\ncaused by ZeroDivisionError: division by zero" id: "cause_zero_division-High-level task failed\\ncaused by ZeroDivisionError: division by zero"📌 Setup phase
duration:
0.00026755034923553467outcome:
passed📌 Call phase
duration:
0.00017936527729034424outcome:
passed📌 Teardown phase
duration:
0.0001819208264350891outcome:
passed -
✅ Test 223
params:func="<function cause_value_error at 0x7feb0a40ad30>", expected_output="High-level task failed\ncaused by ValueError: invalid literal for int() with base 10: 'not_a_number'"📌 Parameters
params: func: "<function cause_value_error at 0x7feb0a40ad30>" expected_output: "High-level task failed\ncaused by ValueError: invalid literal for int() with base 10: 'not_a_number'" id: "cause_value_error-High-level task failed\\ncaused by ValueError: invalid literal for int() with base 10: 'not_a_number'"📌 Setup phase
duration:
0.00026558060199022293outcome:
passed📌 Call phase
duration:
0.00018336530774831772outcome:
passed📌 Teardown phase
duration:
0.00020583905279636383outcome:
passed -
✅ Test 224
params:func="<function cause_type_error at 0x7feb0a40adc0>", expected_output="High-level task failed\ncaused by TypeError: can only concatenate str (not \"int\") to str"📌 Parameters
params: func: "<function cause_type_error at 0x7feb0a40adc0>" expected_output: "High-level task failed\ncaused by TypeError: can only concatenate str (not \"int\") to str" id: "cause_type_error-High-level task failed\\ncaused by TypeError: can only concatenate str (not \"int\") to str"📌 Setup phase
duration:
0.0002652732655405998outcome:
passed📌 Call phase
duration:
0.00018240511417388916outcome:
passed📌 Teardown phase
duration:
0.00017846561968326569outcome:
passed
↳ Function: test_printed_exception
-
✅ Test 225
params:func="<function cause_key_error at 0x7feb0aa50a60>", expected_output="KeyError: 'missing'"📌 Parameters
params: func: "<function cause_key_error at 0x7feb0aa50a60>" expected_output: "KeyError: 'missing'" id: "cause_key_error-KeyError: 'missing'"📌 Setup phase
duration:
0.0007697539404034615outcome:
passed📌 Call phase
duration:
0.0010050423443317413outcome:
passed📌 Teardown phase
duration:
0.0004943301901221275outcome:
passed -
✅ Test 226
params:func="<function cause_index_error at 0x7feb0a40ac10>", expected_output="IndexError: list index out of range"📌 Parameters
params: func: "<function cause_index_error at 0x7feb0a40ac10>" expected_output: "IndexError: list index out of range" id: "cause_index_error-IndexError: list index out of range"📌 Setup phase
duration:
0.0006279358640313148outcome:
passed📌 Call phase
duration:
0.0008212374523282051outcome:
passed📌 Teardown phase
duration:
0.0005252780392765999outcome:
passed -
✅ Test 227
params:func="<function cause_zero_division at 0x7feb0a40aca0>", expected_output="ZeroDivisionError: division by zero"📌 Parameters
params: func: "<function cause_zero_division at 0x7feb0a40aca0>" expected_output: "ZeroDivisionError: division by zero" id: "cause_zero_division-ZeroDivisionError: division by zero"📌 Setup phase
duration:
0.0005743596702814102outcome:
passed📌 Call phase
duration:
0.0007774438709020615outcome:
passed📌 Teardown phase
duration:
0.00046464987099170685outcome:
passed -
✅ Test 228
params:func="<function cause_value_error at 0x7feb0a40ad30>", expected_output="ValueError: invalid literal for int() with base 10: 'not_a_number'"📌 Parameters
params: func: "<function cause_value_error at 0x7feb0a40ad30>" expected_output: "ValueError: invalid literal for int() with base 10: 'not_a_number'" id: "cause_value_error-ValueError: invalid literal for int() with base 10: 'not_a_number'"📌 Setup phase
duration:
0.0006184186786413193outcome:
passed📌 Call phase
duration:
0.0008559180423617363outcome:
passed📌 Teardown phase
duration:
0.0004581911489367485outcome:
passed -
✅ Test 229
params:func="<function cause_type_error at 0x7feb0a40adc0>", expected_output="TypeError: can only concatenate str (not \"int\") to str"📌 Parameters
params: func: "<function cause_type_error at 0x7feb0a40adc0>" expected_output: "TypeError: can only concatenate str (not \"int\") to str" id: "cause_type_error-TypeError: can only concatenate str (not \"int\") to str"📌 Setup phase
duration:
0.0006029661744832993outcome:
passed📌 Call phase
duration:
0.000798461027443409outcome:
passed📌 Teardown phase
duration:
0.00047109462320804596outcome:
passed
-
-
📄 test_utils_get_adj.py
↳ Function: test_get_adj_success
-
✅ Test 230
📌 Setup phase
duration:
0.00017236825078725815outcome:
passed📌 Call phase
duration:
0.0008259480819106102outcome:
passed📌 Teardown phase
duration:
0.0001577446237206459outcome:
passed
↳ Function: test_get_adj_not_found
-
✅ Test 231
📌 Setup phase
duration:
0.0005764169618487358outcome:
passed📌 Call phase
duration:
0.000984998419880867outcome:
passed📌 Teardown phase
duration:
0.0004398319870233536outcome:
passed
↳ Function: test_ensure_adjs_mixed
-
✅ Test 232
📌 Setup phase
duration:
0.0001711016520857811outcome:
passed📌 Call phase
duration:
0.0008076559752225876outcome:
passed📌 Teardown phase
duration:
0.00014907494187355042outcome:
passed
-
-
📄 test_utils_ipy.py
↳ Function: test_devices_repr_fallback_and_ignore
-
✅ Test 234
📌 Setup phase
duration:
0.0004907501861453056outcome:
passed📌 Call phase
duration:
0.0010883482173085213outcome:
passedstdout:
test_desc: desc ok test_doc: doc ok test_id: D4 test_name: name ok📌 Teardown phase
duration:
0.0003043757751584053outcome:
passed
-
-
📄 test_utils_jsonext.py
↳ Function: test_json_validate_save_load
-
✅ Test 235
params:input_obj="[1 2 3]", expected=[1, 2, 3]📌 Parameters
params: input_obj: "[1 2 3]" expected: [1, 2, 3] id: "input_obj0-expected0"📌 Setup phase
duration:
0.0007651355117559433outcome:
passed📌 Call phase
duration:
0.0004907818511128426outcome:
passed📌 Teardown phase
duration:
0.00025903433561325073outcome:
passed -
✅ Test 236
params:input_obj="42", expected=42📌 Parameters
params: input_obj: "42" expected: 42 id: "input_obj1-42"📌 Setup phase
duration:
0.0007057245820760727outcome:
passed📌 Call phase
duration:
0.0004361635074019432outcome:
passed📌 Teardown phase
duration:
0.00026330258697271347outcome:
passed -
✅ Test 237
params:input_obj="(1-1j)", expected={"real": 1.0, "imag": -1.0}📌 Parameters
params: input_obj: "(1-1j)" expected: {"real": 1.0, "imag": -1.0} id: "(1-1j)-expected2"📌 Setup phase
duration:
0.0006354087963700294outcome:
passed📌 Call phase
duration:
0.00045669544488191605outcome:
passed📌 Teardown phase
duration:
0.00023453030735254288outcome:
passed -
✅ Test 238
params:input_obj="/tmp/file.txt", expected="/tmp/file.txt"📌 Parameters
params: input_obj: "/tmp/file.txt" expected: "/tmp/file.txt" id: "input_obj3-/tmp/file.txt"📌 Setup phase
duration:
0.0006722910329699516outcome:
passed📌 Call phase
duration:
0.0004058787599205971outcome:
passed📌 Teardown phase
duration:
0.00022372975945472717outcome:
passed -
✅ Test 239
params:input_obj="{1, 2, 3}", expected=[1, 2, 3]📌 Parameters
params: input_obj: "{1, 2, 3}" expected: [1, 2, 3] id: "input_obj4-expected4"📌 Setup phase
duration:
0.0006602490320801735outcome:
passed📌 Call phase
duration:
0.0004401998594403267outcome:
passed📌 Teardown phase
duration:
0.00022577401250600815outcome:
passed -
✅ Test 240
params:input_obj="{'a': array([10, 20])}", expected={"a": [10, 20]}📌 Parameters
params: input_obj: "{'a': array([10, 20])}" expected: {"a": [10, 20]} id: "input_obj5-expected5"📌 Setup phase
duration:
0.000688435509800911outcome:
passed📌 Call phase
duration:
0.00045117922127246857outcome:
passed📌 Teardown phase
duration:
0.0002353135496377945outcome:
passed -
✅ Test 241
params:input_obj="{'c': (2+3j)}", expected={"c": {"real": 2.0, "imag": 3.0}}📌 Parameters
params: input_obj: "{'c': (2+3j)}" expected: {"c": {"real": 2.0, "imag": 3.0}} id: "input_obj6-expected6"📌 Setup phase
duration:
0.0007104640826582909outcome:
passed📌 Call phase
duration:
0.0004640268161892891outcome:
passed📌 Teardown phase
duration:
0.0002208976075053215outcome:
passed -
✅ Test 242
params:input_obj="{'nested': {'arr': array([[10, 20],\n [30, 40]]), 'complex_num': (-1+5j), 'files': [PosixPath('/file1'), PosixPath('/file2')], 'set_values': {200, 100}, 'inner': {'num': 7}}}", expected={"nested": {"arr": [[10, 20], [30, 40]], "complex_num": {"real": -1.0, "imag": 5.0}, "files": ["/file1", "/file2"], "set_values": [100, 200], "inner": {"num": 7}}}📌 Parameters
params: input_obj: "{'nested': {'arr': array([[10, 20],\n [30, 40]]), 'complex_num': (-1+5j), 'files': [PosixPath('/file1'), PosixPath('/file2')], 'set_values': {200, 100}, 'inner': {'num': 7}}}" expected: {"nested": {"arr": [[10, 20], [30, 40]], "complex_num": {"real": -1.0, "imag": 5.0}, "files": ["/file1", "/file2"], "set_values": [100, 200], "inner": {"num": 7}}} id: "input_obj7-expected7"📌 Setup phase
duration:
0.0006501683965325356outcome:
passed📌 Call phase
duration:
0.0007592644542455673outcome:
passed📌 Teardown phase
duration:
0.00024243909865617752outcome:
passed
-
-
📄 test_utils_lazypv.py
↳ Function: test_getattr
-
✅ Test 243
📌 Setup phase
duration:
0.00017841067165136337outcome:
passed📌 Call phase
duration:
151.3954442385584outcome:
passed📌 Teardown phase
duration:
0.00031461194157600403outcome:
passed
-
-
📄 test_utils_logcfg.py
↳ Function: test_custom_log_outputs
-
✅ Test 244
params:levelname="LONG", logfunc="<function <lambda> at 0x7feb09da0160>", message="This is a LONG message"📌 Parameters
params: levelname: "LONG" logfunc: "<function <lambda> at 0x7feb09da0160>" message: "This is a LONG message" id: "LONG-<lambda>-This is a LONG message"📌 Setup phase
duration:
0.001408495008945465outcome:
passed📌 Call phase
duration:
0.0012766234576702118outcome:
passedstdout:
Captured stderr: '[L 250828 10:15:54 test_utils_logcfg:41] This is a LONG message\n'📌 Teardown phase
duration:
0.0004579313099384308outcome:
passed -
✅ Test 245
params:levelname="ENLARGE", logfunc="<function <lambda> at 0x7feb09da01f0>", message="Please ENLARGE this!"📌 Parameters
params: levelname: "ENLARGE" logfunc: "<function <lambda> at 0x7feb09da01f0>" message: "Please ENLARGE this!" id: "ENLARGE-<lambda>-Please ENLARGE this!"📌 Setup phase
duration:
0.0006312122568488121outcome:
passed📌 Call phase
duration:
0.0009828191250562668outcome:
passedstdout:
Captured stderr: '[E 250828 10:15:54 test_utils_logcfg:41] Please ENLARGE this!\n'📌 Teardown phase
duration:
0.00031099840998649597outcome:
passed
-
-
📄 test_utils_logign.py
↳ Function: test_ignore_log_msg_behavior
-
✅ Test 247
params:levelname="WARNING", msg_to_ignore="This should be ignored", msg_to_keep="This should appear"📌 Parameters
params: levelname: "WARNING" msg_to_ignore: "This should be ignored" msg_to_keep: "This should appear" id: "WARNING-This should be ignored-This should appear"📌 Setup phase
duration:
0.0006395550444722176outcome:
passed📌 Call phase
duration:
0.0008427537977695465outcome:
passed📌 Teardown phase
duration:
0.00030824728310108185outcome:
passed -
✅ Test 248
params:levelname="ENLARGE", msg_to_ignore="ENLARGE this", msg_to_keep="Keep this ENLARGE"📌 Parameters
params: levelname: "ENLARGE" msg_to_ignore: "ENLARGE this" msg_to_keep: "Keep this ENLARGE" id: "ENLARGE-ENLARGE this-Keep this ENLARGE"📌 Setup phase
duration:
0.00046116020530462265outcome:
passed📌 Call phase
duration:
0.0005076434463262558outcome:
passed📌 Teardown phase
duration:
0.0002826368436217308outcome:
passed
↳ Function: test_ignore_only_by_level
-
✅ Test 249
📌 Setup phase
duration:
0.0002803727984428406outcome:
passed📌 Call phase
duration:
0.00046435464173555374outcome:
passed📌 Teardown phase
duration:
0.0002130027860403061outcome:
passed
↳ Function: test_ignore_only_by_msg
-
✅ Test 250
📌 Setup phase
duration:
0.00028053298592567444outcome:
passed📌 Call phase
duration:
0.0004361579194664955outcome:
passed📌 Teardown phase
duration:
0.00020905770361423492outcome:
passed
↳ Function: test_filter_removed_after_context
-
✅ Test 251
📌 Setup phase
duration:
0.0002823648974299431outcome:
passed📌 Call phase
duration:
0.00042544305324554443outcome:
passed📌 Teardown phase
duration:
0.0002305973321199417outcome:
passed
-
-
📄 test_utils_marker.py
↳ Function: test_format_value_with_units
-
✅ Test 252
📌 Setup phase
duration:
0.00016749463975429535outcome:
passed📌 Call phase
duration:
0.0002111317589879036outcome:
passed📌 Teardown phase
duration:
0.00014679506421089172outcome:
passed
↳ Function: test_format_value_without_units
-
✅ Test 253
📌 Setup phase
duration:
0.00016143452376127243outcome:
passed📌 Call phase
duration:
0.00020717456936836243outcome:
passed📌 Teardown phase
duration:
0.00016266386955976486outcome:
passed
↳ Function: test_marker_name_default
-
✅ Test 254
📌 Setup phase
duration:
0.0002158014103770256outcome:
passed📌 Call phase
duration:
0.00031486619263887405outcome:
passed📌 Teardown phase
duration:
0.00018708407878875732outcome:
passed
↳ Function: test_marker_name_custom
-
✅ Test 255
📌 Setup phase
duration:
0.00018797721713781357outcome:
passed📌 Call phase
duration:
0.00025486480444669724outcome:
passed📌 Teardown phase
duration:
0.0001846523955464363outcome:
passed
↳ Function: test_marker_repr_format
-
✅ Test 256
📌 Setup phase
duration:
0.0001903977245092392outcome:
passed📌 Call phase
duration:
0.0003222646191716194outcome:
passed📌 Teardown phase
duration:
0.00017275940626859665outcome:
passed
↳ Function: test_marker_update_changes_value
-
✅ Test 257
📌 Setup phase
duration:
0.0001958310604095459outcome:
passed📌 Call phase
duration:
0.00024024024605751038outcome:
passed📌 Teardown phase
duration:
0.00017174333333969116outcome:
passed
↳ Function: test_marker_update_with_explicit_value
-
✅ Test 258
📌 Setup phase
duration:
0.0001722872257232666outcome:
passed📌 Call phase
duration:
0.00024454109370708466outcome:
passed📌 Teardown phase
duration:
0.00015797186642885208outcome:
passed
↳ Function: test_marker_goto_sets_value_and_returns_result
-
✅ Test 259
📌 Setup phase
duration:
0.00018707197159528732outcome:
passed📌 Call phase
duration:
0.0007072584703564644outcome:
passedstdout:
Going to "Device_TGG at 3.3 V"📌 Teardown phase
duration:
0.00019473955035209656outcome:
passed
↳ Function: test_marker_call_is_alias_of_goto
-
✅ Test 260
📌 Setup phase
duration:
0.00017725583165884018outcome:
passed📌 Call phase
duration:
0.000613105483353138outcome:
passedstdout:
Going to "Device_TAC at 3.3 V"📌 Teardown phase
duration:
0.00016724132001399994outcome:
passed
↳ Function: test_markers_register_and_access
-
✅ Test 261
📌 Setup phase
duration:
0.000164092518389225outcome:
passed📌 Call phase
duration:
0.0003393329679965973outcome:
passed📌 Teardown phase
duration:
0.00015369709581136703outcome:
passed
↳ Function: test_markers_repr_contains_all
-
✅ Test 262
📌 Setup phase
duration:
0.00016462337225675583outcome:
passed📌 Call phase
duration:
0.0003760438412427902outcome:
passed📌 Teardown phase
duration:
0.00015283375978469849outcome:
passed
↳ Function: test_marker_registry_dict_is_printable_dict
-
✅ Test 263
📌 Setup phase
duration:
0.00015860982239246368outcome:
passed📌 Call phase
duration:
0.00026455149054527283outcome:
passed📌 Teardown phase
duration:
0.00014755409210920334outcome:
passed
↳ Function: test_markers_getitem_invalid_key_raises
-
✅ Test 264
📌 Setup phase
duration:
0.0001590736210346222outcome:
passed📌 Call phase
duration:
0.0002753427252173424outcome:
passed📌 Teardown phase
duration:
0.00014892034232616425outcome:
passed
-
-
📄 test_utils_metaclasses.py
↳ Function: test_combine_classes_combines_methods
-
✅ Test 265
📌 Setup phase
duration:
0.00019108504056930542outcome:
passed📌 Call phase
duration:
0.00022565852850675583outcome:
passed📌 Teardown phase
duration:
0.00016507133841514587outcome:
passed
↳ Function: test_registryabc_combines_registrymeta_and_abcmeta
-
✅ Test 266
📌 Setup phase
duration:
0.00015187356621026993outcome:
passed📌 Call phase
duration:
0.002683660015463829outcome:
passed📌 Teardown phase
duration:
0.00017129722982645035outcome:
passed
-
-
📄 test_utils_namespace.py
↳ Function: test_namespace_pretty_repr_mixed_and_nested
-
✅ Test 267
📌 Setup phase
duration:
0.00018950551748275757outcome:
passed📌 Call phase
duration:
0.00030793994665145874outcome:
passed📌 Teardown phase
duration:
0.0001787366345524788outcome:
passed
-
-
📄 test_utils_npy.py
↳ Function: test_nice_arange
-
✅ Test 268
params:start=0, stop=5, step=1, expected=[0, 1, 2, 3, 4, 5]📌 Parameters
params: start: 0 stop: 5 step: 1 expected: [0, 1, 2, 3, 4, 5] id: "0-5-1-expected0"📌 Setup phase
duration:
0.00043272972106933594outcome:
passed📌 Call phase
duration:
0.005520062521100044outcome:
passed📌 Teardown phase
duration:
0.0002744821831583977outcome:
passed -
✅ Test 269
params:start=5, stop=0, step=-1, expected=[0, 1, 2, 3, 4, 5]📌 Parameters
params: start: 5 stop: 0 step: -1 expected: [0, 1, 2, 3, 4, 5] id: "5-0--1-expected1"📌 Setup phase
duration:
0.00040444266051054outcome:
passed📌 Call phase
duration:
0.0004925262182950974outcome:
passed📌 Teardown phase
duration:
0.0002642069011926651outcome:
passed -
✅ Test 270
params:start=1, stop=2, step=0.3, expected=[1, 1.3333333333333333, 1.6666666666666667, 2]📌 Parameters
params: start: 1 stop: 2 step: 0.3 expected: [1, 1.3333333333333333, 1.6666666666666667, 2] id: "1-2-0.3-expected2"📌 Setup phase
duration:
0.0003951415419578552outcome:
passed📌 Call phase
duration:
0.0006285598501563072outcome:
passed📌 Teardown phase
duration:
0.00025017280131578445outcome:
passed -
✅ Test 271
params:start=-2, stop=2, step=1.5, expected=[-2, -0.6666666666666666, 0.6666666666666666, 2]📌 Parameters
params: start: -2 stop: 2 step: 1.5 expected: [-2, -0.6666666666666666, 0.6666666666666666, 2] id: "-2-2-1.5-expected3"📌 Setup phase
duration:
0.00041262339800596237outcome:
passed📌 Call phase
duration:
0.0004546837881207466outcome:
passed📌 Teardown phase
duration:
0.00024906639009714127outcome:
passed -
✅ Test 272
params:start=2.5, stop=0.5, step=-0.4, expected=[0.5, 0.9, 1.3, 1.7, 2.1, 2.5]📌 Parameters
params: start: 2.5 stop: 0.5 step: -0.4 expected: [0.5, 0.9, 1.3, 1.7, 2.1, 2.5] id: "2.5-0.5--0.4-expected4"📌 Setup phase
duration:
0.0003885924816131592outcome:
passed📌 Call phase
duration:
0.0004294170066714287outcome:
passed📌 Teardown phase
duration:
0.0002329787239432335outcome:
passed
↳ Function: test_nice_linspace
-
✅ Test 273
params:start=0, stop=10, num=4, expected="[ 0. 2.5 5. 7.5 10. ]"📌 Parameters
params: start: 0 stop: 10 num: 4 expected: "[ 0. 2.5 5. 7.5 10. ]" id: "0-10-4-expected0"📌 Setup phase
duration:
0.0003890218213200569outcome:
passed📌 Call phase
duration:
0.0004116576164960861outcome:
passed📌 Teardown phase
duration:
0.00026735011488199234outcome:
passed -
✅ Test 274
params:start=5, stop=15, num=2, expected="[ 5. 10. 15.]"📌 Parameters
params: start: 5 stop: 15 num: 2 expected: "[ 5. 10. 15.]" id: "5-15-2-expected1"📌 Setup phase
duration:
0.0004012472927570343outcome:
passed📌 Call phase
duration:
0.0004338519647717476outcome:
passed📌 Teardown phase
duration:
0.0002560904249548912outcome:
passed -
✅ Test 275
params:start=-5, stop=5, num=4, expected="[-5. -2.5 0. 2.5 5. ]"📌 Parameters
params: start: -5 stop: 5 num: 4 expected: "[-5. -2.5 0. 2.5 5. ]" id: "-5-5-4-expected2"📌 Setup phase
duration:
0.0004037488251924515outcome:
passed📌 Call phase
duration:
0.00040995609015226364outcome:
passed📌 Teardown phase
duration:
0.00023584067821502686outcome:
passed -
✅ Test 276
params:start=0, stop=1, num=3, expected="[0. 0.33333333 0.66666667 1. ]"📌 Parameters
params: start: 0 stop: 1 num: 3 expected: "[0. 0.33333333 0.66666667 1. ]" id: "0-1-3-expected3"📌 Setup phase
duration:
0.0003910670056939125outcome:
passed📌 Call phase
duration:
0.0004059039056301117outcome:
passed📌 Teardown phase
duration:
0.0002358071506023407outcome:
passed -
✅ Test 277
params:start=2, stop=2, num=3, expected="[2. 2. 2. 2.]"📌 Parameters
params: start: 2 stop: 2 num: 3 expected: "[2. 2. 2. 2.]" id: "2-2-3-expected4"📌 Setup phase
duration:
0.0003807181492447853outcome:
passed📌 Call phase
duration:
0.000410386361181736outcome:
passed📌 Teardown phase
duration:
0.0002474868670105934outcome:
passed -
✅ Test 278
params:start=3, stop=0, num=3, expected="[3. 2. 1. 0.]"📌 Parameters
params: start: 3 stop: 0 num: 3 expected: "[3. 2. 1. 0.]" id: "3-0-3-expected5"📌 Setup phase
duration:
0.0003945911303162575outcome:
passed📌 Call phase
duration:
0.00041286181658506393outcome:
passed📌 Teardown phase
duration:
0.00023608841001987457outcome:
passed -
✅ Test 279
params:start=0, stop=1, num=0, expected="[0.]"📌 Parameters
params: start: 0 stop: 1 num: 0 expected: "[0.]" id: "0-1-0-expected6"📌 Setup phase
duration:
0.00039051566272974014outcome:
passed📌 Call phase
duration:
0.00040220655500888824outcome:
passed📌 Teardown phase
duration:
0.00024004466831684113outcome:
passed -
✅ Test 280
params:start=-2, stop=2, num=3, expected="[-2. -0.66666667 0.66666667 2. ]"📌 Parameters
params: start: -2 stop: 2 num: 3 expected: "[-2. -0.66666667 0.66666667 2. ]" id: "-2-2-3-expected7"📌 Setup phase
duration:
0.0004071425646543503outcome:
passed📌 Call phase
duration:
0.000400039367377758outcome:
passed📌 Teardown phase
duration:
0.0002515781670808792outcome:
passed
↳ Function: test_nice_steps_centered
-
✅ Test 281
params:start=-2, stop=2, step=2, endpoint=true, expected="[-2. 0. 2.]"📌 Parameters
params: start: -2 stop: 2 step: 2 endpoint: true expected: "[-2. 0. 2.]" id: "-2-2-2-True-expected0"📌 Setup phase
duration:
0.0004654582589864731outcome:
passed📌 Call phase
duration:
0.0004252437502145767outcome:
passed📌 Teardown phase
duration:
0.0002570170909166336outcome:
passed -
✅ Test 282
params:start=0, stop=5, step=2, endpoint=true, expected="[0. 2. 4.]"📌 Parameters
params: start: 0 stop: 5 step: 2 endpoint: true expected: "[0. 2. 4.]" id: "0-5-2-True-expected1"📌 Setup phase
duration:
0.0004547722637653351outcome:
passed📌 Call phase
duration:
0.00039336085319519043outcome:
passed📌 Teardown phase
duration:
0.0002635344862937927outcome:
passed -
✅ Test 283
params:start=0, stop=5, step=2, endpoint=false, expected="[0. 2.]"📌 Parameters
params: start: 0 stop: 5 step: 2 endpoint: false expected: "[0. 2.]" id: "0-5-2-False-expected2"📌 Setup phase
duration:
0.00045314617455005646outcome:
passed📌 Call phase
duration:
0.00040230248123407364outcome:
passed📌 Teardown phase
duration:
0.00026334356516599655outcome:
passed -
✅ Test 284
params:start=-1, stop=2, step=1.5, endpoint=true, expected="[-1.5 0. 1.5]"📌 Parameters
params: start: -1 stop: 2 step: 1.5 endpoint: true expected: "[-1.5 0. 1.5]" id: "-1-2-1.5-True-expected3"📌 Setup phase
duration:
0.00042972713708877563outcome:
passed📌 Call phase
duration:
0.00039712339639663696outcome:
passed📌 Teardown phase
duration:
0.0002613235265016556outcome:
passed -
✅ Test 285
params:start=-1, stop=2, step=-1.5, endpoint=true, expected="[ 1.5 0. -1.5]"📌 Parameters
params: start: -1 stop: 2 step: -1.5 endpoint: true expected: "[ 1.5 0. -1.5]" id: "-1-2--1.5-True-expected4"📌 Setup phase
duration:
0.00044645369052886963outcome:
passed📌 Call phase
duration:
0.00038844719529151917outcome:
passed📌 Teardown phase
duration:
0.00025347061455249786outcome:
passed -
✅ Test 286
params:start=5, stop=0, step=-2, endpoint=true, expected="[0. 2. 4.]"📌 Parameters
params: start: 5 stop: 0 step: -2 endpoint: true expected: "[0. 2. 4.]" id: "5-0--2-True-expected5"📌 Setup phase
duration:
0.0004448890686035156outcome:
passed📌 Call phase
duration:
0.00039639417082071304outcome:
passed📌 Teardown phase
duration:
0.00026718340814113617outcome:
passed
↳ Function: test_nice_steps_left_aligned
-
✅ Test 287
params:start=0, stop=5, step=2, endpoint=true, expected="[0. 2. 4.]"📌 Parameters
params: start: 0 stop: 5 step: 2 endpoint: true expected: "[0. 2. 4.]" id: "0-5-2-True-expected0"📌 Setup phase
duration:
0.00043951068073511124outcome:
passed📌 Call phase
duration:
0.0004055909812450409outcome:
passed📌 Teardown phase
duration:
0.00025737471878528595outcome:
passed -
✅ Test 288
params:start=0, stop=5, step=2, endpoint=false, expected="[0. 2.]"📌 Parameters
params: start: 0 stop: 5 step: 2 endpoint: false expected: "[0. 2.]" id: "0-5-2-False-expected1"📌 Setup phase
duration:
0.0004473831504583359outcome:
passed📌 Call phase
duration:
0.0003942437469959259outcome:
passed📌 Teardown phase
duration:
0.0002496633678674698outcome:
passed -
✅ Test 289
params:start=-1, stop=2, step=1.5, endpoint=true, expected="[-1. 0.5 2. ]"📌 Parameters
params: start: -1 stop: 2 step: 1.5 endpoint: true expected: "[-1. 0.5 2. ]" id: "-1-2-1.5-True-expected2"📌 Setup phase
duration:
0.00043468642979860306outcome:
passed📌 Call phase
duration:
0.0003848690539598465outcome:
passed📌 Teardown phase
duration:
0.0002621859312057495outcome:
passed -
✅ Test 290
params:start=-1, stop=2, step=1.5, endpoint=false, expected="[-1. 0.5]"📌 Parameters
params: start: -1 stop: 2 step: 1.5 endpoint: false expected: "[-1. 0.5]" id: "-1-2-1.5-False-expected3"📌 Setup phase
duration:
0.0004540104418992996outcome:
passed📌 Call phase
duration:
0.00038496311753988266outcome:
passed📌 Teardown phase
duration:
0.00026197172701358795outcome:
passed -
✅ Test 291
params:start=-2, stop=1, step=1.2, endpoint=true, expected="[-2. -0.8 0.4]"📌 Parameters
params: start: -2 stop: 1 step: 1.2 endpoint: true expected: "[-2. -0.8 0.4]" id: "-2-1-1.2-True-expected4"📌 Setup phase
duration:
0.0004398934543132782outcome:
passed📌 Call phase
duration:
0.0003900211304426193outcome:
passed📌 Teardown phase
duration:
0.00025874003767967224outcome:
passed -
✅ Test 292
params:start=5, stop=0, step=-2, endpoint=true, expected="[0. 2. 4.]"📌 Parameters
params: start: 5 stop: 0 step: -2 endpoint: true expected: "[0. 2. 4.]" id: "5-0--2-True-expected5"📌 Setup phase
duration:
0.0004480397328734398outcome:
passed📌 Call phase
duration:
0.0003903741016983986outcome:
passed📌 Teardown phase
duration:
0.00026257336139678955outcome:
passed -
✅ Test 293
params:start=5, stop=0, step=-2, endpoint=false, expected="[0. 2.]"📌 Parameters
params: start: 5 stop: 0 step: -2 endpoint: false expected: "[0. 2.]" id: "5-0--2-False-expected6"📌 Setup phase
duration:
0.00041790958493947983outcome:
passed📌 Call phase
duration:
0.0003816811367869377outcome:
passed📌 Teardown phase
duration:
0.0002738572657108307outcome:
passed
↳ Function: test_nice_steps_right_aligned
-
✅ Test 294
params:start=0, stop=5, step=2, endpoint=true, expected="[1. 3. 5.]"📌 Parameters
params: start: 0 stop: 5 step: 2 endpoint: true expected: "[1. 3. 5.]" id: "0-5-2-True-expected0"📌 Setup phase
duration:
0.00042881816625595093outcome:
passed📌 Call phase
duration:
0.0005025360733270645outcome:
passed📌 Teardown phase
duration:
0.00027466844767332077outcome:
passed -
✅ Test 295
params:start=0, stop=5, step=2, endpoint=false, expected="[3. 5.]"📌 Parameters
params: start: 0 stop: 5 step: 2 endpoint: false expected: "[3. 5.]" id: "0-5-2-False-expected1"📌 Setup phase
duration:
0.0004348214715719223outcome:
passed📌 Call phase
duration:
0.0004015043377876282outcome:
passed📌 Teardown phase
duration:
0.0002688895910978317outcome:
passed -
✅ Test 296
params:start=-1, stop=2, step=1.5, endpoint=true, expected="[-1. 0.5 2. ]"📌 Parameters
params: start: -1 stop: 2 step: 1.5 endpoint: true expected: "[-1. 0.5 2. ]" id: "-1-2-1.5-True-expected2"📌 Setup phase
duration:
0.00045419950038194656outcome:
passed📌 Call phase
duration:
0.0004007713869214058outcome:
passed📌 Teardown phase
duration:
0.00026607047766447067outcome:
passed -
✅ Test 297
params:start=-1, stop=2, step=1.5, endpoint=false, expected="[0.5 2. ]"📌 Parameters
params: start: -1 stop: 2 step: 1.5 endpoint: false expected: "[0.5 2. ]" id: "-1-2-1.5-False-expected3"📌 Setup phase
duration:
0.0004438776522874832outcome:
passed📌 Call phase
duration:
0.00039994344115257263outcome:
passed📌 Teardown phase
duration:
0.0002754228189587593outcome:
passed -
✅ Test 298
params:start=5, stop=0, step=-2, endpoint=true, expected="[1. 3. 5.]"📌 Parameters
params: start: 5 stop: 0 step: -2 endpoint: true expected: "[1. 3. 5.]" id: "5-0--2-True-expected4"📌 Setup phase
duration:
0.00045099202543497086outcome:
passed📌 Call phase
duration:
0.0003963615745306015outcome:
passed📌 Teardown phase
duration:
0.0002738693729043007outcome:
passed -
✅ Test 299
params:start=5, stop=0, step=-2, endpoint=false, expected="[3. 5.]"📌 Parameters
params: start: 5 stop: 0 step: -2 endpoint: false expected: "[3. 5.]" id: "5-0--2-False-expected5"📌 Setup phase
duration:
0.0004164092242717743outcome:
passed📌 Call phase
duration:
0.000391143374145031outcome:
passed📌 Teardown phase
duration:
0.00027095526456832886outcome:
passed -
✅ Test 300
params:start=-3, stop=3, step=2, endpoint=true, expected="[-3. -1. 1. 3.]"📌 Parameters
params: start: -3 stop: 3 step: 2 endpoint: true expected: "[-3. -1. 1. 3.]" id: "-3-3-2-True-expected6"📌 Setup phase
duration:
0.0004271306097507477outcome:
passed📌 Call phase
duration:
0.00040322262793779373outcome:
passed📌 Teardown phase
duration:
0.0002727750688791275outcome:
passed
↳ Function: test_within_scalar
-
✅ Test 301
params:val=5, vmin=0, vmax=10, expected=true📌 Parameters
params: val: 5 vmin: 0 vmax: 10 expected: true id: "5-0-10-True"📌 Setup phase
duration:
0.0003852546215057373outcome:
passed📌 Call phase
duration:
0.00019492395222187042outcome:
passed📌 Teardown phase
duration:
0.0002155117690563202outcome:
passed -
✅ Test 302
params:val=5, vmin=6, vmax=10, expected=false📌 Parameters
params: val: 5 vmin: 6 vmax: 10 expected: false id: "5-6-10-False"📌 Setup phase
duration:
0.00039101671427488327outcome:
passed📌 Call phase
duration:
0.00017819739878177643outcome:
passed📌 Teardown phase
duration:
0.00022894609719514847outcome:
passed -
✅ Test 303
params:val=5, vmin=null, vmax=10, expected=true📌 Parameters
params: val: 5 vmin: null vmax: 10 expected: true id: "5-None-10-True"📌 Setup phase
duration:
0.00036317575722932816outcome:
passed📌 Call phase
duration:
0.00019834190607070923outcome:
passed📌 Teardown phase
duration:
0.00021536368876695633outcome:
passed -
✅ Test 304
params:val=5, vmin=0, vmax=null, expected=true📌 Parameters
params: val: 5 vmin: 0 vmax: null expected: true id: "5-0-None-True"📌 Setup phase
duration:
0.00037882663309574127outcome:
passed📌 Call phase
duration:
0.00018384866416454315outcome:
passed📌 Teardown phase
duration:
0.00022497307509183884outcome:
passed -
✅ Test 305
params:val=5, vmin=null, vmax=null, expected=true📌 Parameters
params: val: 5 vmin: null vmax: null expected: true id: "5-None-None-True"📌 Setup phase
duration:
0.0003651585429906845outcome:
passed📌 Call phase
duration:
0.00020106323063373566outcome:
passed📌 Teardown phase
duration:
0.0002211015671491623outcome:
passed
↳ Function: test_within_fraction
-
✅ Test 306
params:data=[1, 2, 3, 4, 5], vmin=2, vmax=5, expected=0.6📌 Parameters
params: data: [1, 2, 3, 4, 5] vmin: 2 vmax: 5 expected: 0.6 id: "data0-2-5-0.6"📌 Setup phase
duration:
0.00037157535552978516outcome:
passed📌 Call phase
duration:
0.0004018917679786682outcome:
passed📌 Teardown phase
duration:
0.0002502715215086937outcome:
passed -
✅ Test 307
params:data=[10, 20, 30], vmin=5, vmax=25, expected=0.6666666666666666📌 Parameters
params: data: [10, 20, 30] vmin: 5 vmax: 25 expected: 0.6666666666666666 id: "data1-5-25-0.6666666666666666"📌 Setup phase
duration:
0.0003825780004262924outcome:
passed📌 Call phase
duration:
0.00037051551043987274outcome:
passed📌 Teardown phase
duration:
0.00022663362324237823outcome:
passed -
✅ Test 308
params:data=[1, 2, 3], vmin=null, vmax=2, expected=0.3333333333333333📌 Parameters
params: data: [1, 2, 3] vmin: null vmax: 2 expected: 0.3333333333333333 id: "data2-None-2-0.3333333333333333"📌 Setup phase
duration:
0.0003706077113747597outcome:
passed📌 Call phase
duration:
0.00034191180020570755outcome:
passed📌 Teardown phase
duration:
0.00023324694484472275outcome:
passed -
✅ Test 309
params:data=[], vmin=0, vmax=1, expected=0📌 Parameters
params: data: [] vmin: 0 vmax: 1 expected: 0 id: "data3-0-1-0"📌 Setup phase
duration:
0.00038699526339769363outcome:
passed📌 Call phase
duration:
0.0003242362290620804outcome:
passed📌 Teardown phase
duration:
0.00023883208632469177outcome:
passed
↳ Function: test_fraction_to_percentage
-
✅ Test 310
params:fraction=0.456, ndigits=1, expected=45.6📌 Parameters
params: fraction: 0.456 ndigits: 1 expected: 45.6 id: "0.456-1-45.6"📌 Setup phase
duration:
0.0003415467217564583outcome:
passed📌 Call phase
duration:
0.0003310795873403549outcome:
passed📌 Teardown phase
duration:
0.00031228549778461456outcome:
passed -
✅ Test 311
params:fraction=0.12345, ndigits=2, expected=12.35📌 Parameters
params: fraction: 0.12345 ndigits: 2 expected: 12.35 id: "0.12345-2-12.35"📌 Setup phase
duration:
0.0004530288279056549outcome:
passed📌 Call phase
duration:
0.00021735671907663345outcome:
passed📌 Teardown phase
duration:
0.0002106139436364174outcome:
passed -
✅ Test 312
params:fraction=0.9999, ndigits=0, expected=100.0📌 Parameters
params: fraction: 0.9999 ndigits: 0 expected: 100.0 id: "0.9999-0-100.0"📌 Setup phase
duration:
0.0003208965063095093outcome:
passed📌 Call phase
duration:
0.00018568150699138641outcome:
passed📌 Teardown phase
duration:
0.00025910697877407074outcome:
passed
↳ Function: test_get_dtype
-
✅ Test 313
params:val="[1 2 3]", expected="<class 'numpy.ndarray'>"📌 Parameters
params: val: "[1 2 3]" expected: "<class 'numpy.ndarray'>" id: "val0-ndarray"📌 Setup phase
duration:
0.0002809092402458191outcome:
passed📌 Call phase
duration:
0.00020250771194696426outcome:
passed📌 Teardown phase
duration:
0.00020481273531913757outcome:
passed -
✅ Test 314
params:val=[1, 2, 3], expected="<class 'list'>"📌 Parameters
params: val: [1, 2, 3] expected: "<class 'list'>" id: "val1-list"📌 Setup phase
duration:
0.0002939123660326004outcome:
passed📌 Call phase
duration:
0.0001805424690246582outcome:
passed📌 Teardown phase
duration:
0.00019543897360563278outcome:
passed -
✅ Test 315
params:val=3.14, expected="<class 'float'>"📌 Parameters
params: val: 3.14 expected: "<class 'float'>" id: "3.14-float"📌 Setup phase
duration:
0.0002798018977046013outcome:
passed📌 Call phase
duration:
0.000186040997505188outcome:
passed📌 Teardown phase
duration:
0.00018349383026361465outcome:
passed
↳ Function: test_get_shape
-
✅ Test 316
params:val="[[1 2]\n [3 4]]", expected=[2, 2]📌 Parameters
params: val: "[[1 2]\n [3 4]]" expected: [2, 2] id: "val0-expected0"📌 Setup phase
duration:
0.000282912515103817outcome:
passed📌 Call phase
duration:
0.00018250476568937302outcome:
passed📌 Teardown phase
duration:
0.00021442491561174393outcome:
passed -
✅ Test 317
params:val=[1, 2, 3], expected=[]📌 Parameters
params: val: [1, 2, 3] expected: [] id: "val1-expected1"📌 Setup phase
duration:
0.00028837844729423523outcome:
passed📌 Call phase
duration:
0.00019081495702266693outcome:
passed📌 Teardown phase
duration:
0.00018540676683187485outcome:
passed -
✅ Test 318
params:val=42, expected=[]📌 Parameters
params: val: 42 expected: [] id: "42-expected2"📌 Setup phase
duration:
0.00027629081159830093outcome:
passed📌 Call phase
duration:
0.0001818845048546791outcome:
passed📌 Teardown phase
duration:
0.00017570890486240387outcome:
passed
↳ Function: test_is_array
-
✅ Test 319
params:val="[1 2 3]", expected=true📌 Parameters
params: val: "[1 2 3]" expected: true id: "val0-True"📌 Setup phase
duration:
0.00037368107587099075outcome:
passed📌 Call phase
duration:
0.00019305851310491562outcome:
passed📌 Teardown phase
duration:
0.0002066856250166893outcome:
passed -
✅ Test 320
params:val=[1, 2, 3], expected=false📌 Parameters
params: val: [1, 2, 3] expected: false id: "val1-False"📌 Setup phase
duration:
0.00028215721249580383outcome:
passed📌 Call phase
duration:
0.00018015503883361816outcome:
passed📌 Teardown phase
duration:
0.0001922324299812317outcome:
passed -
✅ Test 321
params:val=42, expected=false📌 Parameters
params: val: 42 expected: false id: "42-False"📌 Setup phase
duration:
0.00028515327721834183outcome:
passed📌 Call phase
duration:
0.0001749526709318161outcome:
passed📌 Teardown phase
duration:
0.0001806747168302536outcome:
passed
-
-
📄 test_utils_path.py
↳ Function: test_can_create_all_files_user_says_yes
-
✅ Test 322
📌 Setup phase
duration:
0.00018262304365634918outcome:
passed📌 Call phase
duration:
0.0019050752744078636outcome:
passedstdout:
Deleting "/tmp/tmpav9t572j/a.txt". Deleting "/tmp/tmpav9t572j/c.txt".📌 Teardown phase
duration:
0.00023382343351840973outcome:
passed
↳ Function: test_can_create_all_files_user_says_no
-
✅ Test 323
📌 Setup phase
duration:
0.00016407296061515808outcome:
passed📌 Call phase
duration:
0.0004925811663269997outcome:
passed📌 Teardown phase
duration:
0.00015195179730653763outcome:
passed
↳ Function: test_make_missing_dir_creates_folder
-
✅ Test 324
📌 Setup phase
duration:
0.00015495996922254562outcome:
passed📌 Call phase
duration:
0.0012688403949141502outcome:
passedstdout:
Directory "/tmp/tmpnh7mwzhl/nested/dir" does not exist, creating it...📌 Teardown phase
duration:
0.000247882679104805outcome:
passed
↳ Function: test_glob_files_returns_matching_files_only
-
✅ Test 325
📌 Setup phase
duration:
0.00015728827565908432outcome:
passed📌 Call phase
duration:
0.0009944234043359756outcome:
passed📌 Teardown phase
duration:
0.00016167666763067245outcome:
passed
↳ Function: test_filter_files_excludes_directories
-
✅ Test 326
📌 Setup phase
duration:
0.00016267132014036179outcome:
passed📌 Call phase
duration:
0.00068642757833004outcome:
passed📌 Teardown phase
duration:
0.00015434622764587402outcome:
passed
-
-
📄 test_utils_picklio.py
↳ Function: test_pickle_and_unpickle
-
✅ Test 327
params:test_obj={"a": 1, "b": [2, 3], "c": {"world": "ok"}}📌 Parameters
params: test_obj: {"a": 1, "b": [2, 3], "c": {"world": "ok"}} id: "test_obj0"📌 Setup phase
duration:
0.0008100178092718124outcome:
passed📌 Call phase
duration:
0.00037818215787410736outcome:
passed📌 Teardown phase
duration:
0.00022704247385263443outcome:
passed -
✅ Test 328
params:test_obj=[1, 2, 3, 4, 5]📌 Parameters
params: test_obj: [1, 2, 3, 4, 5] id: "test_obj1"📌 Setup phase
duration:
0.0006310539320111275outcome:
passed📌 Call phase
duration:
0.00034017860889434814outcome:
passed📌 Teardown phase
duration:
0.00022399425506591797outcome:
passed -
✅ Test 329
params:test_obj="simple string"📌 Parameters
params: test_obj: "simple string" id: "simple string"📌 Setup phase
duration:
0.0005602790042757988outcome:
passed📌 Call phase
duration:
0.0003324197605252266outcome:
passed📌 Teardown phase
duration:
0.00021005142480134964outcome:
passed -
✅ Test 330
params:test_obj=42📌 Parameters
params: test_obj: 42 id: "42"📌 Setup phase
duration:
0.0005591530352830887outcome:
passed📌 Call phase
duration:
0.0004046391695737839outcome:
passed📌 Teardown phase
duration:
0.00020876899361610413outcome:
passed -
✅ Test 331
params:test_obj=3.14159📌 Parameters
params: test_obj: 3.14159 id: "3.14159"📌 Setup phase
duration:
0.0005732206627726555outcome:
passed📌 Call phase
duration:
0.0003624316304922104outcome:
passed📌 Teardown phase
duration:
0.00021655112504959106outcome:
passed -
✅ Test 332
params:test_obj=[true, false, null]📌 Parameters
params: test_obj: [true, false, null] id: "test_obj5"📌 Setup phase
duration:
0.0006073880940675735outcome:
passed📌 Call phase
duration:
0.00039693061262369156outcome:
passed📌 Teardown phase
duration:
0.00021502003073692322outcome:
passed -
✅ Test 333
params:test_obj={"complex": [{"list": [1, 2]}, {"dict": {"x": 10}}]}📌 Parameters
params: test_obj: {"complex": [{"list": [1, 2]}, {"dict": {"x": 10}}]} id: "test_obj6"📌 Setup phase
duration:
0.0006176820024847984outcome:
passed📌 Call phase
duration:
0.0003823889419436455outcome:
passed📌 Teardown phase
duration:
0.0002175513654947281outcome:
passed
-
-
📄 test_utils_printing.py
↳ Function: test_maxlen_valid
-
✅ Test 334
params:seq=["a", "abc", ""], expected=3📌 Parameters
params: seq: ["a", "abc", ""] expected: 3 id: "seq0-3"📌 Setup phase
duration:
0.0003082379698753357outcome:
passed📌 Call phase
duration:
0.00019573047757148743outcome:
passed📌 Teardown phase
duration:
0.00021085888147354126outcome:
passed -
✅ Test 335
params:seq=[], expected=0📌 Parameters
params: seq: [] expected: 0 id: "seq1-0"📌 Setup phase
duration:
0.00027927104383707047outcome:
passed📌 Call phase
duration:
0.0001839352771639824outcome:
passed📌 Teardown phase
duration:
0.00017895270138978958outcome:
passed -
✅ Test 336
params:seq=[[1, 2], [3], [4, 5, 6]], expected=3📌 Parameters
params: seq: [[1, 2], [3], [4, 5, 6]] expected: 3 id: "seq2-3"📌 Setup phase
duration:
0.0002924129366874695outcome:
passed📌 Call phase
duration:
0.0001832926645874977outcome:
passed📌 Teardown phase
duration:
0.00019487924873828888outcome:
passed -
✅ Test 337
params:seq=[{"a": 2, "b": 3}, {}, {"c": 4}], expected=2📌 Parameters
params: seq: [{"a": 2, "b": 3}, {}, {"c": 4}] expected: 2 id: "seq3-2"📌 Setup phase
duration:
0.000261940062046051outcome:
passed📌 Call phase
duration:
0.0001835934817790985outcome:
passed📌 Teardown phase
duration:
0.00019978079944849014outcome:
passed
↳ Function: test_strlen
-
✅ Test 338
params:value=42, expected=2📌 Parameters
params: value: 42 expected: 2 id: "42-2"📌 Setup phase
duration:
0.0002653142437338829outcome:
passed📌 Call phase
duration:
0.00017881859093904495outcome:
passed📌 Teardown phase
duration:
0.0001776237040758133outcome:
passed -
✅ Test 339
params:value="hello", expected=5📌 Parameters
params: value: "hello" expected: 5 id: "hello-5"📌 Setup phase
duration:
0.00028577540069818497outcome:
passed📌 Call phase
duration:
0.00018875394016504288outcome:
passed📌 Teardown phase
duration:
0.00031988881528377533outcome:
passed -
✅ Test 340
params:value=false, expected=5📌 Parameters
params: value: false expected: 5 id: "False-5"📌 Setup phase
duration:
0.00026805978268384933outcome:
passed📌 Call phase
duration:
0.00017097406089305878outcome:
passed📌 Teardown phase
duration:
0.00019041914492845535outcome:
passed -
✅ Test 341
params:value=null, expected=4📌 Parameters
params: value: null expected: 4 id: "None-4"📌 Setup phase
duration:
0.0002686604857444763outcome:
passed📌 Call phase
duration:
0.00017811637371778488outcome:
passed📌 Teardown phase
duration:
0.00018122047185897827outcome:
passed -
✅ Test 342
params:value=[1, 2, 3], expected=9📌 Parameters
params: value: [1, 2, 3] expected: 9 id: "value4-9"📌 Setup phase
duration:
0.0002778535708785057outcome:
passed📌 Call phase
duration:
0.00019312836229801178outcome:
passed📌 Teardown phase
duration:
0.00019446108490228653outcome:
passed -
✅ Test 343
params:value={"a": 1}, expected=8📌 Parameters
params: value: {"a": 1} expected: 8 id: "value5-8"📌 Setup phase
duration:
0.0002575879916548729outcome:
passed📌 Call phase
duration:
0.00017529074102640152outcome:
passed📌 Teardown phase
duration:
0.00018850620836019516outcome:
passed -
✅ Test 344
params:value=[1, 2], expected=6📌 Parameters
params: value: [1, 2] expected: 6 id: "value6-6"📌 Setup phase
duration:
0.0002662753686308861outcome:
passed📌 Call phase
duration:
0.00018111150711774826outcome:
passed📌 Teardown phase
duration:
0.0001745261251926422outcome:
passed -
✅ Test 345
params:value="", expected=0📌 Parameters
params: value: "" expected: 0 id: "-0"📌 Setup phase
duration:
0.0002849586308002472outcome:
passed📌 Call phase
duration:
0.00017805956304073334outcome:
passed📌 Teardown phase
duration:
0.00017933454364538193outcome:
passed -
✅ Test 346
params:value="this is a phrase", expected=16📌 Parameters
params: value: "this is a phrase" expected: 16 id: "this is a phrase-16"📌 Setup phase
duration:
0.00025924667716026306outcome:
passed📌 Call phase
duration:
0.00017331819981336594outcome:
passed📌 Teardown phase
duration:
0.00019727367907762527outcome:
passed
↳ Function: test_maxstrlen
-
✅ Test 347
params:seq=[1, true, 3.1415], expected=6📌 Parameters
params: seq: [1, true, 3.1415] expected: 6 id: "seq0-6"📌 Setup phase
duration:
0.00026233773678541183outcome:
passed📌 Call phase
duration:
0.0001996755599975586outcome:
passed📌 Teardown phase
duration:
0.00017934292554855347outcome:
passed -
✅ Test 348
params:seq=["aa", "bbb", "c"], expected=3📌 Parameters
params: seq: ["aa", "bbb", "c"] expected: 3 id: "seq1-3"📌 Setup phase
duration:
0.0002829059958457947outcome:
passed📌 Call phase
duration:
0.00021064653992652893outcome:
passed📌 Teardown phase
duration:
0.00018684379756450653outcome:
passed -
✅ Test 349
params:seq=[[1, 2], [], [1, 2, 3]], expected=9📌 Parameters
params: seq: [[1, 2], [], [1, 2, 3]] expected: 9 id: "seq2-9"📌 Setup phase
duration:
0.00027456972748041153outcome:
passed📌 Call phase
duration:
0.00021025072783231735outcome:
passed📌 Teardown phase
duration:
0.0001975707709789276outcome:
passed -
✅ Test 350
params:seq=[{"a": 1}, {}, {"a": 1, "b": 2}], expected=16📌 Parameters
params: seq: [{"a": 1}, {}, {"a": 1, "b": 2}] expected: 16 id: "seq3-16"📌 Setup phase
duration:
0.00025700032711029053outcome:
passed📌 Call phase
duration:
0.00019359495490789413outcome:
passed📌 Teardown phase
duration:
0.00019301194697618484outcome:
passed -
✅ Test 351
params:seq=[null, false, 12345], expected=5📌 Parameters
params: seq: [null, false, 12345] expected: 5 id: "seq4-5"📌 Setup phase
duration:
0.0002826498821377754outcome:
passed📌 Call phase
duration:
0.00018592458218336105outcome:
passed📌 Teardown phase
duration:
0.00018248148262500763outcome:
passed
↳ Function: test_transpose_matrix
-
✅ Test 352
params:data=[[1, 2], [3, 4]], expected=[[1, 3], [2, 4]]📌 Parameters
params: data: [[1, 2], [3, 4]] expected: [[1, 3], [2, 4]] id: "data0-expected0"📌 Setup phase
duration:
0.000281468965113163outcome:
passed📌 Call phase
duration:
0.00018134992569684982outcome:
passed📌 Teardown phase
duration:
0.00019231997430324554outcome:
passed -
✅ Test 353
params:data=[["a", "b"], ["c", "d"]], expected=[["a", "c"], ["b", "d"]]📌 Parameters
params: data: [["a", "b"], ["c", "d"]] expected: [["a", "c"], ["b", "d"]] id: "data1-expected1"📌 Setup phase
duration:
0.0002629058435559273outcome:
passed📌 Call phase
duration:
0.00017240457236766815outcome:
passed📌 Teardown phase
duration:
0.00018875300884246826outcome:
passed -
✅ Test 354
params:data=[[{"x": 1}, {"y": 2}], [{"x": 3}, {"y": 4}]], expected=[[{"x": 1}, {"x": 3}], [{"y": 2}, {"y": 4}]]📌 Parameters
params: data: [[{"x": 1}, {"y": 2}], [{"x": 3}, {"y": 4}]] expected: [[{"x": 1}, {"x": 3}], [{"y": 2}, {"y": 4}]] id: "data2-expected2"📌 Setup phase
duration:
0.00026540178805589676outcome:
passed📌 Call phase
duration:
0.00017795059829950333outcome:
passed📌 Teardown phase
duration:
0.00017922837287187576outcome:
passed
↳ Function: test_prepend
-
✅ Test 355
params:initial=[1, 2, 3], prepend=1, expected=[1, 2, 3]📌 Parameters
params: initial: [1, 2, 3] prepend: 1 expected: [1, 2, 3] id: "initial0-1-expected0"📌 Setup phase
duration:
0.0003384789451956749outcome:
passed📌 Call phase
duration:
0.00018114037811756134outcome:
passed📌 Teardown phase
duration:
0.0002076961100101471outcome:
passed -
✅ Test 356
params:initial=["a", "b", "c"], prepend="a", expected=["a", "b", "c"]📌 Parameters
params: initial: ["a", "b", "c"] prepend: "a" expected: ["a", "b", "c"] id: "initial1-a-expected1"📌 Setup phase
duration:
0.00030688755214214325outcome:
passed📌 Call phase
duration:
0.00017094332724809647outcome:
passed📌 Teardown phase
duration:
0.0002080155536532402outcome:
passed -
✅ Test 357
params:initial=[{"a": 1}, {"b": 2}], prepend={"a": 1}, expected=[{"a": 1}, {"b": 2}]📌 Parameters
params: initial: [{"a": 1}, {"b": 2}] prepend: {"a": 1} expected: [{"a": 1}, {"b": 2}] id: "initial2-prepend2-expected2"📌 Setup phase
duration:
0.0003110375255346298outcome:
passed📌 Call phase
duration:
0.00017871707677841187outcome:
passed📌 Teardown phase
duration:
0.0002088630571961403outcome:
passed -
✅ Test 358
params:initial=[[1], [2], [3]], prepend=[1], expected=[[1], [2], [3]]📌 Parameters
params: initial: [[1], [2], [3]] prepend: [1] expected: [[1], [2], [3]] id: "initial3-prepend3-expected3"📌 Setup phase
duration:
0.00032189302146434784outcome:
passed📌 Call phase
duration:
0.00017442461103200912outcome:
passed📌 Teardown phase
duration:
0.00020736642181873322outcome:
passed
↳ Function: test_fmt_table_line
-
✅ Test 359
params:entries=["a", "bbb"], widths=[3, 5], expected=" a bbb"📌 Parameters
params: entries: ["a", "bbb"] widths: [3, 5] expected: " a bbb" id: "entries0-widths0- a bbb"📌 Setup phase
duration:
0.00031786970794200897outcome:
passed📌 Call phase
duration:
0.00021624844521284103outcome:
passed📌 Teardown phase
duration:
0.00020835455507040024outcome:
passed -
✅ Test 360
params:entries=[1, 2], widths=[2, 2], expected=" 1 2"📌 Parameters
params: entries: [1, 2] widths: [2, 2] expected: " 1 2" id: "entries1-widths1- 1 2"📌 Setup phase
duration:
0.0003279782831668854outcome:
passed📌 Call phase
duration:
0.0001855427399277687outcome:
passed📌 Teardown phase
duration:
0.0002012643963098526outcome:
passed -
✅ Test 361
params:entries=["long", "val"], widths=[6, 4], expected=" long val"📌 Parameters
params: entries: ["long", "val"] widths: [6, 4] expected: " long val" id: "entries2-widths2- long val"📌 Setup phase
duration:
0.00032909493893384933outcome:
passed📌 Call phase
duration:
0.00018479209393262863outcome:
passed📌 Teardown phase
duration:
0.00020287279039621353outcome:
passed -
✅ Test 362
params:entries=[true, false], widths=[5, 6], expected=" True False"📌 Parameters
params: entries: [true, false] widths: [5, 6] expected: " True False" id: "entries3-widths3- True False"📌 Setup phase
duration:
0.00033091194927692413outcome:
passed📌 Call phase
duration:
0.0001874621957540512outcome:
passed📌 Teardown phase
duration:
0.00020068231970071793outcome:
passed -
✅ Test 363
params:entries=[123, 4567], widths=[5, 5], expected=" 123 4567"📌 Parameters
params: entries: [123, 4567] widths: [5, 5] expected: " 123 4567" id: "entries4-widths4- 123 4567"📌 Setup phase
duration:
0.00033292267471551895outcome:
passed📌 Call phase
duration:
0.00018179602921009064outcome:
passed📌 Teardown phase
duration:
0.0002016862854361534outcome:
passed -
✅ Test 364
params:entries=["text with space", "end"], widths=[16, 5], expected=" text with space end"📌 Parameters
params: entries: ["text with space", "end"] widths: [16, 5] expected: " text with space end" id: "entries5-widths5- text with space end"📌 Setup phase
duration:
0.00032591819763183594outcome:
passed📌 Call phase
duration:
0.00029618944972753525outcome:
passed📌 Teardown phase
duration:
0.00020897295325994492outcome:
passed -
✅ Test 365
params:entries=[{"a": 1}, {"b": 2}], widths=[10, 10], expected=" {'a': 1} {'b': 2}"📌 Parameters
params: entries: [{"a": 1}, {"b": 2}] widths: [10, 10] expected: " {'a': 1} {'b': 2}" id: "entries6-widths6- {'a': 1} {'b': 2}"📌 Setup phase
duration:
0.0003226427361369133outcome:
passed📌 Call phase
duration:
0.00018796510994434357outcome:
passed📌 Teardown phase
duration:
0.00019729789346456528outcome:
passed -
✅ Test 366
params:entries=[[1, 2], [3, 4]], widths=[10, 10], expected=" [1, 2] [3, 4]"📌 Parameters
params: entries: [[1, 2], [3, 4]] widths: [10, 10] expected: " [1, 2] [3, 4]" id: "entries7-widths7- [1, 2] [3, 4]"📌 Setup phase
duration:
0.0003166086971759796outcome:
passed📌 Call phase
duration:
0.00019481033086776733outcome:
passed📌 Teardown phase
duration:
0.00020612124353647232outcome:
passed
↳ Function: test_fmt_label_sep
-
✅ Test 367
params:widths=[3, 4], line="-", expected="--- ----"📌 Parameters
params: widths: [3, 4] line: "-" expected: "--- ----" id: "widths0------ ----"📌 Setup phase
duration:
0.0003119213506579399outcome:
passed📌 Call phase
duration:
0.00017887819558382034outcome:
passed📌 Teardown phase
duration:
0.0001974916085600853outcome:
passed -
✅ Test 368
params:widths=[2, 3], line="=", expected="== ==="📌 Parameters
params: widths: [2, 3] line: "=" expected: "== ===" id: "widths1-=-== ==="📌 Setup phase
duration:
0.0003263670951128006outcome:
passed📌 Call phase
duration:
0.00018601026386022568outcome:
passed📌 Teardown phase
duration:
0.00019209738820791245outcome:
passed -
✅ Test 369
params:widths=[5, 2], line="*", expected="***** **"📌 Parameters
params: widths: [5, 2] line: "*" expected: "***** **" id: "widths2-*-***** **"📌 Setup phase
duration:
0.0003206860274076462outcome:
passed📌 Call phase
duration:
0.00018698815256357193outcome:
passed📌 Teardown phase
duration:
0.00023760180920362473outcome:
passed
↳ Function: test_printable_dict_with_header
-
✅ Test 370
params:d={"medium": true, "very_long_key": 3.14, "x": 1}, header="HeaderTest", expected_lines=["HeaderTest:", "-----------", "medium: True", "very_long_key: 3.14", "x: 1", ""]📌 Parameters
params: d: {"medium": true, "very_long_key": 3.14, "x": 1} header: "HeaderTest" expected_lines: ["HeaderTest:", "-----------", "medium: True", "very_long_key: 3.14", "x: 1", ""] id: "d0-HeaderTest-expected_lines0"📌 Setup phase
duration:
0.0003601759672164917outcome:
passed📌 Call phase
duration:
0.00028285011649131775outcome:
passed📌 Teardown phase
duration:
0.00022088084369897842outcome:
passed
↳ Function: test_printable_dict_of_dicts
-
✅ Test 371
📌 Setup phase
duration:
0.00017418991774320602outcome:
passed📌 Call phase
duration:
0.0003168918192386627outcome:
passed📌 Teardown phase
duration:
0.00018531084060668945outcome:
passed
↳ Function: test_printable_table
-
✅ Test 372
params:data=[["X1", true, 0.1234, {"meta": "ok"}], ["AnotherSample", false, 98765.4321, {"meta": [1, 2, 3]}], ["Z", null, 0.0, {"meta": {"nested_key": 42}}]], labels=["ID", "✓ Success?", "SuperPrecisionValue", "Result Metadata"], expected="A: ID\nB: ✓ Success?\nC: SuperPrecisionValue\nD: Result Metadata\n\n# A B C D\n- ------------- ----- ---------- ----------------------------\n0 X1 True 0.1234 {'meta': 'ok'}\n1 AnotherSample False 98765.4321 {'meta': [1, 2, 3]}\n2 Z None 0.0 {'meta': {'nested_key': 42}}"📌 Parameters
params: data: [["X1", true, 0.1234, {"meta": "ok"}], ["AnotherSample", false, 98765.4321, {"meta": [1, 2, 3]}], ["Z", null, 0.0, {"meta": {"nested_key": 42}}]] labels: ["ID", "✓ Success?", "SuperPrecisionValue", "Result Metadata"] expected: "A: ID\nB: ✓ Success?\nC: SuperPrecisionValue\nD: Result Metadata\n\n# A B C D\n- ------------- ----- ---------- ----------------------------\n0 X1 True 0.1234 {'meta': 'ok'}\n1 AnotherSample False 98765.4321 {'meta': [1, 2, 3]}\n2 Z None 0.0 {'meta': {'nested_key': 42}}" id: "data0-labels0-A: ID\\nB: \\u2713 Success?\\nC: SuperPrecisionValue\\nD: Result Metadata\\n\\n# A B C D\\n- ------------- ----- ---------- ----------------------------\\n0 X1 True 0.1234 {'meta': 'ok'}\\n1 AnotherSample False 98765.4321 {'meta': [1, 2, 3]}\\n2 Z None 0.0 {'meta': {'nested_key': 42}}"📌 Setup phase
duration:
0.00040270015597343445outcome:
passed📌 Call phase
duration:
0.0009598797187209129outcome:
passedstdout:
"A: ID\nB: ✓ Success?\nC: SuperPrecisionValue\nD: Result Metadata\n\n# A B C D\n- ------------- ----- ---------- ----------------------------\n0 X1 True 0.1234 {'meta': 'ok'}\n1 AnotherSample False 98765.4321 {'meta': [1, 2, 3]}\n2 Z None 0.0 {'meta': {'nested_key': 42}}" "A: ID\nB: ✓ Success?\nC: SuperPrecisionValue\nD: Result Metadata\n\n# A B C D\n- ------------- ----- ---------- ----------------------------\n0 X1 True 0.1234 {'meta': 'ok'}\n1 AnotherSample False 98765.4321 {'meta': [1, 2, 3]}\n2 Z None 0.0 {'meta': {'nested_key': 42}}"📌 Teardown phase
duration:
0.00025779008865356445outcome:
passed
-
-
📄 test_utils_rangebar.py
↳ Function: test_full_progress_bar
-
✅ Test 373
📌 Setup phase
duration:
0.00037714093923568726outcome:
passed📌 Call phase
duration:
0.0004237247630953789outcome:
passed📌 Teardown phase
duration:
0.0002473881468176842outcome:
passed
↳ Function: test_half_progress_bar
-
✅ Test 374
📌 Setup phase
duration:
0.00031964201480150223outcome:
passed📌 Call phase
duration:
0.00034843478351831436outcome:
passed📌 Teardown phase
duration:
0.0002344902604818344outcome:
passed
↳ Function: test_zero_progress_bar
-
✅ Test 375
📌 Setup phase
duration:
0.0003020334988832474outcome:
passed📌 Call phase
duration:
0.0003155414015054703outcome:
passed📌 Teardown phase
duration:
0.0002504996955394745outcome:
passed
↳ Function: test_overflow_bar
-
✅ Test 376
📌 Setup phase
duration:
0.00028259120881557465outcome:
passed📌 Call phase
duration:
0.0003201281651854515outcome:
passed📌 Teardown phase
duration:
0.00023700017482042313outcome:
passed
↳ Function: test_underflow_bar
-
✅ Test 377
📌 Setup phase
duration:
0.00030382443219423294outcome:
passed📌 Call phase
duration:
0.00028922874480485916outcome:
passed📌 Teardown phase
duration:
0.00024807173758745193outcome:
passed
↳ Function: test_repr
-
✅ Test 378
📌 Setup phase
duration:
0.0001561138778924942outcome:
passed📌 Call phase
duration:
0.00020906701683998108outcome:
passed📌 Teardown phase
duration:
0.00015017762780189514outcome:
passed
↳ Function: test_each_value_separately
-
✅ Test 379
params:value=0, expected_bar_part=" "📌 Parameters
params: value: 0 expected_bar_part: " " id: "0- "📌 Setup phase
duration:
0.00041365623474121094outcome:
passed📌 Call phase
duration:
0.000322144478559494outcome:
passed📌 Teardown phase
duration:
0.00026783812791109085outcome:
passed -
✅ Test 380
params:value=10, expected_bar_part="█ "📌 Parameters
params: value: 10 expected_bar_part: "█ " id: "10-\\u2588 "📌 Setup phase
duration:
0.00040978938341140747outcome:
passed📌 Call phase
duration:
0.00035447534173727036outcome:
passed📌 Teardown phase
duration:
0.0002650618553161621outcome:
passed -
✅ Test 381
params:value=25, expected_bar_part="██▌ "📌 Parameters
params: value: 25 expected_bar_part: "██▌ " id: "25-\\u2588\\u2588\\u258c "📌 Setup phase
duration:
0.00037463661283254623outcome:
passed📌 Call phase
duration:
0.0003107599914073944outcome:
passed📌 Teardown phase
duration:
0.0002733049914240837outcome:
passed -
✅ Test 382
params:value=27, expected_bar_part="██▊ "📌 Parameters
params: value: 27 expected_bar_part: "██▊ " id: "27-\\u2588\\u2588\\u258a "📌 Setup phase
duration:
0.0004058629274368286outcome:
passed📌 Call phase
duration:
0.0003096172586083412outcome:
passed📌 Teardown phase
duration:
0.0002819793298840523outcome:
passed -
✅ Test 383
params:value=49, expected_bar_part="████▉ "📌 Parameters
params: value: 49 expected_bar_part: "████▉ " id: "49-\\u2588\\u2588\\u2588\\u2588\\u2589 "📌 Setup phase
duration:
0.00038386788219213486outcome:
passed📌 Call phase
duration:
0.0003000497817993164outcome:
passed📌 Teardown phase
duration:
0.00024235527962446213outcome:
passed -
✅ Test 384
params:value=50, expected_bar_part="█████ "📌 Parameters
params: value: 50 expected_bar_part: "█████ " id: "50-\\u2588\\u2588\\u2588\\u2588\\u2588 "📌 Setup phase
duration:
0.00041327811777591705outcome:
passed📌 Call phase
duration:
0.00032085832208395004outcome:
passed📌 Teardown phase
duration:
0.00024381279945373535outcome:
passed -
✅ Test 385
params:value=51, expected_bar_part="█████▏ "📌 Parameters
params: value: 51 expected_bar_part: "█████▏ " id: "51-\\u2588\\u2588\\u2588\\u2588\\u2588\\u258f "📌 Setup phase
duration:
0.000391373410820961outcome:
passed📌 Call phase
duration:
0.000297030434012413outcome:
passed📌 Teardown phase
duration:
0.0002931226044893265outcome:
passed -
✅ Test 386
params:value=73, expected_bar_part="███████▎ "📌 Parameters
params: value: 73 expected_bar_part: "███████▎ " id: "73-\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u258e "📌 Setup phase
duration:
0.0003734556958079338outcome:
passed📌 Call phase
duration:
0.00031639356166124344outcome:
passed📌 Teardown phase
duration:
0.000250302255153656outcome:
passed -
✅ Test 387
params:value=75, expected_bar_part="███████▌ "📌 Parameters
params: value: 75 expected_bar_part: "███████▌ " id: "75-\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u258c "📌 Setup phase
duration:
0.0003808876499533653outcome:
passed📌 Call phase
duration:
0.0003053685650229454outcome:
passed📌 Teardown phase
duration:
0.0003347983583807945outcome:
passed -
✅ Test 388
params:value=90, expected_bar_part="█████████ "📌 Parameters
params: value: 90 expected_bar_part: "█████████ " id: "90-\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588 "📌 Setup phase
duration:
0.0003916611894965172outcome:
passed📌 Call phase
duration:
0.00029730889946222305outcome:
passed📌 Teardown phase
duration:
0.00025415048003196716outcome:
passed -
✅ Test 389
params:value=100, expected_bar_part="██████████"📌 Parameters
params: value: 100 expected_bar_part: "██████████" id: "100-\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588"📌 Setup phase
duration:
0.00036335084587335587outcome:
passed📌 Call phase
duration:
0.0002810228615999222outcome:
passed📌 Teardown phase
duration:
0.0002653133124113083outcome:
passed
-
-
📄 test_utils_readable.py
↳ Function: test_readable_seconds
-
✅ Test 390
params:seconds=59.4, expected="59 seconds"📌 Parameters
params: seconds: 59.4 expected: "59 seconds" id: "59.4-59 seconds"📌 Setup phase
duration:
0.0003138221800327301outcome:
passed📌 Call phase
duration:
0.00022480078041553497outcome:
passed📌 Teardown phase
duration:
0.00021800212562084198outcome:
passed -
✅ Test 391
params:seconds=59.9, expected="60 seconds"📌 Parameters
params: seconds: 59.9 expected: "60 seconds" id: "59.9-60 seconds"📌 Setup phase
duration:
0.00031657423824071884outcome:
passed📌 Call phase
duration:
0.00020070839673280716outcome:
passed📌 Teardown phase
duration:
0.0001998376101255417outcome:
passed -
✅ Test 392
params:seconds=119.9, expected="120 seconds"📌 Parameters
params: seconds: 119.9 expected: "120 seconds" id: "119.9-120 seconds"📌 Setup phase
duration:
0.0003180950880050659outcome:
passed📌 Call phase
duration:
0.00021444447338581085outcome:
passed📌 Teardown phase
duration:
0.0002055717632174492outcome:
passed -
✅ Test 393
params:seconds=120.1, expected="2 minutes"📌 Parameters
params: seconds: 120.1 expected: "2 minutes" id: "120.1-2 minutes"📌 Setup phase
duration:
0.00030079204589128494outcome:
passed📌 Call phase
duration:
0.0002114204689860344outcome:
passed📌 Teardown phase
duration:
0.00021409336477518082outcome:
passed -
✅ Test 394
params:seconds=3599.9, expected="60 minutes"📌 Parameters
params: seconds: 3599.9 expected: "60 minutes" id: "3599.9-60 minutes"📌 Setup phase
duration:
0.00030194129794836044outcome:
passed📌 Call phase
duration:
0.00020453613251447678outcome:
passed📌 Teardown phase
duration:
0.00021558813750743866outcome:
passed -
✅ Test 395
params:seconds=3600.1, expected="60 minutes"📌 Parameters
params: seconds: 3600.1 expected: "60 minutes" id: "3600.1-60 minutes"📌 Setup phase
duration:
0.0002900008112192154outcome:
passed📌 Call phase
duration:
0.00022143498063087463outcome:
passed📌 Teardown phase
duration:
0.00022386573255062103outcome:
passed -
✅ Test 396
params:seconds=7199.9, expected="120 minutes"📌 Parameters
params: seconds: 7199.9 expected: "120 minutes" id: "7199.9-120 minutes"📌 Setup phase
duration:
0.00029870402067899704outcome:
passed📌 Call phase
duration:
0.00018621422350406647outcome:
passed📌 Teardown phase
duration:
0.00019866228103637695outcome:
passed -
✅ Test 397
params:seconds=7200.1, expected="2 hours"📌 Parameters
params: seconds: 7200.1 expected: "2 hours" id: "7200.1-2 hours"📌 Setup phase
duration:
0.00029171910136938095outcome:
passed📌 Call phase
duration:
0.00020640064030885696outcome:
passed📌 Teardown phase
duration:
0.00018928013741970062outcome:
passed -
✅ Test 398
params:seconds=90.4, expected="90 seconds"📌 Parameters
params: seconds: 90.4 expected: "90 seconds" id: "90.4-90 seconds"📌 Setup phase
duration:
0.0002764444798231125outcome:
passed📌 Call phase
duration:
0.00018789619207382202outcome:
passed📌 Teardown phase
duration:
0.00019883457571268082outcome:
passed -
✅ Test 399
params:seconds=90.6, expected="91 seconds"📌 Parameters
params: seconds: 90.6 expected: "91 seconds" id: "90.6-91 seconds"📌 Setup phase
duration:
0.00026923418045043945outcome:
passed📌 Call phase
duration:
0.0001758243888616562outcome:
passed📌 Teardown phase
duration:
0.00021437089890241623outcome:
passed -
✅ Test 400
params:seconds=121.9, expected="2 minutes"📌 Parameters
params: seconds: 121.9 expected: "2 minutes" id: "121.9-2 minutes"📌 Setup phase
duration:
0.0002694185823202133outcome:
passed📌 Call phase
duration:
0.00021050777286291122outcome:
passed📌 Teardown phase
duration:
0.00018417462706565857outcome:
passed -
✅ Test 401
params:seconds=1296000.0, expected="2 weeks"📌 Parameters
params: seconds: 1296000.0 expected: "2 weeks" id: "1296000.0-2 weeks"📌 Setup phase
duration:
0.00028632115572690964outcome:
passed📌 Call phase
duration:
0.00019096769392490387outcome:
passed📌 Teardown phase
duration:
0.00017675384879112244outcome:
passed -
✅ Test 402
params:seconds=2592000.0, expected="4 weeks"📌 Parameters
params: seconds: 2592000.0 expected: "4 weeks" id: "2592000.0-4 weeks"📌 Setup phase
duration:
0.00026632845401763916outcome:
passed📌 Call phase
duration:
0.0001775696873664856outcome:
passed📌 Teardown phase
duration:
0.00019577611237764359outcome:
passed -
✅ Test 403
params:seconds=2800000.0, expected="5 weeks"📌 Parameters
params: seconds: 2800000.0 expected: "5 weeks" id: "2800000.0-5 weeks"📌 Setup phase
duration:
0.00025820452719926834outcome:
passed📌 Call phase
duration:
0.00017582066357135773outcome:
passed📌 Teardown phase
duration:
0.0001860056072473526outcome:
passed -
✅ Test 404
params:seconds=3888000.0, expected="6 weeks"📌 Parameters
params: seconds: 3888000.0 expected: "6 weeks" id: "3888000.0-6 weeks"📌 Setup phase
duration:
0.00026435405015945435outcome:
passed📌 Call phase
duration:
0.00019328109920024872outcome:
passed📌 Teardown phase
duration:
0.00019618868827819824outcome:
passed -
✅ Test 405
params:seconds=5097600.0, expected="8 weeks"📌 Parameters
params: seconds: 5097600.0 expected: "8 weeks" id: "5097600.0-8 weeks"📌 Setup phase
duration:
0.0003143260255455971outcome:
passed📌 Call phase
duration:
0.00020302832126617432outcome:
passed📌 Teardown phase
duration:
0.000203033909201622outcome:
passed -
✅ Test 406
params:seconds=5184000.0, expected="9 weeks"📌 Parameters
params: seconds: 5184000.0 expected: "9 weeks" id: "5184000.0-9 weeks"📌 Setup phase
duration:
0.0002817045897245407outcome:
passed📌 Call phase
duration:
0.0002089487388730049outcome:
passed📌 Teardown phase
duration:
0.0001916978508234024outcome:
passed -
✅ Test 407
params:seconds=5270400.0, expected="2 months"📌 Parameters
params: seconds: 5270400.0 expected: "2 months" id: "5270400.0-2 months"📌 Setup phase
duration:
0.00029099639505147934outcome:
passed📌 Call phase
duration:
0.0002061808481812477outcome:
passed📌 Teardown phase
duration:
0.00018191244453191757outcome:
passed -
✅ Test 408
params:seconds=23328000.0, expected="9 months"📌 Parameters
params: seconds: 23328000.0 expected: "9 months" id: "23328000.0-9 months"📌 Setup phase
duration:
0.0002943156287074089outcome:
passed📌 Call phase
duration:
0.00020530074834823608outcome:
passed📌 Teardown phase
duration:
0.00018773693591356277outcome:
passed -
✅ Test 409
params:seconds=31104000.0, expected="12 months"📌 Parameters
params: seconds: 31104000.0 expected: "12 months" id: "31104000.0-12 months"📌 Setup phase
duration:
0.00026233773678541183outcome:
passed📌 Call phase
duration:
0.0001992601901292801outcome:
passed📌 Teardown phase
duration:
0.0001871492713689804outcome:
passed -
✅ Test 410
params:seconds=33696000.0, expected="13 months"📌 Parameters
params: seconds: 33696000.0 expected: "13 months" id: "33696000.0-13 months"📌 Setup phase
duration:
0.00029864534735679626outcome:
passed📌 Call phase
duration:
0.00018602143973112106outcome:
passed📌 Teardown phase
duration:
0.00020373519510030746outcome:
passed -
✅ Test 411
params:seconds=59616000.0, expected="23 months"📌 Parameters
params: seconds: 59616000.0 expected: "23 months" id: "59616000.0-23 months"📌 Setup phase
duration:
0.0002858443185687065outcome:
passed📌 Call phase
duration:
0.00018497556447982788outcome:
passed📌 Teardown phase
duration:
0.0002050669863820076outcome:
passed -
✅ Test 412
params:seconds=62208000.0, expected="24 months"📌 Parameters
params: seconds: 62208000.0 expected: "24 months" id: "62208000.0-24 months"📌 Setup phase
duration:
0.00027197226881980896outcome:
passed📌 Call phase
duration:
0.00019845180213451385outcome:
passed📌 Teardown phase
duration:
0.00027712155133485794outcome:
passed -
✅ Test 413
params:seconds=64208000.0, expected="2 years"📌 Parameters
params: seconds: 64208000.0 expected: "2 years" id: "64208000.0-2 years"📌 Setup phase
duration:
0.00029013585299253464outcome:
passed📌 Call phase
duration:
0.00018754694610834122outcome:
passed📌 Teardown phase
duration:
0.00018777325749397278outcome:
passed
-
-
📄 test_utils_registry.py
↳ Function: test_metaclass_creates_weakset
-
✅ Test 414
📌 Setup phase
duration:
0.00016773492097854614outcome:
passed📌 Call phase
duration:
0.0006941072642803192outcome:
passed📌 Teardown phase
duration:
0.00017187558114528656outcome:
passed
↳ Function: test_metaclass_tracks_instances
-
✅ Test 415
📌 Setup phase
duration:
0.00016823504120111465outcome:
passed📌 Call phase
duration:
0.0002742977812886238outcome:
passed📌 Teardown phase
duration:
0.00015669409185647964outcome:
passed
↳ Function: test_registry_inheritance
-
✅ Test 416
📌 Setup phase
duration:
0.0002751573920249939outcome:
passed📌 Call phase
duration:
0.0007515931501984596outcome:
passed📌 Teardown phase
duration:
0.0002087559551000595outcome:
passed
↳ Function: test_instance_tracking
-
✅ Test 417
📌 Setup phase
duration:
0.0002518771216273308outcome:
passed📌 Call phase
duration:
0.00029723532497882843outcome:
passed📌 Teardown phase
duration:
0.00018538814038038254outcome:
passed
↳ Function: test_collect_instances_recursive
-
✅ Test 418
📌 Setup phase
duration:
0.00024632643908262253outcome:
passed📌 Call phase
duration:
0.0011574635282158852outcome:
passed📌 Teardown phase
duration:
0.00020015332847833633outcome:
passed
↳ Function: test_instances_function
-
✅ Test 419
📌 Setup phase
duration:
0.0002624429762363434outcome:
passed📌 Call phase
duration:
0.0011836448684334755outcome:
passed📌 Teardown phase
duration:
0.00020292215049266815outcome:
passed
↳ Function: test_non_registry_class_error
-
✅ Test 420
📌 Setup phase
duration:
0.00018721912056207657outcome:
passed📌 Call phase
duration:
0.00027151405811309814outcome:
passed📌 Teardown phase
duration:
0.00014911498874425888outcome:
passed
↳ Function: test_signature_preservation
-
✅ Test 421
📌 Setup phase
duration:
0.00017163529992103577outcome:
passed📌 Call phase
duration:
0.00030252616852521896outcome:
passed📌 Teardown phase
duration:
0.00016244594007730484outcome:
passed
-
-
📄 test_utils_richcfg.py
↳ Function: test_rich_inspector_outputs_more_than_builtin
-
✅ Test 422
📌 Setup phase
duration:
0.0002968553453683853outcome:
passed📌 Call phase
duration:
0.09684761241078377outcome:
passed📌 Teardown phase
duration:
0.00032688211649656296outcome:
passed
-
-
📄 test_utils_run_later.py
↳ Function: test_init_and_repr
-
✅ Test 423
📌 Setup phase
duration:
0.00020857807248830795outcome:
passed📌 Call phase
duration:
0.00025030970573425293outcome:
passed📌 Teardown phase
duration:
0.0001671425998210907outcome:
passed
↳ Function: test_call
-
✅ Test 424
📌 Setup phase
duration:
0.0001661926507949829outcome:
passed📌 Call phase
duration:
0.00021208170801401138outcome:
passed📌 Teardown phase
duration:
0.0001463964581489563outcome:
passed
↳ Function: test_matmul_with_string
-
✅ Test 425
📌 Setup phase
duration:
0.0001441650092601776outcome:
passed📌 Call phase
duration:
0.00020553451031446457outcome:
passed📌 Teardown phase
duration:
0.00014722347259521484outcome:
passed
↳ Function: test_matmul_with_list
-
✅ Test 426
📌 Setup phase
duration:
0.00015130918473005295outcome:
passed📌 Call phase
duration:
0.0002226307988166809outcome:
passed📌 Teardown phase
duration:
0.00014619529247283936outcome:
passed
↳ Function: test_matmul_with_single_int
-
✅ Test 427
📌 Setup phase
duration:
0.00016473140567541122outcome:
passed📌 Call phase
duration:
0.00020120199769735336outcome:
passed📌 Teardown phase
duration:
0.0001443019136786461outcome:
passed
↳ Function: test_run_at_future_triggered_and_logs
-
✅ Test 428
📌 Setup phase
duration:
0.00037251412868499756outcome:
passed📌 Call phase
duration:
0.2041758866980672outcome:
passed📌 Teardown phase
duration:
0.0003512650728225708outcome:
passed
↳ Function: test_run_at_already_past
-
✅ Test 429
📌 Setup phase
duration:
0.0003832811489701271outcome:
passed📌 Call phase
duration:
0.0003831852227449417outcome:
passed📌 Teardown phase
duration:
0.00022527296096086502outcome:
passed
↳ Function: test_run_in_future_triggered_and_logs
-
✅ Test 430
📌 Setup phase
duration:
0.0002957656979560852outcome:
passed📌 Call phase
duration:
0.2020842181518674outcome:
passed📌 Teardown phase
duration:
0.00034115370362997055outcome:
passed
↳ Function: test_run_in_past
-
✅ Test 431
📌 Setup phase
duration:
0.0003701159730553627outcome:
passed📌 Call phase
duration:
0.0004230951890349388outcome:
passed📌 Teardown phase
duration:
0.0002292301505804062outcome:
passed
↳ Function: test_run_later_with_seconds
-
✅ Test 432
📌 Setup phase
duration:
0.00030142348259687424outcome:
passed📌 Call phase
duration:
0.20210157614201307outcome:
passed📌 Teardown phase
duration:
0.0003714142367243767outcome:
passed
↳ Function: test_run_later_with_past_datetime
-
✅ Test 433
📌 Setup phase
duration:
0.00037454627454280853outcome:
passed📌 Call phase
duration:
0.0004364829510450363outcome:
passed📌 Teardown phase
duration:
0.00024178996682167053outcome:
passed
↳ Function: test_run_at_tqdm_multiple_updates
-
✅ Test 434
📌 Setup phase
duration:
0.00038225390017032623outcome:
passed📌 Call phase
duration:
0.20198021922260523outcome:
passed📌 Teardown phase
duration:
0.0003622882068157196outcome:
passed
↳ Function: test_today_basic
-
✅ Test 435
📌 Setup phase
duration:
0.0001916075125336647outcome:
passed📌 Call phase
duration:
0.0007424075156450272outcome:
passed📌 Teardown phase
duration:
0.0001611672341823578outcome:
passed
↳ Function: test_tomorrow_basic
-
✅ Test 436
📌 Setup phase
duration:
0.00017350446432828903outcome:
passed📌 Call phase
duration:
0.0004210248589515686outcome:
passed📌 Teardown phase
duration:
0.00015190709382295609outcome:
passed
↳ Function: test_yesterday_basic
-
✅ Test 437
📌 Setup phase
duration:
0.0001482982188463211outcome:
passed📌 Call phase
duration:
0.0004157479852437973outcome:
passed📌 Teardown phase
duration:
0.00015239231288433075outcome:
passed
↳ Function: test_today_matmul_string
-
✅ Test 438
📌 Setup phase
duration:
0.0001571429893374443outcome:
passed📌 Call phase
duration:
0.00038092397153377533outcome:
passed📌 Teardown phase
duration:
0.0001485198736190796outcome:
passed
↳ Function: test_tomorrow_matmul_list
-
✅ Test 439
📌 Setup phase
duration:
0.00015611015260219574outcome:
passed📌 Call phase
duration:
0.0005970671772956848outcome:
passed📌 Teardown phase
duration:
0.00014739017933607101outcome:
passed
↳ Function: test_yesterday_matmul_single
-
✅ Test 440
📌 Setup phase
duration:
0.00015234202146530151outcome:
passed📌 Call phase
duration:
0.00039090216159820557outcome:
passed📌 Teardown phase
duration:
0.00015112664550542831outcome:
passed
-
-
📄 test_utils_sendmail.py
↳ Function: test_sendmail_local_delivery
-
✅ Test 441
📌 Setup phase
duration:
0.00017531868070363998outcome:
passed📌 Call phase
duration:
0.12127373553812504outcome:
passed📌 Teardown phase
duration:
0.0003046216443181038outcome:
passed
↳ Function: test_sendmail_raises_on_sendmail_failure
-
✅ Test 442
📌 Setup phase
duration:
0.0004067299887537956outcome:
passed📌 Call phase
duration:
0.0008269818499684334outcome:
passed📌 Teardown phase
duration:
0.0002271728590130806outcome:
passed
-
-
📄 test_utils_sendsms.py
↳ Function: test_sendsms_local_delivery
-
✅ Test 443
📌 Setup phase
duration:
0.00017751473933458328outcome:
passed📌 Call phase
duration:
0.11858505848795176outcome:
passed📌 Teardown phase
duration:
0.000314297154545784outcome:
passed
-
-
📄 test_utils_shortcut.py
↳ Function: TestShortcutInitialization
-
✅ Test 444
📌 Setup phase
duration:
0.00046906713396310806outcome:
passed📌 Call phase
duration:
0.00031425803899765015outcome:
passed📌 Teardown phase
duration:
0.0002003619447350502outcome:
passed -
✅ Test 445
📌 Setup phase
duration:
0.00025065336376428604outcome:
passed📌 Call phase
duration:
0.00019852351397275925outcome:
passed📌 Teardown phase
duration:
0.0001841289922595024outcome:
passed
↳ Function: test_run_method
-
✅ Test 446
📌 Setup phase
duration:
0.0004248861223459244outcome:
passed📌 Call phase
duration:
0.0007668305188417435outcome:
passed📌 Teardown phase
duration:
0.00026889052242040634outcome:
passed
↳ Function: test_repr_output
-
✅ Test 447
📌 Setup phase
duration:
0.00024757348001003265outcome:
passed📌 Call phase
duration:
0.000207425095140934outcome:
passed📌 Teardown phase
duration:
0.0001961439847946167outcome:
passed
↳ Function: test_source_with_regular_function
-
✅ Test 448
📌 Setup phase
duration:
0.00023345183581113815outcome:
passed📌 Call phase
duration:
0.0013425201177597046outcome:
passed📌 Teardown phase
duration:
0.00019204430282115936outcome:
passed
↳ Function: test_source_error_handling
-
✅ Test 449
📌 Setup phase
duration:
0.00023711379617452621outcome:
passed📌 Call phase
duration:
0.0011542122811079025outcome:
passed📌 Teardown phase
duration:
0.00020823348313570023outcome:
passed
↳ Function: test_as_shortcut_basic
-
✅ Test 450
📌 Setup phase
duration:
0.00024557579308748245outcome:
passed📌 Call phase
duration:
0.0002122214064002037outcome:
passed📌 Teardown phase
duration:
0.00017667561769485474outcome:
passed
↳ Function: test_as_shortcut_with_name
-
✅ Test 451
📌 Setup phase
duration:
0.00022527389228343964outcome:
passed📌 Call phase
duration:
0.0002011144533753395outcome:
passed📌 Teardown phase
duration:
0.00018620584160089493outcome:
passed
↳ Function: test_as_shortcut_factory_pattern
-
✅ Test 452
📌 Setup phase
duration:
0.00021681003272533417outcome:
passed📌 Call phase
duration:
0.00018133409321308136outcome:
passed📌 Teardown phase
duration:
0.00016799569129943848outcome:
passed
↳ Function: TestShortcutsSingleton
-
✅ Test 453
📌 Setup phase
duration:
0.0003332430496811867outcome:
passed📌 Call phase
duration:
0.000186956487596035outcome:
passed📌 Teardown phase
duration:
0.00019214767962694168outcome:
passed -
✅ Test 455
📌 Setup phase
duration:
0.0003495793789625168outcome:
passed📌 Call phase
duration:
0.0002503441646695137outcome:
passed📌 Teardown phase
duration:
0.00020842161029577255outcome:
passed -
✅ Test 456
📌 Setup phase
duration:
0.0003012167289853096outcome:
passed📌 Call phase
duration:
0.000250483863055706outcome:
passed📌 Teardown phase
duration:
0.00019186921417713165outcome:
passed -
✅ Test 457
📌 Setup phase
duration:
0.00031526945531368256outcome:
passed📌 Call phase
duration:
0.00029521621763706207outcome:
passed📌 Teardown phase
duration:
0.00020668096840381622outcome:
passed
↳ Function: TestFullIntegration
-
✅ Test 458
📌 Setup phase
duration:
0.0004349770024418831outcome:
passed📌 Call phase
duration:
0.0011692848056554794outcome:
passedstdout:
Calculating 3 + 4📌 Teardown phase
duration:
0.00028903596103191376outcome:
passed
↳ Function: test_registry_inheritance
-
✅ Test 460
📌 Setup phase
duration:
0.0002915775403380394outcome:
passed📌 Call phase
duration:
0.0001970706507563591outcome:
passed📌 Teardown phase
duration:
0.00019791815429925919outcome:
passed
-
-
📄 test_utils_snapshot.py
↳ Function: test_snapshot
-
✅ Test 461
params:test_input=[["v1", "Visible", false], ["h1", "Hidden", true]], expected=["Visible"], kwargs={}📌 Parameters
params: test_input: [["v1", "Visible", false], ["h1", "Hidden", true]] expected: ["Visible"] kwargs: {} id: "exclude_internals"📌 Setup phase
duration:
0.00038327742367982864outcome:
passed📌 Call phase
duration:
0.0006749983876943588outcome:
passed📌 Teardown phase
duration:
0.0002248017117381096outcome:
passed -
✅ Test 462
params:test_input=[["v1", "Visible", false], ["h1", "Hidden", true]], expected=["Visible", "Hidden"], kwargs={"include_internal": true}📌 Parameters
params: test_input: [["v1", "Visible", false], ["h1", "Hidden", true]] expected: ["Visible", "Hidden"] kwargs: {"include_internal": true} id: "include_internals"📌 Setup phase
duration:
0.00034182798117399216outcome:
passed📌 Call phase
duration:
0.0005067214369773865outcome:
passed📌 Teardown phase
duration:
0.00021888595074415207outcome:
passed -
✅ Test 463
params:test_input=[], expected=[], kwargs={}📌 Parameters
params: test_input: [] expected: [] kwargs: {} id: "empty_case"📌 Setup phase
duration:
0.00032636988908052444outcome:
passed📌 Call phase
duration:
0.00019330158829689026outcome:
passed📌 Teardown phase
duration:
0.00020355172455310822outcome:
passed -
✅ Test 464
params:test_input=[["3", "Charlie"], ["1", "Alpha"], ["2", "Beta"]], expected=["Alpha", "Beta", "Charlie"], kwargs="{'sort_key': <class 'str'>}"📌 Parameters
params: test_input: [["3", "Charlie"], ["1", "Alpha"], ["2", "Beta"]] expected: ["Alpha", "Beta", "Charlie"] kwargs: "{'sort_key': <class 'str'>}" id: "sort_str"📌 Setup phase
duration:
0.0003245966508984566outcome:
passed📌 Call phase
duration:
0.00063319131731987outcome:
passed📌 Teardown phase
duration:
0.00021393503993749619outcome:
passed -
✅ Test 465
params:test_input=[["z3", "C"], ["a1", "A"], ["m2", "B"]], expected=["A", "B", "C"], kwargs="{'sort_key': <function <lambda> at 0x7feb09cd7310>}"📌 Parameters
params: test_input: [["z3", "C"], ["a1", "A"], ["m2", "B"]] expected: ["A", "B", "C"] kwargs: "{'sort_key': <function <lambda> at 0x7feb09cd7310>}" id: "sort_id"📌 Setup phase
duration:
0.0003246814012527466outcome:
passed📌 Call phase
duration:
0.0006214724853634834outcome:
passed📌 Teardown phase
duration:
0.00021344609558582306outcome:
passed -
✅ Test 466
params:test_input=[["3", "Charlie"], ["1", "alpha"], ["2", "Beta"]], expected=["alpha", "Beta", "Charlie"], kwargs="{'sort_key': <function <lambda> at 0x7feb09cd73a0>}"📌 Parameters
params: test_input: [["3", "Charlie"], ["1", "alpha"], ["2", "Beta"]] expected: ["alpha", "Beta", "Charlie"] kwargs: "{'sort_key': <function <lambda> at 0x7feb09cd73a0>}" id: "sort_case_insensitive"📌 Setup phase
duration:
0.00032947398722171783outcome:
passed📌 Call phase
duration:
0.0006153350695967674outcome:
passed📌 Teardown phase
duration:
0.00020976737141609192outcome:
passed -
✅ Test 467
params:test_input=[["1", "A"], ["2", "BB"], ["3", "CCC"]], expected=["A", "BB", "CCC"], kwargs="{'sort_key': <function <lambda> at 0x7feb09cd7430>}"📌 Parameters
params: test_input: [["1", "A"], ["2", "BB"], ["3", "CCC"]] expected: ["A", "BB", "CCC"] kwargs: "{'sort_key': <function <lambda> at 0x7feb09cd7430>}" id: "sort_length"📌 Setup phase
duration:
0.0003279149532318115outcome:
passed📌 Call phase
duration:
0.0006207823753356934outcome:
passed📌 Teardown phase
duration:
0.00022152718156576157outcome:
passed -
✅ Test 468
params:test_input=[["1", "A"], ["2", "B"], ["3", "C"]], expected=["C", "B", "A"], kwargs="{'sort_key': <function <lambda> at 0x7feb09cd74c0>}"📌 Parameters
params: test_input: [["1", "A"], ["2", "B"], ["3", "C"]] expected: ["C", "B", "A"] kwargs: "{'sort_key': <function <lambda> at 0x7feb09cd74c0>}" id: "sort_reverse"📌 Setup phase
duration:
0.0003222888335585594outcome:
passed📌 Call phase
duration:
0.0006293850019574165outcome:
passed📌 Teardown phase
duration:
0.0002262098714709282outcome:
passed
-
-
📄 test_utils_termtitle.py
↳ Function: test_terminal_title_with_tmux
-
✅ Test 469
📌 Setup phase
duration:
0.00019367597997188568outcome:
passed📌 Call phase
duration:
0.018981858156621456outcome:
passed📌 Teardown phase
duration:
0.0003194352611899376outcome:
passed
-
-
📄 test_utils_tqdm_mod.py
↳ Function: test_complete_progress_bar
-
✅ Test 470
📌 Setup phase
duration:
0.0002346700057387352outcome:
passed📌 Call phase
duration:
0.0042618652805686outcome:
passed📌 Teardown phase
duration:
0.00018843263387680054outcome:
passed
↳ Function: test_set_progress_multiple_points
-
✅ Test 471
📌 Setup phase
duration:
0.00017390400171279907outcome:
passed📌 Call phase
duration:
0.0019596489146351814outcome:
passed📌 Teardown phase
duration:
0.00019361544400453568outcome:
passed
↳ Function: test_format_sizeof_alignment
-
✅ Test 472
📌 Setup phase
duration:
0.00017280690371990204outcome:
passed📌 Call phase
duration:
0.0002129664644598961outcome:
passed📌 Teardown phase
duration:
0.0001519676297903061outcome:
passed
↳ Function: test_custom_unit
-
✅ Test 474
📌 Setup phase
duration:
0.00019384920597076416outcome:
passed📌 Call phase
duration:
0.005001497454941273outcome:
passed📌 Teardown phase
duration:
0.00016845762729644775outcome:
passed
↳ Function: test_clamp_above_total
-
✅ Test 475
📌 Setup phase
duration:
0.00019558798521757126outcome:
passed📌 Call phase
duration:
0.0006101960316300392outcome:
passed📌 Teardown phase
duration:
0.0001548323780298233outcome:
passed
↳ Function: test_clamp_below_zero
-
✅ Test 476
📌 Setup phase
duration:
0.00016428250819444656outcome:
passed📌 Call phase
duration:
0.0007148310542106628outcome:
passed📌 Teardown phase
duration:
0.00015729479491710663outcome:
passed
-
-
📄 test_utils_trinary.py
↳ Function: test_check_trinary_valid_values
-
✅ Test 477
📌 Setup phase
duration:
0.00018956884741783142outcome:
passed📌 Call phase
duration:
0.00019540078938007355outcome:
passed📌 Teardown phase
duration:
0.00013936497271060944outcome:
passed
↳ Function: test_check_trinary_invalid_value
-
✅ Test 478
📌 Setup phase
duration:
0.00014570634812116623outcome:
passed📌 Call phase
duration:
0.00044011790305376053outcome:
passed📌 Teardown phase
duration:
0.00015186332166194916outcome:
passed
↳ Function: test_check_trinary_with_custom_allowed_values
-
✅ Test 479
📌 Setup phase
duration:
0.00014861486852169037outcome:
passed📌 Call phase
duration:
0.00020589306950569153outcome:
passed📌 Teardown phase
duration:
0.000138135626912117outcome:
passed
-
-
📄 test_utils_typecast.py
↳ Function: test_downcast_success
-
✅ Test 480
📌 Setup phase
duration:
0.0001777568832039833outcome:
passed📌 Call phase
duration:
0.00020448770374059677outcome:
passed📌 Teardown phase
duration:
0.0001525580883026123outcome:
passed
↳ Function: test_upcast_success
-
✅ Test 481
📌 Setup phase
duration:
0.00014890171587467194outcome:
passed📌 Call phase
duration:
0.0001921607181429863outcome:
passed📌 Teardown phase
duration:
0.0001458786427974701outcome:
passed
↳ Function: test_downcast_invalid
-
✅ Test 482
📌 Setup phase
duration:
0.0001454707235097885outcome:
passed📌 Call phase
duration:
0.000439714640378952outcome:
passed📌 Teardown phase
duration:
0.0001532621681690216outcome:
passed
↳ Function: test_upcast_invalid
-
✅ Test 483
📌 Setup phase
duration:
0.00015473738312721252outcome:
passed📌 Call phase
duration:
0.00021784566342830658outcome:
passed📌 Teardown phase
duration:
0.00013852957636117935outcome:
passed
↳ Function: test_object_identity_preserved
-
✅ Test 484
📌 Setup phase
duration:
0.00015909504145383835outcome:
passed📌 Call phase
duration:
0.0001858845353126526outcome:
passed📌 Teardown phase
duration:
0.0001406325027346611outcome:
passed
↳ Function: test_ensure_subclass_valid
-
✅ Test 485
📌 Setup phase
duration:
0.00014024879783391953outcome:
passed📌 Call phase
duration:
0.0001738937571644783outcome:
passed📌 Teardown phase
duration:
0.00014271028339862823outcome:
passed
↳ Function: test_ensure_subclass_invalid
-
✅ Test 486
📌 Setup phase
duration:
0.0001507354900240898outcome:
passed📌 Call phase
duration:
0.0002164868637919426outcome:
passed📌 Teardown phase
duration:
0.0001374194398522377outcome:
passed
↳ Function: test_cast_changes_class
-
✅ Test 487
📌 Setup phase
duration:
0.00015542376786470413outcome:
passed📌 Call phase
duration:
0.00018319208174943924outcome:
passed📌 Teardown phase
duration:
0.00013968441635370255outcome:
passed
↳ Function: test_cast_preserves_identity
-
✅ Test 488
📌 Setup phase
duration:
0.00014663301408290863outcome:
passed📌 Call phase
duration:
0.00016838312149047852outcome:
passed📌 Teardown phase
duration:
0.0001413905993103981outcome:
passed
-
-
📄 test_utils_utils.py
↳ Function: test_singleton_instance
-
✅ Test 489
📌 Setup phase
duration:
0.00017802976071834564outcome:
passed📌 Call phase
duration:
0.00019732490181922913outcome:
passed📌 Teardown phase
duration:
0.00014154240489006042outcome:
passed
↳ Function: test_singleton_identity
-
✅ Test 490
📌 Setup phase
duration:
0.00014685094356536865outcome:
passed📌 Call phase
duration:
0.0001815827563405037outcome:
passed📌 Teardown phase
duration:
0.00013835541903972626outcome:
passed
↳ Function: test_typename
-
✅ Test 491
params:obj=null, expected="NoneType"📌 Parameters
params: obj: null expected: "NoneType" id: "None-NoneType"📌 Setup phase
duration:
0.0003714459016919136outcome:
passed📌 Call phase
duration:
0.00018587429076433182outcome:
passed📌 Teardown phase
duration:
0.00021265540271997452outcome:
passed -
✅ Test 492
params:obj=true, expected="bool"📌 Parameters
params: obj: true expected: "bool" id: "True-bool"📌 Setup phase
duration:
0.0002755848690867424outcome:
passed📌 Call phase
duration:
0.00019382312893867493outcome:
passed📌 Teardown phase
duration:
0.00018442515283823013outcome:
passed -
✅ Test 493
params:obj=42, expected="int"📌 Parameters
params: obj: 42 expected: "int" id: "42-int"📌 Setup phase
duration:
0.0002830410376191139outcome:
passed📌 Call phase
duration:
0.00017241481691598892outcome:
passed📌 Teardown phase
duration:
0.00018270593136548996outcome:
passed -
✅ Test 494
params:obj=3.14, expected="float"📌 Parameters
params: obj: 3.14 expected: "float" id: "3.14-float"📌 Setup phase
duration:
0.0002698088064789772outcome:
passed📌 Call phase
duration:
0.00017377827316522598outcome:
passed📌 Teardown phase
duration:
0.00019336771219968796outcome:
passed -
✅ Test 495
params:obj="text", expected="str"📌 Parameters
params: obj: "text" expected: "str" id: "text-str"📌 Setup phase
duration:
0.0002666367217898369outcome:
passed📌 Call phase
duration:
0.00017684325575828552outcome:
passed📌 Teardown phase
duration:
0.0001746276393532753outcome:
passed -
✅ Test 496
params:obj="{1, 2, 3}", expected="set"📌 Parameters
params: obj: "{1, 2, 3}" expected: "set" id: "obj5-set"📌 Setup phase
duration:
0.00027497392147779465outcome:
passed📌 Call phase
duration:
0.0001774970442056656outcome:
passed📌 Teardown phase
duration:
0.0001946818083524704outcome:
passed -
✅ Test 497
params:obj=[[1], [2, 3]], expected="list"📌 Parameters
params: obj: [[1], [2, 3]] expected: "list" id: "obj6-list"📌 Setup phase
duration:
0.00025684572756290436outcome:
passed📌 Call phase
duration:
0.00018990878015756607outcome:
passed📌 Teardown phase
duration:
0.00018556974828243256outcome:
passed -
✅ Test 498
params:obj=[{"a": [1, 2]}, {"b": [3, 4]}], expected="list"📌 Parameters
params: obj: [{"a": [1, 2]}, {"b": [3, 4]}] expected: "list" id: "obj7-list"📌 Setup phase
duration:
0.00027788616716861725outcome:
passed📌 Call phase
duration:
0.0001714024692773819outcome:
passed📌 Teardown phase
duration:
0.00018005724996328354outcome:
passed -
✅ Test 499
params:obj={"key": [{"nested": 1}, [2, 3]]}, expected="dict"📌 Parameters
params: obj: {"key": [{"nested": 1}, [2, 3]]} expected: "dict" id: "obj8-dict"📌 Setup phase
duration:
0.00027439091354608536outcome:
passed📌 Call phase
duration:
0.00017805583775043488outcome:
passed📌 Teardown phase
duration:
0.00018903892487287521outcome:
passed -
✅ Test 500
params:obj="<function <lambda> at 0x7feb09cebc10>", expected="function"📌 Parameters
params: obj: "<function <lambda> at 0x7feb09cebc10>" expected: "function" id: "<lambda>-function"📌 Setup phase
duration:
0.0002655861899256706outcome:
passed📌 Call phase
duration:
0.00019093602895736694outcome:
passed📌 Teardown phase
duration:
0.00018602237105369568outcome:
passed -
✅ Test 501
params:obj="<function sample_function at 0x7feb09cebb80>", expected="function"📌 Parameters
params: obj: "<function sample_function at 0x7feb09cebb80>" expected: "function" id: "sample_function-function"📌 Setup phase
duration:
0.00027579814195632935outcome:
passed📌 Call phase
duration:
0.00017857085913419724outcome:
passed📌 Teardown phase
duration:
0.0001959158107638359outcome:
passed -
✅ Test 502
params:obj="<function sample_function.<locals>.nested at 0x7feb09cebca0>", expected="function"📌 Parameters
params: obj: "<function sample_function.<locals>.nested at 0x7feb09cebca0>" expected: "function" id: "nested-function"📌 Setup phase
duration:
0.00038846954703330994outcome:
passed📌 Call phase
duration:
0.00018608104437589645outcome:
passed📌 Teardown phase
duration:
0.00018203537911176682outcome:
passed -
✅ Test 503
params:obj="<built-in function len>", expected="builtin_function_or_method"📌 Parameters
params: obj: "<built-in function len>" expected: "builtin_function_or_method" id: "len-builtin_function_or_method"📌 Setup phase
duration:
0.0002792738378047943outcome:
passed📌 Call phase
duration:
0.0001774132251739502outcome:
passed📌 Teardown phase
duration:
0.0001941164955496788outcome:
passed -
✅ Test 504
params:obj="<built-in function sum>", expected="builtin_function_or_method"📌 Parameters
params: obj: "<built-in function sum>" expected: "builtin_function_or_method" id: "sum-builtin_function_or_method"📌 Setup phase
duration:
0.00025474000722169876outcome:
passed📌 Call phase
duration:
0.00018316134810447693outcome:
passed📌 Teardown phase
duration:
0.00018133968114852905outcome:
passed -
✅ Test 505
params:obj="<module 'math' from '/root/mambaforge/envs/ci-env/lib/python3.8/lib-dynload/math.cpython-38-x86_64-linux-gnu.so'>", expected="module"📌 Parameters
params: obj: "<module 'math' from '/root/mambaforge/envs/ci-env/lib/python3.8/lib-dynload/math.cpython-38-x86_64-linux-gnu.so'>" expected: "module" id: "math-module"📌 Setup phase
duration:
0.0002760225906968117outcome:
passed📌 Call phase
duration:
0.00017341412603855133outcome:
passed📌 Teardown phase
duration:
0.00020028557628393173outcome:
passed -
✅ Test 506
params:obj="<module 'sys' (built-in)>", expected="module"📌 Parameters
params: obj: "<module 'sys' (built-in)>" expected: "module" id: "sys-module"📌 Setup phase
duration:
0.00026947353035211563outcome:
passed📌 Call phase
duration:
0.00017322320491075516outcome:
passed📌 Teardown phase
duration:
0.00018423981964588165outcome:
passed -
✅ Test 507
params:obj="<class 'function'>", expected="type"📌 Parameters
params: obj: "<class 'function'>" expected: "type" id: "function-type"📌 Setup phase
duration:
0.00026755034923553467outcome:
passed📌 Call phase
duration:
0.000180819071829319outcome:
passed📌 Teardown phase
duration:
0.00018321536481380463outcome:
passed -
✅ Test 508
params:obj="<generator object <genexpr> at 0x7feb09bcec10>", expected="generator"📌 Parameters
params: obj: "<generator object <genexpr> at 0x7feb09bcec10>" expected: "generator" id: "<genexpr>-generator"📌 Setup phase
duration:
0.00026103854179382324outcome:
passed📌 Call phase
duration:
0.00016846228390932083outcome:
passed📌 Teardown phase
duration:
0.00020331423729658127outcome:
passed -
✅ Test 509
params:obj="<list_iterator object at 0x7feb09c785e0>", expected="list_iterator"📌 Parameters
params: obj: "<list_iterator object at 0x7feb09c785e0>" expected: "list_iterator" id: "obj18-list_iterator"📌 Setup phase
duration:
0.00026931334286928177outcome:
passed📌 Call phase
duration:
0.00018553808331489563outcome:
passed📌 Teardown phase
duration:
0.00018282979726791382outcome:
passed
↳ Function: test_next_int
-
✅ Test 510
params:nums=[1, 2, 3], expected=4📌 Parameters
params: nums: [1, 2, 3] expected: 4 id: "nums0-4"📌 Setup phase
duration:
0.00028667040169239044outcome:
passed📌 Call phase
duration:
0.00018168147653341293outcome:
passed📌 Teardown phase
duration:
0.00019428692758083344outcome:
passed -
✅ Test 511
params:nums=[10, 20], expected=21📌 Parameters
params: nums: [10, 20] expected: 21 id: "nums1-21"📌 Setup phase
duration:
0.00027309078723192215outcome:
passed📌 Call phase
duration:
0.00017748214304447174outcome:
passed📌 Teardown phase
duration:
0.0001831473782658577outcome:
passed -
✅ Test 512
params:nums=[], expected=0📌 Parameters
params: nums: [] expected: 0 id: "nums2-0"📌 Setup phase
duration:
0.00026734545826911926outcome:
passed📌 Call phase
duration:
0.00018641911447048187outcome:
passed📌 Teardown phase
duration:
0.00018342584371566772outcome:
passed
↳ Function: test_zero_pad
-
✅ Test 513
params:i=7, n=3, expected="007"📌 Parameters
params: i: 7 n: 3 expected: "007" id: "7-3-007"📌 Setup phase
duration:
0.00030928757041692734outcome:
passed📌 Call phase
duration:
0.0001851087436079979outcome:
passed📌 Teardown phase
duration:
0.0002100858837366104outcome:
passed -
✅ Test 514
params:i=123, n=5, expected="00123"📌 Parameters
params: i: 123 n: 5 expected: "00123" id: "123-5-00123"📌 Setup phase
duration:
0.0003066128119826317outcome:
passed📌 Call phase
duration:
0.00018456857651472092outcome:
passed📌 Teardown phase
duration:
0.00019272230565547943outcome:
passed -
✅ Test 515
params:i=0, n=2, expected="00"📌 Parameters
params: i: 0 n: 2 expected: "00" id: "0-2-00"📌 Setup phase
duration:
0.0003362474963068962outcome:
passed📌 Call phase
duration:
0.00017605815082788467outcome:
passed📌 Teardown phase
duration:
0.00021626148372888565outcome:
passed
↳ Function: test_iround
-
✅ Test 516
params:val=3.6, expected=4📌 Parameters
params: val: 3.6 expected: 4 id: "3.6-4"📌 Setup phase
duration:
0.0002670893445611outcome:
passed📌 Call phase
duration:
0.00018953531980514526outcome:
passed📌 Teardown phase
duration:
0.00017960835248231888outcome:
passed -
✅ Test 517
params:val=2.1, expected=2📌 Parameters
params: val: 2.1 expected: 2 id: "2.1-2"📌 Setup phase
duration:
0.00026748981326818466outcome:
passed📌 Call phase
duration:
0.00017599016427993774outcome:
passed📌 Teardown phase
duration:
0.0001852121204137802outcome:
passed -
✅ Test 518
params:val=-1.5, expected=-2📌 Parameters
params: val: -1.5 expected: -2 id: "-1.5--2"📌 Setup phase
duration:
0.000261940062046051outcome:
passed📌 Call phase
duration:
0.00017040222883224487outcome:
passed📌 Teardown phase
duration:
0.0001784488558769226outcome:
passed -
✅ Test 519
params:val=-1.4, expected=-1📌 Parameters
params: val: -1.4 expected: -1 id: "-1.4--1"📌 Setup phase
duration:
0.0002670334652066231outcome:
passed📌 Call phase
duration:
0.00019069761037826538outcome:
passed📌 Teardown phase
duration:
0.00017879344522953033outcome:
passed
↳ Function: test_sorted_naturally
-
✅ Test 520
params:items=["file1", "file10", "file2"], expected=["file1", "file2", "file10"]📌 Parameters
params: items: ["file1", "file10", "file2"] expected: ["file1", "file2", "file10"] id: "items0-expected0"📌 Setup phase
duration:
0.00028410833328962326outcome:
passed📌 Call phase
duration:
0.00022188108414411545outcome:
passed📌 Teardown phase
duration:
0.00020156055688858032outcome:
passed -
✅ Test 521
params:items=["z9", "z10", "z2", "z1"], expected=["z1", "z2", "z9", "z10"]📌 Parameters
params: items: ["z9", "z10", "z2", "z1"] expected: ["z1", "z2", "z9", "z10"] id: "items1-expected1"📌 Setup phase
duration:
0.0002579018473625183outcome:
passed📌 Call phase
duration:
0.00021862424910068512outcome:
passed📌 Teardown phase
duration:
0.00018369406461715698outcome:
passed
↳ Function: test_sorted_naturally_reverse
-
✅ Test 522
params:items=["file1", "file10", "file2"], expected=["file10", "file2", "file1"]📌 Parameters
params: items: ["file1", "file10", "file2"] expected: ["file10", "file2", "file1"] id: "items0-expected0"📌 Setup phase
duration:
0.00027686450630426407outcome:
passed📌 Call phase
duration:
0.00020112097263336182outcome:
passed📌 Teardown phase
duration:
0.00018761120736598969outcome:
passed
-
-
📄 test_utils_xrange.py
↳ Function: test_xrange_finite
-
✅ Test 523
params:args=[10], kwargs={}, expected=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]📌 Parameters
params: args: [10] kwargs: {} expected: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] id: "args0-kwargs0-expected0"📌 Setup phase
duration:
0.00033854320645332336outcome:
passed📌 Call phase
duration:
0.00020172912627458572outcome:
passed📌 Teardown phase
duration:
0.0002064034342765808outcome:
passed -
✅ Test 524
params:args=[0, 10], kwargs={}, expected=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]📌 Parameters
params: args: [0, 10] kwargs: {} expected: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] id: "args1-kwargs1-expected1"📌 Setup phase
duration:
0.0003257840871810913outcome:
passed📌 Call phase
duration:
0.0001764567568898201outcome:
passed📌 Teardown phase
duration:
0.00021591782569885254outcome:
passed -
✅ Test 525
params:args=[0, 10, 2], kwargs={}, expected=[0, 2, 4, 6, 8]📌 Parameters
params: args: [0, 10, 2] kwargs: {} expected: [0, 2, 4, 6, 8] id: "args2-kwargs2-expected2"📌 Setup phase
duration:
0.0003087390214204788outcome:
passed📌 Call phase
duration:
0.0001918664202094078outcome:
passed📌 Teardown phase
duration:
0.00019357167184352875outcome:
passed -
✅ Test 526
params:args=[10], kwargs={"step": 2}, expected=[0, 2, 4, 6, 8]📌 Parameters
params: args: [10] kwargs: {"step": 2} expected: [0, 2, 4, 6, 8] id: "args3-kwargs3-expected3"📌 Setup phase
duration:
0.0003307731822133064outcome:
passed📌 Call phase
duration:
0.0001806207001209259outcome:
passed📌 Teardown phase
duration:
0.00020755920559167862outcome:
passed
↳ Function: test_xrange_infinite
-
✅ Test 527
params:args=[], kwargs={}, expected_repr="count(0)"📌 Parameters
params: args: [] kwargs: {} expected_repr: "count(0)" id: "args0-kwargs0-count(0)"📌 Setup phase
duration:
0.0003159577026963234outcome:
passed📌 Call phase
duration:
0.00020732637494802475outcome:
passed📌 Teardown phase
duration:
0.0002815639600157738outcome:
passed -
✅ Test 528
params:args=[], kwargs={"step": 2}, expected_repr="count(0, 2)"📌 Parameters
params: args: [] kwargs: {"step": 2} expected_repr: "count(0, 2)" id: "args1-kwargs1-count(0, 2)"📌 Setup phase
duration:
0.00031597260385751724outcome:
passed📌 Call phase
duration:
0.00018497370183467865outcome:
passed📌 Teardown phase
duration:
0.0002176240086555481outcome:
passed
↳ Function: test_xrange_too_many_args
-
✅ Test 529
params:args=[1, 2, 3, 4]📌 Parameters
params: args: [1, 2, 3, 4] id: "args0"📌 Setup phase
duration:
0.0002137674018740654outcome:
passed📌 Call phase
duration:
0.0005807345733046532outcome:
passed📌 Teardown phase
duration:
0.0007893117144703865outcome:
passed
-
❌ Failed (11)
-
📄 test_utils_debug.py
↳ Function: test_short_repr
-
❌ Test 141
params:value="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", cutoff=10, expected="'aaaaaaaaaa..."📌 Parameters
params: value: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" cutoff: 10 expected: "'aaaaaaaaaa..." id: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-10-'aaaaaaaaaa..."📌 Setup phase
duration:
0.00033028610050678253outcome:
passed📌 Call phase
duration:
0.0009202640503644943outcome:
failedcrash:
path: /workspace/tligui_y/slic/tests/test_utils_debug.py lineno: 66 message: assert "'aaaaaaaaa..." == "'aaaaaaaaaa..." - 'aaaaaaaaaa... ? - + 'aaaaaaaaa...traceback:
- path: tests/test_utils_debug.py lineno: 66 message: AssertionErrorlongrepr:
value = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' cutoff = 10, expected = "'aaaaaaaaaa..." @pytest.mark.parametrize( "value, cutoff, expected", [ ("abc", 10, "'abc'"), ("a" * 100, 10, "'aaaaaaaaaa..."), (12345, 10, "12345"), ([0]*100, 15, str(repr([0]*100))[:15] + "..."), (None, 10, "None"), (type("Obj", (), {"__repr__": lambda self: "Obj(" + "x"*50 + ")"})(), 20, "Obj(xxxxxxxxxxxxxxxxx..."), ] ) def test_short_repr(value, cutoff, expected): > assert short_repr(value, cutoff) == expected E assert "'aaaaaaaaa..." == "'aaaaaaaaaa..." E E - 'aaaaaaaaaa... E ? - E + 'aaaaaaaaa... tests/test_utils_debug.py:66: AssertionError📌 Teardown phase
duration:
0.0006833542138338089outcome:
passed -
❌ Test 145
params:value="Obj(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)", cutoff=20, expected="Obj(xxxxxxxxxxxxxxxxx..."📌 Parameters
params: value: "Obj(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)" cutoff: 20 expected: "Obj(xxxxxxxxxxxxxxxxx..." id: "value5-20-Obj(xxxxxxxxxxxxxxxxx..."📌 Setup phase
duration:
0.0004992326721549034outcome:
passed📌 Call phase
duration:
0.0008177496492862701outcome:
failedcrash:
path: /workspace/tligui_y/slic/tests/test_utils_debug.py lineno: 66 message: AssertionError: assert 'Obj(xxxxxxxxxxxxxxxx...' == 'Obj(xxxxxxxxxxxxxxxxx...' - Obj(xxxxxxxxxxxxxxxxx... ? - + Obj(xxxxxxxxxxxxxxxx...traceback:
- path: tests/test_utils_debug.py lineno: 66 message: AssertionErrorlongrepr:
value = Obj(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx), cutoff = 20 expected = 'Obj(xxxxxxxxxxxxxxxxx...' @pytest.mark.parametrize( "value, cutoff, expected", [ ("abc", 10, "'abc'"), ("a" * 100, 10, "'aaaaaaaaaa..."), (12345, 10, "12345"), ([0]*100, 15, str(repr([0]*100))[:15] + "..."), (None, 10, "None"), (type("Obj", (), {"__repr__": lambda self: "Obj(" + "x"*50 + ")"})(), 20, "Obj(xxxxxxxxxxxxxxxxx..."), ] ) def test_short_repr(value, cutoff, expected): > assert short_repr(value, cutoff) == expected E AssertionError: assert 'Obj(xxxxxxxxxxxxxxxx...' == 'Obj(xxxxxxxxxxxxxxxxx...' E E - Obj(xxxxxxxxxxxxxxxxx... E ? - E + Obj(xxxxxxxxxxxxxxxx... tests/test_utils_debug.py:66: AssertionError📌 Teardown phase
duration:
0.0003174496814608574outcome:
passed
-
-
📄 test_utils_elog.py
↳ Function: test_get_default_elog_instance_with_direct_password_and_real_check
-
❌ Test 177
📌 Setup phase
duration:
0.00017974711954593658outcome:
passed📌 Call phase
duration:
0.009863845072686672outcome:
failedcrash:
path: /workspace/tligui_y/slic/tests/test_utils_elog.py lineno: 24 message: Failed: elog.post() raised an unexpected exception: No response from the logbook server. Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused'))traceback:
- path: tests/test_utils_elog.py lineno: 24 message: Failedlongrepr:
self = <urllib3.connection.HTTPConnection object at 0x7feb09b79310> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection raise err _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ address = ('localhost', 8080), timeout = None, source_address = None socket_options = [(6, 1, 1)] def create_connection( address: tuple[str, int], timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, source_address: tuple[str, int] | None = None, socket_options: _TYPE_SOCKET_OPTIONS | None = None, ) -> socket.socket: """Connect to *address* and return the socket object. Convenience function. Connect to *address* (a 2-tuple ``(host, port)``) and return the socket object. Passing the optional *timeout* parameter will set the timeout on the socket instance before attempting to connect. If no *timeout* is supplied, the global default timeout setting returned by :func:`socket.getdefaulttimeout` is used. If *source_address* is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default. """ host, port = address if host.startswith("["): host = host.strip("[]") err = None # Using the value from allowed_gai_family() in the context of getaddrinfo lets # us select whether to work with IPv4 DNS records, IPv6 records, or both. # The original create_connection function always returns all records. family = allowed_gai_family() try: host.encode("idna") except UnicodeError: raise LocationParseError(f"'{host}', label empty or too long") from None for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res sock = None try: sock = socket.socket(af, socktype, proto) # If provided, set socket level options before connecting. _set_socket_options(sock, socket_options) if timeout is not _DEFAULT_TIMEOUT: sock.settimeout(timeout) if source_address: sock.bind(source_address) > sock.connect(sa) E ConnectionRefusedError: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError The above exception was the direct cause of the following exception: self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b79910> method = 'POST', url = '/demo/' body = b'--06a2aba8224344deb19cc358b997508b\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--06a2aba8224344...Disposition: form-data; name="Text"; filename=""\r\n\r\nThis is a message1\r\n--06a2aba8224344deb19cc358b997508b--\r\n' headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=06a2aba8224344deb19cc358b997508b'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None) destination_scheme = None, conn = None, release_this_conn = True http_tunnel_required = False, err = None, clean_exit = False def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ parsed_url = parse_url(url) destination_scheme = parsed_url.scheme if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): url = to_str(_encode_target(url)) else: url = to_str(parsed_url.url) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] <https://github.com/urllib3/urllib3/issues/651> release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) try: # Request a connection from the queue. timeout_obj = self._get_timeout(timeout) conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request conn.request( /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request self.endheaders() /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders self._send_output(message_body, encode_chunked=encode_chunked) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output self.send(msg) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send self.connect() /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect self.sock = self._new_conn() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <urllib3.connection.HTTPConnection object at 0x7feb09b79310> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: raise NameResolutionError(self.host, self, e) from e except SocketTimeout as e: raise ConnectTimeoutError( self, f"Connection to {self.host} timed out. (connect timeout={self.timeout})", ) from e except OSError as e: > raise NewConnectionError( self, f"Failed to establish a new connection: {e}" ) from e E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb09b79310>: Failed to establish a new connection: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError The above exception was the direct cause of the following exception: self = <requests.adapters.HTTPAdapter object at 0x7feb09b79730> request = <PreparedRequest [POST]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=False, redirect=None, status=None) method = 'POST', url = '/demo/', response = None error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b79310>: Failed to establish a new connection: [Errno 111] Connection refused') _pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b79910> _stacktrace = <traceback object at 0x7feb09b744c0> def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b79310>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError During handling of the above exception, another exception occurred: self = <elog.logbook.Logbook object at 0x7feb09b79e80> message = 'This is a message1', msg_id = None, reply = False attributes = {'Author': 'robot', 'When': 1756376001, 'cmd': 'Submit', 'exp': 'demo', ...} attachments = [], suppress_email_notification = False, encoding = None timeout = None, kwargs = {'Author': 'robot'} new_attachment_list = [('Text', ('', b'This is a message1'))] objects_to_close = [] attributes_to_edit = {'Author': b'robot', 'When': 1756376001, 'cmd': b'Submit', 'exp': b'demo', ...} def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None, suppress_email_notification=False, encoding=None, timeout=None, **kwargs): """ Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id of the newly created message. :param message: string with message text :param msg_id: ID number of message to edit or reply. If not specified new message is created. :param reply: If 'True' reply to existing message is created instead of editing it :param attributes: Dictionary of attributes. Following attributes are used internally by the elog and will be ignored: Text, Date, Encoding, Reply to, In reply to, Locked by, Attachment :param attachments: list of: - file like objects which read() will return bytes (if file_like_object.name is not defined, default name "attachment<i>" will be used. - paths to the files All items will be appended as attachment to the elog entry. In case of unknown attachment an exception LogbookInvalidAttachment will be raised. :param suppress_email_notification: If set to True or 1, E-Mail notification will be suppressed, defaults to False. :param encoding: Defines encoding of the message. Can be: 'plain' -> plain text, 'html'->html-text, 'ELCode' --> elog formatting syntax :param timeout: Define the timeout to be used by the post request. Its value is directly passed to the requests post. Use None to disable the request timeout. :param kwargs: Anything in the kwargs will be interpreted as attribute. e.g.: logbook.post('Test text', Author='Rok Vintar), "Author" will be sent as an attribute. If named same as one of the attributes defined in "attributes", kwargs will have priority. :return: msg_id """ attributes = attributes or {} attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority attachments = attachments or [] if encoding is not None: if encoding not in ['plain', 'HTML', 'ELCode']: raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.') attributes['Encoding'] = encoding if suppress_email_notification: attributes["suppress"] = 1 # THE ATTACHMENT STRATEGY WHEN DEALING WITH POST MODIFICATION # # 1. Does the message on the server have already attachments? # 1.1 - We read the message getting the existing attachment list. # 1.2 - Add to the attributes dictionary one line for each attachment like this: # attributes['attachmentN'] = timestamped_filename_name # # 2. Do we have new attachments? # 2.1 - Those are in the new_attachment_list. This is a list of this type: # [ ('attfileN', ('filename', fileobject)) ] # 2.2 - We need to loop over all the new attachments: # 2.2.1 - Does a file already on the server with the same name exist? # 2.2.1.1 - No: OK. Then we go ahead with the next attachment. # 2.2.1.2 - Yes: # 2.2.1.2.1 - Are the two files identical? # 2.2.1.2.1.1 - Yes: then we remove this current entry from the new_attachment_list and we leave the one # already on server. # 2.2.1.2.1.2 - No: # 2.2.1.2.1.2.1 - Then the file has been update. # 2.2.1.2.1.2.2 - We need to remove the file on server first (using special post) # 2.2.1.2.1.2.3 - We have to remove the old attachment from the attributes dictionary. # if attachments: # here we accomplish point 2.1. # new_attachment_list is something like [ ('attfileN', ('filename', fileobject)) ] new_attachment_list, objects_to_close = self._prepare_attachments(attachments) else: objects_to_close = list() new_attachment_list = list() attributes_to_edit = dict() if msg_id: # Message exists, we can continue if reply: # Verify that there is a message on the server, otherwise do not reply to it! self._check_if_message_on_server(msg_id) # raises exception in case of none existing message attributes['reply_to'] = str(msg_id) else: # Edit existing attributes['edit_id'] = str(msg_id) attributes['skiplock'] = '1' # here we accomplish point 1.1. # existing_attachments_list is something like: # [ 'https://elog.url.com/logbook/timestamped_filename' ] msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id) for attribute, data in attributes.items(): new_data = attributes.get(attribute) if new_data is not None: attributes_to_edit[attribute] = new_data i = 0 existing_attachments_filename_list = list() for attachment in existing_attachments_list: # here we accomplish point 1.2. We strip the timestamped_filename from the whole URL. attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) existing_attachments_filename_list.append(os.path.basename(attachment)[14:]) i += 1 # let's accomplish 2.2. Loop over all new attachment duplicate_attachment_list = list() for new_attachment in new_attachment_list: # the new_attachment_list is something like: # [ ('attfileN', ('filename', fileobject)) ] new_attachment_filename = new_attachment[1][0] if new_attachment_filename in existing_attachments_filename_list: # a file with the same name existing already on the server. # we need to check if the two files are the same. # read the content of the new file new_attachment_content = new_attachment[1][1].read() # don't forget to reset the fileobj to the beginning of the file new_attachment[1][1].seek(0) # get the existing attachment content attachment_index = existing_attachments_filename_list.index(new_attachment_filename) existing_attachment_content = self.download_attachment( url=existing_attachments_list[attachment_index], timeout=timeout ) # check if the two contents are the same if new_attachment_content == existing_attachment_content: # yes. then we don't upload a second copy. we remove the current entry from the list duplicate_attachment_list.append(new_attachment) else: # no. they are not the same file. we will replace the existing file with the new one # first: we need to remove the attachment from the server using the dedicated method self.delete_attachment(msg_id, attributes=attributes_to_edit, attachment_id=attachment_index, timeout=timeout, text=msg_to_edit) # now we can remove this attachment from the auxiliary lists. existing_attachments_filename_list.pop(attachment_index) existing_attachments_list.pop(attachment_index) # now we need to rebuild the attributes dictionary for the part concerning the attachments. # we remove all of them first keys_to_be_removed = list() for key in attributes_to_edit.keys(): if key.startswith('attachment'): keys_to_be_removed.append(key) if key.startswith('delatt'): keys_to_be_removed.append(key) for key in keys_to_be_removed: del attributes_to_edit[key] # now we rebuild it for i, attachment in enumerate(existing_attachments_list): attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) # remove all duplicate attachments from the new_attachment_list for attach in duplicate_attachment_list: new_attachment_list.remove(attach) else: # As we create a new message, specify creation time if not already specified in attributes if 'When' not in attributes: attributes['When'] = int(datetime.now().timestamp()) if not attributes_to_edit: attributes_to_edit = attributes # Remove any attributes that should not be sent _remove_reserved_attributes(attributes_to_edit) # Make requests module think that Text is a "file". This is the only way to force requests to send data as # multipart/form-data even if there are no attachments. Elog understands only multipart/form-data new_attachment_list.append(('Text', ('', message.encode('iso-8859-1')))) # Base attributes are common to all messages self._add_base_msg_attributes(attributes_to_edit) # Keys in attributes cannot have certain characters like whitespaces or dashes for the http request attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit) # All string values in the attributes must be encoded in latin1 attributes_to_edit = _encode_values(attributes_to_edit) try: > response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list, allow_redirects=False, verify=False, timeout=timeout) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:288: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:115: in post return request("post", url, data=data, json=json, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request return session.request(method=method, url=url, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request resp = self.send(prep, **send_kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send r = adapter.send(request, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <requests.adapters.HTTPAdapter object at 0x7feb09b79730> request = <PreparedRequest [POST]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b79310>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError During handling of the above exception, another exception occurred: self = <urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection raise err _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ address = ('localhost', 8080), timeout = None, source_address = None socket_options = [(6, 1, 1)] def create_connection( address: tuple[str, int], timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, source_address: tuple[str, int] | None = None, socket_options: _TYPE_SOCKET_OPTIONS | None = None, ) -> socket.socket: """Connect to *address* and return the socket object. Convenience function. Connect to *address* (a 2-tuple ``(host, port)``) and return the socket object. Passing the optional *timeout* parameter will set the timeout on the socket instance before attempting to connect. If no *timeout* is supplied, the global default timeout setting returned by :func:`socket.getdefaulttimeout` is used. If *source_address* is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default. """ host, port = address if host.startswith("["): host = host.strip("[]") err = None # Using the value from allowed_gai_family() in the context of getaddrinfo lets # us select whether to work with IPv4 DNS records, IPv6 records, or both. # The original create_connection function always returns all records. family = allowed_gai_family() try: host.encode("idna") except UnicodeError: raise LocationParseError(f"'{host}', label empty or too long") from None for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res sock = None try: sock = socket.socket(af, socktype, proto) # If provided, set socket level options before connecting. _set_socket_options(sock, socket_options) if timeout is not _DEFAULT_TIMEOUT: sock.settimeout(timeout) if source_address: sock.bind(source_address) > sock.connect(sa) E ConnectionRefusedError: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError The above exception was the direct cause of the following exception: self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b7e820> method = 'GET', url = '/demo/None', body = None headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None) destination_scheme = None, conn = None, release_this_conn = True http_tunnel_required = False, err = None, clean_exit = False def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ parsed_url = parse_url(url) destination_scheme = parsed_url.scheme if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): url = to_str(_encode_target(url)) else: url = to_str(parsed_url.url) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] <https://github.com/urllib3/urllib3/issues/651> release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) try: # Request a connection from the queue. timeout_obj = self._get_timeout(timeout) conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request conn.request( /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request self.endheaders() /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders self._send_output(message_body, encode_chunked=encode_chunked) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output self.send(msg) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send self.connect() /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect self.sock = self._new_conn() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: raise NameResolutionError(self.host, self, e) from e except SocketTimeout as e: raise ConnectTimeoutError( self, f"Connection to {self.host} timed out. (connect timeout={self.timeout})", ) from e except OSError as e: > raise NewConnectionError( self, f"Failed to establish a new connection: {e}" ) from e E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError The above exception was the direct cause of the following exception: self = <requests.adapters.HTTPAdapter object at 0x7feb09b7ea00> request = <PreparedRequest [GET]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=False, redirect=None, status=None) method = 'GET', url = '/demo/None', response = None error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused') _pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b7e820> _stacktrace = <traceback object at 0x7feb09bbad40> def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError During handling of the above exception, another exception occurred: self = <elog.logbook.Logbook object at 0x7feb09b79e80>, msg_id = None timeout = None def _check_if_message_on_server(self, msg_id, timeout=None): """Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no such message. :param msg_id: ID of message to be checked :params timeout: The value of timeout to be passed to the get request :return: """ request_headers = dict() if self._user or self._password: request_headers['Cookie'] = self._make_user_and_pswd_cookie() try: > response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False, verify=False, timeout=timeout) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:581: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:73: in get return request("get", url, params=params, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request return session.request(method=method, url=url, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request resp = self.send(prep, **send_kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send r = adapter.send(request, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <requests.adapters.HTTPAdapter object at 0x7feb09b7ea00> request = <PreparedRequest [GET]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError During handling of the above exception, another exception occurred: def test_get_default_elog_instance_with_direct_password_and_real_check(): url = "http://localhost:8080/demo" user = "robot" password = "testpassword" text = "This is a message1" elog = Elog("http://localhost:8080/demo", user=user, password=password) try: > msg_id = elog.post(text) tests/test_utils_elog.py:22: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ slic/utils/elog.py:16: in post return self._log.post(*args, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:307: in post self._check_if_message_on_server(msg_id) # raises exceptions if no message or no response from server _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <elog.logbook.Logbook object at 0x7feb09b79e80>, msg_id = None timeout = None def _check_if_message_on_server(self, msg_id, timeout=None): """Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no such message. :param msg_id: ID of message to be checked :params timeout: The value of timeout to be passed to the get request :return: """ request_headers = dict() if self._user or self._password: request_headers['Cookie'] = self._make_user_and_pswd_cookie() try: response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False, verify=False, timeout=timeout) # If there is no message code 200 will be returned (OK) and _validate_response will not recognise it # but there will be some error in the html code. resp_message, resp_headers, resp_msg_id = _validate_response(response) # If there is no message, code 200 will be returned (OK) but there will be some error indication in # the html code. if re.findall('<td.*?class="errormsg".*?>.*?</td>', resp_message.decode('utf-8', 'ignore'), flags=re.DOTALL): raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.') except requests.Timeout as e: # Catch here a timeout o the post request. # Raise the logbook exception and let the user handle it raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\n' + '{1}'.format(sys._getframe().f_code.co_name, e)) except requests.RequestException as e: > raise LogbookServerProblem('No response from the logbook server.\nDetails: ' + '{0}'.format(e)) E elog.logbook_exceptions.LogbookServerProblem: No response from the logbook server. E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:601: LogbookServerProblem During handling of the above exception, another exception occurred: def test_get_default_elog_instance_with_direct_password_and_real_check(): url = "http://localhost:8080/demo" user = "robot" password = "testpassword" text = "This is a message1" elog = Elog("http://localhost:8080/demo", user=user, password=password) try: msg_id = elog.post(text) except Exception as e: > pytest.fail(f"elog.post() raised an unexpected exception: {e}") E Failed: elog.post() raised an unexpected exception: No response from the logbook server. E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7e4f0>: Failed to establish a new connection: [Errno 111] Connection refused')) tests/test_utils_elog.py:24: Failed📌 Teardown phase
duration:
0.000399087555706501outcome:
passed
↳ Function: test_get_default_elog_instance_asks_password_and_opens
-
�� Test 179
📌 Setup phase
duration:
0.00018332060426473618outcome:
passed📌 Call phase
duration:
0.009587502107024193outcome:
failedcrash:
path: /workspace/tligui_y/slic/tests/test_utils_elog.py lineno: 57 message: Failed: elog.post() raised an unexpected exception: No response from the logbook server. Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused'))traceback:
- path: tests/test_utils_elog.py lineno: 57 message: Failedstdout:
Enter elog password for user: robotlongrepr:
self = <urllib3.connection.HTTPConnection object at 0x7feb09830f40> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection raise err _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ address = ('localhost', 8080), timeout = None, source_address = None socket_options = [(6, 1, 1)] def create_connection( address: tuple[str, int], timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, source_address: tuple[str, int] | None = None, socket_options: _TYPE_SOCKET_OPTIONS | None = None, ) -> socket.socket: """Connect to *address* and return the socket object. Convenience function. Connect to *address* (a 2-tuple ``(host, port)``) and return the socket object. Passing the optional *timeout* parameter will set the timeout on the socket instance before attempting to connect. If no *timeout* is supplied, the global default timeout setting returned by :func:`socket.getdefaulttimeout` is used. If *source_address* is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default. """ host, port = address if host.startswith("["): host = host.strip("[]") err = None # Using the value from allowed_gai_family() in the context of getaddrinfo lets # us select whether to work with IPv4 DNS records, IPv6 records, or both. # The original create_connection function always returns all records. family = allowed_gai_family() try: host.encode("idna") except UnicodeError: raise LocationParseError(f"'{host}', label empty or too long") from None for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res sock = None try: sock = socket.socket(af, socktype, proto) # If provided, set socket level options before connecting. _set_socket_options(sock, socket_options) if timeout is not _DEFAULT_TIMEOUT: sock.settimeout(timeout) if source_address: sock.bind(source_address) > sock.connect(sa) E ConnectionRefusedError: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError The above exception was the direct cause of the following exception: self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09830bb0> method = 'POST', url = '/demo/' body = b'--aa75161c22b288663152f49dada5f35f\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--aa75161c22b288...Disposition: form-data; name="Text"; filename=""\r\n\r\nThis is a message2\r\n--aa75161c22b288663152f49dada5f35f--\r\n' headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=aa75161c22b288663152f49dada5f35f'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None) destination_scheme = None, conn = None, release_this_conn = True http_tunnel_required = False, err = None, clean_exit = False def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ parsed_url = parse_url(url) destination_scheme = parsed_url.scheme if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): url = to_str(_encode_target(url)) else: url = to_str(parsed_url.url) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] <https://github.com/urllib3/urllib3/issues/651> release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) try: # Request a connection from the queue. timeout_obj = self._get_timeout(timeout) conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request conn.request( /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request self.endheaders() /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders self._send_output(message_body, encode_chunked=encode_chunked) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output self.send(msg) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send self.connect() /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect self.sock = self._new_conn() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <urllib3.connection.HTTPConnection object at 0x7feb09830f40> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: raise NameResolutionError(self.host, self, e) from e except SocketTimeout as e: raise ConnectTimeoutError( self, f"Connection to {self.host} timed out. (connect timeout={self.timeout})", ) from e except OSError as e: > raise NewConnectionError( self, f"Failed to establish a new connection: {e}" ) from e E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb09830f40>: Failed to establish a new connection: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError The above exception was the direct cause of the following exception: self = <requests.adapters.HTTPAdapter object at 0x7feb0522b790> request = <PreparedRequest [POST]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=False, redirect=None, status=None) method = 'POST', url = '/demo/', response = None error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09830f40>: Failed to establish a new connection: [Errno 111] Connection refused') _pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09830bb0> _stacktrace = <traceback object at 0x7feb09590040> def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09830f40>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError During handling of the above exception, another exception occurred: self = <elog.logbook.Logbook object at 0x7feb05e26fd0> message = 'This is a message2', msg_id = None, reply = False attributes = {'Author': 'robot', 'When': 1756376002, 'cmd': 'Submit', 'exp': 'demo', ...} attachments = [], suppress_email_notification = False, encoding = None timeout = None, kwargs = {'Author': 'robot'} new_attachment_list = [('Text', ('', b'This is a message2'))] objects_to_close = [] attributes_to_edit = {'Author': b'robot', 'When': 1756376002, 'cmd': b'Submit', 'exp': b'demo', ...} def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None, suppress_email_notification=False, encoding=None, timeout=None, **kwargs): """ Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id of the newly created message. :param message: string with message text :param msg_id: ID number of message to edit or reply. If not specified new message is created. :param reply: If 'True' reply to existing message is created instead of editing it :param attributes: Dictionary of attributes. Following attributes are used internally by the elog and will be ignored: Text, Date, Encoding, Reply to, In reply to, Locked by, Attachment :param attachments: list of: - file like objects which read() will return bytes (if file_like_object.name is not defined, default name "attachment<i>" will be used. - paths to the files All items will be appended as attachment to the elog entry. In case of unknown attachment an exception LogbookInvalidAttachment will be raised. :param suppress_email_notification: If set to True or 1, E-Mail notification will be suppressed, defaults to False. :param encoding: Defines encoding of the message. Can be: 'plain' -> plain text, 'html'->html-text, 'ELCode' --> elog formatting syntax :param timeout: Define the timeout to be used by the post request. Its value is directly passed to the requests post. Use None to disable the request timeout. :param kwargs: Anything in the kwargs will be interpreted as attribute. e.g.: logbook.post('Test text', Author='Rok Vintar), "Author" will be sent as an attribute. If named same as one of the attributes defined in "attributes", kwargs will have priority. :return: msg_id """ attributes = attributes or {} attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority attachments = attachments or [] if encoding is not None: if encoding not in ['plain', 'HTML', 'ELCode']: raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.') attributes['Encoding'] = encoding if suppress_email_notification: attributes["suppress"] = 1 # THE ATTACHMENT STRATEGY WHEN DEALING WITH POST MODIFICATION # # 1. Does the message on the server have already attachments? # 1.1 - We read the message getting the existing attachment list. # 1.2 - Add to the attributes dictionary one line for each attachment like this: # attributes['attachmentN'] = timestamped_filename_name # # 2. Do we have new attachments? # 2.1 - Those are in the new_attachment_list. This is a list of this type: # [ ('attfileN', ('filename', fileobject)) ] # 2.2 - We need to loop over all the new attachments: # 2.2.1 - Does a file already on the server with the same name exist? # 2.2.1.1 - No: OK. Then we go ahead with the next attachment. # 2.2.1.2 - Yes: # 2.2.1.2.1 - Are the two files identical? # 2.2.1.2.1.1 - Yes: then we remove this current entry from the new_attachment_list and we leave the one # already on server. # 2.2.1.2.1.2 - No: # 2.2.1.2.1.2.1 - Then the file has been update. # 2.2.1.2.1.2.2 - We need to remove the file on server first (using special post) # 2.2.1.2.1.2.3 - We have to remove the old attachment from the attributes dictionary. # if attachments: # here we accomplish point 2.1. # new_attachment_list is something like [ ('attfileN', ('filename', fileobject)) ] new_attachment_list, objects_to_close = self._prepare_attachments(attachments) else: objects_to_close = list() new_attachment_list = list() attributes_to_edit = dict() if msg_id: # Message exists, we can continue if reply: # Verify that there is a message on the server, otherwise do not reply to it! self._check_if_message_on_server(msg_id) # raises exception in case of none existing message attributes['reply_to'] = str(msg_id) else: # Edit existing attributes['edit_id'] = str(msg_id) attributes['skiplock'] = '1' # here we accomplish point 1.1. # existing_attachments_list is something like: # [ 'https://elog.url.com/logbook/timestamped_filename' ] msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id) for attribute, data in attributes.items(): new_data = attributes.get(attribute) if new_data is not None: attributes_to_edit[attribute] = new_data i = 0 existing_attachments_filename_list = list() for attachment in existing_attachments_list: # here we accomplish point 1.2. We strip the timestamped_filename from the whole URL. attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) existing_attachments_filename_list.append(os.path.basename(attachment)[14:]) i += 1 # let's accomplish 2.2. Loop over all new attachment duplicate_attachment_list = list() for new_attachment in new_attachment_list: # the new_attachment_list is something like: # [ ('attfileN', ('filename', fileobject)) ] new_attachment_filename = new_attachment[1][0] if new_attachment_filename in existing_attachments_filename_list: # a file with the same name existing already on the server. # we need to check if the two files are the same. # read the content of the new file new_attachment_content = new_attachment[1][1].read() # don't forget to reset the fileobj to the beginning of the file new_attachment[1][1].seek(0) # get the existing attachment content attachment_index = existing_attachments_filename_list.index(new_attachment_filename) existing_attachment_content = self.download_attachment( url=existing_attachments_list[attachment_index], timeout=timeout ) # check if the two contents are the same if new_attachment_content == existing_attachment_content: # yes. then we don't upload a second copy. we remove the current entry from the list duplicate_attachment_list.append(new_attachment) else: # no. they are not the same file. we will replace the existing file with the new one # first: we need to remove the attachment from the server using the dedicated method self.delete_attachment(msg_id, attributes=attributes_to_edit, attachment_id=attachment_index, timeout=timeout, text=msg_to_edit) # now we can remove this attachment from the auxiliary lists. existing_attachments_filename_list.pop(attachment_index) existing_attachments_list.pop(attachment_index) # now we need to rebuild the attributes dictionary for the part concerning the attachments. # we remove all of them first keys_to_be_removed = list() for key in attributes_to_edit.keys(): if key.startswith('attachment'): keys_to_be_removed.append(key) if key.startswith('delatt'): keys_to_be_removed.append(key) for key in keys_to_be_removed: del attributes_to_edit[key] # now we rebuild it for i, attachment in enumerate(existing_attachments_list): attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) # remove all duplicate attachments from the new_attachment_list for attach in duplicate_attachment_list: new_attachment_list.remove(attach) else: # As we create a new message, specify creation time if not already specified in attributes if 'When' not in attributes: attributes['When'] = int(datetime.now().timestamp()) if not attributes_to_edit: attributes_to_edit = attributes # Remove any attributes that should not be sent _remove_reserved_attributes(attributes_to_edit) # Make requests module think that Text is a "file". This is the only way to force requests to send data as # multipart/form-data even if there are no attachments. Elog understands only multipart/form-data new_attachment_list.append(('Text', ('', message.encode('iso-8859-1')))) # Base attributes are common to all messages self._add_base_msg_attributes(attributes_to_edit) # Keys in attributes cannot have certain characters like whitespaces or dashes for the http request attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit) # All string values in the attributes must be encoded in latin1 attributes_to_edit = _encode_values(attributes_to_edit) try: > response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list, allow_redirects=False, verify=False, timeout=timeout) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:288: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:115: in post return request("post", url, data=data, json=json, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request return session.request(method=method, url=url, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request resp = self.send(prep, **send_kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send r = adapter.send(request, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <requests.adapters.HTTPAdapter object at 0x7feb0522b790> request = <PreparedRequest [POST]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09830f40>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError During handling of the above exception, another exception occurred: self = <urllib3.connection.HTTPConnection object at 0x7feb098025b0> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection raise err _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ address = ('localhost', 8080), timeout = None, source_address = None socket_options = [(6, 1, 1)] def create_connection( address: tuple[str, int], timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, source_address: tuple[str, int] | None = None, socket_options: _TYPE_SOCKET_OPTIONS | None = None, ) -> socket.socket: """Connect to *address* and return the socket object. Convenience function. Connect to *address* (a 2-tuple ``(host, port)``) and return the socket object. Passing the optional *timeout* parameter will set the timeout on the socket instance before attempting to connect. If no *timeout* is supplied, the global default timeout setting returned by :func:`socket.getdefaulttimeout` is used. If *source_address* is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default. """ host, port = address if host.startswith("["): host = host.strip("[]") err = None # Using the value from allowed_gai_family() in the context of getaddrinfo lets # us select whether to work with IPv4 DNS records, IPv6 records, or both. # The original create_connection function always returns all records. family = allowed_gai_family() try: host.encode("idna") except UnicodeError: raise LocationParseError(f"'{host}', label empty or too long") from None for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res sock = None try: sock = socket.socket(af, socktype, proto) # If provided, set socket level options before connecting. _set_socket_options(sock, socket_options) if timeout is not _DEFAULT_TIMEOUT: sock.settimeout(timeout) if source_address: sock.bind(source_address) > sock.connect(sa) E ConnectionRefusedError: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError The above exception was the direct cause of the following exception: self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09830640> method = 'GET', url = '/demo/None', body = None headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None) destination_scheme = None, conn = None, release_this_conn = True http_tunnel_required = False, err = None, clean_exit = False def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ parsed_url = parse_url(url) destination_scheme = parsed_url.scheme if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): url = to_str(_encode_target(url)) else: url = to_str(parsed_url.url) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] <https://github.com/urllib3/urllib3/issues/651> release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) try: # Request a connection from the queue. timeout_obj = self._get_timeout(timeout) conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request conn.request( /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request self.endheaders() /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders self._send_output(message_body, encode_chunked=encode_chunked) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output self.send(msg) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send self.connect() /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect self.sock = self._new_conn() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <urllib3.connection.HTTPConnection object at 0x7feb098025b0> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: raise NameResolutionError(self.host, self, e) from e except SocketTimeout as e: raise ConnectTimeoutError( self, f"Connection to {self.host} timed out. (connect timeout={self.timeout})", ) from e except OSError as e: > raise NewConnectionError( self, f"Failed to establish a new connection: {e}" ) from e E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError The above exception was the direct cause of the following exception: self = <requests.adapters.HTTPAdapter object at 0x7feb098307f0> request = <PreparedRequest [GET]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=False, redirect=None, status=None) method = 'GET', url = '/demo/None', response = None error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused') _pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09830640> _stacktrace = <traceback object at 0x7feb09803440> def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError During handling of the above exception, another exception occurred: self = <elog.logbook.Logbook object at 0x7feb05e26fd0>, msg_id = None timeout = None def _check_if_message_on_server(self, msg_id, timeout=None): """Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no such message. :param msg_id: ID of message to be checked :params timeout: The value of timeout to be passed to the get request :return: """ request_headers = dict() if self._user or self._password: request_headers['Cookie'] = self._make_user_and_pswd_cookie() try: > response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False, verify=False, timeout=timeout) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:581: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:73: in get return request("get", url, params=params, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request return session.request(method=method, url=url, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request resp = self.send(prep, **send_kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send r = adapter.send(request, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <requests.adapters.HTTPAdapter object at 0x7feb098307f0> request = <PreparedRequest [GET]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError During handling of the above exception, another exception occurred: mock_home = <MagicMock name='home' id='140647452478240'> mock_getpass = <MagicMock name='getpass' id='140647452477088'> @patch("slic.utils.elog.getpass") @patch("slic.utils.elog.Path.home") def test_get_default_elog_instance_asks_password_and_opens(mock_home, mock_getpass): mock_home.return_value = Path("/does/not/exist") # Fausse home → lecture échoue mock_getpass.return_value = "testpassword" user = "robot" text = "This is a message2" url = "http://localhost:8080/demo" elog = Elog("http://localhost:8080/demo", user=user) try: > msd_id = elog.post(text) tests/test_utils_elog.py:55: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ slic/utils/elog.py:16: in post return self._log.post(*args, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:307: in post self._check_if_message_on_server(msg_id) # raises exceptions if no message or no response from server _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <elog.logbook.Logbook object at 0x7feb05e26fd0>, msg_id = None timeout = None def _check_if_message_on_server(self, msg_id, timeout=None): """Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no such message. :param msg_id: ID of message to be checked :params timeout: The value of timeout to be passed to the get request :return: """ request_headers = dict() if self._user or self._password: request_headers['Cookie'] = self._make_user_and_pswd_cookie() try: response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False, verify=False, timeout=timeout) # If there is no message code 200 will be returned (OK) and _validate_response will not recognise it # but there will be some error in the html code. resp_message, resp_headers, resp_msg_id = _validate_response(response) # If there is no message, code 200 will be returned (OK) but there will be some error indication in # the html code. if re.findall('<td.*?class="errormsg".*?>.*?</td>', resp_message.decode('utf-8', 'ignore'), flags=re.DOTALL): raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.') except requests.Timeout as e: # Catch here a timeout o the post request. # Raise the logbook exception and let the user handle it raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\n' + '{1}'.format(sys._getframe().f_code.co_name, e)) except requests.RequestException as e: > raise LogbookServerProblem('No response from the logbook server.\nDetails: ' + '{0}'.format(e)) E elog.logbook_exceptions.LogbookServerProblem: No response from the logbook server. E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:601: LogbookServerProblem During handling of the above exception, another exception occurred: mock_home = <MagicMock name='home' id='140647452478240'> mock_getpass = <MagicMock name='getpass' id='140647452477088'> @patch("slic.utils.elog.getpass") @patch("slic.utils.elog.Path.home") def test_get_default_elog_instance_asks_password_and_opens(mock_home, mock_getpass): mock_home.return_value = Path("/does/not/exist") # Fausse home → lecture échoue mock_getpass.return_value = "testpassword" user = "robot" text = "This is a message2" url = "http://localhost:8080/demo" elog = Elog("http://localhost:8080/demo", user=user) try: msd_id = elog.post(text) except Exception as e: > pytest.fail(f"elog.post() raised an unexpected exception: {e}") E Failed: elog.post() raised an unexpected exception: No response from the logbook server. E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098025b0>: Failed to establish a new connection: [Errno 111] Connection refused')) tests/test_utils_elog.py:57: Failed📌 Teardown phase
duration:
0.0003665182739496231outcome:
passed
↳ Function: test_get_default_elog_with_path_home
-
❌ Test 180
📌 Setup phase
duration:
0.00018758885562419891outcome:
passed📌 Call phase
duration:
0.009295018389821053outcome:
failedcrash:
path: /workspace/tligui_y/slic/tests/test_utils_elog.py lineno: 92 message: Failed: elog.post() raised an unexpected exception: No response from the logbook server. Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused'))traceback:
- path: tests/test_utils_elog.py lineno: 92 message: Failedlongrepr:
self = <urllib3.connection.HTTPConnection object at 0x7feb09937130> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection raise err _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ address = ('localhost', 8080), timeout = None, source_address = None socket_options = [(6, 1, 1)] def create_connection( address: tuple[str, int], timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, source_address: tuple[str, int] | None = None, socket_options: _TYPE_SOCKET_OPTIONS | None = None, ) -> socket.socket: """Connect to *address* and return the socket object. Convenience function. Connect to *address* (a 2-tuple ``(host, port)``) and return the socket object. Passing the optional *timeout* parameter will set the timeout on the socket instance before attempting to connect. If no *timeout* is supplied, the global default timeout setting returned by :func:`socket.getdefaulttimeout` is used. If *source_address* is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default. """ host, port = address if host.startswith("["): host = host.strip("[]") err = None # Using the value from allowed_gai_family() in the context of getaddrinfo lets # us select whether to work with IPv4 DNS records, IPv6 records, or both. # The original create_connection function always returns all records. family = allowed_gai_family() try: host.encode("idna") except UnicodeError: raise LocationParseError(f"'{host}', label empty or too long") from None for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res sock = None try: sock = socket.socket(af, socktype, proto) # If provided, set socket level options before connecting. _set_socket_options(sock, socket_options) if timeout is not _DEFAULT_TIMEOUT: sock.settimeout(timeout) if source_address: sock.bind(source_address) > sock.connect(sa) E ConnectionRefusedError: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError The above exception was the direct cause of the following exception: self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09937670> method = 'POST', url = '/demo/' body = b'--e76de29c11540daf53cb0ad4febce9b6\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--e76de29c11540d...Disposition: form-data; name="Text"; filename=""\r\n\r\nThis is a message3\r\n--e76de29c11540daf53cb0ad4febce9b6--\r\n' headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=e76de29c11540daf53cb0ad4febce9b6'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None) destination_scheme = None, conn = None, release_this_conn = True http_tunnel_required = False, err = None, clean_exit = False def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ parsed_url = parse_url(url) destination_scheme = parsed_url.scheme if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): url = to_str(_encode_target(url)) else: url = to_str(parsed_url.url) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] <https://github.com/urllib3/urllib3/issues/651> release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) try: # Request a connection from the queue. timeout_obj = self._get_timeout(timeout) conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request conn.request( /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request self.endheaders() /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders self._send_output(message_body, encode_chunked=encode_chunked) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output self.send(msg) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send self.connect() /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect self.sock = self._new_conn() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <urllib3.connection.HTTPConnection object at 0x7feb09937130> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: raise NameResolutionError(self.host, self, e) from e except SocketTimeout as e: raise ConnectTimeoutError( self, f"Connection to {self.host} timed out. (connect timeout={self.timeout})", ) from e except OSError as e: > raise NewConnectionError( self, f"Failed to establish a new connection: {e}" ) from e E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb09937130>: Failed to establish a new connection: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError The above exception was the direct cause of the following exception: self = <requests.adapters.HTTPAdapter object at 0x7feb09937850> request = <PreparedRequest [POST]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=False, redirect=None, status=None) method = 'POST', url = '/demo/', response = None error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09937130>: Failed to establish a new connection: [Errno 111] Connection refused') _pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09937670> _stacktrace = <traceback object at 0x7feb0965e740> def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09937130>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError During handling of the above exception, another exception occurred: self = <elog.logbook.Logbook object at 0x7feb09937280> message = 'This is a message3', msg_id = None, reply = False attributes = {'Author': 'robot', 'When': 1756376002, 'cmd': 'Submit', 'exp': 'demo', ...} attachments = [], suppress_email_notification = False, encoding = None timeout = None, kwargs = {'Author': 'robot'} new_attachment_list = [('Text', ('', b'This is a message3'))] objects_to_close = [] attributes_to_edit = {'Author': b'robot', 'When': 1756376002, 'cmd': b'Submit', 'exp': b'demo', ...} def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None, suppress_email_notification=False, encoding=None, timeout=None, **kwargs): """ Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id of the newly created message. :param message: string with message text :param msg_id: ID number of message to edit or reply. If not specified new message is created. :param reply: If 'True' reply to existing message is created instead of editing it :param attributes: Dictionary of attributes. Following attributes are used internally by the elog and will be ignored: Text, Date, Encoding, Reply to, In reply to, Locked by, Attachment :param attachments: list of: - file like objects which read() will return bytes (if file_like_object.name is not defined, default name "attachment<i>" will be used. - paths to the files All items will be appended as attachment to the elog entry. In case of unknown attachment an exception LogbookInvalidAttachment will be raised. :param suppress_email_notification: If set to True or 1, E-Mail notification will be suppressed, defaults to False. :param encoding: Defines encoding of the message. Can be: 'plain' -> plain text, 'html'->html-text, 'ELCode' --> elog formatting syntax :param timeout: Define the timeout to be used by the post request. Its value is directly passed to the requests post. Use None to disable the request timeout. :param kwargs: Anything in the kwargs will be interpreted as attribute. e.g.: logbook.post('Test text', Author='Rok Vintar), "Author" will be sent as an attribute. If named same as one of the attributes defined in "attributes", kwargs will have priority. :return: msg_id """ attributes = attributes or {} attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority attachments = attachments or [] if encoding is not None: if encoding not in ['plain', 'HTML', 'ELCode']: raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.') attributes['Encoding'] = encoding if suppress_email_notification: attributes["suppress"] = 1 # THE ATTACHMENT STRATEGY WHEN DEALING WITH POST MODIFICATION # # 1. Does the message on the server have already attachments? # 1.1 - We read the message getting the existing attachment list. # 1.2 - Add to the attributes dictionary one line for each attachment like this: # attributes['attachmentN'] = timestamped_filename_name # # 2. Do we have new attachments? # 2.1 - Those are in the new_attachment_list. This is a list of this type: # [ ('attfileN', ('filename', fileobject)) ] # 2.2 - We need to loop over all the new attachments: # 2.2.1 - Does a file already on the server with the same name exist? # 2.2.1.1 - No: OK. Then we go ahead with the next attachment. # 2.2.1.2 - Yes: # 2.2.1.2.1 - Are the two files identical? # 2.2.1.2.1.1 - Yes: then we remove this current entry from the new_attachment_list and we leave the one # already on server. # 2.2.1.2.1.2 - No: # 2.2.1.2.1.2.1 - Then the file has been update. # 2.2.1.2.1.2.2 - We need to remove the file on server first (using special post) # 2.2.1.2.1.2.3 - We have to remove the old attachment from the attributes dictionary. # if attachments: # here we accomplish point 2.1. # new_attachment_list is something like [ ('attfileN', ('filename', fileobject)) ] new_attachment_list, objects_to_close = self._prepare_attachments(attachments) else: objects_to_close = list() new_attachment_list = list() attributes_to_edit = dict() if msg_id: # Message exists, we can continue if reply: # Verify that there is a message on the server, otherwise do not reply to it! self._check_if_message_on_server(msg_id) # raises exception in case of none existing message attributes['reply_to'] = str(msg_id) else: # Edit existing attributes['edit_id'] = str(msg_id) attributes['skiplock'] = '1' # here we accomplish point 1.1. # existing_attachments_list is something like: # [ 'https://elog.url.com/logbook/timestamped_filename' ] msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id) for attribute, data in attributes.items(): new_data = attributes.get(attribute) if new_data is not None: attributes_to_edit[attribute] = new_data i = 0 existing_attachments_filename_list = list() for attachment in existing_attachments_list: # here we accomplish point 1.2. We strip the timestamped_filename from the whole URL. attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) existing_attachments_filename_list.append(os.path.basename(attachment)[14:]) i += 1 # let's accomplish 2.2. Loop over all new attachment duplicate_attachment_list = list() for new_attachment in new_attachment_list: # the new_attachment_list is something like: # [ ('attfileN', ('filename', fileobject)) ] new_attachment_filename = new_attachment[1][0] if new_attachment_filename in existing_attachments_filename_list: # a file with the same name existing already on the server. # we need to check if the two files are the same. # read the content of the new file new_attachment_content = new_attachment[1][1].read() # don't forget to reset the fileobj to the beginning of the file new_attachment[1][1].seek(0) # get the existing attachment content attachment_index = existing_attachments_filename_list.index(new_attachment_filename) existing_attachment_content = self.download_attachment( url=existing_attachments_list[attachment_index], timeout=timeout ) # check if the two contents are the same if new_attachment_content == existing_attachment_content: # yes. then we don't upload a second copy. we remove the current entry from the list duplicate_attachment_list.append(new_attachment) else: # no. they are not the same file. we will replace the existing file with the new one # first: we need to remove the attachment from the server using the dedicated method self.delete_attachment(msg_id, attributes=attributes_to_edit, attachment_id=attachment_index, timeout=timeout, text=msg_to_edit) # now we can remove this attachment from the auxiliary lists. existing_attachments_filename_list.pop(attachment_index) existing_attachments_list.pop(attachment_index) # now we need to rebuild the attributes dictionary for the part concerning the attachments. # we remove all of them first keys_to_be_removed = list() for key in attributes_to_edit.keys(): if key.startswith('attachment'): keys_to_be_removed.append(key) if key.startswith('delatt'): keys_to_be_removed.append(key) for key in keys_to_be_removed: del attributes_to_edit[key] # now we rebuild it for i, attachment in enumerate(existing_attachments_list): attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) # remove all duplicate attachments from the new_attachment_list for attach in duplicate_attachment_list: new_attachment_list.remove(attach) else: # As we create a new message, specify creation time if not already specified in attributes if 'When' not in attributes: attributes['When'] = int(datetime.now().timestamp()) if not attributes_to_edit: attributes_to_edit = attributes # Remove any attributes that should not be sent _remove_reserved_attributes(attributes_to_edit) # Make requests module think that Text is a "file". This is the only way to force requests to send data as # multipart/form-data even if there are no attachments. Elog understands only multipart/form-data new_attachment_list.append(('Text', ('', message.encode('iso-8859-1')))) # Base attributes are common to all messages self._add_base_msg_attributes(attributes_to_edit) # Keys in attributes cannot have certain characters like whitespaces or dashes for the http request attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit) # All string values in the attributes must be encoded in latin1 attributes_to_edit = _encode_values(attributes_to_edit) try: > response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list, allow_redirects=False, verify=False, timeout=timeout) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:288: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:115: in post return request("post", url, data=data, json=json, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request return session.request(method=method, url=url, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request resp = self.send(prep, **send_kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send r = adapter.send(request, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <requests.adapters.HTTPAdapter object at 0x7feb09937850> request = <PreparedRequest [POST]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09937130>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError During handling of the above exception, another exception occurred: self = <urllib3.connection.HTTPConnection object at 0x7feb098b2bb0> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection raise err _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ address = ('localhost', 8080), timeout = None, source_address = None socket_options = [(6, 1, 1)] def create_connection( address: tuple[str, int], timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, source_address: tuple[str, int] | None = None, socket_options: _TYPE_SOCKET_OPTIONS | None = None, ) -> socket.socket: """Connect to *address* and return the socket object. Convenience function. Connect to *address* (a 2-tuple ``(host, port)``) and return the socket object. Passing the optional *timeout* parameter will set the timeout on the socket instance before attempting to connect. If no *timeout* is supplied, the global default timeout setting returned by :func:`socket.getdefaulttimeout` is used. If *source_address* is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default. """ host, port = address if host.startswith("["): host = host.strip("[]") err = None # Using the value from allowed_gai_family() in the context of getaddrinfo lets # us select whether to work with IPv4 DNS records, IPv6 records, or both. # The original create_connection function always returns all records. family = allowed_gai_family() try: host.encode("idna") except UnicodeError: raise LocationParseError(f"'{host}', label empty or too long") from None for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res sock = None try: sock = socket.socket(af, socktype, proto) # If provided, set socket level options before connecting. _set_socket_options(sock, socket_options) if timeout is not _DEFAULT_TIMEOUT: sock.settimeout(timeout) if source_address: sock.bind(source_address) > sock.connect(sa) E ConnectionRefusedError: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError The above exception was the direct cause of the following exception: self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb098b2730> method = 'GET', url = '/demo/None', body = None headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None) destination_scheme = None, conn = None, release_this_conn = True http_tunnel_required = False, err = None, clean_exit = False def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ parsed_url = parse_url(url) destination_scheme = parsed_url.scheme if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): url = to_str(_encode_target(url)) else: url = to_str(parsed_url.url) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] <https://github.com/urllib3/urllib3/issues/651> release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) try: # Request a connection from the queue. timeout_obj = self._get_timeout(timeout) conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request conn.request( /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request self.endheaders() /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders self._send_output(message_body, encode_chunked=encode_chunked) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output self.send(msg) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send self.connect() /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect self.sock = self._new_conn() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <urllib3.connection.HTTPConnection object at 0x7feb098b2bb0> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: raise NameResolutionError(self.host, self, e) from e except SocketTimeout as e: raise ConnectTimeoutError( self, f"Connection to {self.host} timed out. (connect timeout={self.timeout})", ) from e except OSError as e: > raise NewConnectionError( self, f"Failed to establish a new connection: {e}" ) from e E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError The above exception was the direct cause of the following exception: self = <requests.adapters.HTTPAdapter object at 0x7feb098b25b0> request = <PreparedRequest [GET]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=False, redirect=None, status=None) method = 'GET', url = '/demo/None', response = None error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused') _pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb098b2730> _stacktrace = <traceback object at 0x7feb097c29c0> def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError During handling of the above exception, another exception occurred: self = <elog.logbook.Logbook object at 0x7feb09937280>, msg_id = None timeout = None def _check_if_message_on_server(self, msg_id, timeout=None): """Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no such message. :param msg_id: ID of message to be checked :params timeout: The value of timeout to be passed to the get request :return: """ request_headers = dict() if self._user or self._password: request_headers['Cookie'] = self._make_user_and_pswd_cookie() try: > response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False, verify=False, timeout=timeout) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:581: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:73: in get return request("get", url, params=params, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request return session.request(method=method, url=url, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request resp = self.send(prep, **send_kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send r = adapter.send(request, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <requests.adapters.HTTPAdapter object at 0x7feb098b25b0> request = <PreparedRequest [GET]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError During handling of the above exception, another exception occurred: mock_home = <MagicMock name='home' id='140647451303744'> mock_getuser = <MagicMock name='getuser' id='140647451733824'> mock_getpass = <MagicMock name='getpass' id='140647453841488'> @patch("slic.utils.elog.getpass") @patch("slic.utils.elog.getuser") @patch("slic.utils.elog.Path.home") def test_get_default_elog_with_path_home(mock_home, mock_getuser, mock_getpass): fake_user = "robot" fake_pw = "testpassword" mock_getuser.return_value = fake_user mock_getpass.return_value = fake_pw # fallback safety text = "This is a message3" url = "http://localhost:8080/demo" tmp_home = Path("/tmp/fake_home_for_robot") tmp_home.mkdir(parents=True, exist_ok=True) pw_file = tmp_home / ".elog_psi" pw_file.write_text(fake_pw) mock_home.return_value = tmp_home try: elog = Elog("http://localhost:8080/demo") try: > msg_id = elog.post(text) tests/test_utils_elog.py:90: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ slic/utils/elog.py:16: in post return self._log.post(*args, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:307: in post self._check_if_message_on_server(msg_id) # raises exceptions if no message or no response from server _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <elog.logbook.Logbook object at 0x7feb09937280>, msg_id = None timeout = None def _check_if_message_on_server(self, msg_id, timeout=None): """Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no such message. :param msg_id: ID of message to be checked :params timeout: The value of timeout to be passed to the get request :return: """ request_headers = dict() if self._user or self._password: request_headers['Cookie'] = self._make_user_and_pswd_cookie() try: response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False, verify=False, timeout=timeout) # If there is no message code 200 will be returned (OK) and _validate_response will not recognise it # but there will be some error in the html code. resp_message, resp_headers, resp_msg_id = _validate_response(response) # If there is no message, code 200 will be returned (OK) but there will be some error indication in # the html code. if re.findall('<td.*?class="errormsg".*?>.*?</td>', resp_message.decode('utf-8', 'ignore'), flags=re.DOTALL): raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.') except requests.Timeout as e: # Catch here a timeout o the post request. # Raise the logbook exception and let the user handle it raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\n' + '{1}'.format(sys._getframe().f_code.co_name, e)) except requests.RequestException as e: > raise LogbookServerProblem('No response from the logbook server.\nDetails: ' + '{0}'.format(e)) E elog.logbook_exceptions.LogbookServerProblem: No response from the logbook server. E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:601: LogbookServerProblem During handling of the above exception, another exception occurred: mock_home = <MagicMock name='home' id='140647451303744'> mock_getuser = <MagicMock name='getuser' id='140647451733824'> mock_getpass = <MagicMock name='getpass' id='140647453841488'> @patch("slic.utils.elog.getpass") @patch("slic.utils.elog.getuser") @patch("slic.utils.elog.Path.home") def test_get_default_elog_with_path_home(mock_home, mock_getuser, mock_getpass): fake_user = "robot" fake_pw = "testpassword" mock_getuser.return_value = fake_user mock_getpass.return_value = fake_pw # fallback safety text = "This is a message3" url = "http://localhost:8080/demo" tmp_home = Path("/tmp/fake_home_for_robot") tmp_home.mkdir(parents=True, exist_ok=True) pw_file = tmp_home / ".elog_psi" pw_file.write_text(fake_pw) mock_home.return_value = tmp_home try: elog = Elog("http://localhost:8080/demo") try: msg_id = elog.post(text) except Exception as e: > pytest.fail(f"elog.post() raised an unexpected exception: {e}") E Failed: elog.post() raised an unexpected exception: No response from the logbook server. E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb098b2bb0>: Failed to establish a new connection: [Errno 111] Connection refused')) tests/test_utils_elog.py:92: Failed📌 Teardown phase
duration:
0.00034400075674057007outcome:
passed
↳ Function: test_screenshot
-
❌ Test 181
📌 Setup phase
duration:
0.00019518006592988968outcome:
passed📌 Call phase
duration:
0.010428791865706444outcome:
failedcrash:
path: /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py lineno: 601 message: elog.logbook_exceptions.LogbookServerProblem: No response from the logbook server. Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused'))traceback:
- path: tests/test_utils_elog.py lineno: 116 message: [] - path: slic/utils/elog.py lineno: 21 message: in screenshot - path: slic/utils/elog.py lineno: 16 message: in post - path: /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py lineno: 307 message: in post - path: /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py lineno: 601 message: LogbookServerProblemlongrepr:
self = <urllib3.connection.HTTPConnection object at 0x7feb0958cb20> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection raise err _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ address = ('localhost', 8080), timeout = None, source_address = None socket_options = [(6, 1, 1)] def create_connection( address: tuple[str, int], timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, source_address: tuple[str, int] | None = None, socket_options: _TYPE_SOCKET_OPTIONS | None = None, ) -> socket.socket: """Connect to *address* and return the socket object. Convenience function. Connect to *address* (a 2-tuple ``(host, port)``) and return the socket object. Passing the optional *timeout* parameter will set the timeout on the socket instance before attempting to connect. If no *timeout* is supplied, the global default timeout setting returned by :func:`socket.getdefaulttimeout` is used. If *source_address* is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default. """ host, port = address if host.startswith("["): host = host.strip("[]") err = None # Using the value from allowed_gai_family() in the context of getaddrinfo lets # us select whether to work with IPv4 DNS records, IPv6 records, or both. # The original create_connection function always returns all records. family = allowed_gai_family() try: host.encode("idna") except UnicodeError: raise LocationParseError(f"'{host}', label empty or too long") from None for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res sock = None try: sock = socket.socket(af, socktype, proto) # If provided, set socket level options before connecting. _set_socket_options(sock, socket_options) if timeout is not _DEFAULT_TIMEOUT: sock.settimeout(timeout) if source_address: sock.bind(source_address) > sock.connect(sa) E ConnectionRefusedError: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError The above exception was the direct cause of the following exception: self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb0977c0a0> method = 'POST', url = '/demo/' body = b'--1194c6bfc5b78a946fff64f5d06636c0\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--1194c6bfc5b78a...-data; name="Text"; filename=""\r\n\r\nSCREENSHOT_INTEGRATION_TEST_MSG_456\r\n--1194c6bfc5b78a946fff64f5d06636c0--\r\n' headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '889', 'Content-Type': 'multipart/form-data; boundary=1194c6bfc5b78a946fff64f5d06636c0'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None) destination_scheme = None, conn = None, release_this_conn = True http_tunnel_required = False, err = None, clean_exit = False def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ parsed_url = parse_url(url) destination_scheme = parsed_url.scheme if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): url = to_str(_encode_target(url)) else: url = to_str(parsed_url.url) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] <https://github.com/urllib3/urllib3/issues/651> release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) try: # Request a connection from the queue. timeout_obj = self._get_timeout(timeout) conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request conn.request( /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request self.endheaders() /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders self._send_output(message_body, encode_chunked=encode_chunked) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output self.send(msg) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send self.connect() /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect self.sock = self._new_conn() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <urllib3.connection.HTTPConnection object at 0x7feb0958cb20> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: raise NameResolutionError(self.host, self, e) from e except SocketTimeout as e: raise ConnectTimeoutError( self, f"Connection to {self.host} timed out. (connect timeout={self.timeout})", ) from e except OSError as e: > raise NewConnectionError( self, f"Failed to establish a new connection: {e}" ) from e E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb0958cb20>: Failed to establish a new connection: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError The above exception was the direct cause of the following exception: self = <requests.adapters.HTTPAdapter object at 0x7feb0958c490> request = <PreparedRequest [POST]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=False, redirect=None, status=None) method = 'POST', url = '/demo/', response = None error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb0958cb20>: Failed to establish a new connection: [Errno 111] Connection refused') _pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb0977c0a0> _stacktrace = <traceback object at 0x7feb09808600> def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb0958cb20>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError During handling of the above exception, another exception occurred: self = <elog.logbook.Logbook object at 0x7feb0977c5b0> message = 'SCREENSHOT_INTEGRATION_TEST_MSG_456', msg_id = None, reply = False attributes = {'Author': 'robot', 'When': 1756376002, 'cmd': 'Submit', 'exp': 'demo', ...} attachments = ['/tmp/fake_screenshot.png'], suppress_email_notification = False encoding = None, timeout = None, kwargs = {'Author': 'robot'} new_attachment_list = [('attfile0', ('fake_screenshot.png', <_io.BufferedReader name='/tmp/fake_screenshot.png'>)), ('Text', ('', b'SCREENSHOT_INTEGRATION_TEST_MSG_456'))] objects_to_close = [<_io.BufferedReader name='/tmp/fake_screenshot.png'>] attributes_to_edit = {'Author': b'robot', 'When': 1756376002, 'cmd': b'Submit', 'exp': b'demo', ...} def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None, suppress_email_notification=False, encoding=None, timeout=None, **kwargs): """ Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id of the newly created message. :param message: string with message text :param msg_id: ID number of message to edit or reply. If not specified new message is created. :param reply: If 'True' reply to existing message is created instead of editing it :param attributes: Dictionary of attributes. Following attributes are used internally by the elog and will be ignored: Text, Date, Encoding, Reply to, In reply to, Locked by, Attachment :param attachments: list of: - file like objects which read() will return bytes (if file_like_object.name is not defined, default name "attachment<i>" will be used. - paths to the files All items will be appended as attachment to the elog entry. In case of unknown attachment an exception LogbookInvalidAttachment will be raised. :param suppress_email_notification: If set to True or 1, E-Mail notification will be suppressed, defaults to False. :param encoding: Defines encoding of the message. Can be: 'plain' -> plain text, 'html'->html-text, 'ELCode' --> elog formatting syntax :param timeout: Define the timeout to be used by the post request. Its value is directly passed to the requests post. Use None to disable the request timeout. :param kwargs: Anything in the kwargs will be interpreted as attribute. e.g.: logbook.post('Test text', Author='Rok Vintar), "Author" will be sent as an attribute. If named same as one of the attributes defined in "attributes", kwargs will have priority. :return: msg_id """ attributes = attributes or {} attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority attachments = attachments or [] if encoding is not None: if encoding not in ['plain', 'HTML', 'ELCode']: raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.') attributes['Encoding'] = encoding if suppress_email_notification: attributes["suppress"] = 1 # THE ATTACHMENT STRATEGY WHEN DEALING WITH POST MODIFICATION # # 1. Does the message on the server have already attachments? # 1.1 - We read the message getting the existing attachment list. # 1.2 - Add to the attributes dictionary one line for each attachment like this: # attributes['attachmentN'] = timestamped_filename_name # # 2. Do we have new attachments? # 2.1 - Those are in the new_attachment_list. This is a list of this type: # [ ('attfileN', ('filename', fileobject)) ] # 2.2 - We need to loop over all the new attachments: # 2.2.1 - Does a file already on the server with the same name exist? # 2.2.1.1 - No: OK. Then we go ahead with the next attachment. # 2.2.1.2 - Yes: # 2.2.1.2.1 - Are the two files identical? # 2.2.1.2.1.1 - Yes: then we remove this current entry from the new_attachment_list and we leave the one # already on server. # 2.2.1.2.1.2 - No: # 2.2.1.2.1.2.1 - Then the file has been update. # 2.2.1.2.1.2.2 - We need to remove the file on server first (using special post) # 2.2.1.2.1.2.3 - We have to remove the old attachment from the attributes dictionary. # if attachments: # here we accomplish point 2.1. # new_attachment_list is something like [ ('attfileN', ('filename', fileobject)) ] new_attachment_list, objects_to_close = self._prepare_attachments(attachments) else: objects_to_close = list() new_attachment_list = list() attributes_to_edit = dict() if msg_id: # Message exists, we can continue if reply: # Verify that there is a message on the server, otherwise do not reply to it! self._check_if_message_on_server(msg_id) # raises exception in case of none existing message attributes['reply_to'] = str(msg_id) else: # Edit existing attributes['edit_id'] = str(msg_id) attributes['skiplock'] = '1' # here we accomplish point 1.1. # existing_attachments_list is something like: # [ 'https://elog.url.com/logbook/timestamped_filename' ] msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id) for attribute, data in attributes.items(): new_data = attributes.get(attribute) if new_data is not None: attributes_to_edit[attribute] = new_data i = 0 existing_attachments_filename_list = list() for attachment in existing_attachments_list: # here we accomplish point 1.2. We strip the timestamped_filename from the whole URL. attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) existing_attachments_filename_list.append(os.path.basename(attachment)[14:]) i += 1 # let's accomplish 2.2. Loop over all new attachment duplicate_attachment_list = list() for new_attachment in new_attachment_list: # the new_attachment_list is something like: # [ ('attfileN', ('filename', fileobject)) ] new_attachment_filename = new_attachment[1][0] if new_attachment_filename in existing_attachments_filename_list: # a file with the same name existing already on the server. # we need to check if the two files are the same. # read the content of the new file new_attachment_content = new_attachment[1][1].read() # don't forget to reset the fileobj to the beginning of the file new_attachment[1][1].seek(0) # get the existing attachment content attachment_index = existing_attachments_filename_list.index(new_attachment_filename) existing_attachment_content = self.download_attachment( url=existing_attachments_list[attachment_index], timeout=timeout ) # check if the two contents are the same if new_attachment_content == existing_attachment_content: # yes. then we don't upload a second copy. we remove the current entry from the list duplicate_attachment_list.append(new_attachment) else: # no. they are not the same file. we will replace the existing file with the new one # first: we need to remove the attachment from the server using the dedicated method self.delete_attachment(msg_id, attributes=attributes_to_edit, attachment_id=attachment_index, timeout=timeout, text=msg_to_edit) # now we can remove this attachment from the auxiliary lists. existing_attachments_filename_list.pop(attachment_index) existing_attachments_list.pop(attachment_index) # now we need to rebuild the attributes dictionary for the part concerning the attachments. # we remove all of them first keys_to_be_removed = list() for key in attributes_to_edit.keys(): if key.startswith('attachment'): keys_to_be_removed.append(key) if key.startswith('delatt'): keys_to_be_removed.append(key) for key in keys_to_be_removed: del attributes_to_edit[key] # now we rebuild it for i, attachment in enumerate(existing_attachments_list): attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) # remove all duplicate attachments from the new_attachment_list for attach in duplicate_attachment_list: new_attachment_list.remove(attach) else: # As we create a new message, specify creation time if not already specified in attributes if 'When' not in attributes: attributes['When'] = int(datetime.now().timestamp()) if not attributes_to_edit: attributes_to_edit = attributes # Remove any attributes that should not be sent _remove_reserved_attributes(attributes_to_edit) # Make requests module think that Text is a "file". This is the only way to force requests to send data as # multipart/form-data even if there are no attachments. Elog understands only multipart/form-data new_attachment_list.append(('Text', ('', message.encode('iso-8859-1')))) # Base attributes are common to all messages self._add_base_msg_attributes(attributes_to_edit) # Keys in attributes cannot have certain characters like whitespaces or dashes for the http request attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit) # All string values in the attributes must be encoded in latin1 attributes_to_edit = _encode_values(attributes_to_edit) try: > response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list, allow_redirects=False, verify=False, timeout=timeout) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:288: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:115: in post return request("post", url, data=data, json=json, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request return session.request(method=method, url=url, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request resp = self.send(prep, **send_kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send r = adapter.send(request, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <requests.adapters.HTTPAdapter object at 0x7feb0958c490> request = <PreparedRequest [POST]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb0958cb20>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError During handling of the above exception, another exception occurred: self = <urllib3.connection.HTTPConnection object at 0x7feb09b7ea60> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: > sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:199: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection raise err _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ address = ('localhost', 8080), timeout = None, source_address = None socket_options = [(6, 1, 1)] def create_connection( address: tuple[str, int], timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, source_address: tuple[str, int] | None = None, socket_options: _TYPE_SOCKET_OPTIONS | None = None, ) -> socket.socket: """Connect to *address* and return the socket object. Convenience function. Connect to *address* (a 2-tuple ``(host, port)``) and return the socket object. Passing the optional *timeout* parameter will set the timeout on the socket instance before attempting to connect. If no *timeout* is supplied, the global default timeout setting returned by :func:`socket.getdefaulttimeout` is used. If *source_address* is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default. """ host, port = address if host.startswith("["): host = host.strip("[]") err = None # Using the value from allowed_gai_family() in the context of getaddrinfo lets # us select whether to work with IPv4 DNS records, IPv6 records, or both. # The original create_connection function always returns all records. family = allowed_gai_family() try: host.encode("idna") except UnicodeError: raise LocationParseError(f"'{host}', label empty or too long") from None for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res sock = None try: sock = socket.socket(af, socktype, proto) # If provided, set socket level options before connecting. _set_socket_options(sock, socket_options) if timeout is not _DEFAULT_TIMEOUT: sock.settimeout(timeout) if source_address: sock.bind(source_address) > sock.connect(sa) E ConnectionRefusedError: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError The above exception was the direct cause of the following exception: self = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b7e640> method = 'GET', url = '/demo/None', body = None headers = {'User-Agent': 'python-requests/2.32.4', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None) destination_scheme = None, conn = None, release_this_conn = True http_tunnel_required = False, err = None, clean_exit = False def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param bool preload_content: If True, the response's body will be preloaded into memory. :param bool decode_content: If True, will attempt to decode the body based on the 'content-encoding' header. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ parsed_url = parse_url(url) destination_scheme = parsed_url.scheme if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): url = to_str(_encode_target(url)) else: url = to_str(parsed_url.url) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] <https://github.com/urllib3/urllib3/issues/651> release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) try: # Request a connection from the queue. timeout_obj = self._get_timeout(timeout) conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:789: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request conn.request( /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:441: in request self.endheaders() /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1251: in endheaders self._send_output(message_body, encode_chunked=encode_chunked) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:1011: in _send_output self.send(msg) /root/mambaforge/envs/ci-env/lib/python3.8/http/client.py:951: in send self.connect() /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:279: in connect self.sock = self._new_conn() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <urllib3.connection.HTTPConnection object at 0x7feb09b7ea60> def _new_conn(self) -> socket.socket: """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ try: sock = connection.create_connection( (self._dns_host, self.port), self.timeout, source_address=self.source_address, socket_options=self.socket_options, ) except socket.gaierror as e: raise NameResolutionError(self.host, self, e) from e except SocketTimeout as e: raise ConnectTimeoutError( self, f"Connection to {self.host} timed out. (connect timeout={self.timeout})", ) from e except OSError as e: > raise NewConnectionError( self, f"Failed to establish a new connection: {e}" ) from e E urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError The above exception was the direct cause of the following exception: self = <requests.adapters.HTTPAdapter object at 0x7feb09b7eaf0> request = <PreparedRequest [GET]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:667: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=False, redirect=None, status=None) method = 'GET', url = '/demo/None', response = None error = NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused') _pool = <urllib3.connectionpool.HTTPConnectionPool object at 0x7feb09b7e640> _stacktrace = <traceback object at 0x7feb09906780> def increment( self, method: str | None = None, url: str | None = None, response: BaseHTTPResponse | None = None, error: Exception | None = None, _pool: ConnectionPool | None = None, _stacktrace: TracebackType | None = None, ) -> Self: """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.BaseHTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or method is None or not self._is_method_retryable(method): raise reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" response_redirect_location = response.get_redirect_location() if response_redirect_location: redirect_location = response_redirect_location status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): reason = error or ResponseError(cause) > raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] E urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError During handling of the above exception, another exception occurred: self = <elog.logbook.Logbook object at 0x7feb0977c5b0>, msg_id = None timeout = None def _check_if_message_on_server(self, msg_id, timeout=None): """Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no such message. :param msg_id: ID of message to be checked :params timeout: The value of timeout to be passed to the get request :return: """ request_headers = dict() if self._user or self._password: request_headers['Cookie'] = self._make_user_and_pswd_cookie() try: > response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False, verify=False, timeout=timeout) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:581: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:73: in get return request("get", url, params=params, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/api.py:59: in request return session.request(method=method, url=url, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:589: in request resp = self.send(prep, **send_kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/sessions.py:703: in send r = adapter.send(request, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <requests.adapters.HTTPAdapter object at 0x7feb09b7eaf0> request = <PreparedRequest [GET]>, stream = False timeout = Timeout(connect=None, read=None, total=None), verify = False cert = None, proxies = OrderedDict() def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError During handling of the above exception, another exception occurred: mock_screenshot_class = <MagicMock name='Screenshot' id='140647452388896'> @patch("slic.utils.elog.Screenshot") def test_screenshot(mock_screenshot_class): fake_path = "/tmp/fake_screenshot.png" with open(fake_path, "wb") as f: f.write(b"fake image data") mock_instance = mock_screenshot_class.return_value mock_instance.shoot.return_value = [fake_path] elog = Elog("http://localhost:8080/demo", user="robot", password="testpassword") test_msg = "SCREENSHOT_INTEGRATION_TEST_MSG_456" > msg_id = elog.screenshot(message=test_msg) tests/test_utils_elog.py:116: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ slic/utils/elog.py:21: in screenshot return self.post(message, **kwargs) slic/utils/elog.py:16: in post return self._log.post(*args, **kwargs) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:307: in post self._check_if_message_on_server(msg_id) # raises exceptions if no message or no response from server _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <elog.logbook.Logbook object at 0x7feb0977c5b0>, msg_id = None timeout = None def _check_if_message_on_server(self, msg_id, timeout=None): """Try to load page for specific message. If there is a html tag like <td class="errormsg"> then there is no such message. :param msg_id: ID of message to be checked :params timeout: The value of timeout to be passed to the get request :return: """ request_headers = dict() if self._user or self._password: request_headers['Cookie'] = self._make_user_and_pswd_cookie() try: response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False, verify=False, timeout=timeout) # If there is no message code 200 will be returned (OK) and _validate_response will not recognise it # but there will be some error in the html code. resp_message, resp_headers, resp_msg_id = _validate_response(response) # If there is no message, code 200 will be returned (OK) but there will be some error indication in # the html code. if re.findall('<td.*?class="errormsg".*?>.*?</td>', resp_message.decode('utf-8', 'ignore'), flags=re.DOTALL): raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.') except requests.Timeout as e: # Catch here a timeout o the post request. # Raise the logbook exception and let the user handle it raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\n' + '{1}'.format(sys._getframe().f_code.co_name, e)) except requests.RequestException as e: > raise LogbookServerProblem('No response from the logbook server.\nDetails: ' + '{0}'.format(e)) E elog.logbook_exceptions.LogbookServerProblem: No response from the logbook server. E Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7feb09b7ea60>: Failed to establish a new connection: [Errno 111] Connection refused')) /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/elog/logbook.py:601: LogbookServerProblem📌 Teardown phase
duration:
0.00040868669748306274outcome:
passed
-
-
📄 test_utils_get_adj.py
↳ Function: test_get_adjs_filter
-
❌ Test 233
📌 Setup phase
duration:
0.0001723961904644966outcome:
passed📌 Call phase
duration:
0.0013879667967557907outcome:
failedcrash:
path: /workspace/tligui_y/slic/tests/test_utils_get_adj.py lineno: 42 message: AssertionError: assert {'contrast', ...mid_contrast'} == {'brightness'...mid_contrast'} Extra items in the right set: 'brightness' Full diff: { - 'brightness', 'contrast', 'mid_brightness', 'mid_contrast', }traceback:
- path: tests/test_utils_get_adj.py lineno: 42 message: AssertionErrorlongrepr:
def test_get_adjs_filter(): a4 = SubAdjustable("mid_brightness", units="%", limit_low=0, limit_high=100) a5 = SubAdjustable("debug_internal", internal=True) public = get_adjs() > assert set(public) == {'brightness', 'contrast', 'mid_contrast', 'mid_brightness'} E AssertionError: assert {'contrast', ...mid_contrast'} == {'brightness'...mid_contrast'} E E Extra items in the right set: E 'brightness' E E Full diff: E { E - 'brightness', E 'contrast', E 'mid_brightness', E 'mid_contrast', E } tests/test_utils_get_adj.py:42: AssertionError📌 Teardown phase
duration:
0.00019770953804254532outcome:
passed
-
-
📄 test_utils_logcfg.py
↳ Function: test_import_logging_once_per_module
-
❌ Test 246
📌 Setup phase
duration:
0.00018928758800029755outcome:
passed📌 Call phase
duration:
1.7560598272830248outcome:
failedcrash:
path: /workspace/tligui_y/slic/tests/test_utils_logcfg.py lineno: 78 message: AssertionError: Expected 1 import log for 'math', found 0 assert 0 == 1traceback:
- path: tests/test_utils_logcfg.py lineno: 78 message: AssertionErrorstdout:
[E 250828 10:15:55 tools:40] cannot assign endstation to IP 172.18.0.3 (038eaf845eac)longrepr:
def test_import_logging_once_per_module(): code = textwrap.dedent(""" from slic.utils.logcfg import * import math import io import random """) with tempfile.NamedTemporaryFile("w", suffix=".py", delete=False) as tmp: tmp.write(code) tmp_path = tmp.name env = os.environ.copy() root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) env["PYTHONPATH"] = root_path + os.pathsep + env.get("PYTHONPATH", "") result = subprocess.run([sys.executable, tmp_path], capture_output=True, text=True, env=env) os.remove(tmp_path) assert result.returncode == 0, f"Script failed:\n{result.stderr}" stderr = result.stderr print(stderr) lines = stderr.splitlines() for mod in ["math", "io", "random"]: count = sum(1 for line in lines if f"importing: {mod}" in line) > assert count == 1, f"Expected 1 import log for '{mod}', found {count}" E AssertionError: Expected 1 import log for 'math', found 0 E assert 0 == 1 tests/test_utils_logcfg.py:78: AssertionError📌 Teardown phase
duration:
0.0004467582330107689outcome:
passed
-
-
📄 test_utils_shortcut.py
↳ Function: TestShortcutsSingleton
-
❌ Test 454
📌 Setup phase
duration:
0.0002901945263147354outcome:
passed📌 Call phase
duration:
0.0007099341601133347outcome:
failedcrash:
path: /workspace/tligui_y/slic/tests/test_utils_shortcut.py lineno: 138 message: assert 3 == 2 + where 3 = len({'<lambda>': Shortcut "<lambda>", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB"}) + where {'<lambda>': Shortcut "<lambda>", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB"} = _get() + where _get = <lambda>: Shortcut "<lambda>"\nFuncA: Shortcut "FuncA"\nFuncB: Shortcut "FuncB"\n._gettraceback:
- path: tests/test_utils_shortcut.py lineno: 138 message: AssertionErrorlongrepr:
self = <test_utils_shortcut.TestShortcutsSingleton object at 0x7feb09bdfee0> def test_registration(self): # Test automatic registration @as_shortcut(name="FuncA") def func_a(): pass @as_shortcut(name="FuncB") def func_b(): pass > assert len(shortcuts._get()) == 2 E assert 3 == 2 E + where 3 = len({'<lambda>': Shortcut "<lambda>", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB"}) E + where {'<lambda>': Shortcut "<lambda>", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB"} = _get() E + where _get = <lambda>: Shortcut "<lambda>"\nFuncA: Shortcut "FuncA"\nFuncB: Shortcut "FuncB"\n._get tests/test_utils_shortcut.py:138: AssertionError📌 Teardown phase
duration:
0.0002776775509119034outcome:
passed
↳ Function: TestFullIntegration
-
❌ Test 459
📌 Setup phase
duration:
0.00031516142189502716outcome:
passed📌 Call phase
duration:
0.0006153751164674759outcome:
failedcrash:
path: /workspace/tligui_y/slic/tests/test_utils_shortcut.py lineno: 203 message: assert 5 == 2 + where 5 = len({'<lambda>': Shortcut "<lambda>", 'First': Shortcut "First", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB", ...}) + where {'<lambda>': Shortcut "<lambda>", 'First': Shortcut "First", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB", ...} = _get() + where _get = <lambda>: Shortcut "<lambda>"\nFirst: Shortcut "First"\nFuncA: Shortcut "FuncA"\nFuncB: Shortcut "FuncB"\nSecond: Shortcut "Second"\n._gettraceback:
- path: tests/test_utils_shortcut.py lineno: 203 message: AssertionErrorlongrepr:
self = <test_utils_shortcut.TestFullIntegration object at 0x7feb09cdfcd0> def test_multiple_shortcuts(self): # Test multiple shortcuts coexistence @as_shortcut(name="First") def first(): return 1 @as_shortcut(name="Second") def second(): return 2 assert shortcuts["First"].func() == 1 assert shortcuts["Second"].func() == 2 > assert len(shortcuts._get()) == 2 E assert 5 == 2 E + where 5 = len({'<lambda>': Shortcut "<lambda>", 'First': Shortcut "First", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB", ...}) E + where {'<lambda>': Shortcut "<lambda>", 'First': Shortcut "First", 'FuncA': Shortcut "FuncA", 'FuncB': Shortcut "FuncB", ...} = _get() E + where _get = <lambda>: Shortcut "<lambda>"\nFirst: Shortcut "First"\nFuncA: Shortcut "FuncA"\nFuncB: Shortcut "FuncB"\nSecond: Shortcut "Second"\n._get tests/test_utils_shortcut.py:203: AssertionError📌 Teardown phase
duration:
0.00031558703631162643outcome:
passed
-
-
📄 test_utils_tqdm_mod.py
↳ Function: test_float_alignment_in_bar
-
❌ Test 473
📌 Setup phase
duration:
0.00017123576253652573outcome:
passed📌 Call phase
duration:
0.0033523766323924065outcome:
failedcrash:
path: /workspace/tligui_y/slic/tests/test_utils_tqdm_mod.py lineno: 130 message: assert 3 == 1 + where 3 = len({50, 64, 65}) + where {50, 64, 65} = set([50, 64, 64, 65, 65])traceback:
- path: tests/test_utils_tqdm_mod.py lineno: 130 message: AssertionErrorstdout:
AlignBar: 0%| | 0/100.1 [00:00<?, ? Hz] AlignBar: 1%|1 | 1.3/100.1 [00:00<00:00, 57652.2 Hz] AlignBar: 12%|#2 | 12.5/100.1 [00:00<00:00, 81738.0 Hz] AlignBar: 100%|#########9| 99.9/100.1 [00:00<00:00, 420734.0 Hz] AlignBar: 100%|##########| 100.1/100.1 [00:00<00:00, 217807.9 Hz]longrepr:
def test_float_alignment_in_bar(): # Capture the tqdm output into a string buffer f = io.StringIO() with redirect_stdout(f): bar = tqdm_mod(total=100.12, desc="AlignBar", file=f, miniters=1, mininterval=0) bar.set(1.3333) bar.set(12.5) bar.set(99.89) bar.set(100.12) bar.close() # Extract lines containing the label lines = extract_lines(f.getvalue(), "AlignBar") # Expected formatted values using format_sizeof expected_values = [ "1.3/100.1", "12.5/100.1", "99.9/100.1", "100.1/100.1", ] # Extract the actual padded float/total strings from the full lines values = [] for line in lines: match = re.search(r"(\d{1,3}\.\d)/100\.1", line) if match: values.append(match.group(0)) # Ensure raw 100.12 never appears : format_sizeof must have truncated it assert all("100.12" not in line for line in lines), "Unrounded value '100.12' found in output!" # Check all expected values appear rounded as expected by format_sizeof for expected in expected_values: assert expected in values, f"Missing expected value: {expected}" # Check that all values are visually aligned, output with same length, to ensure that format_sizeof add the good number avec spaces print("\n") bar_segments = [] for line in lines: match = re.search(r".*?\]", line) if match: bar_segments.append(match.group(0)) print(match.group(0)) lengths = [len(seg) for seg in bar_segments] > assert len(set(lengths)) == 1 E assert 3 == 1 E + where 3 = len({50, 64, 65}) E + where {50, 64, 65} = set([50, 64, 64, 65, 65]) tests/test_utils_tqdm_mod.py:130: AssertionError📌 Teardown phase
duration:
0.00024230685085058212outcome:
passed
-
📚 Collected files
✅ (1 tests)
-
✅
- Outcome:
passed - result:
- nodeid: . type: Dir - Outcome:
✅ ci-reports (13 tests)
-
✅ ci-reports
- Outcome:
passed - result:
- nodeid: ci-reports/allure type: Dir - nodeid: ci-reports/junit type: Dir - nodeid: ci-reports/markdown type: Dir-
✅ ci-reports/allure
- Outcome:
passed - result:
- nodeid: ci-reports/allure/data type: Dir - nodeid: ci-reports/allure/export type: Dir - nodeid: ci-reports/allure/history type: Dir - nodeid: ci-reports/allure/plugin type: Dir - nodeid: ci-reports/allure/widgets type: Dir - Outcome:
-
✅ ci-reports/allure/data
- Outcome:
passed - result:
- nodeid: ci-reports/allure/data/test-cases type: Dir - Outcome:
-
✅ ci-reports/allure/data/test-cases
- Outcome:
passed - result:
[] - Outcome:
-
✅ ci-reports/allure/export
- Outcome:
passed - result:
[] - Outcome:
-
✅ ci-reports/allure/history
- Outcome:
passed - result:
[] - Outcome:
-
✅ ci-reports/allure/plugin
- Outcome:
passed - result:
- nodeid: ci-reports/allure/plugin/behaviors type: Dir - nodeid: ci-reports/allure/plugin/packages type: Dir - nodeid: ci-reports/allure/plugin/screen-diff type: Dir - Outcome:
-
✅ ci-reports/allure/plugin/behaviors
- Outcome:
passed - result:
[] - Outcome:
-
✅ ci-reports/allure/plugin/packages
- Outcome:
passed - result:
[] - Outcome:
-
✅ ci-reports/allure/plugin/screen-diff
- Outcome:
passed - result:
[] - Outcome:
-
✅ ci-reports/allure/widgets
- Outcome:
passed - result:
[] - Outcome:
-
✅ ci-reports/junit
- Outcome:
passed - result:
[] - Outcome:
-
✅ ci-reports/markdown
- Outcome:
passed - result:
[] - Outcome:
- Outcome:
✅ markdown (1 tests)
-
✅ markdown
- Outcome:
passed - result:
[] - Outcome:
✅ morbidissimo (6 tests)
-
✅ morbidissimo
- Outcome:
passed - result:
- nodeid: morbidissimo/morbidissimo type: Package-
✅ morbidissimo/morbidissimo
- Outcome:
passed - result:
- nodeid: morbidissimo/morbidissimo/modman type: Package - nodeid: morbidissimo/morbidissimo/morioc type: Package - Outcome:
-
✅ morbidissimo/morbidissimo/modman
- Outcome:
passed - result:
- nodeid: morbidissimo/morbidissimo/modman/scripts type: Dir - Outcome:
-
✅ morbidissimo/morbidissimo/modman/scripts
- Outcome:
passed - result:
[] - Outcome:
-
✅ morbidissimo/morbidissimo/morioc
- Outcome:
passed - result:
- nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py type: Module - Outcome:
-
✅ morbidissimo/morbidissimo/morioc/test_infer_type.py
- Outcome:
passed - result:
- nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_type_str type: Function lineno: 14 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_type_float type: Function lineno: 17 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_type_int type: Function lineno: 20 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_value_str type: Function lineno: 24 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_value_long_str type: Function lineno: 27 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_value_float type: Function lineno: 32 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_value_int type: Function lineno: 35 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_empty_value_str type: Function lineno: 39 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_empty_value_float type: Function lineno: 42 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_empty_value_int type: Function lineno: 45 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_pstrue_str type: Function lineno: 49 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_pstrue_float type: Function lineno: 52 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_pstrue_int type: Function lineno: 55 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_psfalse_str type: Function lineno: 59 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_psfalse_float type: Function lineno: 62 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_psfalse_int type: Function lineno: 65 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_None type: Function lineno: 69 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_True type: Function lineno: 72 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_False type: Function lineno: 75 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_nan type: Function lineno: 78 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_np_nan type: Function lineno: 81 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_np1D_int type: Function lineno: 85 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_np2D_int type: Function lineno: 91 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_np1D_float type: Function lineno: 99 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_np2D_float type: Function lineno: 105 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_np1D_bool type: Function lineno: 114 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_np1D_object type: Function lineno: 119 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_np_scalar_int type: Function lineno: 126 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_np_scalar_float type: Function lineno: 131 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_np_scalar_bool type: Function lineno: 136 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_list type: Function lineno: 145 - nodeid: morbidissimo/morbidissimo/morioc/test_infer_type.py::test_it_tuple type: Function lineno: 150 - Outcome:
- Outcome:
✅ outputs (1 tests)
-
✅ outputs
- Outcome:
passed - result:
[] - Outcome:
✅ slic (30 tests)
-
✅ slic
- Outcome:
passed - result:
- nodeid: slic/core type: Package - nodeid: slic/devices type: Package - nodeid: slic/gui type: Package - nodeid: slic/utils type: Package-
✅ slic/core
- Outcome:
passed - result:
- nodeid: slic/core/acquisition type: Package - nodeid: slic/core/adjustable type: Package - nodeid: slic/core/condition type: Package - nodeid: slic/core/device type: Package - nodeid: slic/core/scanner type: Package - nodeid: slic/core/sensor type: Package - nodeid: slic/core/task type: Package - Outcome:
-
✅ slic/core/acquisition
- Outcome:
passed - result:
- nodeid: slic/core/acquisition/broker type: Package - Outcome:
-
✅ slic/core/acquisition/broker
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/core/adjustable
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/core/condition
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/core/device
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/core/scanner
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/core/sensor
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/core/task
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/devices
- Outcome:
passed - result:
- nodeid: slic/devices/cameras type: Package - nodeid: slic/devices/endstations type: Package - nodeid: slic/devices/general type: Package - nodeid: slic/devices/loptics type: Package - nodeid: slic/devices/timing type: Package - nodeid: slic/devices/xdiagnostics type: Package - nodeid: slic/devices/xoptics type: Package - Outcome:
-
✅ slic/devices/cameras
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/devices/endstations
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/devices/general
- Outcome:
passed - result:
- nodeid: slic/devices/general/detectors type: Package - nodeid: slic/devices/general/unused type: Dir - Outcome:
-
✅ slic/devices/general/detectors
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/devices/general/unused
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/devices/loptics
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/devices/timing
- Outcome:
passed - result:
- nodeid: slic/devices/timing/events type: Package - Outcome:
-
✅ slic/devices/timing/events
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/devices/xdiagnostics
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/devices/xoptics
- Outcome:
passed - result:
- nodeid: slic/devices/xoptics/slits type: Package - nodeid: slic/devices/xoptics/unused type: Dir - Outcome:
-
✅ slic/devices/xoptics/slits
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/devices/xoptics/unused
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/gui
- Outcome:
passed - result:
- nodeid: slic/gui/daqpanels type: Package - nodeid: slic/gui/widgets type: Package - Outcome:
-
✅ slic/gui/daqpanels
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/gui/widgets
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/utils
- Outcome:
passed - result:
- nodeid: slic/utils/ioc type: Package - nodeid: slic/utils/unused type: Dir - Outcome:
-
✅ slic/utils/ioc
- Outcome:
passed - result:
[] - Outcome:
-
✅ slic/utils/unused
- Outcome:
passed - result:
- nodeid: slic/utils/unused/xsim type: Package - Outcome:
-
✅ slic/utils/unused/xsim
- Outcome:
passed - result:
[] - Outcome:
- Outcome:
✅ temp-ci (1 tests)
-
✅ temp-ci
- Outcome:
passed - result:
[] - Outcome:
✅ test-ci (1 tests)
-
✅ test-ci
- Outcome:
passed - result:
[] - Outcome:
✅ tests (54 tests)
-
✅ tests
- Outcome:
passed - result:
- nodeid: tests/test_utils_argfwd.py type: Module - nodeid: tests/test_utils_ask_yes_no.py type: Module - nodeid: tests/test_utils_channels.py type: Module - nodeid: tests/test_utils_config.py type: Module - nodeid: tests/test_utils_cpint.py type: Module - nodeid: tests/test_utils_dbusnotify.py type: Module - nodeid: tests/test_utils_debug.py type: Module - nodeid: tests/test_utils_dictext.py type: Module - nodeid: tests/test_utils_dotdir.py type: Module - nodeid: tests/test_utils_duo.py type: Module - nodeid: tests/test_utils_elog.py type: Module - nodeid: tests/test_utils_eval.py type: Module - nodeid: tests/test_utils_exceptions.py type: Module - nodeid: tests/test_utils_get_adj.py type: Module - nodeid: tests/test_utils_hastepics.py type: Module - nodeid: tests/test_utils_ipy.py type: Module - nodeid: tests/test_utils_jsonext.py type: Module - nodeid: tests/test_utils_lazypv.py type: Module - nodeid: tests/test_utils_logcfg.py type: Module - nodeid: tests/test_utils_logign.py type: Module - nodeid: tests/test_utils_marker.py type: Module - nodeid: tests/test_utils_metaclasses.py type: Module - nodeid: tests/test_utils_namespace.py type: Module - nodeid: tests/test_utils_npy.py type: Module - nodeid: tests/test_utils_opmsg.py type: Module - nodeid: tests/test_utils_path.py type: Module - nodeid: tests/test_utils_picklio.py type: Module - nodeid: tests/test_utils_printing.py type: Module - nodeid: tests/test_utils_pv.py type: Module - nodeid: tests/test_utils_pvpreload.py type: Module - nodeid: tests/test_utils_pyepics.py type: Module - nodeid: tests/test_utils_rangebar.py type: Module - nodeid: tests/test_utils_readable.py type: Module - nodeid: tests/test_utils_registry.py type: Module - nodeid: tests/test_utils_reprate.py type: Module - nodeid: tests/test_utils_richcfg.py type: Module - nodeid: tests/test_utils_run_later.py type: Module - nodeid: tests/test_utils_sendmail.py type: Module - nodeid: tests/test_utils_sendsms.py type: Module - nodeid: tests/test_utils_shortcut.py type: Module - nodeid: tests/test_utils_snapshot.py type: Module - nodeid: tests/test_utils_termtitle.py type: Module - nodeid: tests/test_utils_tqdm_mod.py type: Module - nodeid: tests/test_utils_trinary.py type: Module - nodeid: tests/test_utils_typecast.py type: Module - nodeid: tests/test_utils_utils.py type: Module - nodeid: tests/test_utils_xrange.py type: Module-
✅ tests/test_utils_argfwd.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_argfwd.py::test_split_at[lst0-2-expected0] type: Function lineno: 7 - nodeid: tests/test_utils_argfwd.py::test_split_at[lst1-1-expected1] type: Function lineno: 7 - nodeid: tests/test_utils_argfwd.py::test_split_at[lst2-0-expected2] type: Function lineno: 7 - nodeid: tests/test_utils_argfwd.py::test_merge_lists_unique[a0-b0-expected0] type: Function lineno: 16 - nodeid: tests/test_utils_argfwd.py::test_merge_lists_unique[a1-b1-expected1] type: Function lineno: 16 - nodeid: tests/test_utils_argfwd.py::test_merge_lists_unique[a2-b2-expected2] type: Function lineno: 16 - nodeid: tests/test_utils_argfwd.py::test_merge_dicts_unique[a0-b0-expected0] type: Function lineno: 25 - nodeid: tests/test_utils_argfwd.py::test_merge_dicts_unique[a1-b1-expected1] type: Function lineno: 25 - nodeid: tests/test_utils_argfwd.py::test_merge_dicts_unique[a2-b2-expected2] type: Function lineno: 25 - nodeid: tests/test_utils_argfwd.py::test_make_params_pos_basic[pos0-expected_names0] type: Function lineno: 34 - nodeid: tests/test_utils_argfwd.py::test_make_params_pos_basic[pos1-expected_names1] type: Function lineno: 34 - nodeid: tests/test_utils_argfwd.py::test_make_params_pos_basic[pos2-expected_names2] type: Function lineno: 34 - nodeid: tests/test_utils_argfwd.py::test_make_params_kw_basic[kw0-expected_keys0-expected_defaults0] type: Function lineno: 47 - nodeid: tests/test_utils_argfwd.py::test_make_params_kw_basic[kw1-expected_keys1-expected_defaults1] type: Function lineno: 47 - nodeid: tests/test_utils_argfwd.py::test_make_params_kw_basic[kw2-expected_keys2-expected_defaults2] type: Function lineno: 47 - nodeid: tests/test_utils_argfwd.py::test_make_signature_parametrized[pos0-kw0-(x, y, z=3)] type: Function lineno: 59 - nodeid: tests/test_utils_argfwd.py::test_make_signature_parametrized[pos1-kw1-(a, b=1, c=2)] type: Function lineno: 59 - nodeid: tests/test_utils_argfwd.py::test_make_signature_parametrized[pos2-kw2-(flag=False)] type: Function lineno: 59 - nodeid: tests/test_utils_argfwd.py::test_get_args_parametrized[<lambda>-expected_pos0-expected_kw0] type: Function lineno: 70 - nodeid: tests/test_utils_argfwd.py::test_get_args_parametrized[<lambda>-expected_pos1-expected_kw1] type: Function lineno: 70 - nodeid: tests/test_utils_argfwd.py::test_get_args_parametrized[<lambda>-expected_pos2-expected_kw2] type: Function lineno: 70 - nodeid: tests/test_utils_argfwd.py::test_signature_visible[wrap_all-(a, b, d=30, c=10)] type: Function lineno: 103 - nodeid: tests/test_utils_argfwd.py::test_signature_visible[wrap_skip-(a, b, c=10, d=20)] type: Function lineno: 103 - nodeid: tests/test_utils_argfwd.py::test_signature_visible[wrap_ignore_all-(x, y, c=10, d=20)] type: Function lineno: 103 - nodeid: tests/test_utils_argfwd.py::test_wrapper_behavior[wrap_all-args0-kwargs0-36] type: Function lineno: 111 - nodeid: tests/test_utils_argfwd.py::test_wrapper_behavior[wrap_all-args1-kwargs1-11] type: Function lineno: 111 - nodeid: tests/test_utils_argfwd.py::test_wrapper_behavior[wrap_skip-args2-kwargs2-10] type: Function lineno: 111 - nodeid: tests/test_utils_argfwd.py::test_wrapper_behavior[wrap_ignore_all-args3-kwargs3-10] type: Function lineno: 111 - Outcome:
-
✅ tests/test_utils_ask_yes_no.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[None-y-True-Question? [y/n] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[None-yes-True-Question? [y/n] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[None-n-False-Question? [y/n] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[None-no-False-Question? [y/n] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[None-user_input4-True-Question? [y/n] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[None-user_input5-False-Question? [y/n] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[None-user_input6-True-Question? [y/n] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[y-y-True-Question? [Y/n] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[y-n-False-Question? [Y/n] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[y--True-Question? [Y/n] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[n-y-True-Question? [y/N] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[n-n-False-Question? [y/N] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no[n--False-Question? [y/N] ] type: Function lineno: 8 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_c[None-KeyboardInterrupt-False-n] type: Function lineno: 46 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_c[None-KeyboardInterrupt-True-y] type: Function lineno: 46 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_c[y-KeyboardInterrupt-False-n] type: Function lineno: 46 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_c[y-KeyboardInterrupt-True-y] type: Function lineno: 46 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_c[n-KeyboardInterrupt-False-n] type: Function lineno: 46 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_c[None-user_input5-False-n] type: Function lineno: 46 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_c[None-user_input6-True-y] type: Function lineno: 46 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_c[None-user_input7-False-None] type: Function lineno: 46 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_c[n-user_input8-False-None] type: Function lineno: 46 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_c[n-user_input9-False-Invalid] type: Function lineno: 46 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[None-EOFError-False-n] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[None-EOFError-True-y] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[y-EOFError-True-y] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[n-EOFError-True-y] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[n-EOFError-False-n] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[None-user_input5-True-y] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[None-user_input6-False-n] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[y-EOFError-True-None] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[n-EOFError-False-None] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[None-user_input9-True-None] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[n-user_input10-False-None] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[None-user_input11-True-None] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[None-user_input12-False-n] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_ctrl_d[None-user_input13-True-y] type: Function lineno: 79 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_mixed_sequences[None-invalid-None-user_input0-False] type: Function lineno: 117 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_mixed_sequences[None-None-notananswer-user_input1-True] type: Function lineno: 117 - nodeid: tests/test_utils_ask_yes_no.py::test_ask_yes_no_mixed_sequences[None-n-nop-user_input2-False] type: Function lineno: 117 - Outcome:
-
✅ tests/test_utils_channels.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_channels.py::test_load_channels_and_channels_class_with_professional_names type: Function lineno: 42 - Outcome:
-
✅ tests/test_utils_config.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_config.py::test_config_with_nested_and_list_data type: Function lineno: 15 - nodeid: tests/test_utils_config.py::test_config_with_strange_and_edge_keys type: Function lineno: 73 - Outcome:
-
✅ tests/test_utils_cpint.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_cpint.py::test_load_color_variants_all_keys_and_types[red] type: Function lineno: 9 - nodeid: tests/test_utils_cpint.py::test_load_color_variants_all_keys_and_types[blue] type: Function lineno: 9 - nodeid: tests/test_utils_cpint.py::test_load_color_variants_all_keys_and_types[yellow] type: Function lineno: 9 - nodeid: tests/test_utils_cpint.py::test_load_color_variants_all_keys_and_types[green] type: Function lineno: 9 - nodeid: tests/test_utils_cpint.py::test_load_color_variants_all_keys_and_types[cyan] type: Function lineno: 9 - nodeid: tests/test_utils_cpint.py::test_load_color_variants_all_keys_and_types[magenta] type: Function lineno: 9 - nodeid: tests/test_utils_cpint.py::test_load_color_variants_all_keys_and_types[white] type: Function lineno: 9 - nodeid: tests/test_utils_cpint.py::test_load_color_variants_all_keys_and_types[black] type: Function lineno: 9 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects0-color_spec0- | -['Fancy', 'list'] | {'a': 7} | None-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects1-color_spec1- - -{'k': [1, 2]} - 99 - ['X', ['Y']]-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects2-color_spec2- / -[] / {} / End-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects3-color_spec3-;-['', [3, 4]];done;0-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects4-color_spec4-::-['alpha', None]::['beta', {}]::stop-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects5-color_spec5- ... -['deep', ['deeper', ['deepest']]] ... X-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects6-color_spec6- // -{'dict': {'nested': [4, 5]}} // [True, False] // 6.28-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects7-color_spec7-==-['A', ['B']]==string==C-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects8-color_spec8- ++ -['Test', None, []] ++ {'v': 0}-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects9-None-;-['no', 'color'];plain-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects10-None- | -['simple'] | | 12-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects11-None- : -[['very', 'deep']] : {'ok': True}-None] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects12-color_spec12-|-['fail', 'color']|123-ValueError] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects13-color_spec13- * -['error'] * {}-ValueError] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects14-color_spec14-//-['nope']//['bad']-ValueError] type: Function lineno: 24 - nodeid: tests/test_utils_cpint.py::test_cprint_all_cases_fancy[objects15-color_spec15----wrong--base-ValueError] type: Function lineno: 24 - Outcome:
-
✅ tests/test_utils_dbusnotify.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_dbusnotify.py::DBusTestCase type: UnitTestCase - nodeid: tests/test_utils_dbusnotify.py::test_notify_create type: Function lineno: 26 - nodeid: tests/test_utils_dbusnotify.py::test_notify_update type: Function lineno: 37 - nodeid: tests/test_utils_dbusnotify.py::test_get_server_info type: Function lineno: 46 - nodeid: tests/test_utils_dbusnotify.py::test_get_capabilities type: Function lineno: 57 - nodeid: tests/test_utils_dbusnotify.py::test_notify_and_close type: Function lineno: 72 - nodeid: tests/test_utils_dbusnotify.py::test_notify_invalid_value type: Function lineno: 82 - nodeid: tests/test_utils_dbusnotify.py::test_convert_dbus_strings type: Function lineno: 88 - Outcome:
-
✅ tests/test_utils_dbusnotify.py::DBusTestCase
- Outcome:
passed - result:
[] - Outcome:
-
✅ tests/test_utils_debug.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_debug.py::test_traceable[A-entry0-creating: A(10, 20)] type: Function lineno: 21 - nodeid: tests/test_utils_debug.py::test_traceable[A-entry1-creating: A(10, 20, e=100)] type: Function lineno: 21 - nodeid: tests/test_utils_debug.py::test_traceable[A-entry2-creating: A('foo', [1, 2, 3], flag=True, data={'x': 9})] type: Function lineno: 21 - nodeid: tests/test_utils_debug.py::test_traceable[A-entry3-creating: A(CustomObj(big), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], name='test', meta='yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy...)] type: Function lineno: 21 - nodeid: tests/test_utils_debug.py::test_traceable[A-entry4-creating: A('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA..., [0, 0, 0, 0, 0])] type: Function lineno: 21 - nodeid: tests/test_utils_debug.py::test_short_repr[abc-10-'abc'] type: Function lineno: 52 - nodeid: tests/test_utils_debug.py::test_short_repr[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-10-'aaaaaaaaaa...] type: Function lineno: 52 - nodeid: tests/test_utils_debug.py::test_short_repr[12345-10-12345] type: Function lineno: 52 - nodeid: tests/test_utils_debug.py::test_short_repr[value3-15-[0, 0, 0, 0, 0,...] type: Function lineno: 52 - nodeid: tests/test_utils_debug.py::test_short_repr[None-10-None] type: Function lineno: 52 - nodeid: tests/test_utils_debug.py::test_short_repr[value5-20-Obj(xxxxxxxxxxxxxxxxx...] type: Function lineno: 52 - Outcome:
-
✅ tests/test_utils_dictext.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_dictext.py::test_attrdict_getattr[data0-x-1] type: Function lineno: 12 - nodeid: tests/test_utils_dictext.py::test_attrdict_getattr[data1-world-ok] type: Function lineno: 12 - nodeid: tests/test_utils_dictext.py::test_attrdict_getattr[data2-outer-expected2] type: Function lineno: 12 - nodeid: tests/test_utils_dictext.py::test_attrdict_setattr[initial0-nouveau-123] type: Function lineno: 26 - nodeid: tests/test_utils_dictext.py::test_attrdict_setattr[initial1-b-valeur] type: Function lineno: 26 - nodeid: tests/test_utils_dictext.py::test_attrdict_delattr[initial0-a-expected_keys0] type: Function lineno: 40 - nodeid: tests/test_utils_dictext.py::test_attrdict_delattr[initial1-k-expected_keys1] type: Function lineno: 40 - nodeid: tests/test_utils_dictext.py::test_attrdict_dir[data0-expected_keys0] type: Function lineno: 55 - nodeid: tests/test_utils_dictext.py::test_attrdict_dir[data1-expected_keys1] type: Function lineno: 55 - nodeid: tests/test_utils_dictext.py::test_attrdict_getattr_and_missing[data0-x-1-None] type: Function lineno: 69 - nodeid: tests/test_utils_dictext.py::test_attrdict_getattr_and_missing[data1-missing-None-'MyDict' object has no attribute 'missing'] type: Function lineno: 69 - nodeid: tests/test_utils_dictext.py::test_dictupdatemixin_init_and_update[init_kwargs0-None-kwargs0-expected0] type: Function lineno: 90 - nodeid: tests/test_utils_dictext.py::test_dictupdatemixin_init_and_update[init_kwargs1-other1-kwargs1-expected1] type: Function lineno: 90 - nodeid: tests/test_utils_dictext.py::test_dictupdatemixin_init_and_update[init_kwargs2-other2-kwargs2-expected2] type: Function lineno: 90 - nodeid: tests/test_utils_dictext.py::test_dictupdatemixin_init_and_update[init_kwargs3-None-kwargs3-expected3] type: Function lineno: 90 - nodeid: tests/test_utils_dictext.py::test_dictupdatemixin_init_and_update[init_kwargs4-other4-kwargs4-expected4] type: Function lineno: 90 - nodeid: tests/test_utils_dictext.py::test_dictupdatemixin_init_and_update[init_kwargs5-other5-kwargs5-expected5] type: Function lineno: 90 - Outcome:
-
✅ tests/test_utils_dotdir.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_dotdir.py::test_dotdir_creation_and_base_exists type: Function lineno: 14 - nodeid: tests/test_utils_dotdir.py::test_dotdir_repr_returns_path_str type: Function lineno: 28 - nodeid: tests/test_utils_dotdir.py::test_dotdir_call type: Function lineno: 35 - Outcome:
-
✅ tests/test_utils_duo.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_duo.py::TestPickledDictReal type: Class - nodeid: tests/test_utils_duo.py::TestSecrets type: Class - nodeid: tests/test_utils_duo.py::test_get_pgroup_raises_if_no_key type: Function lineno: 142 - nodeid: tests/test_utils_duo.py::test_get_pgroup_info_with_props_same_name_and_pi type: Function lineno: 148 - nodeid: tests/test_utils_duo.py::test_get_pgroup_info_with_props_different_pi type: Function lineno: 175 - nodeid: tests/test_utils_duo.py::test_get_pgroup_info_without_props_with_owner type: Function lineno: 202 - nodeid: tests/test_utils_duo.py::test_get_pgroup_info_without_props_no_owner type: Function lineno: 222 - nodeid: tests/test_utils_duo.py::test_get_pgroup_info_mock type: Function lineno: 240 - Outcome:
-
✅ tests/test_utils_duo.py::TestPickledDictReal
- Outcome:
passed - result:
- nodeid: tests/test_utils_duo.py::TestPickledDictReal::test_set_get type: Function lineno: 15 - nodeid: tests/test_utils_duo.py::TestPickledDictReal::test_load type: Function lineno: 49 - Outcome:
-
✅ tests/test_utils_duo.py::TestSecrets
- Outcome:
passed - result:
- nodeid: tests/test_utils_duo.py::TestSecrets::test_secret_workflow type: Function lineno: 93 - nodeid: tests/test_utils_duo.py::TestSecrets::test_multiple_secrets type: Function lineno: 110 - nodeid: tests/test_utils_duo.py::TestSecrets::test_keyboard_interrupt type: Function lineno: 122 - Outcome:
-
✅ tests/test_utils_elog.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_elog.py::test_get_default_elog_instance_with_direct_password_and_real_check type: Function lineno: 12 - nodeid: tests/test_utils_elog.py::test_get_default_elog_instance_with_wrong_password_and_real_check type: Function lineno: 31 - nodeid: tests/test_utils_elog.py::test_get_default_elog_instance_asks_password_and_opens type: Function lineno: 42 - nodeid: tests/test_utils_elog.py::test_get_default_elog_with_path_home type: Function lineno: 69 - nodeid: tests/test_utils_elog.py::test_screenshot type: Function lineno: 103 - Outcome:
-
✅ tests/test_utils_eval.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[1 + 2-3] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[4 - 2-2] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[3 * 5-15] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[10 / 2-5.0] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[10 % 3-1] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[-5--5] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[+7-7] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[1 + 2 * 3-7] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[(1 + 2) * 3-9] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[-(-3)-3] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[-2 + 4 * 2-6] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[(4 + 5) * (6 - 1)-45] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[(((3)))-3] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[-(-(-2))--2] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[3 + +4-7] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[3 + -4--1] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[True + 1-2] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid['string'-string] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid[1e1000 * 1e1000-inf] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_valid['a' + 'b'-ab] type: Function lineno: 7 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_raises_with_message[2 ** 3-Unsupported BinOp Pow] type: Function lineno: 33 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_raises_with_message[3 << 1-Unsupported BinOp LShift] type: Function lineno: 33 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_raises_with_message[1 < 2-Unsupported node type Compare] type: Function lineno: 33 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_raises_with_message[abs(3)-Unsupported node type Call] type: Function lineno: 33 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_raises_with_message[a + 2-Unsupported node type Name] type: Function lineno: 33 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_raises_with_message[string-Unsupported node type Name] type: Function lineno: 33 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_raises_with_message[[1, 2] + [3]-Unsupported node type List] type: Function lineno: 33 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_raises_with_message[{1: 2}-Unsupported node type Dict] type: Function lineno: 33 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_runtime_errors[1 / 0-ZeroDivisionError] type: Function lineno: 52 - nodeid: tests/test_utils_eval.py::test_arithmetic_eval_runtime_errors[10 % 0-ZeroDivisionError] type: Function lineno: 52 - nodeid: tests/test_utils_eval.py::test_forgiving_eval[1 + 2-3] type: Function lineno: 61 - nodeid: tests/test_utils_eval.py::test_forgiving_eval[bad + 2-bad + 2] type: Function lineno: 61 - nodeid: tests/test_utils_eval.py::test_forgiving_eval[1 / 0-1 / 0] type: Function lineno: 61 - nodeid: tests/test_utils_eval.py::test_forgiving_eval[2 ** 10-2 ** 10] type: Function lineno: 61 - nodeid: tests/test_utils_eval.py::test_defaulting_eval[3 * 4-0-12] type: Function lineno: 71 - nodeid: tests/test_utils_eval.py::test_defaulting_eval[invalid + 1-99-99] type: Function lineno: 71 - nodeid: tests/test_utils_eval.py::test_defaulting_eval[1 / 0--1--1] type: Function lineno: 71 - nodeid: tests/test_utils_eval.py::test_defaulting_eval[2 ** 10-42-42] type: Function lineno: 71 - Outcome:
-
✅ tests/test_utils_exceptions.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_exceptions.py::test_chained_exception_various[cause_key_error-High-level task failed\ncaused by KeyError: 'missing'] type: Function lineno: 28 - nodeid: tests/test_utils_exceptions.py::test_chained_exception_various[cause_index_error-High-level task failed\ncaused by IndexError: list index out of range] type: Function lineno: 28 - nodeid: tests/test_utils_exceptions.py::test_chained_exception_various[cause_zero_division-High-level task failed\ncaused by ZeroDivisionError: division by zero] type: Function lineno: 28 - nodeid: tests/test_utils_exceptions.py::test_chained_exception_various[cause_value_error-High-level task failed\ncaused by ValueError: invalid literal for int() with base 10: 'not_a_number'] type: Function lineno: 28 - nodeid: tests/test_utils_exceptions.py::test_chained_exception_various[cause_type_error-High-level task failed\ncaused by TypeError: can only concatenate str (not "int") to str] type: Function lineno: 28 - nodeid: tests/test_utils_exceptions.py::test_printed_exception[cause_key_error-KeyError: 'missing'] type: Function lineno: 60 - nodeid: tests/test_utils_exceptions.py::test_printed_exception[cause_index_error-IndexError: list index out of range] type: Function lineno: 60 - nodeid: tests/test_utils_exceptions.py::test_printed_exception[cause_zero_division-ZeroDivisionError: division by zero] type: Function lineno: 60 - nodeid: tests/test_utils_exceptions.py::test_printed_exception[cause_value_error-ValueError: invalid literal for int() with base 10: 'not_a_number'] type: Function lineno: 60 - nodeid: tests/test_utils_exceptions.py::test_printed_exception[cause_type_error-TypeError: can only concatenate str (not "int") to str] type: Function lineno: 60 - Outcome:
-
✅ tests/test_utils_get_adj.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_get_adj.py::test_get_adj_success type: Function lineno: 23 - nodeid: tests/test_utils_get_adj.py::test_get_adj_not_found type: Function lineno: 27 - nodeid: tests/test_utils_get_adj.py::test_ensure_adjs_mixed type: Function lineno: 31 - nodeid: tests/test_utils_get_adj.py::test_get_adjs_filter type: Function lineno: 37 - Outcome:
-
✅ tests/test_utils_hastepics.py
- Outcome:
passed - result:
[] - Outcome:
-
✅ tests/test_utils_ipy.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_ipy.py::test_devices_repr_fallback_and_ignore type: Function lineno: 19 - Outcome:
-
✅ tests/test_utils_jsonext.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_jsonext.py::test_json_validate_save_load[input_obj0-expected0] type: Function lineno: 7 - nodeid: tests/test_utils_jsonext.py::test_json_validate_save_load[input_obj1-42] type: Function lineno: 7 - nodeid: tests/test_utils_jsonext.py::test_json_validate_save_load[(1-1j)-expected2] type: Function lineno: 7 - nodeid: tests/test_utils_jsonext.py::test_json_validate_save_load[input_obj3-/tmp/file.txt] type: Function lineno: 7 - nodeid: tests/test_utils_jsonext.py::test_json_validate_save_load[input_obj4-expected4] type: Function lineno: 7 - nodeid: tests/test_utils_jsonext.py::test_json_validate_save_load[input_obj5-expected5] type: Function lineno: 7 - nodeid: tests/test_utils_jsonext.py::test_json_validate_save_load[input_obj6-expected6] type: Function lineno: 7 - nodeid: tests/test_utils_jsonext.py::test_json_validate_save_load[input_obj7-expected7] type: Function lineno: 7 - Outcome:
-
✅ tests/test_utils_lazypv.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_lazypv.py::test_getattr type: Function lineno: 7 - Outcome:
-
✅ tests/test_utils_logcfg.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_logcfg.py::test_custom_log_outputs[LONG-<lambda>-This is a LONG message] type: Function lineno: 21 - nodeid: tests/test_utils_logcfg.py::test_custom_log_outputs[ENLARGE-<lambda>-Please ENLARGE this!] type: Function lineno: 21 - nodeid: tests/test_utils_logcfg.py::test_import_logging_once_per_module type: Function lineno: 51 - Outcome:
-
✅ tests/test_utils_logign.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_logign.py::test_ignore_log_msg_behavior[WARNING-This should be ignored-This should appear] type: Function lineno: 9 - nodeid: tests/test_utils_logign.py::test_ignore_log_msg_behavior[ENLARGE-ENLARGE this-Keep this ENLARGE] type: Function lineno: 9 - nodeid: tests/test_utils_logign.py::test_ignore_only_by_level type: Function lineno: 42 - nodeid: tests/test_utils_logign.py::test_ignore_only_by_msg type: Function lineno: 64 - nodeid: tests/test_utils_logign.py::test_filter_removed_after_context type: Function lineno: 86 - Outcome:
-
✅ tests/test_utils_marker.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_marker.py::test_format_value_with_units type: Function lineno: 30 - nodeid: tests/test_utils_marker.py::test_format_value_without_units type: Function lineno: 33 - nodeid: tests/test_utils_marker.py::test_marker_name_default type: Function lineno: 39 - nodeid: tests/test_utils_marker.py::test_marker_name_custom type: Function lineno: 44 - nodeid: tests/test_utils_marker.py::test_marker_repr_format type: Function lineno: 49 - nodeid: tests/test_utils_marker.py::test_marker_update_changes_value type: Function lineno: 56 - nodeid: tests/test_utils_marker.py::test_marker_update_with_explicit_value type: Function lineno: 63 - nodeid: tests/test_utils_marker.py::test_marker_goto_sets_value_and_returns_result type: Function lineno: 69 - nodeid: tests/test_utils_marker.py::test_marker_call_is_alias_of_goto type: Function lineno: 77 - nodeid: tests/test_utils_marker.py::test_markers_register_and_access type: Function lineno: 87 - nodeid: tests/test_utils_marker.py::test_markers_repr_contains_all type: Function lineno: 103 - nodeid: tests/test_utils_marker.py::test_marker_registry_dict_is_printable_dict type: Function lineno: 114 - nodeid: tests/test_utils_marker.py::test_markers_getitem_invalid_key_raises type: Function lineno: 122 - Outcome:
-
✅ tests/test_utils_metaclasses.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_metaclasses.py::test_combine_classes_combines_methods type: Function lineno: 14 - nodeid: tests/test_utils_metaclasses.py::test_registryabc_combines_registrymeta_and_abcmeta type: Function lineno: 25 - Outcome:
-
✅ tests/test_utils_namespace.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_namespace.py::test_namespace_pretty_repr_mixed_and_nested type: Function lineno: 4 - Outcome:
-
✅ tests/test_utils_npy.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_npy.py::test_nice_arange[0-5-1-expected0] type: Function lineno: 7 - nodeid: tests/test_utils_npy.py::test_nice_arange[5-0--1-expected1] type: Function lineno: 7 - nodeid: tests/test_utils_npy.py::test_nice_arange[1-2-0.3-expected2] type: Function lineno: 7 - nodeid: tests/test_utils_npy.py::test_nice_arange[-2-2-1.5-expected3] type: Function lineno: 7 - nodeid: tests/test_utils_npy.py::test_nice_arange[2.5-0.5--0.4-expected4] type: Function lineno: 7 - nodeid: tests/test_utils_npy.py::test_nice_linspace[0-10-4-expected0] type: Function lineno: 18 - nodeid: tests/test_utils_npy.py::test_nice_linspace[5-15-2-expected1] type: Function lineno: 18 - nodeid: tests/test_utils_npy.py::test_nice_linspace[-5-5-4-expected2] type: Function lineno: 18 - nodeid: tests/test_utils_npy.py::test_nice_linspace[0-1-3-expected3] type: Function lineno: 18 - nodeid: tests/test_utils_npy.py::test_nice_linspace[2-2-3-expected4] type: Function lineno: 18 - nodeid: tests/test_utils_npy.py::test_nice_linspace[3-0-3-expected5] type: Function lineno: 18 - nodeid: tests/test_utils_npy.py::test_nice_linspace[0-1-0-expected6] type: Function lineno: 18 - nodeid: tests/test_utils_npy.py::test_nice_linspace[-2-2-3-expected7] type: Function lineno: 18 - nodeid: tests/test_utils_npy.py::test_nice_steps_centered[-2-2-2-True-expected0] type: Function lineno: 33 - nodeid: tests/test_utils_npy.py::test_nice_steps_centered[0-5-2-True-expected1] type: Function lineno: 33 - nodeid: tests/test_utils_npy.py::test_nice_steps_centered[0-5-2-False-expected2] type: Function lineno: 33 - nodeid: tests/test_utils_npy.py::test_nice_steps_centered[-1-2-1.5-True-expected3] type: Function lineno: 33 - nodeid: tests/test_utils_npy.py::test_nice_steps_centered[-1-2--1.5-True-expected4] type: Function lineno: 33 - nodeid: tests/test_utils_npy.py::test_nice_steps_centered[5-0--2-True-expected5] type: Function lineno: 33 - nodeid: tests/test_utils_npy.py::test_nice_steps_left_aligned[0-5-2-True-expected0] type: Function lineno: 46 - nodeid: tests/test_utils_npy.py::test_nice_steps_left_aligned[0-5-2-False-expected1] type: Function lineno: 46 - nodeid: tests/test_utils_npy.py::test_nice_steps_left_aligned[-1-2-1.5-True-expected2] type: Function lineno: 46 - nodeid: tests/test_utils_npy.py::test_nice_steps_left_aligned[-1-2-1.5-False-expected3] type: Function lineno: 46 - nodeid: tests/test_utils_npy.py::test_nice_steps_left_aligned[-2-1-1.2-True-expected4] type: Function lineno: 46 - nodeid: tests/test_utils_npy.py::test_nice_steps_left_aligned[5-0--2-True-expected5] type: Function lineno: 46 - nodeid: tests/test_utils_npy.py::test_nice_steps_left_aligned[5-0--2-False-expected6] type: Function lineno: 46 - nodeid: tests/test_utils_npy.py::test_nice_steps_right_aligned[0-5-2-True-expected0] type: Function lineno: 60 - nodeid: tests/test_utils_npy.py::test_nice_steps_right_aligned[0-5-2-False-expected1] type: Function lineno: 60 - nodeid: tests/test_utils_npy.py::test_nice_steps_right_aligned[-1-2-1.5-True-expected2] type: Function lineno: 60 - nodeid: tests/test_utils_npy.py::test_nice_steps_right_aligned[-1-2-1.5-False-expected3] type: Function lineno: 60 - nodeid: tests/test_utils_npy.py::test_nice_steps_right_aligned[5-0--2-True-expected4] type: Function lineno: 60 - nodeid: tests/test_utils_npy.py::test_nice_steps_right_aligned[5-0--2-False-expected5] type: Function lineno: 60 - nodeid: tests/test_utils_npy.py::test_nice_steps_right_aligned[-3-3-2-True-expected6] type: Function lineno: 60 - nodeid: tests/test_utils_npy.py::test_within_scalar[5-0-10-True] type: Function lineno: 74 - nodeid: tests/test_utils_npy.py::test_within_scalar[5-6-10-False] type: Function lineno: 74 - nodeid: tests/test_utils_npy.py::test_within_scalar[5-None-10-True] type: Function lineno: 74 - nodeid: tests/test_utils_npy.py::test_within_scalar[5-0-None-True] type: Function lineno: 74 - nodeid: tests/test_utils_npy.py::test_within_scalar[5-None-None-True] type: Function lineno: 74 - nodeid: tests/test_utils_npy.py::test_within_fraction[data0-2-5-0.6] type: Function lineno: 85 - nodeid: tests/test_utils_npy.py::test_within_fraction[data1-5-25-0.6666666666666666] type: Function lineno: 85 - nodeid: tests/test_utils_npy.py::test_within_fraction[data2-None-2-0.3333333333333333] type: Function lineno: 85 - nodeid: tests/test_utils_npy.py::test_within_fraction[data3-0-1-0] type: Function lineno: 85 - nodeid: tests/test_utils_npy.py::test_fraction_to_percentage[0.456-1-45.6] type: Function lineno: 96 - nodeid: tests/test_utils_npy.py::test_fraction_to_percentage[0.12345-2-12.35] type: Function lineno: 96 - nodeid: tests/test_utils_npy.py::test_fraction_to_percentage[0.9999-0-100.0] type: Function lineno: 96 - nodeid: tests/test_utils_npy.py::test_get_dtype[val0-ndarray] type: Function lineno: 105 - nodeid: tests/test_utils_npy.py::test_get_dtype[val1-list] type: Function lineno: 105 - nodeid: tests/test_utils_npy.py::test_get_dtype[3.14-float] type: Function lineno: 105 - nodeid: tests/test_utils_npy.py::test_get_shape[val0-expected0] type: Function lineno: 118 - nodeid: tests/test_utils_npy.py::test_get_shape[val1-expected1] type: Function lineno: 118 - nodeid: tests/test_utils_npy.py::test_get_shape[42-expected2] type: Function lineno: 118 - nodeid: tests/test_utils_npy.py::test_is_array[val0-True] type: Function lineno: 127 - nodeid: tests/test_utils_npy.py::test_is_array[val1-False] type: Function lineno: 127 - nodeid: tests/test_utils_npy.py::test_is_array[42-False] type: Function lineno: 127 - Outcome:
-
✅ tests/test_utils_opmsg.py
- Outcome:
passed - result:
[] - Outcome:
-
✅ tests/test_utils_path.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_path.py::test_can_create_all_files_user_says_yes type: Function lineno: 10 - nodeid: tests/test_utils_path.py::test_can_create_all_files_user_says_no type: Function lineno: 36 - nodeid: tests/test_utils_path.py::test_make_missing_dir_creates_folder type: Function lineno: 54 - nodeid: tests/test_utils_path.py::test_glob_files_returns_matching_files_only type: Function lineno: 66 - nodeid: tests/test_utils_path.py::test_filter_files_excludes_directories type: Function lineno: 83 - Outcome:
-
✅ tests/test_utils_picklio.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_picklio.py::test_pickle_and_unpickle[test_obj0] type: Function lineno: 6 - nodeid: tests/test_utils_picklio.py::test_pickle_and_unpickle[test_obj1] type: Function lineno: 6 - nodeid: tests/test_utils_picklio.py::test_pickle_and_unpickle[simple string] type: Function lineno: 6 - nodeid: tests/test_utils_picklio.py::test_pickle_and_unpickle[42] type: Function lineno: 6 - nodeid: tests/test_utils_picklio.py::test_pickle_and_unpickle[3.14159] type: Function lineno: 6 - nodeid: tests/test_utils_picklio.py::test_pickle_and_unpickle[test_obj5] type: Function lineno: 6 - nodeid: tests/test_utils_picklio.py::test_pickle_and_unpickle[test_obj6] type: Function lineno: 6 - Outcome:
-
✅ tests/test_utils_printing.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_printing.py::test_maxlen_valid[seq0-3] type: Function lineno: 8 - nodeid: tests/test_utils_printing.py::test_maxlen_valid[seq1-0] type: Function lineno: 8 - nodeid: tests/test_utils_printing.py::test_maxlen_valid[seq2-3] type: Function lineno: 8 - nodeid: tests/test_utils_printing.py::test_maxlen_valid[seq3-2] type: Function lineno: 8 - nodeid: tests/test_utils_printing.py::test_strlen[42-2] type: Function lineno: 17 - nodeid: tests/test_utils_printing.py::test_strlen[hello-5] type: Function lineno: 17 - nodeid: tests/test_utils_printing.py::test_strlen[False-5] type: Function lineno: 17 - nodeid: tests/test_utils_printing.py::test_strlen[None-4] type: Function lineno: 17 - nodeid: tests/test_utils_printing.py::test_strlen[value4-9] type: Function lineno: 17 - nodeid: tests/test_utils_printing.py::test_strlen[value5-8] type: Function lineno: 17 - nodeid: tests/test_utils_printing.py::test_strlen[value6-6] type: Function lineno: 17 - nodeid: tests/test_utils_printing.py::test_strlen[-0] type: Function lineno: 17 - nodeid: tests/test_utils_printing.py::test_strlen[this is a phrase-16] type: Function lineno: 17 - nodeid: tests/test_utils_printing.py::test_maxstrlen[seq0-6] type: Function lineno: 31 - nodeid: tests/test_utils_printing.py::test_maxstrlen[seq1-3] type: Function lineno: 31 - nodeid: tests/test_utils_printing.py::test_maxstrlen[seq2-9] type: Function lineno: 31 - nodeid: tests/test_utils_printing.py::test_maxstrlen[seq3-16] type: Function lineno: 31 - nodeid: tests/test_utils_printing.py::test_maxstrlen[seq4-5] type: Function lineno: 31 - nodeid: tests/test_utils_printing.py::test_transpose_matrix[data0-expected0] type: Function lineno: 41 - nodeid: tests/test_utils_printing.py::test_transpose_matrix[data1-expected1] type: Function lineno: 41 - nodeid: tests/test_utils_printing.py::test_transpose_matrix[data2-expected2] type: Function lineno: 41 - nodeid: tests/test_utils_printing.py::test_prepend[initial0-1-expected0] type: Function lineno: 50 - nodeid: tests/test_utils_printing.py::test_prepend[initial1-a-expected1] type: Function lineno: 50 - nodeid: tests/test_utils_printing.py::test_prepend[initial2-prepend2-expected2] type: Function lineno: 50 - nodeid: tests/test_utils_printing.py::test_prepend[initial3-prepend3-expected3] type: Function lineno: 50 - nodeid: tests/test_utils_printing.py::test_fmt_table_line[entries0-widths0- a bbb] type: Function lineno: 61 - nodeid: tests/test_utils_printing.py::test_fmt_table_line[entries1-widths1- 1 2] type: Function lineno: 61 - nodeid: tests/test_utils_printing.py::test_fmt_table_line[entries2-widths2- long val] type: Function lineno: 61 - nodeid: tests/test_utils_printing.py::test_fmt_table_line[entries3-widths3- True False] type: Function lineno: 61 - nodeid: tests/test_utils_printing.py::test_fmt_table_line[entries4-widths4- 123 4567] type: Function lineno: 61 - nodeid: tests/test_utils_printing.py::test_fmt_table_line[entries5-widths5- text with space end] type: Function lineno: 61 - nodeid: tests/test_utils_printing.py::test_fmt_table_line[entries6-widths6- {'a': 1} {'b': 2}] type: Function lineno: 61 - nodeid: tests/test_utils_printing.py::test_fmt_table_line[entries7-widths7- [1, 2] [3, 4]] type: Function lineno: 61 - nodeid: tests/test_utils_printing.py::test_fmt_label_sep[widths0------ ----] type: Function lineno: 74 - nodeid: tests/test_utils_printing.py::test_fmt_label_sep[widths1-=-== ===] type: Function lineno: 74 - nodeid: tests/test_utils_printing.py::test_fmt_label_sep[widths2-*-***** **] type: Function lineno: 74 - nodeid: tests/test_utils_printing.py::test_printable_dict_with_header[d0-HeaderTest-expected_lines0] type: Function lineno: 82 - nodeid: tests/test_utils_printing.py::test_printable_dict_of_dicts type: Function lineno: 101 - nodeid: tests/test_utils_printing.py::test_printable_table[data0-labels0-A: ID\nB: \u2713 Success?\nC: SuperPrecisionValue\nD: Result Metadata\n\n# A B C D\n- ------------- ----- ---------- ----------------------------\n0 X1 True 0.1234 {'meta': 'ok'}\n1 AnotherSample False 98765.4321 {'meta': [1, 2, 3]}\n2 Z None 0.0 {'meta': {'nested_key': 42}}] type: Function lineno: 128 - Outcome:
-
✅ tests/test_utils_pv.py
- Outcome:
passed - result:
[] - Outcome:
-
✅ tests/test_utils_pvpreload.py
- Outcome:
passed - result:
[] - Outcome:
-
✅ tests/test_utils_pyepics.py
- Outcome:
passed - result:
[] - Outcome:
-
✅ tests/test_utils_rangebar.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_rangebar.py::test_full_progress_bar type: Function lineno: 10 - nodeid: tests/test_utils_rangebar.py::test_half_progress_bar type: Function lineno: 24 - nodeid: tests/test_utils_rangebar.py::test_zero_progress_bar type: Function lineno: 39 - nodeid: tests/test_utils_rangebar.py::test_overflow_bar type: Function lineno: 54 - nodeid: tests/test_utils_rangebar.py::test_underflow_bar type: Function lineno: 68 - nodeid: tests/test_utils_rangebar.py::test_repr type: Function lineno: 82 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[0- ] type: Function lineno: 88 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[10-\u2588 ] type: Function lineno: 88 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[25-\u2588\u2588\u258c ] type: Function lineno: 88 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[27-\u2588\u2588\u258a ] type: Function lineno: 88 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[49-\u2588\u2588\u2588\u2588\u2589 ] type: Function lineno: 88 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[50-\u2588\u2588\u2588\u2588\u2588 ] type: Function lineno: 88 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[51-\u2588\u2588\u2588\u2588\u2588\u258f ] type: Function lineno: 88 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[73-\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258e ] type: Function lineno: 88 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[75-\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258c ] type: Function lineno: 88 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[90-\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 ] type: Function lineno: 88 - nodeid: tests/test_utils_rangebar.py::test_each_value_separately[100-\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588] type: Function lineno: 88 - Outcome:
-
✅ tests/test_utils_readable.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_readable.py::test_readable_seconds[59.4-59 seconds] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[59.9-60 seconds] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[119.9-120 seconds] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[120.1-2 minutes] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[3599.9-60 minutes] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[3600.1-60 minutes] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[7199.9-120 minutes] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[7200.1-2 hours] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[90.4-90 seconds] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[90.6-91 seconds] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[121.9-2 minutes] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[1296000.0-2 weeks] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[2592000.0-4 weeks] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[2800000.0-5 weeks] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[3888000.0-6 weeks] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[5097600.0-8 weeks] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[5184000.0-9 weeks] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[5270400.0-2 months] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[23328000.0-9 months] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[31104000.0-12 months] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[33696000.0-13 months] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[59616000.0-23 months] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[62208000.0-24 months] type: Function lineno: 3 - nodeid: tests/test_utils_readable.py::test_readable_seconds[64208000.0-2 years] type: Function lineno: 3 - Outcome:
-
✅ tests/test_utils_registry.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_registry.py::test_metaclass_creates_weakset type: Function lineno: 13 - nodeid: tests/test_utils_registry.py::test_metaclass_tracks_instances type: Function lineno: 22 - nodeid: tests/test_utils_registry.py::test_registry_inheritance type: Function lineno: 32 - nodeid: tests/test_utils_registry.py::test_instance_tracking type: Function lineno: 39 - nodeid: tests/test_utils_registry.py::test_collect_instances_recursive type: Function lineno: 53 - nodeid: tests/test_utils_registry.py::test_instances_function type: Function lineno: 69 - nodeid: tests/test_utils_registry.py::test_non_registry_class_error type: Function lineno: 93 - nodeid: tests/test_utils_registry.py::test_signature_preservation type: Function lineno: 102 - Outcome:
-
✅ tests/test_utils_reprate.py
- Outcome:
passed - result:
[] - Outcome:
-
✅ tests/test_utils_richcfg.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_richcfg.py::test_rich_inspector_outputs_more_than_builtin type: Function lineno: 45 - Outcome:
-
✅ tests/test_utils_run_later.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_run_later.py::test_init_and_repr type: Function lineno: 17 - nodeid: tests/test_utils_run_later.py::test_call type: Function lineno: 22 - nodeid: tests/test_utils_run_later.py::test_matmul_with_string type: Function lineno: 27 - nodeid: tests/test_utils_run_later.py::test_matmul_with_list type: Function lineno: 32 - nodeid: tests/test_utils_run_later.py::test_matmul_with_single_int type: Function lineno: 37 - nodeid: tests/test_utils_run_later.py::test_run_at_future_triggered_and_logs type: Function lineno: 49 - nodeid: tests/test_utils_run_later.py::test_run_at_already_past type: Function lineno: 61 - nodeid: tests/test_utils_run_later.py::test_run_in_future_triggered_and_logs type: Function lineno: 72 - nodeid: tests/test_utils_run_later.py::test_run_in_past type: Function lineno: 83 - nodeid: tests/test_utils_run_later.py::test_run_later_with_seconds type: Function lineno: 95 - nodeid: tests/test_utils_run_later.py::test_run_later_with_past_datetime type: Function lineno: 105 - nodeid: tests/test_utils_run_later.py::test_run_at_tqdm_multiple_updates type: Function lineno: 115 - nodeid: tests/test_utils_run_later.py::test_today_basic type: Function lineno: 137 - nodeid: tests/test_utils_run_later.py::test_tomorrow_basic type: Function lineno: 143 - nodeid: tests/test_utils_run_later.py::test_yesterday_basic type: Function lineno: 149 - nodeid: tests/test_utils_run_later.py::test_today_matmul_string type: Function lineno: 155 - nodeid: tests/test_utils_run_later.py::test_tomorrow_matmul_list type: Function lineno: 161 - nodeid: tests/test_utils_run_later.py::test_yesterday_matmul_single type: Function lineno: 167 - Outcome:
-
✅ tests/test_utils_sendmail.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_sendmail.py::test_sendmail_local_delivery type: Function lineno: 13 - nodeid: tests/test_utils_sendmail.py::test_sendmail_raises_on_sendmail_failure type: Function lineno: 60 - Outcome:
-
✅ tests/test_utils_sendsms.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_sendsms.py::test_sendsms_local_delivery type: Function lineno: 6 - Outcome:
-
✅ tests/test_utils_shortcut.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_shortcut.py::TestShortcutInitialization type: Class - nodeid: tests/test_utils_shortcut.py::test_run_method type: Function lineno: 31 - nodeid: tests/test_utils_shortcut.py::test_repr_output type: Function lineno: 54 - nodeid: tests/test_utils_shortcut.py::test_source_with_regular_function type: Function lineno: 62 - nodeid: tests/test_utils_shortcut.py::test_source_error_handling type: Function lineno: 76 - nodeid: tests/test_utils_shortcut.py::test_as_shortcut_basic type: Function lineno: 86 - nodeid: tests/test_utils_shortcut.py::test_as_shortcut_with_name type: Function lineno: 96 - nodeid: tests/test_utils_shortcut.py::test_as_shortcut_factory_pattern type: Function lineno: 104 - nodeid: tests/test_utils_shortcut.py::TestShortcutsSingleton type: Class - nodeid: tests/test_utils_shortcut.py::TestFullIntegration type: Class - nodeid: tests/test_utils_shortcut.py::test_registry_inheritance type: Function lineno: 204 - Outcome:
-
✅ tests/test_utils_shortcut.py::TestFullIntegration
- Outcome:
passed - result:
- nodeid: tests/test_utils_shortcut.py::TestFullIntegration::test_workflow type: Function lineno: 170 - nodeid: tests/test_utils_shortcut.py::TestFullIntegration::test_multiple_shortcuts type: Function lineno: 190 - Outcome:
-
✅ tests/test_utils_shortcut.py::TestShortcutInitialization
- Outcome:
passed - result:
- nodeid: tests/test_utils_shortcut.py::TestShortcutInitialization::test_init_with_custom_name type: Function lineno: 16 - nodeid: tests/test_utils_shortcut.py::TestShortcutInitialization::test_init_without_name type: Function lineno: 23 - Outcome:
-
✅ tests/test_utils_shortcut.py::TestShortcutsSingleton
- Outcome:
passed - result:
- nodeid: tests/test_utils_shortcut.py::TestShortcutsSingleton::test_singleton_behavior type: Function lineno: 121 - nodeid: tests/test_utils_shortcut.py::TestShortcutsSingleton::test_registration type: Function lineno: 127 - nodeid: tests/test_utils_shortcut.py::TestShortcutsSingleton::test_getitem_access type: Function lineno: 141 - nodeid: tests/test_utils_shortcut.py::TestShortcutsSingleton::test_missing_key type: Function lineno: 149 - nodeid: tests/test_utils_shortcut.py::TestShortcutsSingleton::test_repr_output type: Function lineno: 154 - Outcome:
-
✅ tests/test_utils_snapshot.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_snapshot.py::test_snapshot[exclude_internals] type: Function lineno: 83 - nodeid: tests/test_utils_snapshot.py::test_snapshot[include_internals] type: Function lineno: 83 - nodeid: tests/test_utils_snapshot.py::test_snapshot[empty_case] type: Function lineno: 83 - nodeid: tests/test_utils_snapshot.py::test_snapshot[sort_str] type: Function lineno: 83 - nodeid: tests/test_utils_snapshot.py::test_snapshot[sort_id] type: Function lineno: 83 - nodeid: tests/test_utils_snapshot.py::test_snapshot[sort_case_insensitive] type: Function lineno: 83 - nodeid: tests/test_utils_snapshot.py::test_snapshot[sort_length] type: Function lineno: 83 - nodeid: tests/test_utils_snapshot.py::test_snapshot[sort_reverse] type: Function lineno: 83 - Outcome:
-
✅ tests/test_utils_termtitle.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_termtitle.py::test_terminal_title_with_tmux type: Function lineno: 9 - Outcome:
-
✅ tests/test_utils_tqdm_mod.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_tqdm_mod.py::test_complete_progress_bar type: Function lineno: 25 - nodeid: tests/test_utils_tqdm_mod.py::test_set_progress_multiple_points type: Function lineno: 42 - nodeid: tests/test_utils_tqdm_mod.py::test_format_sizeof_alignment type: Function lineno: 65 - nodeid: tests/test_utils_tqdm_mod.py::test_float_alignment_in_bar type: Function lineno: 83 - nodeid: tests/test_utils_tqdm_mod.py::test_custom_unit type: Function lineno: 132 - nodeid: tests/test_utils_tqdm_mod.py::test_clamp_above_total type: Function lineno: 146 - nodeid: tests/test_utils_tqdm_mod.py::test_clamp_below_zero type: Function lineno: 163 - Outcome:
-
✅ tests/test_utils_trinary.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_trinary.py::test_check_trinary_valid_values type: Function lineno: 6 - nodeid: tests/test_utils_trinary.py::test_check_trinary_invalid_value type: Function lineno: 14 - nodeid: tests/test_utils_trinary.py::test_check_trinary_with_custom_allowed_values type: Function lineno: 22 - Outcome:
-
✅ tests/test_utils_typecast.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_typecast.py::test_downcast_success type: Function lineno: 24 - nodeid: tests/test_utils_typecast.py::test_upcast_success type: Function lineno: 30 - nodeid: tests/test_utils_typecast.py::test_downcast_invalid type: Function lineno: 41 - nodeid: tests/test_utils_typecast.py::test_upcast_invalid type: Function lineno: 48 - nodeid: tests/test_utils_typecast.py::test_object_identity_preserved type: Function lineno: 53 - nodeid: tests/test_utils_typecast.py::test_ensure_subclass_valid type: Function lineno: 64 - nodeid: tests/test_utils_typecast.py::test_ensure_subclass_invalid type: Function lineno: 67 - nodeid: tests/test_utils_typecast.py::test_cast_changes_class type: Function lineno: 79 - nodeid: tests/test_utils_typecast.py::test_cast_preserves_identity type: Function lineno: 86 - Outcome:
-
✅ tests/test_utils_utils.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_utils.py::test_singleton_instance type: Function lineno: 17 - nodeid: tests/test_utils_utils.py::test_singleton_identity type: Function lineno: 25 - nodeid: tests/test_utils_utils.py::test_typename[None-NoneType] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[True-bool] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[42-int] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[3.14-float] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[text-str] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[obj5-set] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[obj6-list] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[obj7-list] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[obj8-dict] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[<lambda>-function] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[sample_function-function] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[nested-function] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[len-builtin_function_or_method] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[sum-builtin_function_or_method] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[math-module] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[sys-module] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[function-type] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[<genexpr>-generator] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_typename[obj18-list_iterator] type: Function lineno: 44 - nodeid: tests/test_utils_utils.py::test_next_int[nums0-4] type: Function lineno: 77 - nodeid: tests/test_utils_utils.py::test_next_int[nums1-21] type: Function lineno: 77 - nodeid: tests/test_utils_utils.py::test_next_int[nums2-0] type: Function lineno: 77 - nodeid: tests/test_utils_utils.py::test_zero_pad[7-3-007] type: Function lineno: 87 - nodeid: tests/test_utils_utils.py::test_zero_pad[123-5-00123] type: Function lineno: 87 - nodeid: tests/test_utils_utils.py::test_zero_pad[0-2-00] type: Function lineno: 87 - nodeid: tests/test_utils_utils.py::test_iround[3.6-4] type: Function lineno: 97 - nodeid: tests/test_utils_utils.py::test_iround[2.1-2] type: Function lineno: 97 - nodeid: tests/test_utils_utils.py::test_iround[-1.5--2] type: Function lineno: 97 - nodeid: tests/test_utils_utils.py::test_iround[-1.4--1] type: Function lineno: 97 - nodeid: tests/test_utils_utils.py::test_sorted_naturally[items0-expected0] type: Function lineno: 108 - nodeid: tests/test_utils_utils.py::test_sorted_naturally[items1-expected1] type: Function lineno: 108 - nodeid: tests/test_utils_utils.py::test_sorted_naturally_reverse[items0-expected0] type: Function lineno: 115 - Outcome:
-
✅ tests/test_utils_xrange.py
- Outcome:
passed - result:
- nodeid: tests/test_utils_xrange.py::test_xrange_finite[args0-kwargs0-expected0] type: Function lineno: 11 - nodeid: tests/test_utils_xrange.py::test_xrange_finite[args1-kwargs1-expected1] type: Function lineno: 11 - nodeid: tests/test_utils_xrange.py::test_xrange_finite[args2-kwargs2-expected2] type: Function lineno: 11 - nodeid: tests/test_utils_xrange.py::test_xrange_finite[args3-kwargs3-expected3] type: Function lineno: 11 - nodeid: tests/test_utils_xrange.py::test_xrange_infinite[args0-kwargs0-count(0)] type: Function lineno: 20 - nodeid: tests/test_utils_xrange.py::test_xrange_infinite[args1-kwargs1-count(0, 2)] type: Function lineno: 20 - nodeid: tests/test_utils_xrange.py::test_xrange_too_many_args[args0] type: Function lineno: 31 - Outcome:
- Outcome:
✅ . (1 tests)
-
✅ .
- Outcome:
passed - result:
- nodeid: ci-reports type: Dir - nodeid: markdown type: Dir - nodeid: morbidissimo type: Dir - nodeid: outputs type: Dir - nodeid: slic type: Package - nodeid: temp-ci type: Dir - nodeid: test-ci type: Dir - nodeid: tests type: Dir - Outcome:
⚠️ Warnings
Warnings nº1
message: The module numpy.dual is deprecated. Instead of using dual, use the functions directly from numpy or scipy.
category: DeprecationWarning
when: collect
filename: /root/mambaforge/envs/ci-env/lib/python3.8/site-packages/scipy/fft/__init__.py
lineno: 97
Warnings nº2
message: invalid escape sequence \[
category: DeprecationWarning
when: collect
filename: /workspace/tligui_y/slic/tests/test_utils_pv.py
lineno: 12