diff --git a/markdown/TEST-REPORT.md b/markdown/TEST-REPORT.md index 0c3c8c390..da53088c8 100644 --- a/markdown/TEST-REPORT.md +++ b/markdown/TEST-REPORT.md @@ -1,35 +1,34 @@ # πŸ§ͺ Test Report -*Generated on 2025-08-14 14:30:14 CEST* +*Generated on 2025-08-14 14:34:19 CEST* ## 🧾 General Info -- **duration**: 5.750641107559204 +- **duration**: 7.61622428894043 - **root**: /workspace/tligui_y/slic - **environment**: {} ## πŸ“‹ Summary -- **Passed**: 4 -- **Failed**: 1 +- **Failed**: 5 - **Total**: 5 - **Collected**: 5 ## πŸ”Ž Tests
-βœ… Passed (4) +❌ Failed (5) -
πŸ“„ test_utils_elog.py ↳ Function: test_get_default_elog_instance_with_direct_password_and_real_check -
- βœ… Test 1 + ❌ Test 1 **_*πŸ“Œ Setup phase*_** **duration:** ```python - 0.00041637104004621506 + 0.0004124320112168789 ``` **outcome:** @@ -43,201 +42,7 @@ **duration:** ```python - 0.05062804976478219 - ``` - - **outcome:** - - ```python - passed - ``` - - **_*πŸ“Œ Teardown phase*_** - - **duration:** - - ```python - 0.0003547673113644123 - ``` - - **outcome:** - - ```python - passed - ``` -
- ↳ Function: test_get_default_elog_instance_asks_password_and_opens - -
- βœ… Test 3 - - **_*πŸ“Œ Setup phase*_** - - **duration:** - - ```python - 0.00014722859486937523 - ``` - - **outcome:** - - ```python - passed - ``` - - **_*πŸ“Œ Call phase*_** - - **duration:** - - ```python - 0.03722065594047308 - ``` - - **outcome:** - - ```python - passed - ``` - - **_*πŸ“Œ Teardown phase*_** - - **duration:** - - ```python - 0.00023599294945597649 - ``` - - **outcome:** - - ```python - passed - ``` -
- ↳ Function: test_get_default_elog_with_path_home - -
- βœ… Test 4 - - **_*πŸ“Œ Setup phase*_** - - **duration:** - - ```python - 0.00017005391418933868 - ``` - - **outcome:** - - ```python - passed - ``` - - **_*πŸ“Œ Call phase*_** - - **duration:** - - ```python - 0.04208977613598108 - ``` - - **outcome:** - - ```python - passed - ``` - - **_*πŸ“Œ Teardown phase*_** - - **duration:** - - ```python - 0.0001906808465719223 - ``` - - **outcome:** - - ```python - passed - ``` -
- ↳ Function: test_screenshot - -
- βœ… Test 5 - - **_*πŸ“Œ Setup phase*_** - - **duration:** - - ```python - 0.00015419302508234978 - ``` - - **outcome:** - - ```python - passed - ``` - - **_*πŸ“Œ Call phase*_** - - **duration:** - - ```python - 0.04473493807017803 - ``` - - **outcome:** - - ```python - passed - ``` - - **_*πŸ“Œ Teardown phase*_** - - **duration:** - - ```python - 0.00021846918389201164 - ``` - - **outcome:** - - ```python - passed - ``` -
-
- -
- -
-❌ Failed (1) - - -
- πŸ“„ test_utils_elog.py - - ↳ Function: test_get_default_elog_instance_with_wrong_password_and_real_check - -
- ❌ Test 2 - - **_*πŸ“Œ Setup phase*_** - - **duration:** - - ```python - 0.00015277601778507233 - ``` - - **outcome:** - - ```python - passed - ``` - - **_*πŸ“Œ Call phase*_** - - **duration:** - - ```python - 0.008753607980906963 + 0.009815620258450508 ``` **outcome:** @@ -250,8 +55,1621 @@ ```python path: /workspace/tligui_y/slic/tests/test_utils_elog.py - lineno: 46 - message: Failed: DID NOT RAISE + lineno: 24 + message: Failed: elog.open() 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + ``` + + **traceback:** + + ```python + - path: tests/test_utils_elog.py + lineno: 24 + message: Failed + ``` + + **longrepr:** + + ```python + self = + + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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 + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError + + The above exception was the direct cause of the following exception: + + self = + method = 'POST', url = '/demo/' + body = b'--96e112f59bda8f70bf549fa0e3934bfe\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--96e112f59bda8f...Disposition: form-data; name="Text"; filename=""\r\n\r\nThis is a message1\r\n--96e112f59bda8f70bf549fa0e3934bfe--\r\n' + headers = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=96e112f59bda8f70bf549fa0e3934bfe'} + 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] + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request + conn.request( + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request + self.endheaders() + .pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders + self._send_output(message_body, encode_chunked=encode_chunked) + .pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output + self.send(msg) + .pixi/envs/default/lib/python3.8/http/client.py:951: in send + self.connect() + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect + self.sock = self._new_conn() + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + + 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: : Failed to establish a new connection: [Errno 111] Connection refused + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError + + The above exception was the direct cause of the following exception: + + self = + request = , 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 ` 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) ` 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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(': Failed to establish a new connection: [Errno 111] Connection refused') + _pool = + _stacktrace = + + 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError + + During handling of the above exception, another exception occurred: + + self = + message = 'This is a message1', msg_id = None, reply = False + attributes = {'Author': 'robot', 'When': 1755174853, 'cmd': 'Submit', 'exp': 'demo', ...} + attachments = [], suppress_email_notification = False, encoding = None + timeout = None, kwargs = {'Author': 'robot'} + logbook_directory = 'elog_instance/logbooks/demo' + new_attachment_list = [('Text', ('', b'This is a message1'))] + objects_to_close = [] + attributes_to_edit = {'Author': b'robot', 'When': 1755174853, '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. + """ + + logbook_directory = "elog_instance/logbooks/demo" + print(f"Checking the existence of the directory {logbook_directory}") + + # Check if the directory exists + if not os.path.exists(logbook_directory): + print(f"The directory {logbook_directory} does not exist.") + else: + print(f"The directory {logbook_directory} exists.") + + # Check write permissions + if os.access(logbook_directory, os.W_OK): + print(f"The directory {logbook_directory} has write permissions.") + else: + print(f"The directory {logbook_directory} does not have write permissions.") + + + print("STARTING POST") + # Ajout des impressions pour dΓ©boguer + print(f"Message to post: {message}") + print(f"msg_id: {msg_id}") + print(f"Attributes: {attributes}") + print(f"Attachments: {attachments}") + print(f"Encoding: {encoding}") + print(f"Timeout: {timeout}") + print(f"Additional kwargs: {kwargs}") + + attributes = attributes or {} + attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority + print(f"Updated attributes: {attributes}") + + attachments = attachments or [] + print(f"Attachments list: {attachments}") + + 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 + + # Prepare attachments + if attachments: + new_attachment_list, objects_to_close = self._prepare_attachments(attachments) + print(f"New attachments prepared: {new_attachment_list}") + else: + objects_to_close = [] + new_attachment_list = [] + + attributes_to_edit = dict() + + if msg_id: + print(f"Editing message with msg_id: {msg_id}") + if reply: + print(f"Replying to message with msg_id: {msg_id}") + self._check_if_message_on_server(msg_id) + attributes['reply_to'] = str(msg_id) + else: + print("Editing existing message.") + attributes['edit_id'] = str(msg_id) + attributes['skiplock'] = '1' + msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id) + + # Merge new attributes + for attribute, data in attributes.items(): + if data is not None: + attributes_to_edit[attribute] = data + + print(f"Attributes after merging: {attributes_to_edit}") + + # Process existing attachments + i = 0 + existing_attachments_filename_list = [] + for attachment in existing_attachments_list: + attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) + existing_attachments_filename_list.append(os.path.basename(attachment)[14:]) + i += 1 + + print(f"Existing attachments: {existing_attachments_filename_list}") + + duplicate_attachment_list = [] + for new_attachment in new_attachment_list: + new_attachment_filename = new_attachment[1][0] + print(f"Checking new attachment: {new_attachment_filename}") + if new_attachment_filename in existing_attachments_filename_list: + # Same attachment exists on the server, compare content + new_attachment_content = new_attachment[1][1].read() + new_attachment[1][1].seek(0) + attachment_index = existing_attachments_filename_list.index(new_attachment_filename) + existing_attachment_content = self.download_attachment( + url=existing_attachments_list[attachment_index], + timeout=timeout + ) + if new_attachment_content == existing_attachment_content: + print(f"Duplicate attachment detected: {new_attachment_filename}") + duplicate_attachment_list.append(new_attachment) + else: + print(f"Attachment content has changed: {new_attachment_filename}") + self.delete_attachment(msg_id, attributes=attributes_to_edit, + attachment_id=attachment_index, + timeout=timeout, text=msg_to_edit) + existing_attachments_filename_list.pop(attachment_index) + existing_attachments_list.pop(attachment_index) + + print(f"Duplicate attachments to remove: {duplicate_attachment_list}") + + # Remove duplicates + for attach in duplicate_attachment_list: + new_attachment_list.remove(attach) + + print(f"Final new attachments list: {new_attachment_list}") + else: + # Creating a new message, add timestamp if not present + if 'When' not in attributes: + attributes['When'] = int(datetime.now().timestamp()) + + # Final check on attributes + if not attributes_to_edit: + attributes_to_edit = attributes + + print(f"Final attributes to send to the server: {attributes_to_edit}") + + # Remove reserved attributes + _remove_reserved_attributes(attributes_to_edit) + + new_attachment_list.append(('Text', ('', message.encode('iso-8859-1')))) + print(f"Final attachment list including message text: {new_attachment_list}") + + # Add base message attributes + self._add_base_msg_attributes(attributes_to_edit) + print(f"Attributes with base message added: {attributes_to_edit}") + + # Sanitize attribute keys + attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit) + print(f"Attributes after sanitizing keys: {attributes_to_edit}") + + # Encode all string values in latin1 + attributes_to_edit = _encode_values(attributes_to_edit) + print(f"Attributes after encoding: {attributes_to_edit}") + + try: + print("Sending POST request to the server...") + > response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list, + allow_redirects=False, verify=False, timeout=timeout) + + slic/utils/logbook.py:269: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:115: in post + return request("post", url, data=data, json=json, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request + return session.request(method=method, url=url, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request + resp = self.send(prep, **send_kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send + r = adapter.send(request, **kwargs) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + request = , 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 ` 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) ` 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError + + During handling of the above exception, another exception occurred: + + self = + + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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 + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError + + The above exception was the direct cause of the following exception: + + self = + method = 'GET', url = '/demo/None', body = None + headers = {'User-Agent': 'python-requests/2.32.3', '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] + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request + conn.request( + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request + self.endheaders() + .pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders + self._send_output(message_body, encode_chunked=encode_chunked) + .pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output + self.send(msg) + .pixi/envs/default/lib/python3.8/http/client.py:951: in send + self.connect() + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect + self.sock = self._new_conn() + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + + 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: : Failed to establish a new connection: [Errno 111] Connection refused + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError + + The above exception was the direct cause of the following exception: + + self = + request = , 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 ` 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) ` 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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(': Failed to establish a new connection: [Errno 111] Connection refused') + _pool = + _stacktrace = + + 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError + + During handling of the above exception, another exception occurred: + + self = , 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 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) + + slic/utils/logbook.py:570: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:73: in get + return request("get", url, params=params, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request + return session.request(method=method, url=url, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request + resp = self.send(prep, **send_kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send + r = adapter.send(request, **kwargs) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + request = , 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 ` 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) ` 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/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: + > elog.post(text) + + tests/test_utils_elog.py:22: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + slic/utils/elog.py:17: in post + return self._log.post(*args, **kwargs) + slic/utils/logbook.py:289: in post + self._check_if_message_on_server(msg_id) # Raises exceptions if no message or no response from server + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = , 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 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('.*?', + 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 slic.utils.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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + slic/utils/logbook.py:590: 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: + elog.post(text) + except Exception as e: + > pytest.fail(f"elog.open() raised an unexpected exception: {e}") + E Failed: elog.open() 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + tests/test_utils_elog.py:24: Failed + ``` + + **_*πŸ“Œ Teardown phase*_** + + **duration:** + + ```python + 0.0004334989935159683 + ``` + + **outcome:** + + ```python + passed + ``` +
+ ↳ Function: test_get_default_elog_instance_with_wrong_password_and_real_check + -
+ ❌ Test 2 + + **_*πŸ“Œ Setup phase*_** + + **duration:** + + ```python + 0.00015929201617836952 + ``` + + **outcome:** + + ```python + passed + ``` + + **_*πŸ“Œ Call phase*_** + + **duration:** + + ```python + 0.008063088171184063 + ``` + + **outcome:** + + ```python + failed + ``` + + **crash:** + + ```python + path: /workspace/tligui_y/slic/slic/utils/logbook.py + lineno: 590 + message: slic.utils.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(': Failed to establish a new connection: [Errno 111] Connection refused')) ``` **traceback:** @@ -259,13 +1677,1487 @@ ```python - path: tests/test_utils_elog.py lineno: 46 - message: Failed + message: None + - path: slic/utils/elog.py + lineno: 17 + message: in post + - path: slic/utils/logbook.py + lineno: 289 + message: in post + - path: slic/utils/logbook.py + lineno: 590 + message: LogbookServerProblem ``` **longrepr:** ```python - def test_get_default_elog_instance_with_wrong_password_and_real_check(): + self = + + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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 + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError + + The above exception was the direct cause of the following exception: + + self = + method = 'POST', url = '/demo/' + body = b'--b64e560eb0f5f2b0688d5d5d1b3ce36d\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--b64e560eb0f5f2...ta; name="Text"; filename=""\r\n\r\nThis should fail due to wrong password\r\n--b64e560eb0f5f2b0688d5d5d1b3ce36d--\r\n' + headers = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '756', 'Content-Type': 'multipart/form-data; boundary=b64e560eb0f5f2b0688d5d5d1b3ce36d'} + 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] + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request + conn.request( + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request + self.endheaders() + .pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders + self._send_output(message_body, encode_chunked=encode_chunked) + .pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output + self.send(msg) + .pixi/envs/default/lib/python3.8/http/client.py:951: in send + self.connect() + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect + self.sock = self._new_conn() + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + + 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: : Failed to establish a new connection: [Errno 111] Connection refused + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError + + The above exception was the direct cause of the following exception: + + self = + request = , 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 ` 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) ` 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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(': Failed to establish a new connection: [Errno 111] Connection refused') + _pool = + _stacktrace = + + 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError + + During handling of the above exception, another exception occurred: + + self = + message = 'This should fail due to wrong password', msg_id = None, reply = False + attributes = {'Author': 'robot', 'When': 1755174854, 'cmd': 'Submit', 'exp': 'demo', ...} + attachments = [], suppress_email_notification = False, encoding = None + timeout = None, kwargs = {'Author': 'robot'} + logbook_directory = 'elog_instance/logbooks/demo' + new_attachment_list = [('Text', ('', b'This should fail due to wrong password'))] + objects_to_close = [] + attributes_to_edit = {'Author': b'robot', 'When': 1755174854, '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. + """ + + logbook_directory = "elog_instance/logbooks/demo" + print(f"Checking the existence of the directory {logbook_directory}") + + # Check if the directory exists + if not os.path.exists(logbook_directory): + print(f"The directory {logbook_directory} does not exist.") + else: + print(f"The directory {logbook_directory} exists.") + + # Check write permissions + if os.access(logbook_directory, os.W_OK): + print(f"The directory {logbook_directory} has write permissions.") + else: + print(f"The directory {logbook_directory} does not have write permissions.") + + + print("STARTING POST") + # Ajout des impressions pour dΓ©boguer + print(f"Message to post: {message}") + print(f"msg_id: {msg_id}") + print(f"Attributes: {attributes}") + print(f"Attachments: {attachments}") + print(f"Encoding: {encoding}") + print(f"Timeout: {timeout}") + print(f"Additional kwargs: {kwargs}") + + attributes = attributes or {} + attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority + print(f"Updated attributes: {attributes}") + + attachments = attachments or [] + print(f"Attachments list: {attachments}") + + 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 + + # Prepare attachments + if attachments: + new_attachment_list, objects_to_close = self._prepare_attachments(attachments) + print(f"New attachments prepared: {new_attachment_list}") + else: + objects_to_close = [] + new_attachment_list = [] + + attributes_to_edit = dict() + + if msg_id: + print(f"Editing message with msg_id: {msg_id}") + if reply: + print(f"Replying to message with msg_id: {msg_id}") + self._check_if_message_on_server(msg_id) + attributes['reply_to'] = str(msg_id) + else: + print("Editing existing message.") + attributes['edit_id'] = str(msg_id) + attributes['skiplock'] = '1' + msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id) + + # Merge new attributes + for attribute, data in attributes.items(): + if data is not None: + attributes_to_edit[attribute] = data + + print(f"Attributes after merging: {attributes_to_edit}") + + # Process existing attachments + i = 0 + existing_attachments_filename_list = [] + for attachment in existing_attachments_list: + attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) + existing_attachments_filename_list.append(os.path.basename(attachment)[14:]) + i += 1 + + print(f"Existing attachments: {existing_attachments_filename_list}") + + duplicate_attachment_list = [] + for new_attachment in new_attachment_list: + new_attachment_filename = new_attachment[1][0] + print(f"Checking new attachment: {new_attachment_filename}") + if new_attachment_filename in existing_attachments_filename_list: + # Same attachment exists on the server, compare content + new_attachment_content = new_attachment[1][1].read() + new_attachment[1][1].seek(0) + attachment_index = existing_attachments_filename_list.index(new_attachment_filename) + existing_attachment_content = self.download_attachment( + url=existing_attachments_list[attachment_index], + timeout=timeout + ) + if new_attachment_content == existing_attachment_content: + print(f"Duplicate attachment detected: {new_attachment_filename}") + duplicate_attachment_list.append(new_attachment) + else: + print(f"Attachment content has changed: {new_attachment_filename}") + self.delete_attachment(msg_id, attributes=attributes_to_edit, + attachment_id=attachment_index, + timeout=timeout, text=msg_to_edit) + existing_attachments_filename_list.pop(attachment_index) + existing_attachments_list.pop(attachment_index) + + print(f"Duplicate attachments to remove: {duplicate_attachment_list}") + + # Remove duplicates + for attach in duplicate_attachment_list: + new_attachment_list.remove(attach) + + print(f"Final new attachments list: {new_attachment_list}") + else: + # Creating a new message, add timestamp if not present + if 'When' not in attributes: + attributes['When'] = int(datetime.now().timestamp()) + + # Final check on attributes + if not attributes_to_edit: + attributes_to_edit = attributes + + print(f"Final attributes to send to the server: {attributes_to_edit}") + + # Remove reserved attributes + _remove_reserved_attributes(attributes_to_edit) + + new_attachment_list.append(('Text', ('', message.encode('iso-8859-1')))) + print(f"Final attachment list including message text: {new_attachment_list}") + + # Add base message attributes + self._add_base_msg_attributes(attributes_to_edit) + print(f"Attributes with base message added: {attributes_to_edit}") + + # Sanitize attribute keys + attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit) + print(f"Attributes after sanitizing keys: {attributes_to_edit}") + + # Encode all string values in latin1 + attributes_to_edit = _encode_values(attributes_to_edit) + print(f"Attributes after encoding: {attributes_to_edit}") + + try: + print("Sending POST request to the server...") + > response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list, + allow_redirects=False, verify=False, timeout=timeout) + + slic/utils/logbook.py:269: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:115: in post + return request("post", url, data=data, json=json, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request + return session.request(method=method, url=url, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request + resp = self.send(prep, **send_kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send + r = adapter.send(request, **kwargs) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + request = , 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 ` 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) ` 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError + + During handling of the above exception, another exception occurred: + + self = + + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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 + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError + + The above exception was the direct cause of the following exception: + + self = + method = 'GET', url = '/demo/None', body = None + headers = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=Aj8sEsZ0GjABo6Ky3wVo9vClIh8jCGRqB0l6XLwkR38;'} + 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] + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request + conn.request( + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request + self.endheaders() + .pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders + self._send_output(message_body, encode_chunked=encode_chunked) + .pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output + self.send(msg) + .pixi/envs/default/lib/python3.8/http/client.py:951: in send + self.connect() + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect + self.sock = self._new_conn() + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + + 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: : Failed to establish a new connection: [Errno 111] Connection refused + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError + + The above exception was the direct cause of the following exception: + + self = + request = , 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 ` 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) ` 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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(': Failed to establish a new connection: [Errno 111] Connection refused') + _pool = + _stacktrace = + + 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError + + During handling of the above exception, another exception occurred: + + self = , 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 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) + + slic/utils/logbook.py:570: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:73: in get + return request("get", url, params=params, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request + return session.request(method=method, url=url, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request + resp = self.send(prep, **send_kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send + r = adapter.send(request, **kwargs) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + request = , 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 ` 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) ` 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/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_wrong_password_and_real_check(): url = "http://localhost:8080/demo" user = "robot" wrong_password = "wrongpassword" @@ -274,9 +3166,56 @@ with pytest.raises(LogbookAuthenticationError): > elog.post("This should fail due to wrong password") - E Failed: DID NOT RAISE - tests/test_utils_elog.py:46: Failed + tests/test_utils_elog.py:46: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + slic/utils/elog.py:17: in post + return self._log.post(*args, **kwargs) + slic/utils/logbook.py:289: in post + self._check_if_message_on_server(msg_id) # Raises exceptions if no message or no response from server + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = , 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 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('.*?', + 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 slic.utils.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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + slic/utils/logbook.py:590: LogbookServerProblem ``` **_*πŸ“Œ Teardown phase*_** @@ -284,7 +3223,4885 @@ **duration:** ```python - 0.00027218740433454514 + 0.0002921079285442829 + ``` + + **outcome:** + + ```python + passed + ``` +
+ ↳ Function: test_get_default_elog_instance_asks_password_and_opens + -
+ ❌ Test 3 + + **_*πŸ“Œ Setup phase*_** + + **duration:** + + ```python + 0.00015496276319026947 + ``` + + **outcome:** + + ```python + passed + ``` + + **_*πŸ“Œ Call phase*_** + + **duration:** + + ```python + 0.014144825749099255 + ``` + + **outcome:** + + ```python + failed + ``` + + **crash:** + + ```python + path: /workspace/tligui_y/slic/tests/test_utils_elog.py + lineno: 68 + message: Failed: elog.open() 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + ``` + + **traceback:** + + ```python + - path: tests/test_utils_elog.py + lineno: 68 + message: Failed + ``` + + **longrepr:** + + ```python + self = + + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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 + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError + + The above exception was the direct cause of the following exception: + + self = + method = 'POST', url = '/demo/' + body = b'--edb3c41c85b235f5b6f6b089151ef961\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--edb3c41c85b235...Disposition: form-data; name="Text"; filename=""\r\n\r\nThis is a message2\r\n--edb3c41c85b235f5b6f6b089151ef961--\r\n' + headers = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=edb3c41c85b235f5b6f6b089151ef961'} + 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] + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request + conn.request( + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request + self.endheaders() + .pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders + self._send_output(message_body, encode_chunked=encode_chunked) + .pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output + self.send(msg) + .pixi/envs/default/lib/python3.8/http/client.py:951: in send + self.connect() + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect + self.sock = self._new_conn() + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + + 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: : Failed to establish a new connection: [Errno 111] Connection refused + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError + + The above exception was the direct cause of the following exception: + + self = + request = , 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 ` 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) ` 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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(': Failed to establish a new connection: [Errno 111] Connection refused') + _pool = + _stacktrace = + + 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError + + During handling of the above exception, another exception occurred: + + self = + message = 'This is a message2', msg_id = None, reply = False + attributes = {'Author': 'robot', 'When': 1755174854, 'cmd': 'Submit', 'exp': 'demo', ...} + attachments = [], suppress_email_notification = False, encoding = None + timeout = None, kwargs = {'Author': 'robot'} + logbook_directory = 'elog_instance/logbooks/demo' + new_attachment_list = [('Text', ('', b'This is a message2'))] + objects_to_close = [] + attributes_to_edit = {'Author': b'robot', 'When': 1755174854, '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. + """ + + logbook_directory = "elog_instance/logbooks/demo" + print(f"Checking the existence of the directory {logbook_directory}") + + # Check if the directory exists + if not os.path.exists(logbook_directory): + print(f"The directory {logbook_directory} does not exist.") + else: + print(f"The directory {logbook_directory} exists.") + + # Check write permissions + if os.access(logbook_directory, os.W_OK): + print(f"The directory {logbook_directory} has write permissions.") + else: + print(f"The directory {logbook_directory} does not have write permissions.") + + + print("STARTING POST") + # Ajout des impressions pour dΓ©boguer + print(f"Message to post: {message}") + print(f"msg_id: {msg_id}") + print(f"Attributes: {attributes}") + print(f"Attachments: {attachments}") + print(f"Encoding: {encoding}") + print(f"Timeout: {timeout}") + print(f"Additional kwargs: {kwargs}") + + attributes = attributes or {} + attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority + print(f"Updated attributes: {attributes}") + + attachments = attachments or [] + print(f"Attachments list: {attachments}") + + 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 + + # Prepare attachments + if attachments: + new_attachment_list, objects_to_close = self._prepare_attachments(attachments) + print(f"New attachments prepared: {new_attachment_list}") + else: + objects_to_close = [] + new_attachment_list = [] + + attributes_to_edit = dict() + + if msg_id: + print(f"Editing message with msg_id: {msg_id}") + if reply: + print(f"Replying to message with msg_id: {msg_id}") + self._check_if_message_on_server(msg_id) + attributes['reply_to'] = str(msg_id) + else: + print("Editing existing message.") + attributes['edit_id'] = str(msg_id) + attributes['skiplock'] = '1' + msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id) + + # Merge new attributes + for attribute, data in attributes.items(): + if data is not None: + attributes_to_edit[attribute] = data + + print(f"Attributes after merging: {attributes_to_edit}") + + # Process existing attachments + i = 0 + existing_attachments_filename_list = [] + for attachment in existing_attachments_list: + attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) + existing_attachments_filename_list.append(os.path.basename(attachment)[14:]) + i += 1 + + print(f"Existing attachments: {existing_attachments_filename_list}") + + duplicate_attachment_list = [] + for new_attachment in new_attachment_list: + new_attachment_filename = new_attachment[1][0] + print(f"Checking new attachment: {new_attachment_filename}") + if new_attachment_filename in existing_attachments_filename_list: + # Same attachment exists on the server, compare content + new_attachment_content = new_attachment[1][1].read() + new_attachment[1][1].seek(0) + attachment_index = existing_attachments_filename_list.index(new_attachment_filename) + existing_attachment_content = self.download_attachment( + url=existing_attachments_list[attachment_index], + timeout=timeout + ) + if new_attachment_content == existing_attachment_content: + print(f"Duplicate attachment detected: {new_attachment_filename}") + duplicate_attachment_list.append(new_attachment) + else: + print(f"Attachment content has changed: {new_attachment_filename}") + self.delete_attachment(msg_id, attributes=attributes_to_edit, + attachment_id=attachment_index, + timeout=timeout, text=msg_to_edit) + existing_attachments_filename_list.pop(attachment_index) + existing_attachments_list.pop(attachment_index) + + print(f"Duplicate attachments to remove: {duplicate_attachment_list}") + + # Remove duplicates + for attach in duplicate_attachment_list: + new_attachment_list.remove(attach) + + print(f"Final new attachments list: {new_attachment_list}") + else: + # Creating a new message, add timestamp if not present + if 'When' not in attributes: + attributes['When'] = int(datetime.now().timestamp()) + + # Final check on attributes + if not attributes_to_edit: + attributes_to_edit = attributes + + print(f"Final attributes to send to the server: {attributes_to_edit}") + + # Remove reserved attributes + _remove_reserved_attributes(attributes_to_edit) + + new_attachment_list.append(('Text', ('', message.encode('iso-8859-1')))) + print(f"Final attachment list including message text: {new_attachment_list}") + + # Add base message attributes + self._add_base_msg_attributes(attributes_to_edit) + print(f"Attributes with base message added: {attributes_to_edit}") + + # Sanitize attribute keys + attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit) + print(f"Attributes after sanitizing keys: {attributes_to_edit}") + + # Encode all string values in latin1 + attributes_to_edit = _encode_values(attributes_to_edit) + print(f"Attributes after encoding: {attributes_to_edit}") + + try: + print("Sending POST request to the server...") + > response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list, + allow_redirects=False, verify=False, timeout=timeout) + + slic/utils/logbook.py:269: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:115: in post + return request("post", url, data=data, json=json, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request + return session.request(method=method, url=url, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request + resp = self.send(prep, **send_kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send + r = adapter.send(request, **kwargs) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + request = , 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 ` 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) ` 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError + + During handling of the above exception, another exception occurred: + + self = + + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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 + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError + + The above exception was the direct cause of the following exception: + + self = + method = 'GET', url = '/demo/None', body = None + headers = {'User-Agent': 'python-requests/2.32.3', '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] + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request + conn.request( + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request + self.endheaders() + .pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders + self._send_output(message_body, encode_chunked=encode_chunked) + .pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output + self.send(msg) + .pixi/envs/default/lib/python3.8/http/client.py:951: in send + self.connect() + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect + self.sock = self._new_conn() + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + + 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: : Failed to establish a new connection: [Errno 111] Connection refused + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError + + The above exception was the direct cause of the following exception: + + self = + request = , 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 ` 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) ` 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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(': Failed to establish a new connection: [Errno 111] Connection refused') + _pool = + _stacktrace = + + 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError + + During handling of the above exception, another exception occurred: + + self = , 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 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) + + slic/utils/logbook.py:570: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:73: in get + return request("get", url, params=params, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request + return session.request(method=method, url=url, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request + resp = self.send(prep, **send_kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send + r = adapter.send(request, **kwargs) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + request = , 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 ` 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) ` 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError + + During handling of the above exception, another exception occurred: + + mock_home = + mock_getpass = + + @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: + > elog.post(text) + + tests/test_utils_elog.py:66: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + slic/utils/elog.py:17: in post + return self._log.post(*args, **kwargs) + slic/utils/logbook.py:289: in post + self._check_if_message_on_server(msg_id) # Raises exceptions if no message or no response from server + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = , 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 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('.*?', + 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 slic.utils.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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + slic/utils/logbook.py:590: LogbookServerProblem + + During handling of the above exception, another exception occurred: + + mock_home = + mock_getpass = + + @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: + elog.post(text) + except Exception as e: + > pytest.fail(f"elog.open() raised an unexpected exception: {e}") + E Failed: elog.open() 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + tests/test_utils_elog.py:68: Failed + ``` + + **_*πŸ“Œ Teardown phase*_** + + **duration:** + + ```python + 0.0003055981360375881 + ``` + + **outcome:** + + ```python + passed + ``` +
+ ↳ Function: test_get_default_elog_with_path_home + -
+ ❌ Test 4 + + **_*πŸ“Œ Setup phase*_** + + **duration:** + + ```python + 0.00015193456783890724 + ``` + + **outcome:** + + ```python + passed + ``` + + **_*πŸ“Œ Call phase*_** + + **duration:** + + ```python + 0.009498361963778734 + ``` + + **outcome:** + + ```python + failed + ``` + + **crash:** + + ```python + path: /workspace/tligui_y/slic/tests/test_utils_elog.py + lineno: 102 + message: Failed: elog.open() 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + ``` + + **traceback:** + + ```python + - path: tests/test_utils_elog.py + lineno: 102 + message: Failed + ``` + + **longrepr:** + + ```python + self = + + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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 + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError + + The above exception was the direct cause of the following exception: + + self = + method = 'POST', url = '/demo/' + body = b'--74b91bc2bd26184234285e5f4a987328\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--74b91bc2bd2618...Disposition: form-data; name="Text"; filename=""\r\n\r\nThis is a message3\r\n--74b91bc2bd26184234285e5f4a987328--\r\n' + headers = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=74b91bc2bd26184234285e5f4a987328'} + 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] + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request + conn.request( + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request + self.endheaders() + .pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders + self._send_output(message_body, encode_chunked=encode_chunked) + .pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output + self.send(msg) + .pixi/envs/default/lib/python3.8/http/client.py:951: in send + self.connect() + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect + self.sock = self._new_conn() + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + + 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: : Failed to establish a new connection: [Errno 111] Connection refused + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError + + The above exception was the direct cause of the following exception: + + self = + request = , 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 ` 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) ` 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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(': Failed to establish a new connection: [Errno 111] Connection refused') + _pool = + _stacktrace = + + 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError + + During handling of the above exception, another exception occurred: + + self = + message = 'This is a message3', msg_id = None, reply = False + attributes = {'Author': 'robot', 'When': 1755174855, 'cmd': 'Submit', 'exp': 'demo', ...} + attachments = [], suppress_email_notification = False, encoding = None + timeout = None, kwargs = {'Author': 'robot'} + logbook_directory = 'elog_instance/logbooks/demo' + new_attachment_list = [('Text', ('', b'This is a message3'))] + objects_to_close = [] + attributes_to_edit = {'Author': b'robot', 'When': 1755174855, '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. + """ + + logbook_directory = "elog_instance/logbooks/demo" + print(f"Checking the existence of the directory {logbook_directory}") + + # Check if the directory exists + if not os.path.exists(logbook_directory): + print(f"The directory {logbook_directory} does not exist.") + else: + print(f"The directory {logbook_directory} exists.") + + # Check write permissions + if os.access(logbook_directory, os.W_OK): + print(f"The directory {logbook_directory} has write permissions.") + else: + print(f"The directory {logbook_directory} does not have write permissions.") + + + print("STARTING POST") + # Ajout des impressions pour dΓ©boguer + print(f"Message to post: {message}") + print(f"msg_id: {msg_id}") + print(f"Attributes: {attributes}") + print(f"Attachments: {attachments}") + print(f"Encoding: {encoding}") + print(f"Timeout: {timeout}") + print(f"Additional kwargs: {kwargs}") + + attributes = attributes or {} + attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority + print(f"Updated attributes: {attributes}") + + attachments = attachments or [] + print(f"Attachments list: {attachments}") + + 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 + + # Prepare attachments + if attachments: + new_attachment_list, objects_to_close = self._prepare_attachments(attachments) + print(f"New attachments prepared: {new_attachment_list}") + else: + objects_to_close = [] + new_attachment_list = [] + + attributes_to_edit = dict() + + if msg_id: + print(f"Editing message with msg_id: {msg_id}") + if reply: + print(f"Replying to message with msg_id: {msg_id}") + self._check_if_message_on_server(msg_id) + attributes['reply_to'] = str(msg_id) + else: + print("Editing existing message.") + attributes['edit_id'] = str(msg_id) + attributes['skiplock'] = '1' + msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id) + + # Merge new attributes + for attribute, data in attributes.items(): + if data is not None: + attributes_to_edit[attribute] = data + + print(f"Attributes after merging: {attributes_to_edit}") + + # Process existing attachments + i = 0 + existing_attachments_filename_list = [] + for attachment in existing_attachments_list: + attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) + existing_attachments_filename_list.append(os.path.basename(attachment)[14:]) + i += 1 + + print(f"Existing attachments: {existing_attachments_filename_list}") + + duplicate_attachment_list = [] + for new_attachment in new_attachment_list: + new_attachment_filename = new_attachment[1][0] + print(f"Checking new attachment: {new_attachment_filename}") + if new_attachment_filename in existing_attachments_filename_list: + # Same attachment exists on the server, compare content + new_attachment_content = new_attachment[1][1].read() + new_attachment[1][1].seek(0) + attachment_index = existing_attachments_filename_list.index(new_attachment_filename) + existing_attachment_content = self.download_attachment( + url=existing_attachments_list[attachment_index], + timeout=timeout + ) + if new_attachment_content == existing_attachment_content: + print(f"Duplicate attachment detected: {new_attachment_filename}") + duplicate_attachment_list.append(new_attachment) + else: + print(f"Attachment content has changed: {new_attachment_filename}") + self.delete_attachment(msg_id, attributes=attributes_to_edit, + attachment_id=attachment_index, + timeout=timeout, text=msg_to_edit) + existing_attachments_filename_list.pop(attachment_index) + existing_attachments_list.pop(attachment_index) + + print(f"Duplicate attachments to remove: {duplicate_attachment_list}") + + # Remove duplicates + for attach in duplicate_attachment_list: + new_attachment_list.remove(attach) + + print(f"Final new attachments list: {new_attachment_list}") + else: + # Creating a new message, add timestamp if not present + if 'When' not in attributes: + attributes['When'] = int(datetime.now().timestamp()) + + # Final check on attributes + if not attributes_to_edit: + attributes_to_edit = attributes + + print(f"Final attributes to send to the server: {attributes_to_edit}") + + # Remove reserved attributes + _remove_reserved_attributes(attributes_to_edit) + + new_attachment_list.append(('Text', ('', message.encode('iso-8859-1')))) + print(f"Final attachment list including message text: {new_attachment_list}") + + # Add base message attributes + self._add_base_msg_attributes(attributes_to_edit) + print(f"Attributes with base message added: {attributes_to_edit}") + + # Sanitize attribute keys + attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit) + print(f"Attributes after sanitizing keys: {attributes_to_edit}") + + # Encode all string values in latin1 + attributes_to_edit = _encode_values(attributes_to_edit) + print(f"Attributes after encoding: {attributes_to_edit}") + + try: + print("Sending POST request to the server...") + > response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list, + allow_redirects=False, verify=False, timeout=timeout) + + slic/utils/logbook.py:269: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:115: in post + return request("post", url, data=data, json=json, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request + return session.request(method=method, url=url, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request + resp = self.send(prep, **send_kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send + r = adapter.send(request, **kwargs) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + request = , 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 ` 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) ` 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError + + During handling of the above exception, another exception occurred: + + self = + + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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 + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError + + The above exception was the direct cause of the following exception: + + self = + method = 'GET', url = '/demo/None', body = None + headers = {'User-Agent': 'python-requests/2.32.3', '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] + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request + conn.request( + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request + self.endheaders() + .pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders + self._send_output(message_body, encode_chunked=encode_chunked) + .pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output + self.send(msg) + .pixi/envs/default/lib/python3.8/http/client.py:951: in send + self.connect() + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect + self.sock = self._new_conn() + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + + 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: : Failed to establish a new connection: [Errno 111] Connection refused + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError + + The above exception was the direct cause of the following exception: + + self = + request = , 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 ` 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) ` 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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(': Failed to establish a new connection: [Errno 111] Connection refused') + _pool = + _stacktrace = + + 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError + + During handling of the above exception, another exception occurred: + + self = , 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 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) + + slic/utils/logbook.py:570: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:73: in get + return request("get", url, params=params, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request + return session.request(method=method, url=url, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request + resp = self.send(prep, **send_kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send + r = adapter.send(request, **kwargs) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + request = , 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 ` 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) ` 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError + + During handling of the above exception, another exception occurred: + + mock_home = + mock_getuser = + mock_getpass = + + @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: + > elog.post(text) + + tests/test_utils_elog.py:100: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + slic/utils/elog.py:17: in post + return self._log.post(*args, **kwargs) + slic/utils/logbook.py:289: in post + self._check_if_message_on_server(msg_id) # Raises exceptions if no message or no response from server + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = , 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 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('.*?', + 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 slic.utils.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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + slic/utils/logbook.py:590: LogbookServerProblem + + During handling of the above exception, another exception occurred: + + mock_home = + mock_getuser = + mock_getpass = + + @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: + elog.post(text) + except Exception as e: + > pytest.fail(f"elog.open() raised an unexpected exception: {e}") + E Failed: elog.open() 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + tests/test_utils_elog.py:102: Failed + ``` + + **_*πŸ“Œ Teardown phase*_** + + **duration:** + + ```python + 0.00037874793633818626 + ``` + + **outcome:** + + ```python + passed + ``` +
+ ↳ Function: test_screenshot + -
+ ❌ Test 5 + + **_*πŸ“Œ Setup phase*_** + + **duration:** + + ```python + 0.0001465831883251667 + ``` + + **outcome:** + + ```python + passed + ``` + + **_*πŸ“Œ Call phase*_** + + **duration:** + + ```python + 0.014574704691767693 + ``` + + **outcome:** + + ```python + failed + ``` + + **crash:** + + ```python + path: /workspace/tligui_y/slic/slic/utils/logbook.py + lineno: 590 + message: slic.utils.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(': Failed to establish a new connection: [Errno 111] Connection refused')) + ``` + + **traceback:** + + ```python + - path: tests/test_utils_elog.py + lineno: 141 + message: None + - path: slic/utils/elog.py + lineno: 22 + message: in screenshot + - path: slic/utils/elog.py + lineno: 17 + message: in post + - path: slic/utils/logbook.py + lineno: 289 + message: in post + - path: slic/utils/logbook.py + lineno: 590 + message: LogbookServerProblem + ``` + + **longrepr:** + + ```python + self = + + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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 + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError + + The above exception was the direct cause of the following exception: + + self = + method = 'POST', url = '/demo/' + body = b'--9eabc9334407552a4222d0e1189b02a7\r\nContent-Disposition: form-data; name="Author"\r\n\r\nrobot\r\n--9eabc933440755...-data; name="Text"; filename=""\r\n\r\nSCREENSHOT_INTEGRATION_TEST_MSG_456\r\n--9eabc9334407552a4222d0e1189b02a7--\r\n' + headers = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '889', 'Content-Type': 'multipart/form-data; boundary=9eabc9334407552a4222d0e1189b02a7'} + 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] + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request + conn.request( + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request + self.endheaders() + .pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders + self._send_output(message_body, encode_chunked=encode_chunked) + .pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output + self.send(msg) + .pixi/envs/default/lib/python3.8/http/client.py:951: in send + self.connect() + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect + self.sock = self._new_conn() + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + + 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: : Failed to establish a new connection: [Errno 111] Connection refused + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError + + The above exception was the direct cause of the following exception: + + self = + request = , 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 ` 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) ` 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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(': Failed to establish a new connection: [Errno 111] Connection refused') + _pool = + _stacktrace = + + 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError + + During handling of the above exception, another exception occurred: + + self = + message = 'SCREENSHOT_INTEGRATION_TEST_MSG_456', msg_id = None, reply = False + attributes = {'Author': 'robot', 'When': 1755174855, 'cmd': 'Submit', 'exp': 'demo', ...} + attachments = ['/tmp/fake_screenshot.png'], suppress_email_notification = False + encoding = None, timeout = None, kwargs = {'Author': 'robot'} + logbook_directory = 'elog_instance/logbooks/demo' + 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': 1755174855, '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. + """ + + logbook_directory = "elog_instance/logbooks/demo" + print(f"Checking the existence of the directory {logbook_directory}") + + # Check if the directory exists + if not os.path.exists(logbook_directory): + print(f"The directory {logbook_directory} does not exist.") + else: + print(f"The directory {logbook_directory} exists.") + + # Check write permissions + if os.access(logbook_directory, os.W_OK): + print(f"The directory {logbook_directory} has write permissions.") + else: + print(f"The directory {logbook_directory} does not have write permissions.") + + + print("STARTING POST") + # Ajout des impressions pour dΓ©boguer + print(f"Message to post: {message}") + print(f"msg_id: {msg_id}") + print(f"Attributes: {attributes}") + print(f"Attachments: {attachments}") + print(f"Encoding: {encoding}") + print(f"Timeout: {timeout}") + print(f"Additional kwargs: {kwargs}") + + attributes = attributes or {} + attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority + print(f"Updated attributes: {attributes}") + + attachments = attachments or [] + print(f"Attachments list: {attachments}") + + 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 + + # Prepare attachments + if attachments: + new_attachment_list, objects_to_close = self._prepare_attachments(attachments) + print(f"New attachments prepared: {new_attachment_list}") + else: + objects_to_close = [] + new_attachment_list = [] + + attributes_to_edit = dict() + + if msg_id: + print(f"Editing message with msg_id: {msg_id}") + if reply: + print(f"Replying to message with msg_id: {msg_id}") + self._check_if_message_on_server(msg_id) + attributes['reply_to'] = str(msg_id) + else: + print("Editing existing message.") + attributes['edit_id'] = str(msg_id) + attributes['skiplock'] = '1' + msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id) + + # Merge new attributes + for attribute, data in attributes.items(): + if data is not None: + attributes_to_edit[attribute] = data + + print(f"Attributes after merging: {attributes_to_edit}") + + # Process existing attachments + i = 0 + existing_attachments_filename_list = [] + for attachment in existing_attachments_list: + attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment) + existing_attachments_filename_list.append(os.path.basename(attachment)[14:]) + i += 1 + + print(f"Existing attachments: {existing_attachments_filename_list}") + + duplicate_attachment_list = [] + for new_attachment in new_attachment_list: + new_attachment_filename = new_attachment[1][0] + print(f"Checking new attachment: {new_attachment_filename}") + if new_attachment_filename in existing_attachments_filename_list: + # Same attachment exists on the server, compare content + new_attachment_content = new_attachment[1][1].read() + new_attachment[1][1].seek(0) + attachment_index = existing_attachments_filename_list.index(new_attachment_filename) + existing_attachment_content = self.download_attachment( + url=existing_attachments_list[attachment_index], + timeout=timeout + ) + if new_attachment_content == existing_attachment_content: + print(f"Duplicate attachment detected: {new_attachment_filename}") + duplicate_attachment_list.append(new_attachment) + else: + print(f"Attachment content has changed: {new_attachment_filename}") + self.delete_attachment(msg_id, attributes=attributes_to_edit, + attachment_id=attachment_index, + timeout=timeout, text=msg_to_edit) + existing_attachments_filename_list.pop(attachment_index) + existing_attachments_list.pop(attachment_index) + + print(f"Duplicate attachments to remove: {duplicate_attachment_list}") + + # Remove duplicates + for attach in duplicate_attachment_list: + new_attachment_list.remove(attach) + + print(f"Final new attachments list: {new_attachment_list}") + else: + # Creating a new message, add timestamp if not present + if 'When' not in attributes: + attributes['When'] = int(datetime.now().timestamp()) + + # Final check on attributes + if not attributes_to_edit: + attributes_to_edit = attributes + + print(f"Final attributes to send to the server: {attributes_to_edit}") + + # Remove reserved attributes + _remove_reserved_attributes(attributes_to_edit) + + new_attachment_list.append(('Text', ('', message.encode('iso-8859-1')))) + print(f"Final attachment list including message text: {new_attachment_list}") + + # Add base message attributes + self._add_base_msg_attributes(attributes_to_edit) + print(f"Attributes with base message added: {attributes_to_edit}") + + # Sanitize attribute keys + attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit) + print(f"Attributes after sanitizing keys: {attributes_to_edit}") + + # Encode all string values in latin1 + attributes_to_edit = _encode_values(attributes_to_edit) + print(f"Attributes after encoding: {attributes_to_edit}") + + try: + print("Sending POST request to the server...") + > response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list, + allow_redirects=False, verify=False, timeout=timeout) + + slic/utils/logbook.py:269: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:115: in post + return request("post", url, data=data, json=json, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request + return session.request(method=method, url=url, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request + resp = self.send(prep, **send_kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send + r = adapter.send(request, **kwargs) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + request = , 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 ` 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) ` 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError + + During handling of the above exception, another exception occurred: + + self = + + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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 + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError + + The above exception was the direct cause of the following exception: + + self = + method = 'GET', url = '/demo/None', body = None + headers = {'User-Agent': 'python-requests/2.32.3', '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] + 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request + conn.request( + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request + self.endheaders() + .pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders + self._send_output(message_body, encode_chunked=encode_chunked) + .pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output + self.send(msg) + .pixi/envs/default/lib/python3.8/http/client.py:951: in send + self.connect() + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect + self.sock = self._new_conn() + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + + 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: : Failed to establish a new connection: [Errno 111] Connection refused + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError + + The above exception was the direct cause of the following exception: + + self = + request = , 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 ` 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) ` 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, + ) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/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(': Failed to establish a new connection: [Errno 111] Connection refused') + _pool = + _stacktrace = + + 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError + + During handling of the above exception, another exception occurred: + + self = , 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 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) + + slic/utils/logbook.py:570: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:73: in get + return request("get", url, params=params, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request + return session.request(method=method, url=url, **kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request + resp = self.send(prep, **send_kwargs) + .pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send + r = adapter.send(request, **kwargs) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = + request = , 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 ` 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) ` 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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + .pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError + + During handling of the above exception, another exception occurred: + + mock_screenshot_class = + + @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 = Elog("http://localhost:8080/demo", user="robot", password="testpassword") + + test_msg = "SCREENSHOT_INTEGRATION_TEST_MSG_456" + > elog.screenshot(message=test_msg) + + tests/test_utils_elog.py:141: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + slic/utils/elog.py:22: in screenshot + self.post(message, **kwargs) + slic/utils/elog.py:17: in post + return self._log.post(*args, **kwargs) + slic/utils/logbook.py:289: in post + self._check_if_message_on_server(msg_id) # Raises exceptions if no message or no response from server + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + self = , 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 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('.*?', + 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 slic.utils.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(': Failed to establish a new connection: [Errno 111] Connection refused')) + + slic/utils/logbook.py:590: LogbookServerProblem + ``` + + **_*πŸ“Œ Teardown phase*_** + + **duration:** + + ```python + 0.0003166687674820423 ``` **outcome:** diff --git a/markdown/coverage-summary.md b/markdown/coverage-summary.md index 5e8365912..5f5dc044b 100644 --- a/markdown/coverage-summary.md +++ b/markdown/coverage-summary.md @@ -27066,3 +27066,230 @@ | slic/utils/utils.py | 17 | 8 | 53% | | slic/utils/xrange.py | 33 | 30 | 9% | | **TOTAL** | **9961** | **7230** | **27%** | +| Name | Stmts | Miss | Cover | +|----------------------------------------------- | -------: | -------: | ------: | +| slic/\_\_init\_\_.py | 20 | 2 | 90% | +| slic/core/\_\_init\_\_.py | 5 | 0 | 100% | +| slic/core/acquisition/\_\_init\_\_.py | 7 | 0 | 100% | +| slic/core/acquisition/acquisition.py | 56 | 42 | 25% | +| slic/core/acquisition/baseacquisition.py | 5 | 1 | 80% | +| slic/core/acquisition/broker/\_\_init\_\_.py | 2 | 0 | 100% | +| slic/core/acquisition/broker/brokerclient.py | 104 | 80 | 23% | +| slic/core/acquisition/broker/brokerconfig.py | 102 | 87 | 15% | +| slic/core/acquisition/broker/pedestal.py | 66 | 57 | 14% | +| slic/core/acquisition/broker/pids.py | 17 | 12 | 29% | +| slic/core/acquisition/broker/post\_retrieve.py | 120 | 120 | 0% | +| slic/core/acquisition/broker/requeststatus.py | 77 | 73 | 5% | +| slic/core/acquisition/broker/restapi.py | 147 | 107 | 27% | +| slic/core/acquisition/broker/tools.py | 52 | 18 | 65% | +| slic/core/acquisition/bsacquisition.py | 10 | 3 | 70% | +| slic/core/acquisition/bschannels.py | 30 | 19 | 37% | +| slic/core/acquisition/channels.py | 51 | 30 | 41% | +| slic/core/acquisition/dbacquisition.py | 19 | 12 | 37% | +| slic/core/acquisition/detcfg.py | 82 | 35 | 57% | +| slic/core/acquisition/diaacquisition.py | 111 | 111 | 0% | +| slic/core/acquisition/diaconfig.py | 36 | 36 | 0% | +| slic/core/acquisition/dummyacquisition.py | 12 | 12 | 0% | +| slic/core/acquisition/fakeacquisition.py | 76 | 53 | 30% | +| slic/core/acquisition/pedestals.py | 69 | 69 | 0% | +| slic/core/acquisition/pvacquisition.py | 60 | 47 | 22% | +| slic/core/acquisition/pvchannels.py | 13 | 7 | 46% | +| slic/core/acquisition/sfacquisition.py | 159 | 129 | 19% | +| slic/core/acquisition/sfpaths.py | 23 | 19 | 17% | +| slic/core/acquisition/spreadsheet.py | 45 | 45 | 0% | +| slic/core/adjustable/\_\_init\_\_.py | 11 | 0 | 100% | +| slic/core/adjustable/adjustable.py | 50 | 30 | 40% | +| slic/core/adjustable/baseadjustable.py | 28 | 18 | 36% | +| slic/core/adjustable/collection.py | 22 | 14 | 36% | +| slic/core/adjustable/combined.py | 15 | 8 | 47% | +| slic/core/adjustable/convenience.py | 35 | 20 | 43% | +| slic/core/adjustable/converted.py | 16 | 10 | 38% | +| slic/core/adjustable/dummyadjustable.py | 41 | 30 | 27% | +| slic/core/adjustable/error.py | 2 | 0 | 100% | +| slic/core/adjustable/genericadjustable.py | 32 | 24 | 25% | +| slic/core/adjustable/limited.py | 29 | 18 | 38% | +| slic/core/adjustable/linked.py | 22 | 15 | 32% | +| slic/core/adjustable/pvadjustable.py | 119 | 91 | 24% | +| slic/core/adjustable/pvchangemon.py | 77 | 56 | 27% | +| slic/core/adjustable/pvenumadjustable.py | 38 | 22 | 42% | +| slic/core/adjustable/scaler.py | 22 | 16 | 27% | +| slic/core/condition/\_\_init\_\_.py | 2 | 0 | 100% | +| slic/core/condition/basecondition.py | 8 | 2 | 75% | +| slic/core/condition/condition.py | 107 | 79 | 26% | +| slic/core/condition/pvcondition.py | 21 | 12 | 43% | +| slic/core/condition/valuecondition.py | 22 | 15 | 32% | +| slic/core/device/\_\_init\_\_.py | 2 | 0 | 100% | +| slic/core/device/auto.py | 12 | 12 | 0% | +| slic/core/device/basedevice.py | 2 | 0 | 100% | +| slic/core/device/device.py | 46 | 35 | 24% | +| slic/core/device/filtered.py | 23 | 23 | 0% | +| slic/core/device/simpledevice.py | 6 | 2 | 67% | +| slic/core/scanner/\_\_init\_\_.py | 1 | 0 | 100% | +| slic/core/scanner/runname.py | 36 | 23 | 36% | +| slic/core/scanner/scanbackend.py | 232 | 197 | 15% | +| slic/core/scanner/scaninfo.py | 45 | 35 | 22% | +| slic/core/scanner/scanner.py | 136 | 89 | 35% | +| slic/core/sensor/\_\_init\_\_.py | 8 | 0 | 100% | +| slic/core/sensor/basesensor.py | 12 | 3 | 75% | +| slic/core/sensor/bscombined.py | 9 | 5 | 44% | +| slic/core/sensor/bsmonitor.py | 102 | 73 | 28% | +| slic/core/sensor/bsnorm.py | 12 | 7 | 42% | +| slic/core/sensor/bssensor.py | 6 | 2 | 67% | +| slic/core/sensor/combined.py | 31 | 20 | 35% | +| slic/core/sensor/monitor.py | 62 | 51 | 18% | +| slic/core/sensor/norm.py | 9 | 5 | 44% | +| slic/core/sensor/pvsensor.py | 32 | 20 | 38% | +| slic/core/sensor/remoteplot.py | 15 | 10 | 33% | +| slic/core/sensor/sensor.py | 60 | 42 | 30% | +| slic/core/task/\_\_init\_\_.py | 4 | 0 | 100% | +| slic/core/task/basetask.py | 11 | 3 | 73% | +| slic/core/task/daqtask.py | 23 | 16 | 30% | +| slic/core/task/loop.py | 57 | 40 | 30% | +| slic/core/task/producer.py | 25 | 18 | 28% | +| slic/core/task/task.py | 62 | 46 | 26% | +| slic/devices/\_\_init\_\_.py | 7 | 0 | 100% | +| slic/devices/cameras/\_\_init\_\_.py | 4 | 0 | 100% | +| slic/devices/cameras/basler.py | 8 | 4 | 50% | +| slic/devices/cameras/camera\_bs.py | 13 | 8 | 38% | +| slic/devices/cameras/camera\_ca.py | 34 | 19 | 44% | +| slic/devices/cameras/camerabase.py | 17 | 12 | 29% | +| slic/devices/cameras/screenpanel.py | 31 | 21 | 32% | +| slic/devices/endstations/\_\_init\_\_.py | 3 | 0 | 100% | +| slic/devices/endstations/alvra\_flex.py | 10 | 5 | 50% | +| slic/devices/endstations/alvra\_huber.py | 8 | 4 | 50% | +| slic/devices/endstations/alvra\_prime.py | 48 | 34 | 29% | +| slic/devices/endstations/alvra\_xtg.py | 8 | 8 | 0% | +| slic/devices/endstations/bernina\_cameras.py | 33 | 33 | 0% | +| slic/devices/endstations/bernina\_platform.py | 46 | 46 | 0% | +| slic/devices/general/\_\_init\_\_.py | 4 | 0 | 100% | +| slic/devices/general/delay\_compensation.py | 13 | 13 | 0% | +| slic/devices/general/delay\_stage.py | 57 | 30 | 47% | +| slic/devices/general/detectors/\_\_init\_\_.py | 2 | 0 | 100% | +| slic/devices/general/detectors/buffer.py | 66 | 35 | 47% | +| slic/devices/general/detectors/digitizer.py | 13 | 7 | 46% | +| slic/devices/general/detectors/pvdatastream.py | 33 | 24 | 27% | +| slic/devices/general/detectors/timer.py | 15 | 9 | 40% | +| slic/devices/general/micosstage.py | 7 | 7 | 0% | +| slic/devices/general/motor.py | 128 | 88 | 31% | +| slic/devices/general/shutter.py | 22 | 12 | 45% | +| slic/devices/general/shutterctx.py | 18 | 7 | 61% | +| slic/devices/general/smaract.py | 169 | 125 | 26% | +| slic/devices/loptics/\_\_init\_\_.py | 2 | 0 | 100% | +| slic/devices/loptics/alvra\_explaser.py | 29 | 21 | 28% | +| slic/devices/loptics/bernina\_explaser.py | 28 | 28 | 0% | +| slic/devices/loptics/lasershutter.py | 22 | 14 | 36% | +| slic/devices/timing/\_\_init\_\_.py | 0 | 0 | 100% | +| slic/devices/timing/events/\_\_init\_\_.py | 3 | 3 | 0% | +| slic/devices/timing/events/codes.py | 5 | 5 | 0% | +| slic/devices/timing/events/ctaseq.py | 190 | 190 | 0% | +| slic/devices/timing/events/evr.py | 37 | 37 | 0% | +| slic/devices/timing/events/tma.py | 40 | 40 | 0% | +| slic/devices/timing/lasertiming.py | 253 | 184 | 27% | +| slic/devices/xdiagnostics/\_\_init\_\_.py | 2 | 0 | 100% | +| slic/devices/xdiagnostics/intensitymonitor.py | 124 | 92 | 26% | +| slic/devices/xdiagnostics/profilemonitor.py | 19 | 9 | 53% | +| slic/devices/xdiagnostics/timetools.py | 48 | 48 | 0% | +| slic/devices/xoptics/\_\_init\_\_.py | 7 | 0 | 100% | +| slic/devices/xoptics/aramis\_attenuator.py | 96 | 66 | 31% | +| slic/devices/xoptics/aramis\_reflaser.py | 23 | 15 | 35% | +| slic/devices/xoptics/dcm.py | 211 | 162 | 23% | +| slic/devices/xoptics/kb.py | 30 | 18 | 40% | +| slic/devices/xoptics/offsetmirrors.py | 9 | 5 | 44% | +| slic/devices/xoptics/pulsepicker.py | 56 | 34 | 39% | +| slic/devices/xoptics/slits/\_\_init\_\_.py | 5 | 0 | 100% | +| slic/devices/xoptics/slits/slitblades.py | 66 | 48 | 27% | +| slic/devices/xoptics/slits/slittwinunit.py | 12 | 6 | 50% | +| slic/devices/xoptics/slits/slitunit.py | 14 | 8 | 43% | +| slic/devices/xoptics/slits/slitunitcw.py | 7 | 3 | 57% | +| slic/devices/xoptics/slits/slitunitjj.py | 8 | 5 | 38% | +| slic/gui/\_\_init\_\_.py | 1 | 0 | 100% | +| slic/gui/daqframe.py | 75 | 54 | 28% | +| slic/gui/daqpanels/\_\_init\_\_.py | 6 | 0 | 100% | +| slic/gui/daqpanels/config.py | 98 | 80 | 18% | +| slic/gui/daqpanels/goto.py | 92 | 76 | 17% | +| slic/gui/daqpanels/run.py | 56 | 46 | 18% | +| slic/gui/daqpanels/scan2d.py | 77 | 66 | 14% | +| slic/gui/daqpanels/scan.py | 63 | 54 | 14% | +| slic/gui/daqpanels/sfx.py | 77 | 60 | 22% | +| slic/gui/daqpanels/special.py | 63 | 54 | 14% | +| slic/gui/daqpanels/static.py | 46 | 37 | 20% | +| slic/gui/daqpanels/tools.py | 140 | 114 | 19% | +| slic/gui/daqpanels/tweak.py | 149 | 127 | 15% | +| slic/gui/gui.py | 16 | 10 | 38% | +| slic/gui/icon.py | 8 | 4 | 50% | +| slic/gui/persist.py | 68 | 48 | 29% | +| slic/gui/widgets/\_\_init\_\_.py | 11 | 0 | 100% | +| slic/gui/widgets/alarm.py | 21 | 9 | 57% | +| slic/gui/widgets/alternative.py | 51 | 40 | 22% | +| slic/gui/widgets/boxes.py | 33 | 26 | 21% | +| slic/gui/widgets/checkbox.py | 8 | 4 | 50% | +| slic/gui/widgets/completers.py | 27 | 19 | 30% | +| slic/gui/widgets/dyncombo.py | 49 | 49 | 0% | +| slic/gui/widgets/entries.py | 253 | 195 | 23% | +| slic/gui/widgets/exc2warn.py | 15 | 13 | 13% | +| slic/gui/widgets/fname.py | 60 | 47 | 22% | +| slic/gui/widgets/jfcfg.py | 290 | 230 | 21% | +| slic/gui/widgets/jfmodcoords.py | 88 | 70 | 20% | +| slic/gui/widgets/labeled.py | 19 | 7 | 63% | +| slic/gui/widgets/lists.py | 96 | 73 | 24% | +| slic/gui/widgets/mods.py | 25 | 17 | 32% | +| slic/gui/widgets/nope.py | 26 | 19 | 27% | +| slic/gui/widgets/plotting.py | 68 | 47 | 31% | +| slic/gui/widgets/tools.py | 11 | 7 | 36% | +| slic/gui/widgets/twobuttons.py | 43 | 30 | 30% | +| slic/gui/wxdebug.py | 15 | 7 | 53% | +| slic/utils/\_\_init\_\_.py | 24 | 0 | 100% | +| slic/utils/argfwd.py | 53 | 14 | 74% | +| slic/utils/ask\_yes\_no.py | 27 | 20 | 26% | +| slic/utils/channels.py | 17 | 12 | 29% | +| slic/utils/config.py | 5 | 2 | 60% | +| slic/utils/cprint.py | 41 | 16 | 61% | +| slic/utils/dbusnotify.py | 40 | 24 | 40% | +| slic/utils/debug.py | 16 | 12 | 25% | +| slic/utils/dictext.py | 30 | 19 | 37% | +| slic/utils/dotdir.py | 10 | 1 | 90% | +| slic/utils/duo.py | 77 | 45 | 42% | +| slic/utils/elog.py | 32 | 0 | 100% | +| slic/utils/eval.py | 49 | 37 | 24% | +| slic/utils/exceptions.py | 22 | 14 | 36% | +| slic/utils/get\_adj.py | 17 | 11 | 35% | +| slic/utils/hastyepics.py | 37 | 25 | 32% | +| slic/utils/ioc/\_\_init\_\_.py | 1 | 1 | 0% | +| slic/utils/ioc/adjdrv.py | 31 | 31 | 0% | +| slic/utils/ioc/ioc.py | 63 | 63 | 0% | +| slic/utils/ipy.py | 22 | 15 | 32% | +| slic/utils/jsonext.py | 24 | 16 | 33% | +| slic/utils/lazypv.py | 12 | 12 | 0% | +| slic/utils/logbook.py | 418 | 258 | 38% | +| slic/utils/logbook\_exceptions.py | 13 | 0 | 100% | +| slic/utils/logcfg.py | 52 | 2 | 96% | +| slic/utils/logign.py | 22 | 14 | 36% | +| slic/utils/marker.py | 48 | 31 | 35% | +| slic/utils/metaclasses.py | 8 | 0 | 100% | +| slic/utils/namespace.py | 5 | 1 | 80% | +| slic/utils/npy.py | 71 | 56 | 21% | +| slic/utils/opmsg.py | 122 | 122 | 0% | +| slic/utils/path.py | 32 | 24 | 25% | +| slic/utils/picklio.py | 7 | 3 | 57% | +| slic/utils/printing.py | 77 | 61 | 21% | +| slic/utils/pv.py | 30 | 20 | 33% | +| slic/utils/pvpreload.py | 50 | 19 | 62% | +| slic/utils/pyepics.py | 64 | 39 | 39% | +| slic/utils/rangebar.py | 92 | 61 | 34% | +| slic/utils/readable.py | 12 | 9 | 25% | +| slic/utils/registry.py | 33 | 19 | 42% | +| slic/utils/reprate.py | 55 | 42 | 24% | +| slic/utils/richcfg.py | 21 | 11 | 48% | +| slic/utils/run\_later.py | 64 | 64 | 0% | +| slic/utils/screenshot.py | 30 | 19 | 37% | +| slic/utils/sendmail.py | 49 | 49 | 0% | +| slic/utils/sendsms.py | 5 | 5 | 0% | +| slic/utils/shortcut.py | 38 | 20 | 47% | +| slic/utils/snapshot.py | 6 | 3 | 50% | +| slic/utils/termtitle.py | 3 | 0 | 100% | +| slic/utils/tqdm\_mod.py | 28 | 18 | 36% | +| slic/utils/trinary.py | 4 | 2 | 50% | +| slic/utils/typecast.py | 19 | 19 | 0% | +| slic/utils/utils.py | 17 | 8 | 53% | +| slic/utils/xrange.py | 33 | 30 | 9% | +| **TOTAL** | **9961** | **7233** | **27%** | diff --git a/markdown/pytest-report.json b/markdown/pytest-report.json index 967ab9206..31f67fa21 100644 --- a/markdown/pytest-report.json +++ b/markdown/pytest-report.json @@ -1 +1 @@ -{"created": 1755174612.2620897, "duration": 5.750641107559204, "exitcode": 1, "root": "/workspace/tligui_y/slic", "environment": {}, "summary": {"passed": 4, "failed": 1, "total": 5, "collected": 5}, "collectors": [{"nodeid": "", "outcome": "passed", "result": [{"nodeid": "tests/test_utils_elog.py", "type": "Module"}]}, {"nodeid": "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": 37}, {"nodeid": "tests/test_utils_elog.py::test_get_default_elog_instance_asks_password_and_opens", "type": "Function", "lineno": 53}, {"nodeid": "tests/test_utils_elog.py::test_get_default_elog_with_path_home", "type": "Function", "lineno": 79}, {"nodeid": "tests/test_utils_elog.py::test_screenshot", "type": "Function", "lineno": 128}]}], "tests": [{"nodeid": "tests/test_utils_elog.py::test_get_default_elog_instance_with_direct_password_and_real_check", "lineno": 12, "outcome": "passed", "keywords": ["test_get_default_elog_instance_with_direct_password_and_real_check", "test_utils_elog.py", "tests", "slic", ""], "setup": {"duration": 0.00041637104004621506, "outcome": "passed"}, "call": {"duration": 0.05062804976478219, "outcome": "passed"}, "teardown": {"duration": 0.0003547673113644123, "outcome": "passed"}}, {"nodeid": "tests/test_utils_elog.py::test_get_default_elog_instance_with_wrong_password_and_real_check", "lineno": 37, "outcome": "failed", "keywords": ["test_get_default_elog_instance_with_wrong_password_and_real_check", "test_utils_elog.py", "tests", "slic", ""], "setup": {"duration": 0.00015277601778507233, "outcome": "passed"}, "call": {"duration": 0.008753607980906963, "outcome": "failed", "crash": {"path": "/workspace/tligui_y/slic/tests/test_utils_elog.py", "lineno": 46, "message": "Failed: DID NOT RAISE "}, "traceback": [{"path": "tests/test_utils_elog.py", "lineno": 46, "message": "Failed"}], "longrepr": "def test_get_default_elog_instance_with_wrong_password_and_real_check():\n url = \"http://localhost:8080/demo\"\n user = \"robot\"\n wrong_password = \"wrongpassword\"\n \n elog = Elog(url, user=user, password=wrong_password)\n \n with pytest.raises(LogbookAuthenticationError):\n> elog.post(\"This should fail due to wrong password\")\nE Failed: DID NOT RAISE \n\ntests/test_utils_elog.py:46: Failed"}, "teardown": {"duration": 0.00027218740433454514, "outcome": "passed"}}, {"nodeid": "tests/test_utils_elog.py::test_get_default_elog_instance_asks_password_and_opens", "lineno": 53, "outcome": "passed", "keywords": ["test_get_default_elog_instance_asks_password_and_opens", "__wrapped__", "patchings", "test_utils_elog.py", "tests", "slic", ""], "setup": {"duration": 0.00014722859486937523, "outcome": "passed"}, "call": {"duration": 0.03722065594047308, "outcome": "passed"}, "teardown": {"duration": 0.00023599294945597649, "outcome": "passed"}}, {"nodeid": "tests/test_utils_elog.py::test_get_default_elog_with_path_home", "lineno": 79, "outcome": "passed", "keywords": ["test_get_default_elog_with_path_home", "__wrapped__", "patchings", "test_utils_elog.py", "tests", "slic", ""], "setup": {"duration": 0.00017005391418933868, "outcome": "passed"}, "call": {"duration": 0.04208977613598108, "outcome": "passed"}, "teardown": {"duration": 0.0001906808465719223, "outcome": "passed"}}, {"nodeid": "tests/test_utils_elog.py::test_screenshot", "lineno": 128, "outcome": "passed", "keywords": ["test_screenshot", "__wrapped__", "patchings", "test_utils_elog.py", "tests", "slic", ""], "setup": {"duration": 0.00015419302508234978, "outcome": "passed"}, "call": {"duration": 0.04473493807017803, "outcome": "passed"}, "teardown": {"duration": 0.00021846918389201164, "outcome": "passed"}}], "warnings": [{"message": "invalid escape sequence \\-", "category": "DeprecationWarning", "when": "collect", "filename": "/workspace/tligui_y/slic/.pixi/envs/default/lib/python3.8/site-packages/bsread/h5.py", "lineno": 207}, {"message": "The module numpy.dual is deprecated. Instead of using dual, use the functions directly from numpy or scipy.", "category": "DeprecationWarning", "when": "collect", "filename": "/workspace/tligui_y/slic/.pixi/envs/default/lib/python3.8/site-packages/scipy/fft/__init__.py", "lineno": 97}]} \ No newline at end of file +{"created": 1755174857.2004645, "duration": 7.61622428894043, "exitcode": 1, "root": "/workspace/tligui_y/slic", "environment": {}, "summary": {"failed": 5, "total": 5, "collected": 5}, "collectors": [{"nodeid": "", "outcome": "passed", "result": [{"nodeid": "tests/test_utils_elog.py", "type": "Module"}]}, {"nodeid": "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": 37}, {"nodeid": "tests/test_utils_elog.py::test_get_default_elog_instance_asks_password_and_opens", "type": "Function", "lineno": 53}, {"nodeid": "tests/test_utils_elog.py::test_get_default_elog_with_path_home", "type": "Function", "lineno": 79}, {"nodeid": "tests/test_utils_elog.py::test_screenshot", "type": "Function", "lineno": 128}]}], "tests": [{"nodeid": "tests/test_utils_elog.py::test_get_default_elog_instance_with_direct_password_and_real_check", "lineno": 12, "outcome": "failed", "keywords": ["test_get_default_elog_instance_with_direct_password_and_real_check", "test_utils_elog.py", "tests", "slic", ""], "setup": {"duration": 0.0004124320112168789, "outcome": "passed"}, "call": {"duration": 0.009815620258450508, "outcome": "failed", "crash": {"path": "/workspace/tligui_y/slic/tests/test_utils_elog.py", "lineno": 24, "message": "Failed: elog.open() raised an unexpected exception: No response from the logbook server.\nDetails: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))"}, "traceback": [{"path": "tests/test_utils_elog.py", "lineno": 24, "message": "Failed"}], "longrepr": "self = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n> sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection\n raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\naddress = ('localhost', 8080), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n def create_connection(\n address: tuple[str, int],\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n source_address: tuple[str, int] | None = None,\n socket_options: _TYPE_SOCKET_OPTIONS | None = None,\n ) -> socket.socket:\n \"\"\"Connect to *address* and return the socket object.\n \n Convenience function. Connect to *address* (a 2-tuple ``(host,\n port)``) and return the socket object. Passing the optional\n *timeout* parameter will set the timeout on the socket instance\n before attempting to connect. If no *timeout* is supplied, the\n global default timeout setting returned by :func:`socket.getdefaulttimeout`\n is used. If *source_address* is set it must be a tuple of (host, port)\n for the socket to bind as a source address before making the connection.\n An host of '' or port 0 tells the OS to use the default.\n \"\"\"\n \n host, port = address\n if host.startswith(\"[\"):\n host = host.strip(\"[]\")\n err = None\n \n # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n # The original create_connection function always returns all records.\n family = allowed_gai_family()\n \n try:\n host.encode(\"idna\")\n except UnicodeError:\n raise LocationParseError(f\"'{host}', label empty or too long\") from None\n \n for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n af, socktype, proto, canonname, sa = res\n sock = None\n try:\n sock = socket.socket(af, socktype, proto)\n \n # If provided, set socket level options before connecting.\n _set_socket_options(sock, socket_options)\n \n if timeout is not _DEFAULT_TIMEOUT:\n sock.settimeout(timeout)\n if source_address:\n sock.bind(source_address)\n> sock.connect(sa)\nE ConnectionRefusedError: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nmethod = 'POST', url = '/demo/'\nbody = b'--96e112f59bda8f70bf549fa0e3934bfe\\r\\nContent-Disposition: form-data; name=\"Author\"\\r\\n\\r\\nrobot\\r\\n--96e112f59bda8f...Disposition: form-data; name=\"Text\"; filename=\"\"\\r\\n\\r\\nThis is a message1\\r\\n--96e112f59bda8f70bf549fa0e3934bfe--\\r\\n'\nheaders = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=96e112f59bda8f70bf549fa0e3934bfe'}\nretries = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = Timeout(connect=None, read=None, total=None), pool_timeout = None\nrelease_conn = False, chunked = False, body_pos = None, preload_content = False\ndecode_content = False, response_kw = {}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n def urlopen( # type: ignore[override]\n self,\n method: str,\n url: str,\n body: _TYPE_BODY | None = None,\n headers: typing.Mapping[str, str] | None = None,\n retries: Retry | bool | int | None = None,\n redirect: bool = True,\n assert_same_host: bool = True,\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n pool_timeout: int | None = None,\n release_conn: bool | None = None,\n chunked: bool = False,\n body_pos: _TYPE_BODY_POSITION | None = None,\n preload_content: bool = True,\n decode_content: bool = True,\n **response_kw: typing.Any,\n ) -> BaseHTTPResponse:\n \"\"\"\n Get a connection from the pool and perform an HTTP request. This is the\n lowest level call for making a request, so you'll need to specify all\n the raw details.\n \n .. note::\n \n More commonly, it's appropriate to use a convenience method\n such as :meth:`request`.\n \n .. note::\n \n `release_conn` will only behave as expected if\n `preload_content=False` because we want to make\n `preload_content=False` the default behaviour someday soon without\n breaking backwards compatibility.\n \n :param method:\n HTTP request method (such as GET, POST, PUT, etc.)\n \n :param url:\n The URL to perform the request on.\n \n :param body:\n Data to send in the request body, either :class:`str`, :class:`bytes`,\n an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n \n :param headers:\n Dictionary of custom headers to send, such as User-Agent,\n If-None-Match, etc. If None, pool headers are used. If provided,\n these headers completely replace any pool-specific headers.\n \n :param retries:\n Configure the number of retries to allow before raising a\n :class:`~urllib3.exceptions.MaxRetryError` exception.\n \n If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a\n :class:`~urllib3.util.retry.Retry` object for fine-grained control\n over different types of retries.\n Pass an integer number to retry connection errors that many times,\n but no other types of errors. Pass zero to never retry.\n \n If ``False``, then retries are disabled and any exception is raised\n immediately. Also, instead of raising a MaxRetryError on redirects,\n the redirect response will be returned.\n \n :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n \n :param redirect:\n If True, automatically handle redirects (status codes 301, 302,\n 303, 307, 308). Each redirect counts as a retry. Disabling retries\n will disable redirect, too.\n \n :param assert_same_host:\n If ``True``, will make sure that the host of the pool requests is\n consistent else will raise HostChangedError. When ``False``, you can\n use the pool on an HTTP proxy and request foreign hosts.\n \n :param timeout:\n If specified, overrides the default timeout for this one\n request. It may be a float (in seconds) or an instance of\n :class:`urllib3.util.Timeout`.\n \n :param pool_timeout:\n If set and the pool is set to block=True, then this method will\n block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n connection is available within the time period.\n \n :param bool preload_content:\n If True, the response's body will be preloaded into memory.\n \n :param bool decode_content:\n If True, will attempt to decode the body based on the\n 'content-encoding' header.\n \n :param release_conn:\n If False, then the urlopen call will not release the connection\n back into the pool once a response is received (but will release if\n you read the entire contents of the response such as when\n `preload_content=True`). This is useful if you're not preloading\n the response's content immediately. You will need to call\n ``r.release_conn()`` on the response ``r`` to return the connection\n back into the pool. If None, it takes the value of ``preload_content``\n which defaults to ``True``.\n \n :param bool chunked:\n If True, urllib3 will send the body using chunked transfer\n encoding. Otherwise, urllib3 will send the body using the standard\n content-length form. Defaults to False.\n \n :param int body_pos:\n Position to seek to in file-like body in the event of a retry or\n redirect. Typically this won't need to be set because urllib3 will\n auto-populate the value when needed.\n \"\"\"\n parsed_url = parse_url(url)\n destination_scheme = parsed_url.scheme\n \n if headers is None:\n headers = self.headers\n \n if not isinstance(retries, Retry):\n retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n \n if release_conn is None:\n release_conn = preload_content\n \n # Check host\n if assert_same_host and not self.is_same_host(url):\n raise HostChangedError(self, url, retries)\n \n # Ensure that the URL we're connecting to is properly encoded\n if url.startswith(\"/\"):\n url = to_str(_encode_target(url))\n else:\n url = to_str(parsed_url.url)\n \n conn = None\n \n # Track whether `conn` needs to be released before\n # returning/raising/recursing. Update this variable if necessary, and\n # leave `release_conn` constant throughout the function. That way, if\n # the function recurses, the original value of `release_conn` will be\n # passed down into the recursive call, and its value will be respected.\n #\n # See issue #651 [1] for details.\n #\n # [1] \n release_this_conn = release_conn\n \n http_tunnel_required = connection_requires_http_tunnel(\n self.proxy, self.proxy_config, destination_scheme\n )\n \n # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n # have to copy the headers dict so we can safely change it without those\n # changes being reflected in anyone else's copy.\n if not http_tunnel_required:\n headers = headers.copy() # type: ignore[attr-defined]\n headers.update(self.proxy_headers) # type: ignore[union-attr]\n \n # Must keep the exception bound to a separate variable or else Python 3\n # complains about UnboundLocalError.\n err = None\n \n # Keep track of whether we cleanly exited the except block. This\n # ensures we do proper cleanup in finally.\n clean_exit = False\n \n # Rewind body position, if needed. Record current position\n # for future rewinds in the event of a redirect/retry.\n body_pos = set_file_position(body, body_pos)\n \n try:\n # Request a connection from the queue.\n timeout_obj = self._get_timeout(timeout)\n conn = self._get_conn(timeout=pool_timeout)\n \n conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]\n \n # Is this a closed/new connection that requires CONNECT tunnelling?\n if self.proxy is not None and http_tunnel_required and conn.is_closed:\n try:\n self._prepare_proxy(conn)\n except (BaseSSLError, OSError, SocketTimeout) as e:\n self._raise_timeout(\n err=e, url=self.proxy.url, timeout_value=conn.timeout\n )\n raise\n \n # If we're going to release the connection in ``finally:``, then\n # the response doesn't need to know about the connection. Otherwise\n # it will also try to release it and we'll have a double-release\n # mess.\n response_conn = conn if not release_conn else None\n \n # Make the request on the HTTPConnection object\n> response = self._make_request(\n conn,\n method,\n url,\n timeout=timeout_obj,\n body=body,\n headers=headers,\n chunked=chunked,\n retries=retries,\n response_conn=response_conn,\n preload_content=preload_content,\n decode_content=decode_content,\n **response_kw,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request\n conn.request(\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request\n self.endheaders()\n.pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders\n self._send_output(message_body, encode_chunked=encode_chunked)\n.pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output\n self.send(msg)\n.pixi/envs/default/lib/python3.8/http/client.py:951: in send\n self.connect()\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect\n self.sock = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n except socket.gaierror as e:\n raise NameResolutionError(self.host, self, e) from e\n except SocketTimeout as e:\n raise ConnectTimeoutError(\n self,\n f\"Connection to {self.host} timed out. (connect timeout={self.timeout})\",\n ) from e\n \n except OSError as e:\n> raise NewConnectionError(\n self, f\"Failed to establish a new connection: {e}\"\n ) from e\nE urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n> resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen\n retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nmethod = 'POST', url = '/demo/', response = None\nerror = NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused')\n_pool = \n_stacktrace = \n\n def increment(\n self,\n method: str | None = None,\n url: str | None = None,\n response: BaseHTTPResponse | None = None,\n error: Exception | None = None,\n _pool: ConnectionPool | None = None,\n _stacktrace: TracebackType | None = None,\n ) -> Self:\n \"\"\"Return a new Retry object with incremented retry counters.\n \n :param response: A response object, or None, if the server did not\n return a response.\n :type response: :class:`~urllib3.response.BaseHTTPResponse`\n :param Exception error: An error encountered during the request, or\n None if the response was received successfully.\n \n :return: A new ``Retry`` object.\n \"\"\"\n if self.total is False and error:\n # Disabled, indicate to re-raise the error.\n raise reraise(type(error), error, _stacktrace)\n \n total = self.total\n if total is not None:\n total -= 1\n \n connect = self.connect\n read = self.read\n redirect = self.redirect\n status_count = self.status\n other = self.other\n cause = \"unknown\"\n status = None\n redirect_location = None\n \n if error and self._is_connection_error(error):\n # Connect retry?\n if connect is False:\n raise reraise(type(error), error, _stacktrace)\n elif connect is not None:\n connect -= 1\n \n elif error and self._is_read_error(error):\n # Read retry?\n if read is False or method is None or not self._is_method_retryable(method):\n raise reraise(type(error), error, _stacktrace)\n elif read is not None:\n read -= 1\n \n elif error:\n # Other retry?\n if other is not None:\n other -= 1\n \n elif response and response.get_redirect_location():\n # Redirect retry?\n if redirect is not None:\n redirect -= 1\n cause = \"too many redirects\"\n response_redirect_location = response.get_redirect_location()\n if response_redirect_location:\n redirect_location = response_redirect_location\n status = response.status\n \n else:\n # Incrementing because of a server error like a 500 in\n # status_forcelist and the given method is in the allowed_methods\n cause = ResponseError.GENERIC_ERROR\n if response and response.status:\n if status_count is not None:\n status_count -= 1\n cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n status = response.status\n \n history = self.history + (\n RequestHistory(method, url, error, status, redirect_location),\n )\n \n new_retry = self.new(\n total=total,\n connect=connect,\n read=read,\n redirect=redirect,\n status=status_count,\n other=other,\n history=history,\n )\n \n if new_retry.is_exhausted():\n reason = error or ResponseError(cause)\n> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]\nE urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \nmessage = 'This is a message1', msg_id = None, reply = False\nattributes = {'Author': 'robot', 'When': 1755174853, 'cmd': 'Submit', 'exp': 'demo', ...}\nattachments = [], suppress_email_notification = False, encoding = None\ntimeout = None, kwargs = {'Author': 'robot'}\nlogbook_directory = 'elog_instance/logbooks/demo'\nnew_attachment_list = [('Text', ('', b'This is a message1'))]\nobjects_to_close = []\nattributes_to_edit = {'Author': b'robot', 'When': 1755174853, 'cmd': b'Submit', 'exp': b'demo', ...}\n\n def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None,\n suppress_email_notification=False, encoding=None, timeout=None, **kwargs):\n \"\"\"\n Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing\n message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id\n of the newly created message.\n \"\"\"\n \n logbook_directory = \"elog_instance/logbooks/demo\"\n print(f\"Checking the existence of the directory {logbook_directory}\")\n \n # Check if the directory exists\n if not os.path.exists(logbook_directory):\n print(f\"The directory {logbook_directory} does not exist.\")\n else:\n print(f\"The directory {logbook_directory} exists.\")\n \n # Check write permissions\n if os.access(logbook_directory, os.W_OK):\n print(f\"The directory {logbook_directory} has write permissions.\")\n else:\n print(f\"The directory {logbook_directory} does not have write permissions.\")\n \n \n print(\"STARTING POST\")\n # Ajout des impressions pour d\u00e9boguer\n print(f\"Message to post: {message}\")\n print(f\"msg_id: {msg_id}\")\n print(f\"Attributes: {attributes}\")\n print(f\"Attachments: {attachments}\")\n print(f\"Encoding: {encoding}\")\n print(f\"Timeout: {timeout}\")\n print(f\"Additional kwargs: {kwargs}\")\n \n attributes = attributes or {}\n attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority\n print(f\"Updated attributes: {attributes}\")\n \n attachments = attachments or []\n print(f\"Attachments list: {attachments}\")\n \n if encoding is not None:\n if encoding not in ['plain', 'HTML', 'ELCode']:\n raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.')\n attributes['Encoding'] = encoding\n \n if suppress_email_notification:\n attributes[\"suppress\"] = 1\n \n # Prepare attachments\n if attachments:\n new_attachment_list, objects_to_close = self._prepare_attachments(attachments)\n print(f\"New attachments prepared: {new_attachment_list}\")\n else:\n objects_to_close = []\n new_attachment_list = []\n \n attributes_to_edit = dict()\n \n if msg_id:\n print(f\"Editing message with msg_id: {msg_id}\")\n if reply:\n print(f\"Replying to message with msg_id: {msg_id}\")\n self._check_if_message_on_server(msg_id)\n attributes['reply_to'] = str(msg_id)\n else:\n print(\"Editing existing message.\")\n attributes['edit_id'] = str(msg_id)\n attributes['skiplock'] = '1'\n msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id)\n \n # Merge new attributes\n for attribute, data in attributes.items():\n if data is not None:\n attributes_to_edit[attribute] = data\n \n print(f\"Attributes after merging: {attributes_to_edit}\")\n \n # Process existing attachments\n i = 0\n existing_attachments_filename_list = []\n for attachment in existing_attachments_list:\n attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)\n existing_attachments_filename_list.append(os.path.basename(attachment)[14:])\n i += 1\n \n print(f\"Existing attachments: {existing_attachments_filename_list}\")\n \n duplicate_attachment_list = []\n for new_attachment in new_attachment_list:\n new_attachment_filename = new_attachment[1][0]\n print(f\"Checking new attachment: {new_attachment_filename}\")\n if new_attachment_filename in existing_attachments_filename_list:\n # Same attachment exists on the server, compare content\n new_attachment_content = new_attachment[1][1].read()\n new_attachment[1][1].seek(0)\n attachment_index = existing_attachments_filename_list.index(new_attachment_filename)\n existing_attachment_content = self.download_attachment(\n url=existing_attachments_list[attachment_index],\n timeout=timeout\n )\n if new_attachment_content == existing_attachment_content:\n print(f\"Duplicate attachment detected: {new_attachment_filename}\")\n duplicate_attachment_list.append(new_attachment)\n else:\n print(f\"Attachment content has changed: {new_attachment_filename}\")\n self.delete_attachment(msg_id, attributes=attributes_to_edit,\n attachment_id=attachment_index,\n timeout=timeout, text=msg_to_edit)\n existing_attachments_filename_list.pop(attachment_index)\n existing_attachments_list.pop(attachment_index)\n \n print(f\"Duplicate attachments to remove: {duplicate_attachment_list}\")\n \n # Remove duplicates\n for attach in duplicate_attachment_list:\n new_attachment_list.remove(attach)\n \n print(f\"Final new attachments list: {new_attachment_list}\")\n else:\n # Creating a new message, add timestamp if not present\n if 'When' not in attributes:\n attributes['When'] = int(datetime.now().timestamp())\n \n # Final check on attributes\n if not attributes_to_edit:\n attributes_to_edit = attributes\n \n print(f\"Final attributes to send to the server: {attributes_to_edit}\")\n \n # Remove reserved attributes\n _remove_reserved_attributes(attributes_to_edit)\n \n new_attachment_list.append(('Text', ('', message.encode('iso-8859-1'))))\n print(f\"Final attachment list including message text: {new_attachment_list}\")\n \n # Add base message attributes\n self._add_base_msg_attributes(attributes_to_edit)\n print(f\"Attributes with base message added: {attributes_to_edit}\")\n \n # Sanitize attribute keys\n attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit)\n print(f\"Attributes after sanitizing keys: {attributes_to_edit}\")\n \n # Encode all string values in latin1\n attributes_to_edit = _encode_values(attributes_to_edit)\n print(f\"Attributes after encoding: {attributes_to_edit}\")\n \n try:\n print(\"Sending POST request to the server...\")\n> response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list,\n allow_redirects=False, verify=False, timeout=timeout)\n\nslic/utils/logbook.py:269: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:115: in post\n return request(\"post\", url, data=data, json=json, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request\n return session.request(method=method, url=url, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request\n resp = self.send(prep, **send_kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send\n r = adapter.send(request, **kwargs)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n \n except (ProtocolError, OSError) as err:\n raise ConnectionError(err, request=request)\n \n except MaxRetryError as e:\n if isinstance(e.reason, ConnectTimeoutError):\n # TODO: Remove this in 3.0.0: see #2811\n if not isinstance(e.reason, NewConnectionError):\n raise ConnectTimeout(e, request=request)\n \n if isinstance(e.reason, ResponseError):\n raise RetryError(e, request=request)\n \n if isinstance(e.reason, _ProxyError):\n raise ProxyError(e, request=request)\n \n if isinstance(e.reason, _SSLError):\n # This branch is for urllib3 v1.22 and later.\n raise SSLError(e, request=request)\n \n> raise ConnectionError(e, request=request)\nE requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n> sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection\n raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\naddress = ('localhost', 8080), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n def create_connection(\n address: tuple[str, int],\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n source_address: tuple[str, int] | None = None,\n socket_options: _TYPE_SOCKET_OPTIONS | None = None,\n ) -> socket.socket:\n \"\"\"Connect to *address* and return the socket object.\n \n Convenience function. Connect to *address* (a 2-tuple ``(host,\n port)``) and return the socket object. Passing the optional\n *timeout* parameter will set the timeout on the socket instance\n before attempting to connect. If no *timeout* is supplied, the\n global default timeout setting returned by :func:`socket.getdefaulttimeout`\n is used. If *source_address* is set it must be a tuple of (host, port)\n for the socket to bind as a source address before making the connection.\n An host of '' or port 0 tells the OS to use the default.\n \"\"\"\n \n host, port = address\n if host.startswith(\"[\"):\n host = host.strip(\"[]\")\n err = None\n \n # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n # The original create_connection function always returns all records.\n family = allowed_gai_family()\n \n try:\n host.encode(\"idna\")\n except UnicodeError:\n raise LocationParseError(f\"'{host}', label empty or too long\") from None\n \n for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n af, socktype, proto, canonname, sa = res\n sock = None\n try:\n sock = socket.socket(af, socktype, proto)\n \n # If provided, set socket level options before connecting.\n _set_socket_options(sock, socket_options)\n \n if timeout is not _DEFAULT_TIMEOUT:\n sock.settimeout(timeout)\n if source_address:\n sock.bind(source_address)\n> sock.connect(sa)\nE ConnectionRefusedError: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nmethod = 'GET', url = '/demo/None', body = None\nheaders = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'}\nretries = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = Timeout(connect=None, read=None, total=None), pool_timeout = None\nrelease_conn = False, chunked = False, body_pos = None, preload_content = False\ndecode_content = False, response_kw = {}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n def urlopen( # type: ignore[override]\n self,\n method: str,\n url: str,\n body: _TYPE_BODY | None = None,\n headers: typing.Mapping[str, str] | None = None,\n retries: Retry | bool | int | None = None,\n redirect: bool = True,\n assert_same_host: bool = True,\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n pool_timeout: int | None = None,\n release_conn: bool | None = None,\n chunked: bool = False,\n body_pos: _TYPE_BODY_POSITION | None = None,\n preload_content: bool = True,\n decode_content: bool = True,\n **response_kw: typing.Any,\n ) -> BaseHTTPResponse:\n \"\"\"\n Get a connection from the pool and perform an HTTP request. This is the\n lowest level call for making a request, so you'll need to specify all\n the raw details.\n \n .. note::\n \n More commonly, it's appropriate to use a convenience method\n such as :meth:`request`.\n \n .. note::\n \n `release_conn` will only behave as expected if\n `preload_content=False` because we want to make\n `preload_content=False` the default behaviour someday soon without\n breaking backwards compatibility.\n \n :param method:\n HTTP request method (such as GET, POST, PUT, etc.)\n \n :param url:\n The URL to perform the request on.\n \n :param body:\n Data to send in the request body, either :class:`str`, :class:`bytes`,\n an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n \n :param headers:\n Dictionary of custom headers to send, such as User-Agent,\n If-None-Match, etc. If None, pool headers are used. If provided,\n these headers completely replace any pool-specific headers.\n \n :param retries:\n Configure the number of retries to allow before raising a\n :class:`~urllib3.exceptions.MaxRetryError` exception.\n \n If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a\n :class:`~urllib3.util.retry.Retry` object for fine-grained control\n over different types of retries.\n Pass an integer number to retry connection errors that many times,\n but no other types of errors. Pass zero to never retry.\n \n If ``False``, then retries are disabled and any exception is raised\n immediately. Also, instead of raising a MaxRetryError on redirects,\n the redirect response will be returned.\n \n :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n \n :param redirect:\n If True, automatically handle redirects (status codes 301, 302,\n 303, 307, 308). Each redirect counts as a retry. Disabling retries\n will disable redirect, too.\n \n :param assert_same_host:\n If ``True``, will make sure that the host of the pool requests is\n consistent else will raise HostChangedError. When ``False``, you can\n use the pool on an HTTP proxy and request foreign hosts.\n \n :param timeout:\n If specified, overrides the default timeout for this one\n request. It may be a float (in seconds) or an instance of\n :class:`urllib3.util.Timeout`.\n \n :param pool_timeout:\n If set and the pool is set to block=True, then this method will\n block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n connection is available within the time period.\n \n :param bool preload_content:\n If True, the response's body will be preloaded into memory.\n \n :param bool decode_content:\n If True, will attempt to decode the body based on the\n 'content-encoding' header.\n \n :param release_conn:\n If False, then the urlopen call will not release the connection\n back into the pool once a response is received (but will release if\n you read the entire contents of the response such as when\n `preload_content=True`). This is useful if you're not preloading\n the response's content immediately. You will need to call\n ``r.release_conn()`` on the response ``r`` to return the connection\n back into the pool. If None, it takes the value of ``preload_content``\n which defaults to ``True``.\n \n :param bool chunked:\n If True, urllib3 will send the body using chunked transfer\n encoding. Otherwise, urllib3 will send the body using the standard\n content-length form. Defaults to False.\n \n :param int body_pos:\n Position to seek to in file-like body in the event of a retry or\n redirect. Typically this won't need to be set because urllib3 will\n auto-populate the value when needed.\n \"\"\"\n parsed_url = parse_url(url)\n destination_scheme = parsed_url.scheme\n \n if headers is None:\n headers = self.headers\n \n if not isinstance(retries, Retry):\n retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n \n if release_conn is None:\n release_conn = preload_content\n \n # Check host\n if assert_same_host and not self.is_same_host(url):\n raise HostChangedError(self, url, retries)\n \n # Ensure that the URL we're connecting to is properly encoded\n if url.startswith(\"/\"):\n url = to_str(_encode_target(url))\n else:\n url = to_str(parsed_url.url)\n \n conn = None\n \n # Track whether `conn` needs to be released before\n # returning/raising/recursing. Update this variable if necessary, and\n # leave `release_conn` constant throughout the function. That way, if\n # the function recurses, the original value of `release_conn` will be\n # passed down into the recursive call, and its value will be respected.\n #\n # See issue #651 [1] for details.\n #\n # [1] \n release_this_conn = release_conn\n \n http_tunnel_required = connection_requires_http_tunnel(\n self.proxy, self.proxy_config, destination_scheme\n )\n \n # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n # have to copy the headers dict so we can safely change it without those\n # changes being reflected in anyone else's copy.\n if not http_tunnel_required:\n headers = headers.copy() # type: ignore[attr-defined]\n headers.update(self.proxy_headers) # type: ignore[union-attr]\n \n # Must keep the exception bound to a separate variable or else Python 3\n # complains about UnboundLocalError.\n err = None\n \n # Keep track of whether we cleanly exited the except block. This\n # ensures we do proper cleanup in finally.\n clean_exit = False\n \n # Rewind body position, if needed. Record current position\n # for future rewinds in the event of a redirect/retry.\n body_pos = set_file_position(body, body_pos)\n \n try:\n # Request a connection from the queue.\n timeout_obj = self._get_timeout(timeout)\n conn = self._get_conn(timeout=pool_timeout)\n \n conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]\n \n # Is this a closed/new connection that requires CONNECT tunnelling?\n if self.proxy is not None and http_tunnel_required and conn.is_closed:\n try:\n self._prepare_proxy(conn)\n except (BaseSSLError, OSError, SocketTimeout) as e:\n self._raise_timeout(\n err=e, url=self.proxy.url, timeout_value=conn.timeout\n )\n raise\n \n # If we're going to release the connection in ``finally:``, then\n # the response doesn't need to know about the connection. Otherwise\n # it will also try to release it and we'll have a double-release\n # mess.\n response_conn = conn if not release_conn else None\n \n # Make the request on the HTTPConnection object\n> response = self._make_request(\n conn,\n method,\n url,\n timeout=timeout_obj,\n body=body,\n headers=headers,\n chunked=chunked,\n retries=retries,\n response_conn=response_conn,\n preload_content=preload_content,\n decode_content=decode_content,\n **response_kw,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request\n conn.request(\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request\n self.endheaders()\n.pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders\n self._send_output(message_body, encode_chunked=encode_chunked)\n.pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output\n self.send(msg)\n.pixi/envs/default/lib/python3.8/http/client.py:951: in send\n self.connect()\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect\n self.sock = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n except socket.gaierror as e:\n raise NameResolutionError(self.host, self, e) from e\n except SocketTimeout as e:\n raise ConnectTimeoutError(\n self,\n f\"Connection to {self.host} timed out. (connect timeout={self.timeout})\",\n ) from e\n \n except OSError as e:\n> raise NewConnectionError(\n self, f\"Failed to establish a new connection: {e}\"\n ) from e\nE urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n> resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen\n retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nmethod = 'GET', url = '/demo/None', response = None\nerror = NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused')\n_pool = \n_stacktrace = \n\n def increment(\n self,\n method: str | None = None,\n url: str | None = None,\n response: BaseHTTPResponse | None = None,\n error: Exception | None = None,\n _pool: ConnectionPool | None = None,\n _stacktrace: TracebackType | None = None,\n ) -> Self:\n \"\"\"Return a new Retry object with incremented retry counters.\n \n :param response: A response object, or None, if the server did not\n return a response.\n :type response: :class:`~urllib3.response.BaseHTTPResponse`\n :param Exception error: An error encountered during the request, or\n None if the response was received successfully.\n \n :return: A new ``Retry`` object.\n \"\"\"\n if self.total is False and error:\n # Disabled, indicate to re-raise the error.\n raise reraise(type(error), error, _stacktrace)\n \n total = self.total\n if total is not None:\n total -= 1\n \n connect = self.connect\n read = self.read\n redirect = self.redirect\n status_count = self.status\n other = self.other\n cause = \"unknown\"\n status = None\n redirect_location = None\n \n if error and self._is_connection_error(error):\n # Connect retry?\n if connect is False:\n raise reraise(type(error), error, _stacktrace)\n elif connect is not None:\n connect -= 1\n \n elif error and self._is_read_error(error):\n # Read retry?\n if read is False or method is None or not self._is_method_retryable(method):\n raise reraise(type(error), error, _stacktrace)\n elif read is not None:\n read -= 1\n \n elif error:\n # Other retry?\n if other is not None:\n other -= 1\n \n elif response and response.get_redirect_location():\n # Redirect retry?\n if redirect is not None:\n redirect -= 1\n cause = \"too many redirects\"\n response_redirect_location = response.get_redirect_location()\n if response_redirect_location:\n redirect_location = response_redirect_location\n status = response.status\n \n else:\n # Incrementing because of a server error like a 500 in\n # status_forcelist and the given method is in the allowed_methods\n cause = ResponseError.GENERIC_ERROR\n if response and response.status:\n if status_count is not None:\n status_count -= 1\n cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n status = response.status\n \n history = self.history + (\n RequestHistory(method, url, error, status, redirect_location),\n )\n \n new_retry = self.new(\n total=total,\n connect=connect,\n read=read,\n redirect=redirect,\n status=status_count,\n other=other,\n history=history,\n )\n \n if new_retry.is_exhausted():\n reason = error or ResponseError(cause)\n> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]\nE urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError\n\nDuring handling of the above exception, another exception occurred:\n\nself = , msg_id = None\ntimeout = None\n\n def _check_if_message_on_server(self, msg_id, timeout=None):\n \"\"\"Try to load page for specific message. If there is a html tag like then there is no\n such message.\n \n :param msg_id: ID of message to be checked\n :params timeout: The value of timeout to be passed to the get request\n :return:\n \"\"\"\n \n request_headers = dict()\n if self._user or self._password:\n request_headers['Cookie'] = self._make_user_and_pswd_cookie()\n try:\n> response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,\n verify=False, timeout=timeout)\n\nslic/utils/logbook.py:570: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:73: in get\n return request(\"get\", url, params=params, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request\n return session.request(method=method, url=url, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request\n resp = self.send(prep, **send_kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send\n r = adapter.send(request, **kwargs)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n \n except (ProtocolError, OSError) as err:\n raise ConnectionError(err, request=request)\n \n except MaxRetryError as e:\n if isinstance(e.reason, ConnectTimeoutError):\n # TODO: Remove this in 3.0.0: see #2811\n if not isinstance(e.reason, NewConnectionError):\n raise ConnectTimeout(e, request=request)\n \n if isinstance(e.reason, ResponseError):\n raise RetryError(e, request=request)\n \n if isinstance(e.reason, _ProxyError):\n raise ProxyError(e, request=request)\n \n if isinstance(e.reason, _SSLError):\n # This branch is for urllib3 v1.22 and later.\n raise SSLError(e, request=request)\n \n> raise ConnectionError(e, request=request)\nE requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\n def test_get_default_elog_instance_with_direct_password_and_real_check():\n url = \"http://localhost:8080/demo\"\n user = \"robot\"\n password = \"testpassword\"\n text = \"This is a message1\"\n \n elog = Elog(\"http://localhost:8080/demo\", user=user, password=password)\n \n try:\n> elog.post(text)\n\ntests/test_utils_elog.py:22: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nslic/utils/elog.py:17: in post\n return self._log.post(*args, **kwargs)\nslic/utils/logbook.py:289: in post\n self._check_if_message_on_server(msg_id) # Raises exceptions if no message or no response from server\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = , msg_id = None\ntimeout = None\n\n def _check_if_message_on_server(self, msg_id, timeout=None):\n \"\"\"Try to load page for specific message. If there is a html tag like then there is no\n such message.\n \n :param msg_id: ID of message to be checked\n :params timeout: The value of timeout to be passed to the get request\n :return:\n \"\"\"\n \n request_headers = dict()\n if self._user or self._password:\n request_headers['Cookie'] = self._make_user_and_pswd_cookie()\n try:\n response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,\n verify=False, timeout=timeout)\n \n # If there is no message code 200 will be returned (OK) and _validate_response will not recognise it\n # but there will be some error in the html code.\n resp_message, resp_headers, resp_msg_id = _validate_response(response)\n # If there is no message, code 200 will be returned (OK) but there will be some error indication in\n # the html code.\n if re.findall('.*?',\n resp_message.decode('utf-8', 'ignore'),\n flags=re.DOTALL):\n raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.')\n \n except requests.Timeout as e:\n # Catch here a timeout o the post request.\n # Raise the logbook exception and let the user handle it\n raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\\n' +\n '{1}'.format(sys._getframe().f_code.co_name, e))\n \n except requests.RequestException as e:\n> raise LogbookServerProblem('No response from the logbook server.\\nDetails: ' + '{0}'.format(e))\nE slic.utils.logbook_exceptions.LogbookServerProblem: No response from the logbook server.\nE Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\nslic/utils/logbook.py:590: LogbookServerProblem\n\nDuring handling of the above exception, another exception occurred:\n\n def test_get_default_elog_instance_with_direct_password_and_real_check():\n url = \"http://localhost:8080/demo\"\n user = \"robot\"\n password = \"testpassword\"\n text = \"This is a message1\"\n \n elog = Elog(\"http://localhost:8080/demo\", user=user, password=password)\n \n try:\n elog.post(text)\n except Exception as e:\n> pytest.fail(f\"elog.open() raised an unexpected exception: {e}\")\nE Failed: elog.open() raised an unexpected exception: No response from the logbook server.\nE Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\ntests/test_utils_elog.py:24: Failed"}, "teardown": {"duration": 0.0004334989935159683, "outcome": "passed"}}, {"nodeid": "tests/test_utils_elog.py::test_get_default_elog_instance_with_wrong_password_and_real_check", "lineno": 37, "outcome": "failed", "keywords": ["test_get_default_elog_instance_with_wrong_password_and_real_check", "test_utils_elog.py", "tests", "slic", ""], "setup": {"duration": 0.00015929201617836952, "outcome": "passed"}, "call": {"duration": 0.008063088171184063, "outcome": "failed", "crash": {"path": "/workspace/tligui_y/slic/slic/utils/logbook.py", "lineno": 590, "message": "slic.utils.logbook_exceptions.LogbookServerProblem: No response from the logbook server.\nDetails: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))"}, "traceback": [{"path": "tests/test_utils_elog.py", "lineno": 46, "message": ""}, {"path": "slic/utils/elog.py", "lineno": 17, "message": "in post"}, {"path": "slic/utils/logbook.py", "lineno": 289, "message": "in post"}, {"path": "slic/utils/logbook.py", "lineno": 590, "message": "LogbookServerProblem"}], "longrepr": "self = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n> sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection\n raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\naddress = ('localhost', 8080), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n def create_connection(\n address: tuple[str, int],\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n source_address: tuple[str, int] | None = None,\n socket_options: _TYPE_SOCKET_OPTIONS | None = None,\n ) -> socket.socket:\n \"\"\"Connect to *address* and return the socket object.\n \n Convenience function. Connect to *address* (a 2-tuple ``(host,\n port)``) and return the socket object. Passing the optional\n *timeout* parameter will set the timeout on the socket instance\n before attempting to connect. If no *timeout* is supplied, the\n global default timeout setting returned by :func:`socket.getdefaulttimeout`\n is used. If *source_address* is set it must be a tuple of (host, port)\n for the socket to bind as a source address before making the connection.\n An host of '' or port 0 tells the OS to use the default.\n \"\"\"\n \n host, port = address\n if host.startswith(\"[\"):\n host = host.strip(\"[]\")\n err = None\n \n # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n # The original create_connection function always returns all records.\n family = allowed_gai_family()\n \n try:\n host.encode(\"idna\")\n except UnicodeError:\n raise LocationParseError(f\"'{host}', label empty or too long\") from None\n \n for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n af, socktype, proto, canonname, sa = res\n sock = None\n try:\n sock = socket.socket(af, socktype, proto)\n \n # If provided, set socket level options before connecting.\n _set_socket_options(sock, socket_options)\n \n if timeout is not _DEFAULT_TIMEOUT:\n sock.settimeout(timeout)\n if source_address:\n sock.bind(source_address)\n> sock.connect(sa)\nE ConnectionRefusedError: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nmethod = 'POST', url = '/demo/'\nbody = b'--b64e560eb0f5f2b0688d5d5d1b3ce36d\\r\\nContent-Disposition: form-data; name=\"Author\"\\r\\n\\r\\nrobot\\r\\n--b64e560eb0f5f2...ta; name=\"Text\"; filename=\"\"\\r\\n\\r\\nThis should fail due to wrong password\\r\\n--b64e560eb0f5f2b0688d5d5d1b3ce36d--\\r\\n'\nheaders = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '756', 'Content-Type': 'multipart/form-data; boundary=b64e560eb0f5f2b0688d5d5d1b3ce36d'}\nretries = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = Timeout(connect=None, read=None, total=None), pool_timeout = None\nrelease_conn = False, chunked = False, body_pos = None, preload_content = False\ndecode_content = False, response_kw = {}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n def urlopen( # type: ignore[override]\n self,\n method: str,\n url: str,\n body: _TYPE_BODY | None = None,\n headers: typing.Mapping[str, str] | None = None,\n retries: Retry | bool | int | None = None,\n redirect: bool = True,\n assert_same_host: bool = True,\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n pool_timeout: int | None = None,\n release_conn: bool | None = None,\n chunked: bool = False,\n body_pos: _TYPE_BODY_POSITION | None = None,\n preload_content: bool = True,\n decode_content: bool = True,\n **response_kw: typing.Any,\n ) -> BaseHTTPResponse:\n \"\"\"\n Get a connection from the pool and perform an HTTP request. This is the\n lowest level call for making a request, so you'll need to specify all\n the raw details.\n \n .. note::\n \n More commonly, it's appropriate to use a convenience method\n such as :meth:`request`.\n \n .. note::\n \n `release_conn` will only behave as expected if\n `preload_content=False` because we want to make\n `preload_content=False` the default behaviour someday soon without\n breaking backwards compatibility.\n \n :param method:\n HTTP request method (such as GET, POST, PUT, etc.)\n \n :param url:\n The URL to perform the request on.\n \n :param body:\n Data to send in the request body, either :class:`str`, :class:`bytes`,\n an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n \n :param headers:\n Dictionary of custom headers to send, such as User-Agent,\n If-None-Match, etc. If None, pool headers are used. If provided,\n these headers completely replace any pool-specific headers.\n \n :param retries:\n Configure the number of retries to allow before raising a\n :class:`~urllib3.exceptions.MaxRetryError` exception.\n \n If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a\n :class:`~urllib3.util.retry.Retry` object for fine-grained control\n over different types of retries.\n Pass an integer number to retry connection errors that many times,\n but no other types of errors. Pass zero to never retry.\n \n If ``False``, then retries are disabled and any exception is raised\n immediately. Also, instead of raising a MaxRetryError on redirects,\n the redirect response will be returned.\n \n :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n \n :param redirect:\n If True, automatically handle redirects (status codes 301, 302,\n 303, 307, 308). Each redirect counts as a retry. Disabling retries\n will disable redirect, too.\n \n :param assert_same_host:\n If ``True``, will make sure that the host of the pool requests is\n consistent else will raise HostChangedError. When ``False``, you can\n use the pool on an HTTP proxy and request foreign hosts.\n \n :param timeout:\n If specified, overrides the default timeout for this one\n request. It may be a float (in seconds) or an instance of\n :class:`urllib3.util.Timeout`.\n \n :param pool_timeout:\n If set and the pool is set to block=True, then this method will\n block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n connection is available within the time period.\n \n :param bool preload_content:\n If True, the response's body will be preloaded into memory.\n \n :param bool decode_content:\n If True, will attempt to decode the body based on the\n 'content-encoding' header.\n \n :param release_conn:\n If False, then the urlopen call will not release the connection\n back into the pool once a response is received (but will release if\n you read the entire contents of the response such as when\n `preload_content=True`). This is useful if you're not preloading\n the response's content immediately. You will need to call\n ``r.release_conn()`` on the response ``r`` to return the connection\n back into the pool. If None, it takes the value of ``preload_content``\n which defaults to ``True``.\n \n :param bool chunked:\n If True, urllib3 will send the body using chunked transfer\n encoding. Otherwise, urllib3 will send the body using the standard\n content-length form. Defaults to False.\n \n :param int body_pos:\n Position to seek to in file-like body in the event of a retry or\n redirect. Typically this won't need to be set because urllib3 will\n auto-populate the value when needed.\n \"\"\"\n parsed_url = parse_url(url)\n destination_scheme = parsed_url.scheme\n \n if headers is None:\n headers = self.headers\n \n if not isinstance(retries, Retry):\n retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n \n if release_conn is None:\n release_conn = preload_content\n \n # Check host\n if assert_same_host and not self.is_same_host(url):\n raise HostChangedError(self, url, retries)\n \n # Ensure that the URL we're connecting to is properly encoded\n if url.startswith(\"/\"):\n url = to_str(_encode_target(url))\n else:\n url = to_str(parsed_url.url)\n \n conn = None\n \n # Track whether `conn` needs to be released before\n # returning/raising/recursing. Update this variable if necessary, and\n # leave `release_conn` constant throughout the function. That way, if\n # the function recurses, the original value of `release_conn` will be\n # passed down into the recursive call, and its value will be respected.\n #\n # See issue #651 [1] for details.\n #\n # [1] \n release_this_conn = release_conn\n \n http_tunnel_required = connection_requires_http_tunnel(\n self.proxy, self.proxy_config, destination_scheme\n )\n \n # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n # have to copy the headers dict so we can safely change it without those\n # changes being reflected in anyone else's copy.\n if not http_tunnel_required:\n headers = headers.copy() # type: ignore[attr-defined]\n headers.update(self.proxy_headers) # type: ignore[union-attr]\n \n # Must keep the exception bound to a separate variable or else Python 3\n # complains about UnboundLocalError.\n err = None\n \n # Keep track of whether we cleanly exited the except block. This\n # ensures we do proper cleanup in finally.\n clean_exit = False\n \n # Rewind body position, if needed. Record current position\n # for future rewinds in the event of a redirect/retry.\n body_pos = set_file_position(body, body_pos)\n \n try:\n # Request a connection from the queue.\n timeout_obj = self._get_timeout(timeout)\n conn = self._get_conn(timeout=pool_timeout)\n \n conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]\n \n # Is this a closed/new connection that requires CONNECT tunnelling?\n if self.proxy is not None and http_tunnel_required and conn.is_closed:\n try:\n self._prepare_proxy(conn)\n except (BaseSSLError, OSError, SocketTimeout) as e:\n self._raise_timeout(\n err=e, url=self.proxy.url, timeout_value=conn.timeout\n )\n raise\n \n # If we're going to release the connection in ``finally:``, then\n # the response doesn't need to know about the connection. Otherwise\n # it will also try to release it and we'll have a double-release\n # mess.\n response_conn = conn if not release_conn else None\n \n # Make the request on the HTTPConnection object\n> response = self._make_request(\n conn,\n method,\n url,\n timeout=timeout_obj,\n body=body,\n headers=headers,\n chunked=chunked,\n retries=retries,\n response_conn=response_conn,\n preload_content=preload_content,\n decode_content=decode_content,\n **response_kw,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request\n conn.request(\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request\n self.endheaders()\n.pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders\n self._send_output(message_body, encode_chunked=encode_chunked)\n.pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output\n self.send(msg)\n.pixi/envs/default/lib/python3.8/http/client.py:951: in send\n self.connect()\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect\n self.sock = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n except socket.gaierror as e:\n raise NameResolutionError(self.host, self, e) from e\n except SocketTimeout as e:\n raise ConnectTimeoutError(\n self,\n f\"Connection to {self.host} timed out. (connect timeout={self.timeout})\",\n ) from e\n \n except OSError as e:\n> raise NewConnectionError(\n self, f\"Failed to establish a new connection: {e}\"\n ) from e\nE urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n> resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen\n retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nmethod = 'POST', url = '/demo/', response = None\nerror = NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused')\n_pool = \n_stacktrace = \n\n def increment(\n self,\n method: str | None = None,\n url: str | None = None,\n response: BaseHTTPResponse | None = None,\n error: Exception | None = None,\n _pool: ConnectionPool | None = None,\n _stacktrace: TracebackType | None = None,\n ) -> Self:\n \"\"\"Return a new Retry object with incremented retry counters.\n \n :param response: A response object, or None, if the server did not\n return a response.\n :type response: :class:`~urllib3.response.BaseHTTPResponse`\n :param Exception error: An error encountered during the request, or\n None if the response was received successfully.\n \n :return: A new ``Retry`` object.\n \"\"\"\n if self.total is False and error:\n # Disabled, indicate to re-raise the error.\n raise reraise(type(error), error, _stacktrace)\n \n total = self.total\n if total is not None:\n total -= 1\n \n connect = self.connect\n read = self.read\n redirect = self.redirect\n status_count = self.status\n other = self.other\n cause = \"unknown\"\n status = None\n redirect_location = None\n \n if error and self._is_connection_error(error):\n # Connect retry?\n if connect is False:\n raise reraise(type(error), error, _stacktrace)\n elif connect is not None:\n connect -= 1\n \n elif error and self._is_read_error(error):\n # Read retry?\n if read is False or method is None or not self._is_method_retryable(method):\n raise reraise(type(error), error, _stacktrace)\n elif read is not None:\n read -= 1\n \n elif error:\n # Other retry?\n if other is not None:\n other -= 1\n \n elif response and response.get_redirect_location():\n # Redirect retry?\n if redirect is not None:\n redirect -= 1\n cause = \"too many redirects\"\n response_redirect_location = response.get_redirect_location()\n if response_redirect_location:\n redirect_location = response_redirect_location\n status = response.status\n \n else:\n # Incrementing because of a server error like a 500 in\n # status_forcelist and the given method is in the allowed_methods\n cause = ResponseError.GENERIC_ERROR\n if response and response.status:\n if status_count is not None:\n status_count -= 1\n cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n status = response.status\n \n history = self.history + (\n RequestHistory(method, url, error, status, redirect_location),\n )\n \n new_retry = self.new(\n total=total,\n connect=connect,\n read=read,\n redirect=redirect,\n status=status_count,\n other=other,\n history=history,\n )\n \n if new_retry.is_exhausted():\n reason = error or ResponseError(cause)\n> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]\nE urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \nmessage = 'This should fail due to wrong password', msg_id = None, reply = False\nattributes = {'Author': 'robot', 'When': 1755174854, 'cmd': 'Submit', 'exp': 'demo', ...}\nattachments = [], suppress_email_notification = False, encoding = None\ntimeout = None, kwargs = {'Author': 'robot'}\nlogbook_directory = 'elog_instance/logbooks/demo'\nnew_attachment_list = [('Text', ('', b'This should fail due to wrong password'))]\nobjects_to_close = []\nattributes_to_edit = {'Author': b'robot', 'When': 1755174854, 'cmd': b'Submit', 'exp': b'demo', ...}\n\n def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None,\n suppress_email_notification=False, encoding=None, timeout=None, **kwargs):\n \"\"\"\n Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing\n message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id\n of the newly created message.\n \"\"\"\n \n logbook_directory = \"elog_instance/logbooks/demo\"\n print(f\"Checking the existence of the directory {logbook_directory}\")\n \n # Check if the directory exists\n if not os.path.exists(logbook_directory):\n print(f\"The directory {logbook_directory} does not exist.\")\n else:\n print(f\"The directory {logbook_directory} exists.\")\n \n # Check write permissions\n if os.access(logbook_directory, os.W_OK):\n print(f\"The directory {logbook_directory} has write permissions.\")\n else:\n print(f\"The directory {logbook_directory} does not have write permissions.\")\n \n \n print(\"STARTING POST\")\n # Ajout des impressions pour d\u00e9boguer\n print(f\"Message to post: {message}\")\n print(f\"msg_id: {msg_id}\")\n print(f\"Attributes: {attributes}\")\n print(f\"Attachments: {attachments}\")\n print(f\"Encoding: {encoding}\")\n print(f\"Timeout: {timeout}\")\n print(f\"Additional kwargs: {kwargs}\")\n \n attributes = attributes or {}\n attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority\n print(f\"Updated attributes: {attributes}\")\n \n attachments = attachments or []\n print(f\"Attachments list: {attachments}\")\n \n if encoding is not None:\n if encoding not in ['plain', 'HTML', 'ELCode']:\n raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.')\n attributes['Encoding'] = encoding\n \n if suppress_email_notification:\n attributes[\"suppress\"] = 1\n \n # Prepare attachments\n if attachments:\n new_attachment_list, objects_to_close = self._prepare_attachments(attachments)\n print(f\"New attachments prepared: {new_attachment_list}\")\n else:\n objects_to_close = []\n new_attachment_list = []\n \n attributes_to_edit = dict()\n \n if msg_id:\n print(f\"Editing message with msg_id: {msg_id}\")\n if reply:\n print(f\"Replying to message with msg_id: {msg_id}\")\n self._check_if_message_on_server(msg_id)\n attributes['reply_to'] = str(msg_id)\n else:\n print(\"Editing existing message.\")\n attributes['edit_id'] = str(msg_id)\n attributes['skiplock'] = '1'\n msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id)\n \n # Merge new attributes\n for attribute, data in attributes.items():\n if data is not None:\n attributes_to_edit[attribute] = data\n \n print(f\"Attributes after merging: {attributes_to_edit}\")\n \n # Process existing attachments\n i = 0\n existing_attachments_filename_list = []\n for attachment in existing_attachments_list:\n attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)\n existing_attachments_filename_list.append(os.path.basename(attachment)[14:])\n i += 1\n \n print(f\"Existing attachments: {existing_attachments_filename_list}\")\n \n duplicate_attachment_list = []\n for new_attachment in new_attachment_list:\n new_attachment_filename = new_attachment[1][0]\n print(f\"Checking new attachment: {new_attachment_filename}\")\n if new_attachment_filename in existing_attachments_filename_list:\n # Same attachment exists on the server, compare content\n new_attachment_content = new_attachment[1][1].read()\n new_attachment[1][1].seek(0)\n attachment_index = existing_attachments_filename_list.index(new_attachment_filename)\n existing_attachment_content = self.download_attachment(\n url=existing_attachments_list[attachment_index],\n timeout=timeout\n )\n if new_attachment_content == existing_attachment_content:\n print(f\"Duplicate attachment detected: {new_attachment_filename}\")\n duplicate_attachment_list.append(new_attachment)\n else:\n print(f\"Attachment content has changed: {new_attachment_filename}\")\n self.delete_attachment(msg_id, attributes=attributes_to_edit,\n attachment_id=attachment_index,\n timeout=timeout, text=msg_to_edit)\n existing_attachments_filename_list.pop(attachment_index)\n existing_attachments_list.pop(attachment_index)\n \n print(f\"Duplicate attachments to remove: {duplicate_attachment_list}\")\n \n # Remove duplicates\n for attach in duplicate_attachment_list:\n new_attachment_list.remove(attach)\n \n print(f\"Final new attachments list: {new_attachment_list}\")\n else:\n # Creating a new message, add timestamp if not present\n if 'When' not in attributes:\n attributes['When'] = int(datetime.now().timestamp())\n \n # Final check on attributes\n if not attributes_to_edit:\n attributes_to_edit = attributes\n \n print(f\"Final attributes to send to the server: {attributes_to_edit}\")\n \n # Remove reserved attributes\n _remove_reserved_attributes(attributes_to_edit)\n \n new_attachment_list.append(('Text', ('', message.encode('iso-8859-1'))))\n print(f\"Final attachment list including message text: {new_attachment_list}\")\n \n # Add base message attributes\n self._add_base_msg_attributes(attributes_to_edit)\n print(f\"Attributes with base message added: {attributes_to_edit}\")\n \n # Sanitize attribute keys\n attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit)\n print(f\"Attributes after sanitizing keys: {attributes_to_edit}\")\n \n # Encode all string values in latin1\n attributes_to_edit = _encode_values(attributes_to_edit)\n print(f\"Attributes after encoding: {attributes_to_edit}\")\n \n try:\n print(\"Sending POST request to the server...\")\n> response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list,\n allow_redirects=False, verify=False, timeout=timeout)\n\nslic/utils/logbook.py:269: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:115: in post\n return request(\"post\", url, data=data, json=json, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request\n return session.request(method=method, url=url, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request\n resp = self.send(prep, **send_kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send\n r = adapter.send(request, **kwargs)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n \n except (ProtocolError, OSError) as err:\n raise ConnectionError(err, request=request)\n \n except MaxRetryError as e:\n if isinstance(e.reason, ConnectTimeoutError):\n # TODO: Remove this in 3.0.0: see #2811\n if not isinstance(e.reason, NewConnectionError):\n raise ConnectTimeout(e, request=request)\n \n if isinstance(e.reason, ResponseError):\n raise RetryError(e, request=request)\n \n if isinstance(e.reason, _ProxyError):\n raise ProxyError(e, request=request)\n \n if isinstance(e.reason, _SSLError):\n # This branch is for urllib3 v1.22 and later.\n raise SSLError(e, request=request)\n \n> raise ConnectionError(e, request=request)\nE requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n> sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection\n raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\naddress = ('localhost', 8080), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n def create_connection(\n address: tuple[str, int],\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n source_address: tuple[str, int] | None = None,\n socket_options: _TYPE_SOCKET_OPTIONS | None = None,\n ) -> socket.socket:\n \"\"\"Connect to *address* and return the socket object.\n \n Convenience function. Connect to *address* (a 2-tuple ``(host,\n port)``) and return the socket object. Passing the optional\n *timeout* parameter will set the timeout on the socket instance\n before attempting to connect. If no *timeout* is supplied, the\n global default timeout setting returned by :func:`socket.getdefaulttimeout`\n is used. If *source_address* is set it must be a tuple of (host, port)\n for the socket to bind as a source address before making the connection.\n An host of '' or port 0 tells the OS to use the default.\n \"\"\"\n \n host, port = address\n if host.startswith(\"[\"):\n host = host.strip(\"[]\")\n err = None\n \n # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n # The original create_connection function always returns all records.\n family = allowed_gai_family()\n \n try:\n host.encode(\"idna\")\n except UnicodeError:\n raise LocationParseError(f\"'{host}', label empty or too long\") from None\n \n for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n af, socktype, proto, canonname, sa = res\n sock = None\n try:\n sock = socket.socket(af, socktype, proto)\n \n # If provided, set socket level options before connecting.\n _set_socket_options(sock, socket_options)\n \n if timeout is not _DEFAULT_TIMEOUT:\n sock.settimeout(timeout)\n if source_address:\n sock.bind(source_address)\n> sock.connect(sa)\nE ConnectionRefusedError: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nmethod = 'GET', url = '/demo/None', body = None\nheaders = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=Aj8sEsZ0GjABo6Ky3wVo9vClIh8jCGRqB0l6XLwkR38;'}\nretries = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = Timeout(connect=None, read=None, total=None), pool_timeout = None\nrelease_conn = False, chunked = False, body_pos = None, preload_content = False\ndecode_content = False, response_kw = {}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n def urlopen( # type: ignore[override]\n self,\n method: str,\n url: str,\n body: _TYPE_BODY | None = None,\n headers: typing.Mapping[str, str] | None = None,\n retries: Retry | bool | int | None = None,\n redirect: bool = True,\n assert_same_host: bool = True,\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n pool_timeout: int | None = None,\n release_conn: bool | None = None,\n chunked: bool = False,\n body_pos: _TYPE_BODY_POSITION | None = None,\n preload_content: bool = True,\n decode_content: bool = True,\n **response_kw: typing.Any,\n ) -> BaseHTTPResponse:\n \"\"\"\n Get a connection from the pool and perform an HTTP request. This is the\n lowest level call for making a request, so you'll need to specify all\n the raw details.\n \n .. note::\n \n More commonly, it's appropriate to use a convenience method\n such as :meth:`request`.\n \n .. note::\n \n `release_conn` will only behave as expected if\n `preload_content=False` because we want to make\n `preload_content=False` the default behaviour someday soon without\n breaking backwards compatibility.\n \n :param method:\n HTTP request method (such as GET, POST, PUT, etc.)\n \n :param url:\n The URL to perform the request on.\n \n :param body:\n Data to send in the request body, either :class:`str`, :class:`bytes`,\n an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n \n :param headers:\n Dictionary of custom headers to send, such as User-Agent,\n If-None-Match, etc. If None, pool headers are used. If provided,\n these headers completely replace any pool-specific headers.\n \n :param retries:\n Configure the number of retries to allow before raising a\n :class:`~urllib3.exceptions.MaxRetryError` exception.\n \n If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a\n :class:`~urllib3.util.retry.Retry` object for fine-grained control\n over different types of retries.\n Pass an integer number to retry connection errors that many times,\n but no other types of errors. Pass zero to never retry.\n \n If ``False``, then retries are disabled and any exception is raised\n immediately. Also, instead of raising a MaxRetryError on redirects,\n the redirect response will be returned.\n \n :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n \n :param redirect:\n If True, automatically handle redirects (status codes 301, 302,\n 303, 307, 308). Each redirect counts as a retry. Disabling retries\n will disable redirect, too.\n \n :param assert_same_host:\n If ``True``, will make sure that the host of the pool requests is\n consistent else will raise HostChangedError. When ``False``, you can\n use the pool on an HTTP proxy and request foreign hosts.\n \n :param timeout:\n If specified, overrides the default timeout for this one\n request. It may be a float (in seconds) or an instance of\n :class:`urllib3.util.Timeout`.\n \n :param pool_timeout:\n If set and the pool is set to block=True, then this method will\n block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n connection is available within the time period.\n \n :param bool preload_content:\n If True, the response's body will be preloaded into memory.\n \n :param bool decode_content:\n If True, will attempt to decode the body based on the\n 'content-encoding' header.\n \n :param release_conn:\n If False, then the urlopen call will not release the connection\n back into the pool once a response is received (but will release if\n you read the entire contents of the response such as when\n `preload_content=True`). This is useful if you're not preloading\n the response's content immediately. You will need to call\n ``r.release_conn()`` on the response ``r`` to return the connection\n back into the pool. If None, it takes the value of ``preload_content``\n which defaults to ``True``.\n \n :param bool chunked:\n If True, urllib3 will send the body using chunked transfer\n encoding. Otherwise, urllib3 will send the body using the standard\n content-length form. Defaults to False.\n \n :param int body_pos:\n Position to seek to in file-like body in the event of a retry or\n redirect. Typically this won't need to be set because urllib3 will\n auto-populate the value when needed.\n \"\"\"\n parsed_url = parse_url(url)\n destination_scheme = parsed_url.scheme\n \n if headers is None:\n headers = self.headers\n \n if not isinstance(retries, Retry):\n retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n \n if release_conn is None:\n release_conn = preload_content\n \n # Check host\n if assert_same_host and not self.is_same_host(url):\n raise HostChangedError(self, url, retries)\n \n # Ensure that the URL we're connecting to is properly encoded\n if url.startswith(\"/\"):\n url = to_str(_encode_target(url))\n else:\n url = to_str(parsed_url.url)\n \n conn = None\n \n # Track whether `conn` needs to be released before\n # returning/raising/recursing. Update this variable if necessary, and\n # leave `release_conn` constant throughout the function. That way, if\n # the function recurses, the original value of `release_conn` will be\n # passed down into the recursive call, and its value will be respected.\n #\n # See issue #651 [1] for details.\n #\n # [1] \n release_this_conn = release_conn\n \n http_tunnel_required = connection_requires_http_tunnel(\n self.proxy, self.proxy_config, destination_scheme\n )\n \n # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n # have to copy the headers dict so we can safely change it without those\n # changes being reflected in anyone else's copy.\n if not http_tunnel_required:\n headers = headers.copy() # type: ignore[attr-defined]\n headers.update(self.proxy_headers) # type: ignore[union-attr]\n \n # Must keep the exception bound to a separate variable or else Python 3\n # complains about UnboundLocalError.\n err = None\n \n # Keep track of whether we cleanly exited the except block. This\n # ensures we do proper cleanup in finally.\n clean_exit = False\n \n # Rewind body position, if needed. Record current position\n # for future rewinds in the event of a redirect/retry.\n body_pos = set_file_position(body, body_pos)\n \n try:\n # Request a connection from the queue.\n timeout_obj = self._get_timeout(timeout)\n conn = self._get_conn(timeout=pool_timeout)\n \n conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]\n \n # Is this a closed/new connection that requires CONNECT tunnelling?\n if self.proxy is not None and http_tunnel_required and conn.is_closed:\n try:\n self._prepare_proxy(conn)\n except (BaseSSLError, OSError, SocketTimeout) as e:\n self._raise_timeout(\n err=e, url=self.proxy.url, timeout_value=conn.timeout\n )\n raise\n \n # If we're going to release the connection in ``finally:``, then\n # the response doesn't need to know about the connection. Otherwise\n # it will also try to release it and we'll have a double-release\n # mess.\n response_conn = conn if not release_conn else None\n \n # Make the request on the HTTPConnection object\n> response = self._make_request(\n conn,\n method,\n url,\n timeout=timeout_obj,\n body=body,\n headers=headers,\n chunked=chunked,\n retries=retries,\n response_conn=response_conn,\n preload_content=preload_content,\n decode_content=decode_content,\n **response_kw,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request\n conn.request(\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request\n self.endheaders()\n.pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders\n self._send_output(message_body, encode_chunked=encode_chunked)\n.pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output\n self.send(msg)\n.pixi/envs/default/lib/python3.8/http/client.py:951: in send\n self.connect()\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect\n self.sock = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n except socket.gaierror as e:\n raise NameResolutionError(self.host, self, e) from e\n except SocketTimeout as e:\n raise ConnectTimeoutError(\n self,\n f\"Connection to {self.host} timed out. (connect timeout={self.timeout})\",\n ) from e\n \n except OSError as e:\n> raise NewConnectionError(\n self, f\"Failed to establish a new connection: {e}\"\n ) from e\nE urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n> resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen\n retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nmethod = 'GET', url = '/demo/None', response = None\nerror = NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused')\n_pool = \n_stacktrace = \n\n def increment(\n self,\n method: str | None = None,\n url: str | None = None,\n response: BaseHTTPResponse | None = None,\n error: Exception | None = None,\n _pool: ConnectionPool | None = None,\n _stacktrace: TracebackType | None = None,\n ) -> Self:\n \"\"\"Return a new Retry object with incremented retry counters.\n \n :param response: A response object, or None, if the server did not\n return a response.\n :type response: :class:`~urllib3.response.BaseHTTPResponse`\n :param Exception error: An error encountered during the request, or\n None if the response was received successfully.\n \n :return: A new ``Retry`` object.\n \"\"\"\n if self.total is False and error:\n # Disabled, indicate to re-raise the error.\n raise reraise(type(error), error, _stacktrace)\n \n total = self.total\n if total is not None:\n total -= 1\n \n connect = self.connect\n read = self.read\n redirect = self.redirect\n status_count = self.status\n other = self.other\n cause = \"unknown\"\n status = None\n redirect_location = None\n \n if error and self._is_connection_error(error):\n # Connect retry?\n if connect is False:\n raise reraise(type(error), error, _stacktrace)\n elif connect is not None:\n connect -= 1\n \n elif error and self._is_read_error(error):\n # Read retry?\n if read is False or method is None or not self._is_method_retryable(method):\n raise reraise(type(error), error, _stacktrace)\n elif read is not None:\n read -= 1\n \n elif error:\n # Other retry?\n if other is not None:\n other -= 1\n \n elif response and response.get_redirect_location():\n # Redirect retry?\n if redirect is not None:\n redirect -= 1\n cause = \"too many redirects\"\n response_redirect_location = response.get_redirect_location()\n if response_redirect_location:\n redirect_location = response_redirect_location\n status = response.status\n \n else:\n # Incrementing because of a server error like a 500 in\n # status_forcelist and the given method is in the allowed_methods\n cause = ResponseError.GENERIC_ERROR\n if response and response.status:\n if status_count is not None:\n status_count -= 1\n cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n status = response.status\n \n history = self.history + (\n RequestHistory(method, url, error, status, redirect_location),\n )\n \n new_retry = self.new(\n total=total,\n connect=connect,\n read=read,\n redirect=redirect,\n status=status_count,\n other=other,\n history=history,\n )\n \n if new_retry.is_exhausted():\n reason = error or ResponseError(cause)\n> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]\nE urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError\n\nDuring handling of the above exception, another exception occurred:\n\nself = , msg_id = None\ntimeout = None\n\n def _check_if_message_on_server(self, msg_id, timeout=None):\n \"\"\"Try to load page for specific message. If there is a html tag like then there is no\n such message.\n \n :param msg_id: ID of message to be checked\n :params timeout: The value of timeout to be passed to the get request\n :return:\n \"\"\"\n \n request_headers = dict()\n if self._user or self._password:\n request_headers['Cookie'] = self._make_user_and_pswd_cookie()\n try:\n> response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,\n verify=False, timeout=timeout)\n\nslic/utils/logbook.py:570: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:73: in get\n return request(\"get\", url, params=params, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request\n return session.request(method=method, url=url, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request\n resp = self.send(prep, **send_kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send\n r = adapter.send(request, **kwargs)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n \n except (ProtocolError, OSError) as err:\n raise ConnectionError(err, request=request)\n \n except MaxRetryError as e:\n if isinstance(e.reason, ConnectTimeoutError):\n # TODO: Remove this in 3.0.0: see #2811\n if not isinstance(e.reason, NewConnectionError):\n raise ConnectTimeout(e, request=request)\n \n if isinstance(e.reason, ResponseError):\n raise RetryError(e, request=request)\n \n if isinstance(e.reason, _ProxyError):\n raise ProxyError(e, request=request)\n \n if isinstance(e.reason, _SSLError):\n # This branch is for urllib3 v1.22 and later.\n raise SSLError(e, request=request)\n \n> raise ConnectionError(e, request=request)\nE requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\n def test_get_default_elog_instance_with_wrong_password_and_real_check():\n url = \"http://localhost:8080/demo\"\n user = \"robot\"\n wrong_password = \"wrongpassword\"\n \n elog = Elog(url, user=user, password=wrong_password)\n \n with pytest.raises(LogbookAuthenticationError):\n> elog.post(\"This should fail due to wrong password\")\n\ntests/test_utils_elog.py:46: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nslic/utils/elog.py:17: in post\n return self._log.post(*args, **kwargs)\nslic/utils/logbook.py:289: in post\n self._check_if_message_on_server(msg_id) # Raises exceptions if no message or no response from server\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = , msg_id = None\ntimeout = None\n\n def _check_if_message_on_server(self, msg_id, timeout=None):\n \"\"\"Try to load page for specific message. If there is a html tag like then there is no\n such message.\n \n :param msg_id: ID of message to be checked\n :params timeout: The value of timeout to be passed to the get request\n :return:\n \"\"\"\n \n request_headers = dict()\n if self._user or self._password:\n request_headers['Cookie'] = self._make_user_and_pswd_cookie()\n try:\n response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,\n verify=False, timeout=timeout)\n \n # If there is no message code 200 will be returned (OK) and _validate_response will not recognise it\n # but there will be some error in the html code.\n resp_message, resp_headers, resp_msg_id = _validate_response(response)\n # If there is no message, code 200 will be returned (OK) but there will be some error indication in\n # the html code.\n if re.findall('.*?',\n resp_message.decode('utf-8', 'ignore'),\n flags=re.DOTALL):\n raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.')\n \n except requests.Timeout as e:\n # Catch here a timeout o the post request.\n # Raise the logbook exception and let the user handle it\n raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\\n' +\n '{1}'.format(sys._getframe().f_code.co_name, e))\n \n except requests.RequestException as e:\n> raise LogbookServerProblem('No response from the logbook server.\\nDetails: ' + '{0}'.format(e))\nE slic.utils.logbook_exceptions.LogbookServerProblem: No response from the logbook server.\nE Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\nslic/utils/logbook.py:590: LogbookServerProblem"}, "teardown": {"duration": 0.0002921079285442829, "outcome": "passed"}}, {"nodeid": "tests/test_utils_elog.py::test_get_default_elog_instance_asks_password_and_opens", "lineno": 53, "outcome": "failed", "keywords": ["test_get_default_elog_instance_asks_password_and_opens", "__wrapped__", "patchings", "test_utils_elog.py", "tests", "slic", ""], "setup": {"duration": 0.00015496276319026947, "outcome": "passed"}, "call": {"duration": 0.014144825749099255, "outcome": "failed", "crash": {"path": "/workspace/tligui_y/slic/tests/test_utils_elog.py", "lineno": 68, "message": "Failed: elog.open() raised an unexpected exception: No response from the logbook server.\nDetails: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))"}, "traceback": [{"path": "tests/test_utils_elog.py", "lineno": 68, "message": "Failed"}], "longrepr": "self = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n> sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection\n raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\naddress = ('localhost', 8080), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n def create_connection(\n address: tuple[str, int],\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n source_address: tuple[str, int] | None = None,\n socket_options: _TYPE_SOCKET_OPTIONS | None = None,\n ) -> socket.socket:\n \"\"\"Connect to *address* and return the socket object.\n \n Convenience function. Connect to *address* (a 2-tuple ``(host,\n port)``) and return the socket object. Passing the optional\n *timeout* parameter will set the timeout on the socket instance\n before attempting to connect. If no *timeout* is supplied, the\n global default timeout setting returned by :func:`socket.getdefaulttimeout`\n is used. If *source_address* is set it must be a tuple of (host, port)\n for the socket to bind as a source address before making the connection.\n An host of '' or port 0 tells the OS to use the default.\n \"\"\"\n \n host, port = address\n if host.startswith(\"[\"):\n host = host.strip(\"[]\")\n err = None\n \n # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n # The original create_connection function always returns all records.\n family = allowed_gai_family()\n \n try:\n host.encode(\"idna\")\n except UnicodeError:\n raise LocationParseError(f\"'{host}', label empty or too long\") from None\n \n for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n af, socktype, proto, canonname, sa = res\n sock = None\n try:\n sock = socket.socket(af, socktype, proto)\n \n # If provided, set socket level options before connecting.\n _set_socket_options(sock, socket_options)\n \n if timeout is not _DEFAULT_TIMEOUT:\n sock.settimeout(timeout)\n if source_address:\n sock.bind(source_address)\n> sock.connect(sa)\nE ConnectionRefusedError: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nmethod = 'POST', url = '/demo/'\nbody = b'--edb3c41c85b235f5b6f6b089151ef961\\r\\nContent-Disposition: form-data; name=\"Author\"\\r\\n\\r\\nrobot\\r\\n--edb3c41c85b235...Disposition: form-data; name=\"Text\"; filename=\"\"\\r\\n\\r\\nThis is a message2\\r\\n--edb3c41c85b235f5b6f6b089151ef961--\\r\\n'\nheaders = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=edb3c41c85b235f5b6f6b089151ef961'}\nretries = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = Timeout(connect=None, read=None, total=None), pool_timeout = None\nrelease_conn = False, chunked = False, body_pos = None, preload_content = False\ndecode_content = False, response_kw = {}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n def urlopen( # type: ignore[override]\n self,\n method: str,\n url: str,\n body: _TYPE_BODY | None = None,\n headers: typing.Mapping[str, str] | None = None,\n retries: Retry | bool | int | None = None,\n redirect: bool = True,\n assert_same_host: bool = True,\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n pool_timeout: int | None = None,\n release_conn: bool | None = None,\n chunked: bool = False,\n body_pos: _TYPE_BODY_POSITION | None = None,\n preload_content: bool = True,\n decode_content: bool = True,\n **response_kw: typing.Any,\n ) -> BaseHTTPResponse:\n \"\"\"\n Get a connection from the pool and perform an HTTP request. This is the\n lowest level call for making a request, so you'll need to specify all\n the raw details.\n \n .. note::\n \n More commonly, it's appropriate to use a convenience method\n such as :meth:`request`.\n \n .. note::\n \n `release_conn` will only behave as expected if\n `preload_content=False` because we want to make\n `preload_content=False` the default behaviour someday soon without\n breaking backwards compatibility.\n \n :param method:\n HTTP request method (such as GET, POST, PUT, etc.)\n \n :param url:\n The URL to perform the request on.\n \n :param body:\n Data to send in the request body, either :class:`str`, :class:`bytes`,\n an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n \n :param headers:\n Dictionary of custom headers to send, such as User-Agent,\n If-None-Match, etc. If None, pool headers are used. If provided,\n these headers completely replace any pool-specific headers.\n \n :param retries:\n Configure the number of retries to allow before raising a\n :class:`~urllib3.exceptions.MaxRetryError` exception.\n \n If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a\n :class:`~urllib3.util.retry.Retry` object for fine-grained control\n over different types of retries.\n Pass an integer number to retry connection errors that many times,\n but no other types of errors. Pass zero to never retry.\n \n If ``False``, then retries are disabled and any exception is raised\n immediately. Also, instead of raising a MaxRetryError on redirects,\n the redirect response will be returned.\n \n :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n \n :param redirect:\n If True, automatically handle redirects (status codes 301, 302,\n 303, 307, 308). Each redirect counts as a retry. Disabling retries\n will disable redirect, too.\n \n :param assert_same_host:\n If ``True``, will make sure that the host of the pool requests is\n consistent else will raise HostChangedError. When ``False``, you can\n use the pool on an HTTP proxy and request foreign hosts.\n \n :param timeout:\n If specified, overrides the default timeout for this one\n request. It may be a float (in seconds) or an instance of\n :class:`urllib3.util.Timeout`.\n \n :param pool_timeout:\n If set and the pool is set to block=True, then this method will\n block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n connection is available within the time period.\n \n :param bool preload_content:\n If True, the response's body will be preloaded into memory.\n \n :param bool decode_content:\n If True, will attempt to decode the body based on the\n 'content-encoding' header.\n \n :param release_conn:\n If False, then the urlopen call will not release the connection\n back into the pool once a response is received (but will release if\n you read the entire contents of the response such as when\n `preload_content=True`). This is useful if you're not preloading\n the response's content immediately. You will need to call\n ``r.release_conn()`` on the response ``r`` to return the connection\n back into the pool. If None, it takes the value of ``preload_content``\n which defaults to ``True``.\n \n :param bool chunked:\n If True, urllib3 will send the body using chunked transfer\n encoding. Otherwise, urllib3 will send the body using the standard\n content-length form. Defaults to False.\n \n :param int body_pos:\n Position to seek to in file-like body in the event of a retry or\n redirect. Typically this won't need to be set because urllib3 will\n auto-populate the value when needed.\n \"\"\"\n parsed_url = parse_url(url)\n destination_scheme = parsed_url.scheme\n \n if headers is None:\n headers = self.headers\n \n if not isinstance(retries, Retry):\n retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n \n if release_conn is None:\n release_conn = preload_content\n \n # Check host\n if assert_same_host and not self.is_same_host(url):\n raise HostChangedError(self, url, retries)\n \n # Ensure that the URL we're connecting to is properly encoded\n if url.startswith(\"/\"):\n url = to_str(_encode_target(url))\n else:\n url = to_str(parsed_url.url)\n \n conn = None\n \n # Track whether `conn` needs to be released before\n # returning/raising/recursing. Update this variable if necessary, and\n # leave `release_conn` constant throughout the function. That way, if\n # the function recurses, the original value of `release_conn` will be\n # passed down into the recursive call, and its value will be respected.\n #\n # See issue #651 [1] for details.\n #\n # [1] \n release_this_conn = release_conn\n \n http_tunnel_required = connection_requires_http_tunnel(\n self.proxy, self.proxy_config, destination_scheme\n )\n \n # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n # have to copy the headers dict so we can safely change it without those\n # changes being reflected in anyone else's copy.\n if not http_tunnel_required:\n headers = headers.copy() # type: ignore[attr-defined]\n headers.update(self.proxy_headers) # type: ignore[union-attr]\n \n # Must keep the exception bound to a separate variable or else Python 3\n # complains about UnboundLocalError.\n err = None\n \n # Keep track of whether we cleanly exited the except block. This\n # ensures we do proper cleanup in finally.\n clean_exit = False\n \n # Rewind body position, if needed. Record current position\n # for future rewinds in the event of a redirect/retry.\n body_pos = set_file_position(body, body_pos)\n \n try:\n # Request a connection from the queue.\n timeout_obj = self._get_timeout(timeout)\n conn = self._get_conn(timeout=pool_timeout)\n \n conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]\n \n # Is this a closed/new connection that requires CONNECT tunnelling?\n if self.proxy is not None and http_tunnel_required and conn.is_closed:\n try:\n self._prepare_proxy(conn)\n except (BaseSSLError, OSError, SocketTimeout) as e:\n self._raise_timeout(\n err=e, url=self.proxy.url, timeout_value=conn.timeout\n )\n raise\n \n # If we're going to release the connection in ``finally:``, then\n # the response doesn't need to know about the connection. Otherwise\n # it will also try to release it and we'll have a double-release\n # mess.\n response_conn = conn if not release_conn else None\n \n # Make the request on the HTTPConnection object\n> response = self._make_request(\n conn,\n method,\n url,\n timeout=timeout_obj,\n body=body,\n headers=headers,\n chunked=chunked,\n retries=retries,\n response_conn=response_conn,\n preload_content=preload_content,\n decode_content=decode_content,\n **response_kw,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request\n conn.request(\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request\n self.endheaders()\n.pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders\n self._send_output(message_body, encode_chunked=encode_chunked)\n.pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output\n self.send(msg)\n.pixi/envs/default/lib/python3.8/http/client.py:951: in send\n self.connect()\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect\n self.sock = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n except socket.gaierror as e:\n raise NameResolutionError(self.host, self, e) from e\n except SocketTimeout as e:\n raise ConnectTimeoutError(\n self,\n f\"Connection to {self.host} timed out. (connect timeout={self.timeout})\",\n ) from e\n \n except OSError as e:\n> raise NewConnectionError(\n self, f\"Failed to establish a new connection: {e}\"\n ) from e\nE urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n> resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen\n retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nmethod = 'POST', url = '/demo/', response = None\nerror = NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused')\n_pool = \n_stacktrace = \n\n def increment(\n self,\n method: str | None = None,\n url: str | None = None,\n response: BaseHTTPResponse | None = None,\n error: Exception | None = None,\n _pool: ConnectionPool | None = None,\n _stacktrace: TracebackType | None = None,\n ) -> Self:\n \"\"\"Return a new Retry object with incremented retry counters.\n \n :param response: A response object, or None, if the server did not\n return a response.\n :type response: :class:`~urllib3.response.BaseHTTPResponse`\n :param Exception error: An error encountered during the request, or\n None if the response was received successfully.\n \n :return: A new ``Retry`` object.\n \"\"\"\n if self.total is False and error:\n # Disabled, indicate to re-raise the error.\n raise reraise(type(error), error, _stacktrace)\n \n total = self.total\n if total is not None:\n total -= 1\n \n connect = self.connect\n read = self.read\n redirect = self.redirect\n status_count = self.status\n other = self.other\n cause = \"unknown\"\n status = None\n redirect_location = None\n \n if error and self._is_connection_error(error):\n # Connect retry?\n if connect is False:\n raise reraise(type(error), error, _stacktrace)\n elif connect is not None:\n connect -= 1\n \n elif error and self._is_read_error(error):\n # Read retry?\n if read is False or method is None or not self._is_method_retryable(method):\n raise reraise(type(error), error, _stacktrace)\n elif read is not None:\n read -= 1\n \n elif error:\n # Other retry?\n if other is not None:\n other -= 1\n \n elif response and response.get_redirect_location():\n # Redirect retry?\n if redirect is not None:\n redirect -= 1\n cause = \"too many redirects\"\n response_redirect_location = response.get_redirect_location()\n if response_redirect_location:\n redirect_location = response_redirect_location\n status = response.status\n \n else:\n # Incrementing because of a server error like a 500 in\n # status_forcelist and the given method is in the allowed_methods\n cause = ResponseError.GENERIC_ERROR\n if response and response.status:\n if status_count is not None:\n status_count -= 1\n cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n status = response.status\n \n history = self.history + (\n RequestHistory(method, url, error, status, redirect_location),\n )\n \n new_retry = self.new(\n total=total,\n connect=connect,\n read=read,\n redirect=redirect,\n status=status_count,\n other=other,\n history=history,\n )\n \n if new_retry.is_exhausted():\n reason = error or ResponseError(cause)\n> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]\nE urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \nmessage = 'This is a message2', msg_id = None, reply = False\nattributes = {'Author': 'robot', 'When': 1755174854, 'cmd': 'Submit', 'exp': 'demo', ...}\nattachments = [], suppress_email_notification = False, encoding = None\ntimeout = None, kwargs = {'Author': 'robot'}\nlogbook_directory = 'elog_instance/logbooks/demo'\nnew_attachment_list = [('Text', ('', b'This is a message2'))]\nobjects_to_close = []\nattributes_to_edit = {'Author': b'robot', 'When': 1755174854, 'cmd': b'Submit', 'exp': b'demo', ...}\n\n def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None,\n suppress_email_notification=False, encoding=None, timeout=None, **kwargs):\n \"\"\"\n Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing\n message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id\n of the newly created message.\n \"\"\"\n \n logbook_directory = \"elog_instance/logbooks/demo\"\n print(f\"Checking the existence of the directory {logbook_directory}\")\n \n # Check if the directory exists\n if not os.path.exists(logbook_directory):\n print(f\"The directory {logbook_directory} does not exist.\")\n else:\n print(f\"The directory {logbook_directory} exists.\")\n \n # Check write permissions\n if os.access(logbook_directory, os.W_OK):\n print(f\"The directory {logbook_directory} has write permissions.\")\n else:\n print(f\"The directory {logbook_directory} does not have write permissions.\")\n \n \n print(\"STARTING POST\")\n # Ajout des impressions pour d\u00e9boguer\n print(f\"Message to post: {message}\")\n print(f\"msg_id: {msg_id}\")\n print(f\"Attributes: {attributes}\")\n print(f\"Attachments: {attachments}\")\n print(f\"Encoding: {encoding}\")\n print(f\"Timeout: {timeout}\")\n print(f\"Additional kwargs: {kwargs}\")\n \n attributes = attributes or {}\n attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority\n print(f\"Updated attributes: {attributes}\")\n \n attachments = attachments or []\n print(f\"Attachments list: {attachments}\")\n \n if encoding is not None:\n if encoding not in ['plain', 'HTML', 'ELCode']:\n raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.')\n attributes['Encoding'] = encoding\n \n if suppress_email_notification:\n attributes[\"suppress\"] = 1\n \n # Prepare attachments\n if attachments:\n new_attachment_list, objects_to_close = self._prepare_attachments(attachments)\n print(f\"New attachments prepared: {new_attachment_list}\")\n else:\n objects_to_close = []\n new_attachment_list = []\n \n attributes_to_edit = dict()\n \n if msg_id:\n print(f\"Editing message with msg_id: {msg_id}\")\n if reply:\n print(f\"Replying to message with msg_id: {msg_id}\")\n self._check_if_message_on_server(msg_id)\n attributes['reply_to'] = str(msg_id)\n else:\n print(\"Editing existing message.\")\n attributes['edit_id'] = str(msg_id)\n attributes['skiplock'] = '1'\n msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id)\n \n # Merge new attributes\n for attribute, data in attributes.items():\n if data is not None:\n attributes_to_edit[attribute] = data\n \n print(f\"Attributes after merging: {attributes_to_edit}\")\n \n # Process existing attachments\n i = 0\n existing_attachments_filename_list = []\n for attachment in existing_attachments_list:\n attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)\n existing_attachments_filename_list.append(os.path.basename(attachment)[14:])\n i += 1\n \n print(f\"Existing attachments: {existing_attachments_filename_list}\")\n \n duplicate_attachment_list = []\n for new_attachment in new_attachment_list:\n new_attachment_filename = new_attachment[1][0]\n print(f\"Checking new attachment: {new_attachment_filename}\")\n if new_attachment_filename in existing_attachments_filename_list:\n # Same attachment exists on the server, compare content\n new_attachment_content = new_attachment[1][1].read()\n new_attachment[1][1].seek(0)\n attachment_index = existing_attachments_filename_list.index(new_attachment_filename)\n existing_attachment_content = self.download_attachment(\n url=existing_attachments_list[attachment_index],\n timeout=timeout\n )\n if new_attachment_content == existing_attachment_content:\n print(f\"Duplicate attachment detected: {new_attachment_filename}\")\n duplicate_attachment_list.append(new_attachment)\n else:\n print(f\"Attachment content has changed: {new_attachment_filename}\")\n self.delete_attachment(msg_id, attributes=attributes_to_edit,\n attachment_id=attachment_index,\n timeout=timeout, text=msg_to_edit)\n existing_attachments_filename_list.pop(attachment_index)\n existing_attachments_list.pop(attachment_index)\n \n print(f\"Duplicate attachments to remove: {duplicate_attachment_list}\")\n \n # Remove duplicates\n for attach in duplicate_attachment_list:\n new_attachment_list.remove(attach)\n \n print(f\"Final new attachments list: {new_attachment_list}\")\n else:\n # Creating a new message, add timestamp if not present\n if 'When' not in attributes:\n attributes['When'] = int(datetime.now().timestamp())\n \n # Final check on attributes\n if not attributes_to_edit:\n attributes_to_edit = attributes\n \n print(f\"Final attributes to send to the server: {attributes_to_edit}\")\n \n # Remove reserved attributes\n _remove_reserved_attributes(attributes_to_edit)\n \n new_attachment_list.append(('Text', ('', message.encode('iso-8859-1'))))\n print(f\"Final attachment list including message text: {new_attachment_list}\")\n \n # Add base message attributes\n self._add_base_msg_attributes(attributes_to_edit)\n print(f\"Attributes with base message added: {attributes_to_edit}\")\n \n # Sanitize attribute keys\n attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit)\n print(f\"Attributes after sanitizing keys: {attributes_to_edit}\")\n \n # Encode all string values in latin1\n attributes_to_edit = _encode_values(attributes_to_edit)\n print(f\"Attributes after encoding: {attributes_to_edit}\")\n \n try:\n print(\"Sending POST request to the server...\")\n> response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list,\n allow_redirects=False, verify=False, timeout=timeout)\n\nslic/utils/logbook.py:269: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:115: in post\n return request(\"post\", url, data=data, json=json, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request\n return session.request(method=method, url=url, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request\n resp = self.send(prep, **send_kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send\n r = adapter.send(request, **kwargs)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n \n except (ProtocolError, OSError) as err:\n raise ConnectionError(err, request=request)\n \n except MaxRetryError as e:\n if isinstance(e.reason, ConnectTimeoutError):\n # TODO: Remove this in 3.0.0: see #2811\n if not isinstance(e.reason, NewConnectionError):\n raise ConnectTimeout(e, request=request)\n \n if isinstance(e.reason, ResponseError):\n raise RetryError(e, request=request)\n \n if isinstance(e.reason, _ProxyError):\n raise ProxyError(e, request=request)\n \n if isinstance(e.reason, _SSLError):\n # This branch is for urllib3 v1.22 and later.\n raise SSLError(e, request=request)\n \n> raise ConnectionError(e, request=request)\nE requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n> sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection\n raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\naddress = ('localhost', 8080), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n def create_connection(\n address: tuple[str, int],\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n source_address: tuple[str, int] | None = None,\n socket_options: _TYPE_SOCKET_OPTIONS | None = None,\n ) -> socket.socket:\n \"\"\"Connect to *address* and return the socket object.\n \n Convenience function. Connect to *address* (a 2-tuple ``(host,\n port)``) and return the socket object. Passing the optional\n *timeout* parameter will set the timeout on the socket instance\n before attempting to connect. If no *timeout* is supplied, the\n global default timeout setting returned by :func:`socket.getdefaulttimeout`\n is used. If *source_address* is set it must be a tuple of (host, port)\n for the socket to bind as a source address before making the connection.\n An host of '' or port 0 tells the OS to use the default.\n \"\"\"\n \n host, port = address\n if host.startswith(\"[\"):\n host = host.strip(\"[]\")\n err = None\n \n # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n # The original create_connection function always returns all records.\n family = allowed_gai_family()\n \n try:\n host.encode(\"idna\")\n except UnicodeError:\n raise LocationParseError(f\"'{host}', label empty or too long\") from None\n \n for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n af, socktype, proto, canonname, sa = res\n sock = None\n try:\n sock = socket.socket(af, socktype, proto)\n \n # If provided, set socket level options before connecting.\n _set_socket_options(sock, socket_options)\n \n if timeout is not _DEFAULT_TIMEOUT:\n sock.settimeout(timeout)\n if source_address:\n sock.bind(source_address)\n> sock.connect(sa)\nE ConnectionRefusedError: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nmethod = 'GET', url = '/demo/None', body = None\nheaders = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'}\nretries = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = Timeout(connect=None, read=None, total=None), pool_timeout = None\nrelease_conn = False, chunked = False, body_pos = None, preload_content = False\ndecode_content = False, response_kw = {}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n def urlopen( # type: ignore[override]\n self,\n method: str,\n url: str,\n body: _TYPE_BODY | None = None,\n headers: typing.Mapping[str, str] | None = None,\n retries: Retry | bool | int | None = None,\n redirect: bool = True,\n assert_same_host: bool = True,\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n pool_timeout: int | None = None,\n release_conn: bool | None = None,\n chunked: bool = False,\n body_pos: _TYPE_BODY_POSITION | None = None,\n preload_content: bool = True,\n decode_content: bool = True,\n **response_kw: typing.Any,\n ) -> BaseHTTPResponse:\n \"\"\"\n Get a connection from the pool and perform an HTTP request. This is the\n lowest level call for making a request, so you'll need to specify all\n the raw details.\n \n .. note::\n \n More commonly, it's appropriate to use a convenience method\n such as :meth:`request`.\n \n .. note::\n \n `release_conn` will only behave as expected if\n `preload_content=False` because we want to make\n `preload_content=False` the default behaviour someday soon without\n breaking backwards compatibility.\n \n :param method:\n HTTP request method (such as GET, POST, PUT, etc.)\n \n :param url:\n The URL to perform the request on.\n \n :param body:\n Data to send in the request body, either :class:`str`, :class:`bytes`,\n an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n \n :param headers:\n Dictionary of custom headers to send, such as User-Agent,\n If-None-Match, etc. If None, pool headers are used. If provided,\n these headers completely replace any pool-specific headers.\n \n :param retries:\n Configure the number of retries to allow before raising a\n :class:`~urllib3.exceptions.MaxRetryError` exception.\n \n If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a\n :class:`~urllib3.util.retry.Retry` object for fine-grained control\n over different types of retries.\n Pass an integer number to retry connection errors that many times,\n but no other types of errors. Pass zero to never retry.\n \n If ``False``, then retries are disabled and any exception is raised\n immediately. Also, instead of raising a MaxRetryError on redirects,\n the redirect response will be returned.\n \n :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n \n :param redirect:\n If True, automatically handle redirects (status codes 301, 302,\n 303, 307, 308). Each redirect counts as a retry. Disabling retries\n will disable redirect, too.\n \n :param assert_same_host:\n If ``True``, will make sure that the host of the pool requests is\n consistent else will raise HostChangedError. When ``False``, you can\n use the pool on an HTTP proxy and request foreign hosts.\n \n :param timeout:\n If specified, overrides the default timeout for this one\n request. It may be a float (in seconds) or an instance of\n :class:`urllib3.util.Timeout`.\n \n :param pool_timeout:\n If set and the pool is set to block=True, then this method will\n block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n connection is available within the time period.\n \n :param bool preload_content:\n If True, the response's body will be preloaded into memory.\n \n :param bool decode_content:\n If True, will attempt to decode the body based on the\n 'content-encoding' header.\n \n :param release_conn:\n If False, then the urlopen call will not release the connection\n back into the pool once a response is received (but will release if\n you read the entire contents of the response such as when\n `preload_content=True`). This is useful if you're not preloading\n the response's content immediately. You will need to call\n ``r.release_conn()`` on the response ``r`` to return the connection\n back into the pool. If None, it takes the value of ``preload_content``\n which defaults to ``True``.\n \n :param bool chunked:\n If True, urllib3 will send the body using chunked transfer\n encoding. Otherwise, urllib3 will send the body using the standard\n content-length form. Defaults to False.\n \n :param int body_pos:\n Position to seek to in file-like body in the event of a retry or\n redirect. Typically this won't need to be set because urllib3 will\n auto-populate the value when needed.\n \"\"\"\n parsed_url = parse_url(url)\n destination_scheme = parsed_url.scheme\n \n if headers is None:\n headers = self.headers\n \n if not isinstance(retries, Retry):\n retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n \n if release_conn is None:\n release_conn = preload_content\n \n # Check host\n if assert_same_host and not self.is_same_host(url):\n raise HostChangedError(self, url, retries)\n \n # Ensure that the URL we're connecting to is properly encoded\n if url.startswith(\"/\"):\n url = to_str(_encode_target(url))\n else:\n url = to_str(parsed_url.url)\n \n conn = None\n \n # Track whether `conn` needs to be released before\n # returning/raising/recursing. Update this variable if necessary, and\n # leave `release_conn` constant throughout the function. That way, if\n # the function recurses, the original value of `release_conn` will be\n # passed down into the recursive call, and its value will be respected.\n #\n # See issue #651 [1] for details.\n #\n # [1] \n release_this_conn = release_conn\n \n http_tunnel_required = connection_requires_http_tunnel(\n self.proxy, self.proxy_config, destination_scheme\n )\n \n # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n # have to copy the headers dict so we can safely change it without those\n # changes being reflected in anyone else's copy.\n if not http_tunnel_required:\n headers = headers.copy() # type: ignore[attr-defined]\n headers.update(self.proxy_headers) # type: ignore[union-attr]\n \n # Must keep the exception bound to a separate variable or else Python 3\n # complains about UnboundLocalError.\n err = None\n \n # Keep track of whether we cleanly exited the except block. This\n # ensures we do proper cleanup in finally.\n clean_exit = False\n \n # Rewind body position, if needed. Record current position\n # for future rewinds in the event of a redirect/retry.\n body_pos = set_file_position(body, body_pos)\n \n try:\n # Request a connection from the queue.\n timeout_obj = self._get_timeout(timeout)\n conn = self._get_conn(timeout=pool_timeout)\n \n conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]\n \n # Is this a closed/new connection that requires CONNECT tunnelling?\n if self.proxy is not None and http_tunnel_required and conn.is_closed:\n try:\n self._prepare_proxy(conn)\n except (BaseSSLError, OSError, SocketTimeout) as e:\n self._raise_timeout(\n err=e, url=self.proxy.url, timeout_value=conn.timeout\n )\n raise\n \n # If we're going to release the connection in ``finally:``, then\n # the response doesn't need to know about the connection. Otherwise\n # it will also try to release it and we'll have a double-release\n # mess.\n response_conn = conn if not release_conn else None\n \n # Make the request on the HTTPConnection object\n> response = self._make_request(\n conn,\n method,\n url,\n timeout=timeout_obj,\n body=body,\n headers=headers,\n chunked=chunked,\n retries=retries,\n response_conn=response_conn,\n preload_content=preload_content,\n decode_content=decode_content,\n **response_kw,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request\n conn.request(\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request\n self.endheaders()\n.pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders\n self._send_output(message_body, encode_chunked=encode_chunked)\n.pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output\n self.send(msg)\n.pixi/envs/default/lib/python3.8/http/client.py:951: in send\n self.connect()\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect\n self.sock = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n except socket.gaierror as e:\n raise NameResolutionError(self.host, self, e) from e\n except SocketTimeout as e:\n raise ConnectTimeoutError(\n self,\n f\"Connection to {self.host} timed out. (connect timeout={self.timeout})\",\n ) from e\n \n except OSError as e:\n> raise NewConnectionError(\n self, f\"Failed to establish a new connection: {e}\"\n ) from e\nE urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n> resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen\n retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nmethod = 'GET', url = '/demo/None', response = None\nerror = NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused')\n_pool = \n_stacktrace = \n\n def increment(\n self,\n method: str | None = None,\n url: str | None = None,\n response: BaseHTTPResponse | None = None,\n error: Exception | None = None,\n _pool: ConnectionPool | None = None,\n _stacktrace: TracebackType | None = None,\n ) -> Self:\n \"\"\"Return a new Retry object with incremented retry counters.\n \n :param response: A response object, or None, if the server did not\n return a response.\n :type response: :class:`~urllib3.response.BaseHTTPResponse`\n :param Exception error: An error encountered during the request, or\n None if the response was received successfully.\n \n :return: A new ``Retry`` object.\n \"\"\"\n if self.total is False and error:\n # Disabled, indicate to re-raise the error.\n raise reraise(type(error), error, _stacktrace)\n \n total = self.total\n if total is not None:\n total -= 1\n \n connect = self.connect\n read = self.read\n redirect = self.redirect\n status_count = self.status\n other = self.other\n cause = \"unknown\"\n status = None\n redirect_location = None\n \n if error and self._is_connection_error(error):\n # Connect retry?\n if connect is False:\n raise reraise(type(error), error, _stacktrace)\n elif connect is not None:\n connect -= 1\n \n elif error and self._is_read_error(error):\n # Read retry?\n if read is False or method is None or not self._is_method_retryable(method):\n raise reraise(type(error), error, _stacktrace)\n elif read is not None:\n read -= 1\n \n elif error:\n # Other retry?\n if other is not None:\n other -= 1\n \n elif response and response.get_redirect_location():\n # Redirect retry?\n if redirect is not None:\n redirect -= 1\n cause = \"too many redirects\"\n response_redirect_location = response.get_redirect_location()\n if response_redirect_location:\n redirect_location = response_redirect_location\n status = response.status\n \n else:\n # Incrementing because of a server error like a 500 in\n # status_forcelist and the given method is in the allowed_methods\n cause = ResponseError.GENERIC_ERROR\n if response and response.status:\n if status_count is not None:\n status_count -= 1\n cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n status = response.status\n \n history = self.history + (\n RequestHistory(method, url, error, status, redirect_location),\n )\n \n new_retry = self.new(\n total=total,\n connect=connect,\n read=read,\n redirect=redirect,\n status=status_count,\n other=other,\n history=history,\n )\n \n if new_retry.is_exhausted():\n reason = error or ResponseError(cause)\n> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]\nE urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError\n\nDuring handling of the above exception, another exception occurred:\n\nself = , msg_id = None\ntimeout = None\n\n def _check_if_message_on_server(self, msg_id, timeout=None):\n \"\"\"Try to load page for specific message. If there is a html tag like then there is no\n such message.\n \n :param msg_id: ID of message to be checked\n :params timeout: The value of timeout to be passed to the get request\n :return:\n \"\"\"\n \n request_headers = dict()\n if self._user or self._password:\n request_headers['Cookie'] = self._make_user_and_pswd_cookie()\n try:\n> response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,\n verify=False, timeout=timeout)\n\nslic/utils/logbook.py:570: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:73: in get\n return request(\"get\", url, params=params, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request\n return session.request(method=method, url=url, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request\n resp = self.send(prep, **send_kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send\n r = adapter.send(request, **kwargs)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n \n except (ProtocolError, OSError) as err:\n raise ConnectionError(err, request=request)\n \n except MaxRetryError as e:\n if isinstance(e.reason, ConnectTimeoutError):\n # TODO: Remove this in 3.0.0: see #2811\n if not isinstance(e.reason, NewConnectionError):\n raise ConnectTimeout(e, request=request)\n \n if isinstance(e.reason, ResponseError):\n raise RetryError(e, request=request)\n \n if isinstance(e.reason, _ProxyError):\n raise ProxyError(e, request=request)\n \n if isinstance(e.reason, _SSLError):\n # This branch is for urllib3 v1.22 and later.\n raise SSLError(e, request=request)\n \n> raise ConnectionError(e, request=request)\nE requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nmock_home = \nmock_getpass = \n\n @patch(\"slic.utils.elog.getpass\")\n @patch(\"slic.utils.elog.Path.home\")\n def test_get_default_elog_instance_asks_password_and_opens(mock_home, mock_getpass):\n mock_home.return_value = Path(\"/does/not/exist\") # Fausse home \u2192 lecture \u00e9choue\n mock_getpass.return_value = \"testpassword\"\n user = \"robot\"\n text = \"This is a message2\"\n url = \"http://localhost:8080/demo\"\n \n elog = Elog(\"http://localhost:8080/demo\", user=user)\n \n try:\n> elog.post(text)\n\ntests/test_utils_elog.py:66: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nslic/utils/elog.py:17: in post\n return self._log.post(*args, **kwargs)\nslic/utils/logbook.py:289: in post\n self._check_if_message_on_server(msg_id) # Raises exceptions if no message or no response from server\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = , msg_id = None\ntimeout = None\n\n def _check_if_message_on_server(self, msg_id, timeout=None):\n \"\"\"Try to load page for specific message. If there is a html tag like then there is no\n such message.\n \n :param msg_id: ID of message to be checked\n :params timeout: The value of timeout to be passed to the get request\n :return:\n \"\"\"\n \n request_headers = dict()\n if self._user or self._password:\n request_headers['Cookie'] = self._make_user_and_pswd_cookie()\n try:\n response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,\n verify=False, timeout=timeout)\n \n # If there is no message code 200 will be returned (OK) and _validate_response will not recognise it\n # but there will be some error in the html code.\n resp_message, resp_headers, resp_msg_id = _validate_response(response)\n # If there is no message, code 200 will be returned (OK) but there will be some error indication in\n # the html code.\n if re.findall('.*?',\n resp_message.decode('utf-8', 'ignore'),\n flags=re.DOTALL):\n raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.')\n \n except requests.Timeout as e:\n # Catch here a timeout o the post request.\n # Raise the logbook exception and let the user handle it\n raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\\n' +\n '{1}'.format(sys._getframe().f_code.co_name, e))\n \n except requests.RequestException as e:\n> raise LogbookServerProblem('No response from the logbook server.\\nDetails: ' + '{0}'.format(e))\nE slic.utils.logbook_exceptions.LogbookServerProblem: No response from the logbook server.\nE Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\nslic/utils/logbook.py:590: LogbookServerProblem\n\nDuring handling of the above exception, another exception occurred:\n\nmock_home = \nmock_getpass = \n\n @patch(\"slic.utils.elog.getpass\")\n @patch(\"slic.utils.elog.Path.home\")\n def test_get_default_elog_instance_asks_password_and_opens(mock_home, mock_getpass):\n mock_home.return_value = Path(\"/does/not/exist\") # Fausse home \u2192 lecture \u00e9choue\n mock_getpass.return_value = \"testpassword\"\n user = \"robot\"\n text = \"This is a message2\"\n url = \"http://localhost:8080/demo\"\n \n elog = Elog(\"http://localhost:8080/demo\", user=user)\n \n try:\n elog.post(text)\n except Exception as e:\n> pytest.fail(f\"elog.open() raised an unexpected exception: {e}\")\nE Failed: elog.open() raised an unexpected exception: No response from the logbook server.\nE Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\ntests/test_utils_elog.py:68: Failed"}, "teardown": {"duration": 0.0003055981360375881, "outcome": "passed"}}, {"nodeid": "tests/test_utils_elog.py::test_get_default_elog_with_path_home", "lineno": 79, "outcome": "failed", "keywords": ["test_get_default_elog_with_path_home", "__wrapped__", "patchings", "test_utils_elog.py", "tests", "slic", ""], "setup": {"duration": 0.00015193456783890724, "outcome": "passed"}, "call": {"duration": 0.009498361963778734, "outcome": "failed", "crash": {"path": "/workspace/tligui_y/slic/tests/test_utils_elog.py", "lineno": 102, "message": "Failed: elog.open() raised an unexpected exception: No response from the logbook server.\nDetails: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))"}, "traceback": [{"path": "tests/test_utils_elog.py", "lineno": 102, "message": "Failed"}], "longrepr": "self = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n> sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection\n raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\naddress = ('localhost', 8080), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n def create_connection(\n address: tuple[str, int],\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n source_address: tuple[str, int] | None = None,\n socket_options: _TYPE_SOCKET_OPTIONS | None = None,\n ) -> socket.socket:\n \"\"\"Connect to *address* and return the socket object.\n \n Convenience function. Connect to *address* (a 2-tuple ``(host,\n port)``) and return the socket object. Passing the optional\n *timeout* parameter will set the timeout on the socket instance\n before attempting to connect. If no *timeout* is supplied, the\n global default timeout setting returned by :func:`socket.getdefaulttimeout`\n is used. If *source_address* is set it must be a tuple of (host, port)\n for the socket to bind as a source address before making the connection.\n An host of '' or port 0 tells the OS to use the default.\n \"\"\"\n \n host, port = address\n if host.startswith(\"[\"):\n host = host.strip(\"[]\")\n err = None\n \n # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n # The original create_connection function always returns all records.\n family = allowed_gai_family()\n \n try:\n host.encode(\"idna\")\n except UnicodeError:\n raise LocationParseError(f\"'{host}', label empty or too long\") from None\n \n for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n af, socktype, proto, canonname, sa = res\n sock = None\n try:\n sock = socket.socket(af, socktype, proto)\n \n # If provided, set socket level options before connecting.\n _set_socket_options(sock, socket_options)\n \n if timeout is not _DEFAULT_TIMEOUT:\n sock.settimeout(timeout)\n if source_address:\n sock.bind(source_address)\n> sock.connect(sa)\nE ConnectionRefusedError: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nmethod = 'POST', url = '/demo/'\nbody = b'--74b91bc2bd26184234285e5f4a987328\\r\\nContent-Disposition: form-data; name=\"Author\"\\r\\n\\r\\nrobot\\r\\n--74b91bc2bd2618...Disposition: form-data; name=\"Text\"; filename=\"\"\\r\\n\\r\\nThis is a message3\\r\\n--74b91bc2bd26184234285e5f4a987328--\\r\\n'\nheaders = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '736', 'Content-Type': 'multipart/form-data; boundary=74b91bc2bd26184234285e5f4a987328'}\nretries = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = Timeout(connect=None, read=None, total=None), pool_timeout = None\nrelease_conn = False, chunked = False, body_pos = None, preload_content = False\ndecode_content = False, response_kw = {}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n def urlopen( # type: ignore[override]\n self,\n method: str,\n url: str,\n body: _TYPE_BODY | None = None,\n headers: typing.Mapping[str, str] | None = None,\n retries: Retry | bool | int | None = None,\n redirect: bool = True,\n assert_same_host: bool = True,\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n pool_timeout: int | None = None,\n release_conn: bool | None = None,\n chunked: bool = False,\n body_pos: _TYPE_BODY_POSITION | None = None,\n preload_content: bool = True,\n decode_content: bool = True,\n **response_kw: typing.Any,\n ) -> BaseHTTPResponse:\n \"\"\"\n Get a connection from the pool and perform an HTTP request. This is the\n lowest level call for making a request, so you'll need to specify all\n the raw details.\n \n .. note::\n \n More commonly, it's appropriate to use a convenience method\n such as :meth:`request`.\n \n .. note::\n \n `release_conn` will only behave as expected if\n `preload_content=False` because we want to make\n `preload_content=False` the default behaviour someday soon without\n breaking backwards compatibility.\n \n :param method:\n HTTP request method (such as GET, POST, PUT, etc.)\n \n :param url:\n The URL to perform the request on.\n \n :param body:\n Data to send in the request body, either :class:`str`, :class:`bytes`,\n an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n \n :param headers:\n Dictionary of custom headers to send, such as User-Agent,\n If-None-Match, etc. If None, pool headers are used. If provided,\n these headers completely replace any pool-specific headers.\n \n :param retries:\n Configure the number of retries to allow before raising a\n :class:`~urllib3.exceptions.MaxRetryError` exception.\n \n If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a\n :class:`~urllib3.util.retry.Retry` object for fine-grained control\n over different types of retries.\n Pass an integer number to retry connection errors that many times,\n but no other types of errors. Pass zero to never retry.\n \n If ``False``, then retries are disabled and any exception is raised\n immediately. Also, instead of raising a MaxRetryError on redirects,\n the redirect response will be returned.\n \n :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n \n :param redirect:\n If True, automatically handle redirects (status codes 301, 302,\n 303, 307, 308). Each redirect counts as a retry. Disabling retries\n will disable redirect, too.\n \n :param assert_same_host:\n If ``True``, will make sure that the host of the pool requests is\n consistent else will raise HostChangedError. When ``False``, you can\n use the pool on an HTTP proxy and request foreign hosts.\n \n :param timeout:\n If specified, overrides the default timeout for this one\n request. It may be a float (in seconds) or an instance of\n :class:`urllib3.util.Timeout`.\n \n :param pool_timeout:\n If set and the pool is set to block=True, then this method will\n block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n connection is available within the time period.\n \n :param bool preload_content:\n If True, the response's body will be preloaded into memory.\n \n :param bool decode_content:\n If True, will attempt to decode the body based on the\n 'content-encoding' header.\n \n :param release_conn:\n If False, then the urlopen call will not release the connection\n back into the pool once a response is received (but will release if\n you read the entire contents of the response such as when\n `preload_content=True`). This is useful if you're not preloading\n the response's content immediately. You will need to call\n ``r.release_conn()`` on the response ``r`` to return the connection\n back into the pool. If None, it takes the value of ``preload_content``\n which defaults to ``True``.\n \n :param bool chunked:\n If True, urllib3 will send the body using chunked transfer\n encoding. Otherwise, urllib3 will send the body using the standard\n content-length form. Defaults to False.\n \n :param int body_pos:\n Position to seek to in file-like body in the event of a retry or\n redirect. Typically this won't need to be set because urllib3 will\n auto-populate the value when needed.\n \"\"\"\n parsed_url = parse_url(url)\n destination_scheme = parsed_url.scheme\n \n if headers is None:\n headers = self.headers\n \n if not isinstance(retries, Retry):\n retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n \n if release_conn is None:\n release_conn = preload_content\n \n # Check host\n if assert_same_host and not self.is_same_host(url):\n raise HostChangedError(self, url, retries)\n \n # Ensure that the URL we're connecting to is properly encoded\n if url.startswith(\"/\"):\n url = to_str(_encode_target(url))\n else:\n url = to_str(parsed_url.url)\n \n conn = None\n \n # Track whether `conn` needs to be released before\n # returning/raising/recursing. Update this variable if necessary, and\n # leave `release_conn` constant throughout the function. That way, if\n # the function recurses, the original value of `release_conn` will be\n # passed down into the recursive call, and its value will be respected.\n #\n # See issue #651 [1] for details.\n #\n # [1] \n release_this_conn = release_conn\n \n http_tunnel_required = connection_requires_http_tunnel(\n self.proxy, self.proxy_config, destination_scheme\n )\n \n # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n # have to copy the headers dict so we can safely change it without those\n # changes being reflected in anyone else's copy.\n if not http_tunnel_required:\n headers = headers.copy() # type: ignore[attr-defined]\n headers.update(self.proxy_headers) # type: ignore[union-attr]\n \n # Must keep the exception bound to a separate variable or else Python 3\n # complains about UnboundLocalError.\n err = None\n \n # Keep track of whether we cleanly exited the except block. This\n # ensures we do proper cleanup in finally.\n clean_exit = False\n \n # Rewind body position, if needed. Record current position\n # for future rewinds in the event of a redirect/retry.\n body_pos = set_file_position(body, body_pos)\n \n try:\n # Request a connection from the queue.\n timeout_obj = self._get_timeout(timeout)\n conn = self._get_conn(timeout=pool_timeout)\n \n conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]\n \n # Is this a closed/new connection that requires CONNECT tunnelling?\n if self.proxy is not None and http_tunnel_required and conn.is_closed:\n try:\n self._prepare_proxy(conn)\n except (BaseSSLError, OSError, SocketTimeout) as e:\n self._raise_timeout(\n err=e, url=self.proxy.url, timeout_value=conn.timeout\n )\n raise\n \n # If we're going to release the connection in ``finally:``, then\n # the response doesn't need to know about the connection. Otherwise\n # it will also try to release it and we'll have a double-release\n # mess.\n response_conn = conn if not release_conn else None\n \n # Make the request on the HTTPConnection object\n> response = self._make_request(\n conn,\n method,\n url,\n timeout=timeout_obj,\n body=body,\n headers=headers,\n chunked=chunked,\n retries=retries,\n response_conn=response_conn,\n preload_content=preload_content,\n decode_content=decode_content,\n **response_kw,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request\n conn.request(\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request\n self.endheaders()\n.pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders\n self._send_output(message_body, encode_chunked=encode_chunked)\n.pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output\n self.send(msg)\n.pixi/envs/default/lib/python3.8/http/client.py:951: in send\n self.connect()\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect\n self.sock = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n except socket.gaierror as e:\n raise NameResolutionError(self.host, self, e) from e\n except SocketTimeout as e:\n raise ConnectTimeoutError(\n self,\n f\"Connection to {self.host} timed out. (connect timeout={self.timeout})\",\n ) from e\n \n except OSError as e:\n> raise NewConnectionError(\n self, f\"Failed to establish a new connection: {e}\"\n ) from e\nE urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n> resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen\n retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nmethod = 'POST', url = '/demo/', response = None\nerror = NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused')\n_pool = \n_stacktrace = \n\n def increment(\n self,\n method: str | None = None,\n url: str | None = None,\n response: BaseHTTPResponse | None = None,\n error: Exception | None = None,\n _pool: ConnectionPool | None = None,\n _stacktrace: TracebackType | None = None,\n ) -> Self:\n \"\"\"Return a new Retry object with incremented retry counters.\n \n :param response: A response object, or None, if the server did not\n return a response.\n :type response: :class:`~urllib3.response.BaseHTTPResponse`\n :param Exception error: An error encountered during the request, or\n None if the response was received successfully.\n \n :return: A new ``Retry`` object.\n \"\"\"\n if self.total is False and error:\n # Disabled, indicate to re-raise the error.\n raise reraise(type(error), error, _stacktrace)\n \n total = self.total\n if total is not None:\n total -= 1\n \n connect = self.connect\n read = self.read\n redirect = self.redirect\n status_count = self.status\n other = self.other\n cause = \"unknown\"\n status = None\n redirect_location = None\n \n if error and self._is_connection_error(error):\n # Connect retry?\n if connect is False:\n raise reraise(type(error), error, _stacktrace)\n elif connect is not None:\n connect -= 1\n \n elif error and self._is_read_error(error):\n # Read retry?\n if read is False or method is None or not self._is_method_retryable(method):\n raise reraise(type(error), error, _stacktrace)\n elif read is not None:\n read -= 1\n \n elif error:\n # Other retry?\n if other is not None:\n other -= 1\n \n elif response and response.get_redirect_location():\n # Redirect retry?\n if redirect is not None:\n redirect -= 1\n cause = \"too many redirects\"\n response_redirect_location = response.get_redirect_location()\n if response_redirect_location:\n redirect_location = response_redirect_location\n status = response.status\n \n else:\n # Incrementing because of a server error like a 500 in\n # status_forcelist and the given method is in the allowed_methods\n cause = ResponseError.GENERIC_ERROR\n if response and response.status:\n if status_count is not None:\n status_count -= 1\n cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n status = response.status\n \n history = self.history + (\n RequestHistory(method, url, error, status, redirect_location),\n )\n \n new_retry = self.new(\n total=total,\n connect=connect,\n read=read,\n redirect=redirect,\n status=status_count,\n other=other,\n history=history,\n )\n \n if new_retry.is_exhausted():\n reason = error or ResponseError(cause)\n> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]\nE urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \nmessage = 'This is a message3', msg_id = None, reply = False\nattributes = {'Author': 'robot', 'When': 1755174855, 'cmd': 'Submit', 'exp': 'demo', ...}\nattachments = [], suppress_email_notification = False, encoding = None\ntimeout = None, kwargs = {'Author': 'robot'}\nlogbook_directory = 'elog_instance/logbooks/demo'\nnew_attachment_list = [('Text', ('', b'This is a message3'))]\nobjects_to_close = []\nattributes_to_edit = {'Author': b'robot', 'When': 1755174855, 'cmd': b'Submit', 'exp': b'demo', ...}\n\n def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None,\n suppress_email_notification=False, encoding=None, timeout=None, **kwargs):\n \"\"\"\n Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing\n message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id\n of the newly created message.\n \"\"\"\n \n logbook_directory = \"elog_instance/logbooks/demo\"\n print(f\"Checking the existence of the directory {logbook_directory}\")\n \n # Check if the directory exists\n if not os.path.exists(logbook_directory):\n print(f\"The directory {logbook_directory} does not exist.\")\n else:\n print(f\"The directory {logbook_directory} exists.\")\n \n # Check write permissions\n if os.access(logbook_directory, os.W_OK):\n print(f\"The directory {logbook_directory} has write permissions.\")\n else:\n print(f\"The directory {logbook_directory} does not have write permissions.\")\n \n \n print(\"STARTING POST\")\n # Ajout des impressions pour d\u00e9boguer\n print(f\"Message to post: {message}\")\n print(f\"msg_id: {msg_id}\")\n print(f\"Attributes: {attributes}\")\n print(f\"Attachments: {attachments}\")\n print(f\"Encoding: {encoding}\")\n print(f\"Timeout: {timeout}\")\n print(f\"Additional kwargs: {kwargs}\")\n \n attributes = attributes or {}\n attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority\n print(f\"Updated attributes: {attributes}\")\n \n attachments = attachments or []\n print(f\"Attachments list: {attachments}\")\n \n if encoding is not None:\n if encoding not in ['plain', 'HTML', 'ELCode']:\n raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.')\n attributes['Encoding'] = encoding\n \n if suppress_email_notification:\n attributes[\"suppress\"] = 1\n \n # Prepare attachments\n if attachments:\n new_attachment_list, objects_to_close = self._prepare_attachments(attachments)\n print(f\"New attachments prepared: {new_attachment_list}\")\n else:\n objects_to_close = []\n new_attachment_list = []\n \n attributes_to_edit = dict()\n \n if msg_id:\n print(f\"Editing message with msg_id: {msg_id}\")\n if reply:\n print(f\"Replying to message with msg_id: {msg_id}\")\n self._check_if_message_on_server(msg_id)\n attributes['reply_to'] = str(msg_id)\n else:\n print(\"Editing existing message.\")\n attributes['edit_id'] = str(msg_id)\n attributes['skiplock'] = '1'\n msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id)\n \n # Merge new attributes\n for attribute, data in attributes.items():\n if data is not None:\n attributes_to_edit[attribute] = data\n \n print(f\"Attributes after merging: {attributes_to_edit}\")\n \n # Process existing attachments\n i = 0\n existing_attachments_filename_list = []\n for attachment in existing_attachments_list:\n attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)\n existing_attachments_filename_list.append(os.path.basename(attachment)[14:])\n i += 1\n \n print(f\"Existing attachments: {existing_attachments_filename_list}\")\n \n duplicate_attachment_list = []\n for new_attachment in new_attachment_list:\n new_attachment_filename = new_attachment[1][0]\n print(f\"Checking new attachment: {new_attachment_filename}\")\n if new_attachment_filename in existing_attachments_filename_list:\n # Same attachment exists on the server, compare content\n new_attachment_content = new_attachment[1][1].read()\n new_attachment[1][1].seek(0)\n attachment_index = existing_attachments_filename_list.index(new_attachment_filename)\n existing_attachment_content = self.download_attachment(\n url=existing_attachments_list[attachment_index],\n timeout=timeout\n )\n if new_attachment_content == existing_attachment_content:\n print(f\"Duplicate attachment detected: {new_attachment_filename}\")\n duplicate_attachment_list.append(new_attachment)\n else:\n print(f\"Attachment content has changed: {new_attachment_filename}\")\n self.delete_attachment(msg_id, attributes=attributes_to_edit,\n attachment_id=attachment_index,\n timeout=timeout, text=msg_to_edit)\n existing_attachments_filename_list.pop(attachment_index)\n existing_attachments_list.pop(attachment_index)\n \n print(f\"Duplicate attachments to remove: {duplicate_attachment_list}\")\n \n # Remove duplicates\n for attach in duplicate_attachment_list:\n new_attachment_list.remove(attach)\n \n print(f\"Final new attachments list: {new_attachment_list}\")\n else:\n # Creating a new message, add timestamp if not present\n if 'When' not in attributes:\n attributes['When'] = int(datetime.now().timestamp())\n \n # Final check on attributes\n if not attributes_to_edit:\n attributes_to_edit = attributes\n \n print(f\"Final attributes to send to the server: {attributes_to_edit}\")\n \n # Remove reserved attributes\n _remove_reserved_attributes(attributes_to_edit)\n \n new_attachment_list.append(('Text', ('', message.encode('iso-8859-1'))))\n print(f\"Final attachment list including message text: {new_attachment_list}\")\n \n # Add base message attributes\n self._add_base_msg_attributes(attributes_to_edit)\n print(f\"Attributes with base message added: {attributes_to_edit}\")\n \n # Sanitize attribute keys\n attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit)\n print(f\"Attributes after sanitizing keys: {attributes_to_edit}\")\n \n # Encode all string values in latin1\n attributes_to_edit = _encode_values(attributes_to_edit)\n print(f\"Attributes after encoding: {attributes_to_edit}\")\n \n try:\n print(\"Sending POST request to the server...\")\n> response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list,\n allow_redirects=False, verify=False, timeout=timeout)\n\nslic/utils/logbook.py:269: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:115: in post\n return request(\"post\", url, data=data, json=json, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request\n return session.request(method=method, url=url, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request\n resp = self.send(prep, **send_kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send\n r = adapter.send(request, **kwargs)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n \n except (ProtocolError, OSError) as err:\n raise ConnectionError(err, request=request)\n \n except MaxRetryError as e:\n if isinstance(e.reason, ConnectTimeoutError):\n # TODO: Remove this in 3.0.0: see #2811\n if not isinstance(e.reason, NewConnectionError):\n raise ConnectTimeout(e, request=request)\n \n if isinstance(e.reason, ResponseError):\n raise RetryError(e, request=request)\n \n if isinstance(e.reason, _ProxyError):\n raise ProxyError(e, request=request)\n \n if isinstance(e.reason, _SSLError):\n # This branch is for urllib3 v1.22 and later.\n raise SSLError(e, request=request)\n \n> raise ConnectionError(e, request=request)\nE requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n> sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection\n raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\naddress = ('localhost', 8080), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n def create_connection(\n address: tuple[str, int],\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n source_address: tuple[str, int] | None = None,\n socket_options: _TYPE_SOCKET_OPTIONS | None = None,\n ) -> socket.socket:\n \"\"\"Connect to *address* and return the socket object.\n \n Convenience function. Connect to *address* (a 2-tuple ``(host,\n port)``) and return the socket object. Passing the optional\n *timeout* parameter will set the timeout on the socket instance\n before attempting to connect. If no *timeout* is supplied, the\n global default timeout setting returned by :func:`socket.getdefaulttimeout`\n is used. If *source_address* is set it must be a tuple of (host, port)\n for the socket to bind as a source address before making the connection.\n An host of '' or port 0 tells the OS to use the default.\n \"\"\"\n \n host, port = address\n if host.startswith(\"[\"):\n host = host.strip(\"[]\")\n err = None\n \n # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n # The original create_connection function always returns all records.\n family = allowed_gai_family()\n \n try:\n host.encode(\"idna\")\n except UnicodeError:\n raise LocationParseError(f\"'{host}', label empty or too long\") from None\n \n for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n af, socktype, proto, canonname, sa = res\n sock = None\n try:\n sock = socket.socket(af, socktype, proto)\n \n # If provided, set socket level options before connecting.\n _set_socket_options(sock, socket_options)\n \n if timeout is not _DEFAULT_TIMEOUT:\n sock.settimeout(timeout)\n if source_address:\n sock.bind(source_address)\n> sock.connect(sa)\nE ConnectionRefusedError: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nmethod = 'GET', url = '/demo/None', body = None\nheaders = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'}\nretries = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = Timeout(connect=None, read=None, total=None), pool_timeout = None\nrelease_conn = False, chunked = False, body_pos = None, preload_content = False\ndecode_content = False, response_kw = {}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n def urlopen( # type: ignore[override]\n self,\n method: str,\n url: str,\n body: _TYPE_BODY | None = None,\n headers: typing.Mapping[str, str] | None = None,\n retries: Retry | bool | int | None = None,\n redirect: bool = True,\n assert_same_host: bool = True,\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n pool_timeout: int | None = None,\n release_conn: bool | None = None,\n chunked: bool = False,\n body_pos: _TYPE_BODY_POSITION | None = None,\n preload_content: bool = True,\n decode_content: bool = True,\n **response_kw: typing.Any,\n ) -> BaseHTTPResponse:\n \"\"\"\n Get a connection from the pool and perform an HTTP request. This is the\n lowest level call for making a request, so you'll need to specify all\n the raw details.\n \n .. note::\n \n More commonly, it's appropriate to use a convenience method\n such as :meth:`request`.\n \n .. note::\n \n `release_conn` will only behave as expected if\n `preload_content=False` because we want to make\n `preload_content=False` the default behaviour someday soon without\n breaking backwards compatibility.\n \n :param method:\n HTTP request method (such as GET, POST, PUT, etc.)\n \n :param url:\n The URL to perform the request on.\n \n :param body:\n Data to send in the request body, either :class:`str`, :class:`bytes`,\n an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n \n :param headers:\n Dictionary of custom headers to send, such as User-Agent,\n If-None-Match, etc. If None, pool headers are used. If provided,\n these headers completely replace any pool-specific headers.\n \n :param retries:\n Configure the number of retries to allow before raising a\n :class:`~urllib3.exceptions.MaxRetryError` exception.\n \n If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a\n :class:`~urllib3.util.retry.Retry` object for fine-grained control\n over different types of retries.\n Pass an integer number to retry connection errors that many times,\n but no other types of errors. Pass zero to never retry.\n \n If ``False``, then retries are disabled and any exception is raised\n immediately. Also, instead of raising a MaxRetryError on redirects,\n the redirect response will be returned.\n \n :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n \n :param redirect:\n If True, automatically handle redirects (status codes 301, 302,\n 303, 307, 308). Each redirect counts as a retry. Disabling retries\n will disable redirect, too.\n \n :param assert_same_host:\n If ``True``, will make sure that the host of the pool requests is\n consistent else will raise HostChangedError. When ``False``, you can\n use the pool on an HTTP proxy and request foreign hosts.\n \n :param timeout:\n If specified, overrides the default timeout for this one\n request. It may be a float (in seconds) or an instance of\n :class:`urllib3.util.Timeout`.\n \n :param pool_timeout:\n If set and the pool is set to block=True, then this method will\n block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n connection is available within the time period.\n \n :param bool preload_content:\n If True, the response's body will be preloaded into memory.\n \n :param bool decode_content:\n If True, will attempt to decode the body based on the\n 'content-encoding' header.\n \n :param release_conn:\n If False, then the urlopen call will not release the connection\n back into the pool once a response is received (but will release if\n you read the entire contents of the response such as when\n `preload_content=True`). This is useful if you're not preloading\n the response's content immediately. You will need to call\n ``r.release_conn()`` on the response ``r`` to return the connection\n back into the pool. If None, it takes the value of ``preload_content``\n which defaults to ``True``.\n \n :param bool chunked:\n If True, urllib3 will send the body using chunked transfer\n encoding. Otherwise, urllib3 will send the body using the standard\n content-length form. Defaults to False.\n \n :param int body_pos:\n Position to seek to in file-like body in the event of a retry or\n redirect. Typically this won't need to be set because urllib3 will\n auto-populate the value when needed.\n \"\"\"\n parsed_url = parse_url(url)\n destination_scheme = parsed_url.scheme\n \n if headers is None:\n headers = self.headers\n \n if not isinstance(retries, Retry):\n retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n \n if release_conn is None:\n release_conn = preload_content\n \n # Check host\n if assert_same_host and not self.is_same_host(url):\n raise HostChangedError(self, url, retries)\n \n # Ensure that the URL we're connecting to is properly encoded\n if url.startswith(\"/\"):\n url = to_str(_encode_target(url))\n else:\n url = to_str(parsed_url.url)\n \n conn = None\n \n # Track whether `conn` needs to be released before\n # returning/raising/recursing. Update this variable if necessary, and\n # leave `release_conn` constant throughout the function. That way, if\n # the function recurses, the original value of `release_conn` will be\n # passed down into the recursive call, and its value will be respected.\n #\n # See issue #651 [1] for details.\n #\n # [1] \n release_this_conn = release_conn\n \n http_tunnel_required = connection_requires_http_tunnel(\n self.proxy, self.proxy_config, destination_scheme\n )\n \n # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n # have to copy the headers dict so we can safely change it without those\n # changes being reflected in anyone else's copy.\n if not http_tunnel_required:\n headers = headers.copy() # type: ignore[attr-defined]\n headers.update(self.proxy_headers) # type: ignore[union-attr]\n \n # Must keep the exception bound to a separate variable or else Python 3\n # complains about UnboundLocalError.\n err = None\n \n # Keep track of whether we cleanly exited the except block. This\n # ensures we do proper cleanup in finally.\n clean_exit = False\n \n # Rewind body position, if needed. Record current position\n # for future rewinds in the event of a redirect/retry.\n body_pos = set_file_position(body, body_pos)\n \n try:\n # Request a connection from the queue.\n timeout_obj = self._get_timeout(timeout)\n conn = self._get_conn(timeout=pool_timeout)\n \n conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]\n \n # Is this a closed/new connection that requires CONNECT tunnelling?\n if self.proxy is not None and http_tunnel_required and conn.is_closed:\n try:\n self._prepare_proxy(conn)\n except (BaseSSLError, OSError, SocketTimeout) as e:\n self._raise_timeout(\n err=e, url=self.proxy.url, timeout_value=conn.timeout\n )\n raise\n \n # If we're going to release the connection in ``finally:``, then\n # the response doesn't need to know about the connection. Otherwise\n # it will also try to release it and we'll have a double-release\n # mess.\n response_conn = conn if not release_conn else None\n \n # Make the request on the HTTPConnection object\n> response = self._make_request(\n conn,\n method,\n url,\n timeout=timeout_obj,\n body=body,\n headers=headers,\n chunked=chunked,\n retries=retries,\n response_conn=response_conn,\n preload_content=preload_content,\n decode_content=decode_content,\n **response_kw,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request\n conn.request(\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request\n self.endheaders()\n.pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders\n self._send_output(message_body, encode_chunked=encode_chunked)\n.pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output\n self.send(msg)\n.pixi/envs/default/lib/python3.8/http/client.py:951: in send\n self.connect()\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect\n self.sock = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n except socket.gaierror as e:\n raise NameResolutionError(self.host, self, e) from e\n except SocketTimeout as e:\n raise ConnectTimeoutError(\n self,\n f\"Connection to {self.host} timed out. (connect timeout={self.timeout})\",\n ) from e\n \n except OSError as e:\n> raise NewConnectionError(\n self, f\"Failed to establish a new connection: {e}\"\n ) from e\nE urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n> resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen\n retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nmethod = 'GET', url = '/demo/None', response = None\nerror = NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused')\n_pool = \n_stacktrace = \n\n def increment(\n self,\n method: str | None = None,\n url: str | None = None,\n response: BaseHTTPResponse | None = None,\n error: Exception | None = None,\n _pool: ConnectionPool | None = None,\n _stacktrace: TracebackType | None = None,\n ) -> Self:\n \"\"\"Return a new Retry object with incremented retry counters.\n \n :param response: A response object, or None, if the server did not\n return a response.\n :type response: :class:`~urllib3.response.BaseHTTPResponse`\n :param Exception error: An error encountered during the request, or\n None if the response was received successfully.\n \n :return: A new ``Retry`` object.\n \"\"\"\n if self.total is False and error:\n # Disabled, indicate to re-raise the error.\n raise reraise(type(error), error, _stacktrace)\n \n total = self.total\n if total is not None:\n total -= 1\n \n connect = self.connect\n read = self.read\n redirect = self.redirect\n status_count = self.status\n other = self.other\n cause = \"unknown\"\n status = None\n redirect_location = None\n \n if error and self._is_connection_error(error):\n # Connect retry?\n if connect is False:\n raise reraise(type(error), error, _stacktrace)\n elif connect is not None:\n connect -= 1\n \n elif error and self._is_read_error(error):\n # Read retry?\n if read is False or method is None or not self._is_method_retryable(method):\n raise reraise(type(error), error, _stacktrace)\n elif read is not None:\n read -= 1\n \n elif error:\n # Other retry?\n if other is not None:\n other -= 1\n \n elif response and response.get_redirect_location():\n # Redirect retry?\n if redirect is not None:\n redirect -= 1\n cause = \"too many redirects\"\n response_redirect_location = response.get_redirect_location()\n if response_redirect_location:\n redirect_location = response_redirect_location\n status = response.status\n \n else:\n # Incrementing because of a server error like a 500 in\n # status_forcelist and the given method is in the allowed_methods\n cause = ResponseError.GENERIC_ERROR\n if response and response.status:\n if status_count is not None:\n status_count -= 1\n cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n status = response.status\n \n history = self.history + (\n RequestHistory(method, url, error, status, redirect_location),\n )\n \n new_retry = self.new(\n total=total,\n connect=connect,\n read=read,\n redirect=redirect,\n status=status_count,\n other=other,\n history=history,\n )\n \n if new_retry.is_exhausted():\n reason = error or ResponseError(cause)\n> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]\nE urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError\n\nDuring handling of the above exception, another exception occurred:\n\nself = , msg_id = None\ntimeout = None\n\n def _check_if_message_on_server(self, msg_id, timeout=None):\n \"\"\"Try to load page for specific message. If there is a html tag like then there is no\n such message.\n \n :param msg_id: ID of message to be checked\n :params timeout: The value of timeout to be passed to the get request\n :return:\n \"\"\"\n \n request_headers = dict()\n if self._user or self._password:\n request_headers['Cookie'] = self._make_user_and_pswd_cookie()\n try:\n> response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,\n verify=False, timeout=timeout)\n\nslic/utils/logbook.py:570: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:73: in get\n return request(\"get\", url, params=params, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request\n return session.request(method=method, url=url, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request\n resp = self.send(prep, **send_kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send\n r = adapter.send(request, **kwargs)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n \n except (ProtocolError, OSError) as err:\n raise ConnectionError(err, request=request)\n \n except MaxRetryError as e:\n if isinstance(e.reason, ConnectTimeoutError):\n # TODO: Remove this in 3.0.0: see #2811\n if not isinstance(e.reason, NewConnectionError):\n raise ConnectTimeout(e, request=request)\n \n if isinstance(e.reason, ResponseError):\n raise RetryError(e, request=request)\n \n if isinstance(e.reason, _ProxyError):\n raise ProxyError(e, request=request)\n \n if isinstance(e.reason, _SSLError):\n # This branch is for urllib3 v1.22 and later.\n raise SSLError(e, request=request)\n \n> raise ConnectionError(e, request=request)\nE requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nmock_home = \nmock_getuser = \nmock_getpass = \n\n @patch(\"slic.utils.elog.getpass\")\n @patch(\"slic.utils.elog.getuser\")\n @patch(\"slic.utils.elog.Path.home\")\n def test_get_default_elog_with_path_home(mock_home, mock_getuser, mock_getpass):\n fake_user = \"robot\"\n fake_pw = \"testpassword\"\n mock_getuser.return_value = fake_user\n mock_getpass.return_value = fake_pw # fallback safety\n text = \"This is a message3\"\n url = \"http://localhost:8080/demo\"\n \n tmp_home = Path(\"/tmp/fake_home_for_robot\")\n tmp_home.mkdir(parents=True, exist_ok=True)\n pw_file = tmp_home / \".elog_psi\"\n pw_file.write_text(fake_pw)\n mock_home.return_value = tmp_home\n \n try:\n elog = Elog(\"http://localhost:8080/demo\")\n try:\n> elog.post(text)\n\ntests/test_utils_elog.py:100: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nslic/utils/elog.py:17: in post\n return self._log.post(*args, **kwargs)\nslic/utils/logbook.py:289: in post\n self._check_if_message_on_server(msg_id) # Raises exceptions if no message or no response from server\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = , msg_id = None\ntimeout = None\n\n def _check_if_message_on_server(self, msg_id, timeout=None):\n \"\"\"Try to load page for specific message. If there is a html tag like then there is no\n such message.\n \n :param msg_id: ID of message to be checked\n :params timeout: The value of timeout to be passed to the get request\n :return:\n \"\"\"\n \n request_headers = dict()\n if self._user or self._password:\n request_headers['Cookie'] = self._make_user_and_pswd_cookie()\n try:\n response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,\n verify=False, timeout=timeout)\n \n # If there is no message code 200 will be returned (OK) and _validate_response will not recognise it\n # but there will be some error in the html code.\n resp_message, resp_headers, resp_msg_id = _validate_response(response)\n # If there is no message, code 200 will be returned (OK) but there will be some error indication in\n # the html code.\n if re.findall('.*?',\n resp_message.decode('utf-8', 'ignore'),\n flags=re.DOTALL):\n raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.')\n \n except requests.Timeout as e:\n # Catch here a timeout o the post request.\n # Raise the logbook exception and let the user handle it\n raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\\n' +\n '{1}'.format(sys._getframe().f_code.co_name, e))\n \n except requests.RequestException as e:\n> raise LogbookServerProblem('No response from the logbook server.\\nDetails: ' + '{0}'.format(e))\nE slic.utils.logbook_exceptions.LogbookServerProblem: No response from the logbook server.\nE Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\nslic/utils/logbook.py:590: LogbookServerProblem\n\nDuring handling of the above exception, another exception occurred:\n\nmock_home = \nmock_getuser = \nmock_getpass = \n\n @patch(\"slic.utils.elog.getpass\")\n @patch(\"slic.utils.elog.getuser\")\n @patch(\"slic.utils.elog.Path.home\")\n def test_get_default_elog_with_path_home(mock_home, mock_getuser, mock_getpass):\n fake_user = \"robot\"\n fake_pw = \"testpassword\"\n mock_getuser.return_value = fake_user\n mock_getpass.return_value = fake_pw # fallback safety\n text = \"This is a message3\"\n url = \"http://localhost:8080/demo\"\n \n tmp_home = Path(\"/tmp/fake_home_for_robot\")\n tmp_home.mkdir(parents=True, exist_ok=True)\n pw_file = tmp_home / \".elog_psi\"\n pw_file.write_text(fake_pw)\n mock_home.return_value = tmp_home\n \n try:\n elog = Elog(\"http://localhost:8080/demo\")\n try:\n elog.post(text)\n except Exception as e:\n> pytest.fail(f\"elog.open() raised an unexpected exception: {e}\")\nE Failed: elog.open() raised an unexpected exception: No response from the logbook server.\nE Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\ntests/test_utils_elog.py:102: Failed"}, "teardown": {"duration": 0.00037874793633818626, "outcome": "passed"}}, {"nodeid": "tests/test_utils_elog.py::test_screenshot", "lineno": 128, "outcome": "failed", "keywords": ["test_screenshot", "__wrapped__", "patchings", "test_utils_elog.py", "tests", "slic", ""], "setup": {"duration": 0.0001465831883251667, "outcome": "passed"}, "call": {"duration": 0.014574704691767693, "outcome": "failed", "crash": {"path": "/workspace/tligui_y/slic/slic/utils/logbook.py", "lineno": 590, "message": "slic.utils.logbook_exceptions.LogbookServerProblem: No response from the logbook server.\nDetails: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))"}, "traceback": [{"path": "tests/test_utils_elog.py", "lineno": 141, "message": ""}, {"path": "slic/utils/elog.py", "lineno": 22, "message": "in screenshot"}, {"path": "slic/utils/elog.py", "lineno": 17, "message": "in post"}, {"path": "slic/utils/logbook.py", "lineno": 289, "message": "in post"}, {"path": "slic/utils/logbook.py", "lineno": 590, "message": "LogbookServerProblem"}], "longrepr": "self = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n> sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection\n raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\naddress = ('localhost', 8080), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n def create_connection(\n address: tuple[str, int],\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n source_address: tuple[str, int] | None = None,\n socket_options: _TYPE_SOCKET_OPTIONS | None = None,\n ) -> socket.socket:\n \"\"\"Connect to *address* and return the socket object.\n \n Convenience function. Connect to *address* (a 2-tuple ``(host,\n port)``) and return the socket object. Passing the optional\n *timeout* parameter will set the timeout on the socket instance\n before attempting to connect. If no *timeout* is supplied, the\n global default timeout setting returned by :func:`socket.getdefaulttimeout`\n is used. If *source_address* is set it must be a tuple of (host, port)\n for the socket to bind as a source address before making the connection.\n An host of '' or port 0 tells the OS to use the default.\n \"\"\"\n \n host, port = address\n if host.startswith(\"[\"):\n host = host.strip(\"[]\")\n err = None\n \n # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n # The original create_connection function always returns all records.\n family = allowed_gai_family()\n \n try:\n host.encode(\"idna\")\n except UnicodeError:\n raise LocationParseError(f\"'{host}', label empty or too long\") from None\n \n for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n af, socktype, proto, canonname, sa = res\n sock = None\n try:\n sock = socket.socket(af, socktype, proto)\n \n # If provided, set socket level options before connecting.\n _set_socket_options(sock, socket_options)\n \n if timeout is not _DEFAULT_TIMEOUT:\n sock.settimeout(timeout)\n if source_address:\n sock.bind(source_address)\n> sock.connect(sa)\nE ConnectionRefusedError: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nmethod = 'POST', url = '/demo/'\nbody = b'--9eabc9334407552a4222d0e1189b02a7\\r\\nContent-Disposition: form-data; name=\"Author\"\\r\\n\\r\\nrobot\\r\\n--9eabc933440755...-data; name=\"Text\"; filename=\"\"\\r\\n\\r\\nSCREENSHOT_INTEGRATION_TEST_MSG_456\\r\\n--9eabc9334407552a4222d0e1189b02a7--\\r\\n'\nheaders = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '889', 'Content-Type': 'multipart/form-data; boundary=9eabc9334407552a4222d0e1189b02a7'}\nretries = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = Timeout(connect=None, read=None, total=None), pool_timeout = None\nrelease_conn = False, chunked = False, body_pos = None, preload_content = False\ndecode_content = False, response_kw = {}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/', query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n def urlopen( # type: ignore[override]\n self,\n method: str,\n url: str,\n body: _TYPE_BODY | None = None,\n headers: typing.Mapping[str, str] | None = None,\n retries: Retry | bool | int | None = None,\n redirect: bool = True,\n assert_same_host: bool = True,\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n pool_timeout: int | None = None,\n release_conn: bool | None = None,\n chunked: bool = False,\n body_pos: _TYPE_BODY_POSITION | None = None,\n preload_content: bool = True,\n decode_content: bool = True,\n **response_kw: typing.Any,\n ) -> BaseHTTPResponse:\n \"\"\"\n Get a connection from the pool and perform an HTTP request. This is the\n lowest level call for making a request, so you'll need to specify all\n the raw details.\n \n .. note::\n \n More commonly, it's appropriate to use a convenience method\n such as :meth:`request`.\n \n .. note::\n \n `release_conn` will only behave as expected if\n `preload_content=False` because we want to make\n `preload_content=False` the default behaviour someday soon without\n breaking backwards compatibility.\n \n :param method:\n HTTP request method (such as GET, POST, PUT, etc.)\n \n :param url:\n The URL to perform the request on.\n \n :param body:\n Data to send in the request body, either :class:`str`, :class:`bytes`,\n an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n \n :param headers:\n Dictionary of custom headers to send, such as User-Agent,\n If-None-Match, etc. If None, pool headers are used. If provided,\n these headers completely replace any pool-specific headers.\n \n :param retries:\n Configure the number of retries to allow before raising a\n :class:`~urllib3.exceptions.MaxRetryError` exception.\n \n If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a\n :class:`~urllib3.util.retry.Retry` object for fine-grained control\n over different types of retries.\n Pass an integer number to retry connection errors that many times,\n but no other types of errors. Pass zero to never retry.\n \n If ``False``, then retries are disabled and any exception is raised\n immediately. Also, instead of raising a MaxRetryError on redirects,\n the redirect response will be returned.\n \n :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n \n :param redirect:\n If True, automatically handle redirects (status codes 301, 302,\n 303, 307, 308). Each redirect counts as a retry. Disabling retries\n will disable redirect, too.\n \n :param assert_same_host:\n If ``True``, will make sure that the host of the pool requests is\n consistent else will raise HostChangedError. When ``False``, you can\n use the pool on an HTTP proxy and request foreign hosts.\n \n :param timeout:\n If specified, overrides the default timeout for this one\n request. It may be a float (in seconds) or an instance of\n :class:`urllib3.util.Timeout`.\n \n :param pool_timeout:\n If set and the pool is set to block=True, then this method will\n block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n connection is available within the time period.\n \n :param bool preload_content:\n If True, the response's body will be preloaded into memory.\n \n :param bool decode_content:\n If True, will attempt to decode the body based on the\n 'content-encoding' header.\n \n :param release_conn:\n If False, then the urlopen call will not release the connection\n back into the pool once a response is received (but will release if\n you read the entire contents of the response such as when\n `preload_content=True`). This is useful if you're not preloading\n the response's content immediately. You will need to call\n ``r.release_conn()`` on the response ``r`` to return the connection\n back into the pool. If None, it takes the value of ``preload_content``\n which defaults to ``True``.\n \n :param bool chunked:\n If True, urllib3 will send the body using chunked transfer\n encoding. Otherwise, urllib3 will send the body using the standard\n content-length form. Defaults to False.\n \n :param int body_pos:\n Position to seek to in file-like body in the event of a retry or\n redirect. Typically this won't need to be set because urllib3 will\n auto-populate the value when needed.\n \"\"\"\n parsed_url = parse_url(url)\n destination_scheme = parsed_url.scheme\n \n if headers is None:\n headers = self.headers\n \n if not isinstance(retries, Retry):\n retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n \n if release_conn is None:\n release_conn = preload_content\n \n # Check host\n if assert_same_host and not self.is_same_host(url):\n raise HostChangedError(self, url, retries)\n \n # Ensure that the URL we're connecting to is properly encoded\n if url.startswith(\"/\"):\n url = to_str(_encode_target(url))\n else:\n url = to_str(parsed_url.url)\n \n conn = None\n \n # Track whether `conn` needs to be released before\n # returning/raising/recursing. Update this variable if necessary, and\n # leave `release_conn` constant throughout the function. That way, if\n # the function recurses, the original value of `release_conn` will be\n # passed down into the recursive call, and its value will be respected.\n #\n # See issue #651 [1] for details.\n #\n # [1] \n release_this_conn = release_conn\n \n http_tunnel_required = connection_requires_http_tunnel(\n self.proxy, self.proxy_config, destination_scheme\n )\n \n # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n # have to copy the headers dict so we can safely change it without those\n # changes being reflected in anyone else's copy.\n if not http_tunnel_required:\n headers = headers.copy() # type: ignore[attr-defined]\n headers.update(self.proxy_headers) # type: ignore[union-attr]\n \n # Must keep the exception bound to a separate variable or else Python 3\n # complains about UnboundLocalError.\n err = None\n \n # Keep track of whether we cleanly exited the except block. This\n # ensures we do proper cleanup in finally.\n clean_exit = False\n \n # Rewind body position, if needed. Record current position\n # for future rewinds in the event of a redirect/retry.\n body_pos = set_file_position(body, body_pos)\n \n try:\n # Request a connection from the queue.\n timeout_obj = self._get_timeout(timeout)\n conn = self._get_conn(timeout=pool_timeout)\n \n conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]\n \n # Is this a closed/new connection that requires CONNECT tunnelling?\n if self.proxy is not None and http_tunnel_required and conn.is_closed:\n try:\n self._prepare_proxy(conn)\n except (BaseSSLError, OSError, SocketTimeout) as e:\n self._raise_timeout(\n err=e, url=self.proxy.url, timeout_value=conn.timeout\n )\n raise\n \n # If we're going to release the connection in ``finally:``, then\n # the response doesn't need to know about the connection. Otherwise\n # it will also try to release it and we'll have a double-release\n # mess.\n response_conn = conn if not release_conn else None\n \n # Make the request on the HTTPConnection object\n> response = self._make_request(\n conn,\n method,\n url,\n timeout=timeout_obj,\n body=body,\n headers=headers,\n chunked=chunked,\n retries=retries,\n response_conn=response_conn,\n preload_content=preload_content,\n decode_content=decode_content,\n **response_kw,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request\n conn.request(\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request\n self.endheaders()\n.pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders\n self._send_output(message_body, encode_chunked=encode_chunked)\n.pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output\n self.send(msg)\n.pixi/envs/default/lib/python3.8/http/client.py:951: in send\n self.connect()\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect\n self.sock = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n except socket.gaierror as e:\n raise NameResolutionError(self.host, self, e) from e\n except SocketTimeout as e:\n raise ConnectTimeoutError(\n self,\n f\"Connection to {self.host} timed out. (connect timeout={self.timeout})\",\n ) from e\n \n except OSError as e:\n> raise NewConnectionError(\n self, f\"Failed to establish a new connection: {e}\"\n ) from e\nE urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n> resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen\n retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nmethod = 'POST', url = '/demo/', response = None\nerror = NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused')\n_pool = \n_stacktrace = \n\n def increment(\n self,\n method: str | None = None,\n url: str | None = None,\n response: BaseHTTPResponse | None = None,\n error: Exception | None = None,\n _pool: ConnectionPool | None = None,\n _stacktrace: TracebackType | None = None,\n ) -> Self:\n \"\"\"Return a new Retry object with incremented retry counters.\n \n :param response: A response object, or None, if the server did not\n return a response.\n :type response: :class:`~urllib3.response.BaseHTTPResponse`\n :param Exception error: An error encountered during the request, or\n None if the response was received successfully.\n \n :return: A new ``Retry`` object.\n \"\"\"\n if self.total is False and error:\n # Disabled, indicate to re-raise the error.\n raise reraise(type(error), error, _stacktrace)\n \n total = self.total\n if total is not None:\n total -= 1\n \n connect = self.connect\n read = self.read\n redirect = self.redirect\n status_count = self.status\n other = self.other\n cause = \"unknown\"\n status = None\n redirect_location = None\n \n if error and self._is_connection_error(error):\n # Connect retry?\n if connect is False:\n raise reraise(type(error), error, _stacktrace)\n elif connect is not None:\n connect -= 1\n \n elif error and self._is_read_error(error):\n # Read retry?\n if read is False or method is None or not self._is_method_retryable(method):\n raise reraise(type(error), error, _stacktrace)\n elif read is not None:\n read -= 1\n \n elif error:\n # Other retry?\n if other is not None:\n other -= 1\n \n elif response and response.get_redirect_location():\n # Redirect retry?\n if redirect is not None:\n redirect -= 1\n cause = \"too many redirects\"\n response_redirect_location = response.get_redirect_location()\n if response_redirect_location:\n redirect_location = response_redirect_location\n status = response.status\n \n else:\n # Incrementing because of a server error like a 500 in\n # status_forcelist and the given method is in the allowed_methods\n cause = ResponseError.GENERIC_ERROR\n if response and response.status:\n if status_count is not None:\n status_count -= 1\n cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n status = response.status\n \n history = self.history + (\n RequestHistory(method, url, error, status, redirect_location),\n )\n \n new_retry = self.new(\n total=total,\n connect=connect,\n read=read,\n redirect=redirect,\n status=status_count,\n other=other,\n history=history,\n )\n \n if new_retry.is_exhausted():\n reason = error or ResponseError(cause)\n> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]\nE urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \nmessage = 'SCREENSHOT_INTEGRATION_TEST_MSG_456', msg_id = None, reply = False\nattributes = {'Author': 'robot', 'When': 1755174855, 'cmd': 'Submit', 'exp': 'demo', ...}\nattachments = ['/tmp/fake_screenshot.png'], suppress_email_notification = False\nencoding = None, timeout = None, kwargs = {'Author': 'robot'}\nlogbook_directory = 'elog_instance/logbooks/demo'\nnew_attachment_list = [('attfile0', ('fake_screenshot.png', <_io.BufferedReader name='/tmp/fake_screenshot.png'>)), ('Text', ('', b'SCREENSHOT_INTEGRATION_TEST_MSG_456'))]\nobjects_to_close = [<_io.BufferedReader name='/tmp/fake_screenshot.png'>]\nattributes_to_edit = {'Author': b'robot', 'When': 1755174855, 'cmd': b'Submit', 'exp': b'demo', ...}\n\n def post(self, message, msg_id=None, reply=False, attributes=None, attachments=None,\n suppress_email_notification=False, encoding=None, timeout=None, **kwargs):\n \"\"\"\n Posts message to the logbook. If msg_id is not specified new message will be created, otherwise existing\n message will be edited, or a reply (if reply=True) to it will be created. This method returns the msg_id\n of the newly created message.\n \"\"\"\n \n logbook_directory = \"elog_instance/logbooks/demo\"\n print(f\"Checking the existence of the directory {logbook_directory}\")\n \n # Check if the directory exists\n if not os.path.exists(logbook_directory):\n print(f\"The directory {logbook_directory} does not exist.\")\n else:\n print(f\"The directory {logbook_directory} exists.\")\n \n # Check write permissions\n if os.access(logbook_directory, os.W_OK):\n print(f\"The directory {logbook_directory} has write permissions.\")\n else:\n print(f\"The directory {logbook_directory} does not have write permissions.\")\n \n \n print(\"STARTING POST\")\n # Ajout des impressions pour d\u00e9boguer\n print(f\"Message to post: {message}\")\n print(f\"msg_id: {msg_id}\")\n print(f\"Attributes: {attributes}\")\n print(f\"Attachments: {attachments}\")\n print(f\"Encoding: {encoding}\")\n print(f\"Timeout: {timeout}\")\n print(f\"Additional kwargs: {kwargs}\")\n \n attributes = attributes or {}\n attributes = {**attributes, **kwargs} # kwargs as attributes with higher priority\n print(f\"Updated attributes: {attributes}\")\n \n attachments = attachments or []\n print(f\"Attachments list: {attachments}\")\n \n if encoding is not None:\n if encoding not in ['plain', 'HTML', 'ELCode']:\n raise LogbookMessageRejected('Invalid message encoding. Valid options: plain, HTML, ELCode.')\n attributes['Encoding'] = encoding\n \n if suppress_email_notification:\n attributes[\"suppress\"] = 1\n \n # Prepare attachments\n if attachments:\n new_attachment_list, objects_to_close = self._prepare_attachments(attachments)\n print(f\"New attachments prepared: {new_attachment_list}\")\n else:\n objects_to_close = []\n new_attachment_list = []\n \n attributes_to_edit = dict()\n \n if msg_id:\n print(f\"Editing message with msg_id: {msg_id}\")\n if reply:\n print(f\"Replying to message with msg_id: {msg_id}\")\n self._check_if_message_on_server(msg_id)\n attributes['reply_to'] = str(msg_id)\n else:\n print(\"Editing existing message.\")\n attributes['edit_id'] = str(msg_id)\n attributes['skiplock'] = '1'\n msg_to_edit, attributes_to_edit, existing_attachments_list = self.read(msg_id)\n \n # Merge new attributes\n for attribute, data in attributes.items():\n if data is not None:\n attributes_to_edit[attribute] = data\n \n print(f\"Attributes after merging: {attributes_to_edit}\")\n \n # Process existing attachments\n i = 0\n existing_attachments_filename_list = []\n for attachment in existing_attachments_list:\n attributes_to_edit[f'attachment{i}'] = os.path.basename(attachment)\n existing_attachments_filename_list.append(os.path.basename(attachment)[14:])\n i += 1\n \n print(f\"Existing attachments: {existing_attachments_filename_list}\")\n \n duplicate_attachment_list = []\n for new_attachment in new_attachment_list:\n new_attachment_filename = new_attachment[1][0]\n print(f\"Checking new attachment: {new_attachment_filename}\")\n if new_attachment_filename in existing_attachments_filename_list:\n # Same attachment exists on the server, compare content\n new_attachment_content = new_attachment[1][1].read()\n new_attachment[1][1].seek(0)\n attachment_index = existing_attachments_filename_list.index(new_attachment_filename)\n existing_attachment_content = self.download_attachment(\n url=existing_attachments_list[attachment_index],\n timeout=timeout\n )\n if new_attachment_content == existing_attachment_content:\n print(f\"Duplicate attachment detected: {new_attachment_filename}\")\n duplicate_attachment_list.append(new_attachment)\n else:\n print(f\"Attachment content has changed: {new_attachment_filename}\")\n self.delete_attachment(msg_id, attributes=attributes_to_edit,\n attachment_id=attachment_index,\n timeout=timeout, text=msg_to_edit)\n existing_attachments_filename_list.pop(attachment_index)\n existing_attachments_list.pop(attachment_index)\n \n print(f\"Duplicate attachments to remove: {duplicate_attachment_list}\")\n \n # Remove duplicates\n for attach in duplicate_attachment_list:\n new_attachment_list.remove(attach)\n \n print(f\"Final new attachments list: {new_attachment_list}\")\n else:\n # Creating a new message, add timestamp if not present\n if 'When' not in attributes:\n attributes['When'] = int(datetime.now().timestamp())\n \n # Final check on attributes\n if not attributes_to_edit:\n attributes_to_edit = attributes\n \n print(f\"Final attributes to send to the server: {attributes_to_edit}\")\n \n # Remove reserved attributes\n _remove_reserved_attributes(attributes_to_edit)\n \n new_attachment_list.append(('Text', ('', message.encode('iso-8859-1'))))\n print(f\"Final attachment list including message text: {new_attachment_list}\")\n \n # Add base message attributes\n self._add_base_msg_attributes(attributes_to_edit)\n print(f\"Attributes with base message added: {attributes_to_edit}\")\n \n # Sanitize attribute keys\n attributes_to_edit = _replace_special_characters_in_attribute_keys(attributes_to_edit)\n print(f\"Attributes after sanitizing keys: {attributes_to_edit}\")\n \n # Encode all string values in latin1\n attributes_to_edit = _encode_values(attributes_to_edit)\n print(f\"Attributes after encoding: {attributes_to_edit}\")\n \n try:\n print(\"Sending POST request to the server...\")\n> response = requests.post(self._url, data=attributes_to_edit, files=new_attachment_list,\n allow_redirects=False, verify=False, timeout=timeout)\n\nslic/utils/logbook.py:269: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:115: in post\n return request(\"post\", url, data=data, json=json, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request\n return session.request(method=method, url=url, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request\n resp = self.send(prep, **send_kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send\n r = adapter.send(request, **kwargs)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n \n except (ProtocolError, OSError) as err:\n raise ConnectionError(err, request=request)\n \n except MaxRetryError as e:\n if isinstance(e.reason, ConnectTimeoutError):\n # TODO: Remove this in 3.0.0: see #2811\n if not isinstance(e.reason, NewConnectionError):\n raise ConnectTimeout(e, request=request)\n \n if isinstance(e.reason, ResponseError):\n raise RetryError(e, request=request)\n \n if isinstance(e.reason, _ProxyError):\n raise ProxyError(e, request=request)\n \n if isinstance(e.reason, _SSLError):\n # This branch is for urllib3 v1.22 and later.\n raise SSLError(e, request=request)\n \n> raise ConnectionError(e, request=request)\nE requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/ (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n> sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:199: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:85: in create_connection\n raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\naddress = ('localhost', 8080), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n def create_connection(\n address: tuple[str, int],\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n source_address: tuple[str, int] | None = None,\n socket_options: _TYPE_SOCKET_OPTIONS | None = None,\n ) -> socket.socket:\n \"\"\"Connect to *address* and return the socket object.\n \n Convenience function. Connect to *address* (a 2-tuple ``(host,\n port)``) and return the socket object. Passing the optional\n *timeout* parameter will set the timeout on the socket instance\n before attempting to connect. If no *timeout* is supplied, the\n global default timeout setting returned by :func:`socket.getdefaulttimeout`\n is used. If *source_address* is set it must be a tuple of (host, port)\n for the socket to bind as a source address before making the connection.\n An host of '' or port 0 tells the OS to use the default.\n \"\"\"\n \n host, port = address\n if host.startswith(\"[\"):\n host = host.strip(\"[]\")\n err = None\n \n # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n # The original create_connection function always returns all records.\n family = allowed_gai_family()\n \n try:\n host.encode(\"idna\")\n except UnicodeError:\n raise LocationParseError(f\"'{host}', label empty or too long\") from None\n \n for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n af, socktype, proto, canonname, sa = res\n sock = None\n try:\n sock = socket.socket(af, socktype, proto)\n \n # If provided, set socket level options before connecting.\n _set_socket_options(sock, socket_options)\n \n if timeout is not _DEFAULT_TIMEOUT:\n sock.settimeout(timeout)\n if source_address:\n sock.bind(source_address)\n> sock.connect(sa)\nE ConnectionRefusedError: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/connection.py:73: ConnectionRefusedError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nmethod = 'GET', url = '/demo/None', body = None\nheaders = {'User-Agent': 'python-requests/2.32.3', 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'unm=robot;upwd=me1T.2jUUqQNa1wNuey9zNBOmOa4eILOaPb.ZSZjpn4;'}\nretries = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = Timeout(connect=None, read=None, total=None), pool_timeout = None\nrelease_conn = False, chunked = False, body_pos = None, preload_content = False\ndecode_content = False, response_kw = {}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/demo/None', query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n def urlopen( # type: ignore[override]\n self,\n method: str,\n url: str,\n body: _TYPE_BODY | None = None,\n headers: typing.Mapping[str, str] | None = None,\n retries: Retry | bool | int | None = None,\n redirect: bool = True,\n assert_same_host: bool = True,\n timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,\n pool_timeout: int | None = None,\n release_conn: bool | None = None,\n chunked: bool = False,\n body_pos: _TYPE_BODY_POSITION | None = None,\n preload_content: bool = True,\n decode_content: bool = True,\n **response_kw: typing.Any,\n ) -> BaseHTTPResponse:\n \"\"\"\n Get a connection from the pool and perform an HTTP request. This is the\n lowest level call for making a request, so you'll need to specify all\n the raw details.\n \n .. note::\n \n More commonly, it's appropriate to use a convenience method\n such as :meth:`request`.\n \n .. note::\n \n `release_conn` will only behave as expected if\n `preload_content=False` because we want to make\n `preload_content=False` the default behaviour someday soon without\n breaking backwards compatibility.\n \n :param method:\n HTTP request method (such as GET, POST, PUT, etc.)\n \n :param url:\n The URL to perform the request on.\n \n :param body:\n Data to send in the request body, either :class:`str`, :class:`bytes`,\n an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n \n :param headers:\n Dictionary of custom headers to send, such as User-Agent,\n If-None-Match, etc. If None, pool headers are used. If provided,\n these headers completely replace any pool-specific headers.\n \n :param retries:\n Configure the number of retries to allow before raising a\n :class:`~urllib3.exceptions.MaxRetryError` exception.\n \n If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a\n :class:`~urllib3.util.retry.Retry` object for fine-grained control\n over different types of retries.\n Pass an integer number to retry connection errors that many times,\n but no other types of errors. Pass zero to never retry.\n \n If ``False``, then retries are disabled and any exception is raised\n immediately. Also, instead of raising a MaxRetryError on redirects,\n the redirect response will be returned.\n \n :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n \n :param redirect:\n If True, automatically handle redirects (status codes 301, 302,\n 303, 307, 308). Each redirect counts as a retry. Disabling retries\n will disable redirect, too.\n \n :param assert_same_host:\n If ``True``, will make sure that the host of the pool requests is\n consistent else will raise HostChangedError. When ``False``, you can\n use the pool on an HTTP proxy and request foreign hosts.\n \n :param timeout:\n If specified, overrides the default timeout for this one\n request. It may be a float (in seconds) or an instance of\n :class:`urllib3.util.Timeout`.\n \n :param pool_timeout:\n If set and the pool is set to block=True, then this method will\n block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n connection is available within the time period.\n \n :param bool preload_content:\n If True, the response's body will be preloaded into memory.\n \n :param bool decode_content:\n If True, will attempt to decode the body based on the\n 'content-encoding' header.\n \n :param release_conn:\n If False, then the urlopen call will not release the connection\n back into the pool once a response is received (but will release if\n you read the entire contents of the response such as when\n `preload_content=True`). This is useful if you're not preloading\n the response's content immediately. You will need to call\n ``r.release_conn()`` on the response ``r`` to return the connection\n back into the pool. If None, it takes the value of ``preload_content``\n which defaults to ``True``.\n \n :param bool chunked:\n If True, urllib3 will send the body using chunked transfer\n encoding. Otherwise, urllib3 will send the body using the standard\n content-length form. Defaults to False.\n \n :param int body_pos:\n Position to seek to in file-like body in the event of a retry or\n redirect. Typically this won't need to be set because urllib3 will\n auto-populate the value when needed.\n \"\"\"\n parsed_url = parse_url(url)\n destination_scheme = parsed_url.scheme\n \n if headers is None:\n headers = self.headers\n \n if not isinstance(retries, Retry):\n retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n \n if release_conn is None:\n release_conn = preload_content\n \n # Check host\n if assert_same_host and not self.is_same_host(url):\n raise HostChangedError(self, url, retries)\n \n # Ensure that the URL we're connecting to is properly encoded\n if url.startswith(\"/\"):\n url = to_str(_encode_target(url))\n else:\n url = to_str(parsed_url.url)\n \n conn = None\n \n # Track whether `conn` needs to be released before\n # returning/raising/recursing. Update this variable if necessary, and\n # leave `release_conn` constant throughout the function. That way, if\n # the function recurses, the original value of `release_conn` will be\n # passed down into the recursive call, and its value will be respected.\n #\n # See issue #651 [1] for details.\n #\n # [1] \n release_this_conn = release_conn\n \n http_tunnel_required = connection_requires_http_tunnel(\n self.proxy, self.proxy_config, destination_scheme\n )\n \n # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n # have to copy the headers dict so we can safely change it without those\n # changes being reflected in anyone else's copy.\n if not http_tunnel_required:\n headers = headers.copy() # type: ignore[attr-defined]\n headers.update(self.proxy_headers) # type: ignore[union-attr]\n \n # Must keep the exception bound to a separate variable or else Python 3\n # complains about UnboundLocalError.\n err = None\n \n # Keep track of whether we cleanly exited the except block. This\n # ensures we do proper cleanup in finally.\n clean_exit = False\n \n # Rewind body position, if needed. Record current position\n # for future rewinds in the event of a redirect/retry.\n body_pos = set_file_position(body, body_pos)\n \n try:\n # Request a connection from the queue.\n timeout_obj = self._get_timeout(timeout)\n conn = self._get_conn(timeout=pool_timeout)\n \n conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment]\n \n # Is this a closed/new connection that requires CONNECT tunnelling?\n if self.proxy is not None and http_tunnel_required and conn.is_closed:\n try:\n self._prepare_proxy(conn)\n except (BaseSSLError, OSError, SocketTimeout) as e:\n self._raise_timeout(\n err=e, url=self.proxy.url, timeout_value=conn.timeout\n )\n raise\n \n # If we're going to release the connection in ``finally:``, then\n # the response doesn't need to know about the connection. Otherwise\n # it will also try to release it and we'll have a double-release\n # mess.\n response_conn = conn if not release_conn else None\n \n # Make the request on the HTTPConnection object\n> response = self._make_request(\n conn,\n method,\n url,\n timeout=timeout_obj,\n body=body,\n headers=headers,\n chunked=chunked,\n retries=retries,\n response_conn=response_conn,\n preload_content=preload_content,\n decode_content=decode_content,\n **response_kw,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:789: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:495: in _make_request\n conn.request(\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:441: in request\n self.endheaders()\n.pixi/envs/default/lib/python3.8/http/client.py:1251: in endheaders\n self._send_output(message_body, encode_chunked=encode_chunked)\n.pixi/envs/default/lib/python3.8/http/client.py:1011: in _send_output\n self.send(msg)\n.pixi/envs/default/lib/python3.8/http/client.py:951: in send\n self.connect()\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:279: in connect\n self.sock = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \n\n def _new_conn(self) -> socket.socket:\n \"\"\"Establish a socket connection and set nodelay settings on it.\n \n :return: New socket connection.\n \"\"\"\n try:\n sock = connection.create_connection(\n (self._dns_host, self.port),\n self.timeout,\n source_address=self.source_address,\n socket_options=self.socket_options,\n )\n except socket.gaierror as e:\n raise NameResolutionError(self.host, self, e) from e\n except SocketTimeout as e:\n raise ConnectTimeoutError(\n self,\n f\"Connection to {self.host} timed out. (connect timeout={self.timeout})\",\n ) from e\n \n except OSError as e:\n> raise NewConnectionError(\n self, f\"Failed to establish a new connection: {e}\"\n ) from e\nE urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connection.py:214: NewConnectionError\n\nThe above exception was the direct cause of the following exception:\n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n> resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:667: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/urllib3/connectionpool.py:843: in urlopen\n retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = Retry(total=0, connect=None, read=False, redirect=None, status=None)\nmethod = 'GET', url = '/demo/None', response = None\nerror = NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused')\n_pool = \n_stacktrace = \n\n def increment(\n self,\n method: str | None = None,\n url: str | None = None,\n response: BaseHTTPResponse | None = None,\n error: Exception | None = None,\n _pool: ConnectionPool | None = None,\n _stacktrace: TracebackType | None = None,\n ) -> Self:\n \"\"\"Return a new Retry object with incremented retry counters.\n \n :param response: A response object, or None, if the server did not\n return a response.\n :type response: :class:`~urllib3.response.BaseHTTPResponse`\n :param Exception error: An error encountered during the request, or\n None if the response was received successfully.\n \n :return: A new ``Retry`` object.\n \"\"\"\n if self.total is False and error:\n # Disabled, indicate to re-raise the error.\n raise reraise(type(error), error, _stacktrace)\n \n total = self.total\n if total is not None:\n total -= 1\n \n connect = self.connect\n read = self.read\n redirect = self.redirect\n status_count = self.status\n other = self.other\n cause = \"unknown\"\n status = None\n redirect_location = None\n \n if error and self._is_connection_error(error):\n # Connect retry?\n if connect is False:\n raise reraise(type(error), error, _stacktrace)\n elif connect is not None:\n connect -= 1\n \n elif error and self._is_read_error(error):\n # Read retry?\n if read is False or method is None or not self._is_method_retryable(method):\n raise reraise(type(error), error, _stacktrace)\n elif read is not None:\n read -= 1\n \n elif error:\n # Other retry?\n if other is not None:\n other -= 1\n \n elif response and response.get_redirect_location():\n # Redirect retry?\n if redirect is not None:\n redirect -= 1\n cause = \"too many redirects\"\n response_redirect_location = response.get_redirect_location()\n if response_redirect_location:\n redirect_location = response_redirect_location\n status = response.status\n \n else:\n # Incrementing because of a server error like a 500 in\n # status_forcelist and the given method is in the allowed_methods\n cause = ResponseError.GENERIC_ERROR\n if response and response.status:\n if status_count is not None:\n status_count -= 1\n cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n status = response.status\n \n history = self.history + (\n RequestHistory(method, url, error, status, redirect_location),\n )\n \n new_retry = self.new(\n total=total,\n connect=connect,\n read=read,\n redirect=redirect,\n status=status_count,\n other=other,\n history=history,\n )\n \n if new_retry.is_exhausted():\n reason = error or ResponseError(cause)\n> raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]\nE urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/urllib3/util/retry.py:519: MaxRetryError\n\nDuring handling of the above exception, another exception occurred:\n\nself = , msg_id = None\ntimeout = None\n\n def _check_if_message_on_server(self, msg_id, timeout=None):\n \"\"\"Try to load page for specific message. If there is a html tag like then there is no\n such message.\n \n :param msg_id: ID of message to be checked\n :params timeout: The value of timeout to be passed to the get request\n :return:\n \"\"\"\n \n request_headers = dict()\n if self._user or self._password:\n request_headers['Cookie'] = self._make_user_and_pswd_cookie()\n try:\n> response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,\n verify=False, timeout=timeout)\n\nslic/utils/logbook.py:570: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:73: in get\n return request(\"get\", url, params=params, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/api.py:59: in request\n return session.request(method=method, url=url, **kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:589: in request\n resp = self.send(prep, **send_kwargs)\n.pixi/envs/default/lib/python3.8/site-packages/requests/sessions.py:703: in send\n r = adapter.send(request, **kwargs)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = \nrequest = , stream = False\ntimeout = Timeout(connect=None, read=None, total=None), verify = False\ncert = None, proxies = OrderedDict()\n\n def send(\n self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None\n ):\n \"\"\"Sends PreparedRequest object. Returns Response object.\n \n :param request: The :class:`PreparedRequest ` being sent.\n :param stream: (optional) Whether to stream the request content.\n :param timeout: (optional) How long to wait for the server to send\n data before giving up, as a float, or a :ref:`(connect timeout,\n read timeout) ` tuple.\n :type timeout: float or tuple or urllib3 Timeout object\n :param verify: (optional) Either a boolean, in which case it controls whether\n we verify the server's TLS certificate, or a string, in which case it\n must be a path to a CA bundle to use\n :param cert: (optional) Any user-provided SSL certificate to be trusted.\n :param proxies: (optional) The proxies dictionary to apply to the request.\n :rtype: requests.Response\n \"\"\"\n \n try:\n conn = self.get_connection_with_tls_context(\n request, verify, proxies=proxies, cert=cert\n )\n except LocationValueError as e:\n raise InvalidURL(e, request=request)\n \n self.cert_verify(conn, request.url, verify, cert)\n url = self.request_url(request, proxies)\n self.add_headers(\n request,\n stream=stream,\n timeout=timeout,\n verify=verify,\n cert=cert,\n proxies=proxies,\n )\n \n chunked = not (request.body is None or \"Content-Length\" in request.headers)\n \n if isinstance(timeout, tuple):\n try:\n connect, read = timeout\n timeout = TimeoutSauce(connect=connect, read=read)\n except ValueError:\n raise ValueError(\n f\"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, \"\n f\"or a single float to set both timeouts to the same value.\"\n )\n elif isinstance(timeout, TimeoutSauce):\n pass\n else:\n timeout = TimeoutSauce(connect=timeout, read=timeout)\n \n try:\n resp = conn.urlopen(\n method=request.method,\n url=url,\n body=request.body,\n headers=request.headers,\n redirect=False,\n assert_same_host=False,\n preload_content=False,\n decode_content=False,\n retries=self.max_retries,\n timeout=timeout,\n chunked=chunked,\n )\n \n except (ProtocolError, OSError) as err:\n raise ConnectionError(err, request=request)\n \n except MaxRetryError as e:\n if isinstance(e.reason, ConnectTimeoutError):\n # TODO: Remove this in 3.0.0: see #2811\n if not isinstance(e.reason, NewConnectionError):\n raise ConnectTimeout(e, request=request)\n \n if isinstance(e.reason, ResponseError):\n raise RetryError(e, request=request)\n \n if isinstance(e.reason, _ProxyError):\n raise ProxyError(e, request=request)\n \n if isinstance(e.reason, _SSLError):\n # This branch is for urllib3 v1.22 and later.\n raise SSLError(e, request=request)\n \n> raise ConnectionError(e, request=request)\nE requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\n.pixi/envs/default/lib/python3.8/site-packages/requests/adapters.py:700: ConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nmock_screenshot_class = \n\n @patch(\"slic.utils.elog.Screenshot\")\n def test_screenshot(mock_screenshot_class):\n fake_path = \"/tmp/fake_screenshot.png\"\n with open(fake_path, \"wb\") as f:\n f.write(b\"fake image data\")\n \n mock_instance = mock_screenshot_class.return_value\n mock_instance.shoot.return_value = [fake_path]\n \n elog = elog = Elog(\"http://localhost:8080/demo\", user=\"robot\", password=\"testpassword\")\n \n test_msg = \"SCREENSHOT_INTEGRATION_TEST_MSG_456\"\n> elog.screenshot(message=test_msg)\n\ntests/test_utils_elog.py:141: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nslic/utils/elog.py:22: in screenshot\n self.post(message, **kwargs)\nslic/utils/elog.py:17: in post\n return self._log.post(*args, **kwargs)\nslic/utils/logbook.py:289: in post\n self._check_if_message_on_server(msg_id) # Raises exceptions if no message or no response from server\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = , msg_id = None\ntimeout = None\n\n def _check_if_message_on_server(self, msg_id, timeout=None):\n \"\"\"Try to load page for specific message. If there is a html tag like then there is no\n such message.\n \n :param msg_id: ID of message to be checked\n :params timeout: The value of timeout to be passed to the get request\n :return:\n \"\"\"\n \n request_headers = dict()\n if self._user or self._password:\n request_headers['Cookie'] = self._make_user_and_pswd_cookie()\n try:\n response = requests.get(self._url + str(msg_id), headers=request_headers, allow_redirects=False,\n verify=False, timeout=timeout)\n \n # If there is no message code 200 will be returned (OK) and _validate_response will not recognise it\n # but there will be some error in the html code.\n resp_message, resp_headers, resp_msg_id = _validate_response(response)\n # If there is no message, code 200 will be returned (OK) but there will be some error indication in\n # the html code.\n if re.findall('.*?',\n resp_message.decode('utf-8', 'ignore'),\n flags=re.DOTALL):\n raise LogbookInvalidMessageID('Message with ID: ' + str(msg_id) + ' does not exist on logbook.')\n \n except requests.Timeout as e:\n # Catch here a timeout o the post request.\n # Raise the logbook exception and let the user handle it\n raise LogbookServerTimeout('{0} method cannot be completed because of a network timeout:\\n' +\n '{1}'.format(sys._getframe().f_code.co_name, e))\n \n except requests.RequestException as e:\n> raise LogbookServerProblem('No response from the logbook server.\\nDetails: ' + '{0}'.format(e))\nE slic.utils.logbook_exceptions.LogbookServerProblem: No response from the logbook server.\nE Details: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /demo/None (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))\n\nslic/utils/logbook.py:590: LogbookServerProblem"}, "teardown": {"duration": 0.0003166687674820423, "outcome": "passed"}}], "warnings": [{"message": "invalid escape sequence \\-", "category": "DeprecationWarning", "when": "collect", "filename": "/workspace/tligui_y/slic/.pixi/envs/default/lib/python3.8/site-packages/bsread/h5.py", "lineno": 207}, {"message": "The module numpy.dual is deprecated. Instead of using dual, use the functions directly from numpy or scipy.", "category": "DeprecationWarning", "when": "collect", "filename": "/workspace/tligui_y/slic/.pixi/envs/default/lib/python3.8/site-packages/scipy/fft/__init__.py", "lineno": 97}]} \ No newline at end of file