Repository: jborean93/smbprotocol

Issue:
smbprotocol.connection.Connection.connect() no longer shows the low-level connection error
Since 1.11.0  smbprotocol.connection.Connection.connect() no longer shows the low-level connection error

This is a change introduced in 1.11.0 

The change is in transport.py

```diff
-raise ValueError("Failed to connect to '%s:%s': %s" % (self.server, self.port, str(err))) from err
+raise ValueError(f"Failed to connect to '{self.server}:{self.port}'") from err
```

https://github.com/jborean93/smbprotocol/compare/v1.10.1...v1.11.0#diff-1037611d131586bd4201108e4c80be46a17a6a1a365766e7190be44673eac0ffL70


It helps to know more about why a connection failed... it can be a DNS error for example.

To reproduce, use this code

```python
from smbprotocol.connection import Connection
conn = Connection('some-id', 'localhost', 1234)
conn.connect()
```

On 1.11.0 the error is just `ValueError: Failed to connect to 'localhost:1234'`
On 1.10.1 the error is `ValueError: Failed to connect to 'localhost:1234': [Errno 111] Connection refused`


Below are the stack traces 

-------------------

1.11.0

```
Python 3.11.7 (4666189, Dec 11 2023, 13:04:52) [GCC 7.3.1 20180712 (Red Hat 7.3.1-17)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from smbprotocol.connection import Connection
conn = Connection('some-id', 'localhost', 1234)
conn.connect()
>>> >>> Traceback (most recent call last):
  File "/home/adi/chevah/server/build-py3/lib/python3.11/site-packages/smbprotocol/transport.py", line 66, in connect
    self._sock = socket.create_connection((self.server, self.port), timeout=self.timeout)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/adi/chevah/server/build-py3/lib/python3.11/socket.py", line 851, in create_connection
    raise exceptions[0]
  File "/home/adi/chevah/server/build-py3/lib/python3.11/socket.py", line 836, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/adi/chevah/server/build-py3/lib/python3.11/site-packages/smbprotocol/connection.py", line 863, in connect
    self.transport.connect()
  File "/home/adi/chevah/server/build-py3/lib/python3.11/site-packages/smbprotocol/transport.py", line 68, in connect
    raise ValueError(f"Failed to connect to '{self.server}:{self.port}'") from err
ValueError: Failed to connect to 'localhost:1234'

```





------------

1.10.1

```
Python 3.11.7 (4666189, Dec 11 2023, 13:04:52) [GCC 7.3.1 20180712 (Red Hat 7.3.1-17)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from smbprotocol.connection import Connection
conn = Connection('some-id', 'localhost', 1234)
conn.connect()
>>> >>> Traceback (most recent call last):
  File "/home/adi/chevah/server/build-py3/lib/python3.11/site-packages/smbprotocol/transport.py", line 68, in connect
    self._sock = socket.create_connection((self.server, self.port), timeout=self.timeout)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/adi/chevah/server/build-py3/lib/python3.11/socket.py", line 851, in create_connection
    raise exceptions[0]
  File "/home/adi/chevah/server/build-py3/lib/python3.11/socket.py", line 836, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/adi/chevah/server/build-py3/lib/python3.11/site-packages/smbprotocol/connection.py", line 861, in connect
    self.transport.connect()
  File "/home/adi/chevah/server/build-py3/lib/python3.11/site-packages/smbprotocol/transport.py", line 70, in connect
    raise ValueError("Failed to connect to '%s:%s': %s" % (self.server, self.port, str(err))) from err
ValueError: Failed to connect to 'localhost:1234': [Errno 111] Connection refused
```


Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`7d6abeb`)](https://app.codecov.io/gh/jborean93/smbprotocol/commit/7d6abeb9e4240a03f7336eb95b8a23e39b109391?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) 99.06% compared to head [(`59dd30e`)](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) 68.15%.
> Report is 1 commits behind head on master.


<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff             @@
##           master     #264       +/-   ##
===========================================
- Coverage   99.06%   68.15%   -30.91%     
===========================================
  Files          24       24               
  Lines        5112     5112               
===========================================
- Hits         5064     3484     -1580     
- Misses         48     1628     +1580     
```

| [Flag](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) | Coverage Δ | |
|---|---|---|
| [](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) | `68.15% <100.00%> (-30.91%)` | :arrow_down: |
| [py3.10](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) | `?` | |
| [py3.11](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) | `?` | |
| [py3.12](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) | `68.15% <100.00%> (-30.87%)` | :arrow_down: |
| [py3.7](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) | `?` | |
| [py3.8](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) | `?` | |
| [py3.9](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) | `?` | |
| [x64](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) | `68.15% <100.00%> (-30.91%)` | :arrow_down: |
| [x86](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean) | `?` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean#carryforward-flags-in-the-pull-request-comment) to find out more.


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/jborean93/smbprotocol/pull/264?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jordan+Borean).

adiroiban: This should be ready for review. Thanks
jborean93: Thanks for fixing this up!

Patch:
diff --git a/src/smbprotocol/transport.py b/src/smbprotocol/transport.py
index 052b43a..2288239 100644
--- a/src/smbprotocol/transport.py
+++ b/src/smbprotocol/transport.py
@@ -65,7 +65,7 @@ class Tcp:
                 try:
                     self._sock = socket.create_connection((self.server, self.port), timeout=self.timeout)
                 except (OSError, socket.gaierror) as err:
-                    raise ValueError(f"Failed to connect to '{self.server}:{self.port}'") from err
+                    raise ValueError(f"Failed to connect to '{self.server}:{self.port}': {err}") from err
                 self._sock.settimeout(None)  # Make sure the socket is in blocking mode.
                 self.connected = True
 


Test patch:
diff --git a/tests/test_transport.py b/tests/test_transport.py
index 960350c..0108dea 100644
--- a/tests/test_transport.py
+++ b/tests/test_transport.py
@@ -72,8 +72,15 @@ class TestTcp:
         )
 
     def test_invalid_host(self):
+        """
+        Raises ValueError when failing to connect to the remote server.
+
+        The error message contains the low-level OS error details.
+        """
         tcp = Tcp("fake-host", 445)
-        with pytest.raises(ValueError, match=re.escape("Failed to connect to 'fake-host:445'")):
+        # We just check for OSError marker, as the actual error message
+        # might be different based on current OS.
+        with pytest.raises(ValueError, match=r"Failed to connect to 'fake-host:445': \[Errno .*"):
             tcp.connect()