Repository: pydicom/pynetdicom

Issue:
T_CONNECT doesn't work with only Tuple[str, int]
Whoops. I meant to emulate the previous behaviour for `AssociationSocket.connect()`, but it obviously won't work since it puts the T_CONNECT A-ASSOCIATE primitive on the DUL's `to_provider_queue`.

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/pydicom/pynetdicom/pull/730?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) Report
> Merging [#730](https://codecov.io/gh/pydicom/pynetdicom/pull/730?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) (26022c0) into [master](https://codecov.io/gh/pydicom/pynetdicom/commit/3ce1bc45ea8d963242beed70133ed34933a637c6?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) (3ce1bc4) will **decrease** coverage by `0.15%`.
> The diff coverage is `100.00%`.

```diff
@@             Coverage Diff             @@
##            master     #730      +/-   ##
===========================================
- Coverage   100.00%   99.84%   -0.16%     
===========================================
  Files           28       28              
  Lines         8647     8596      -51     
===========================================
- Hits          8647     8583      -64     
- Misses           0       13      +13     
```

| [Impacted Files](https://codecov.io/gh/pydicom/pynetdicom/pull/730?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) | Coverage Δ | |
|---|---|---|
| [pynetdicom/transport.py](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHluZXRkaWNvbS90cmFuc3BvcnQucHk=) | `100.00% <100.00%> (ø)` | |
| [pynetdicom/utils.py](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHluZXRkaWNvbS91dGlscy5weQ==) | `88.79% <0.00%> (-11.21%)` | :arrow_down: |
| [pynetdicom/dul.py](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHluZXRkaWNvbS9kdWwucHk=) | `100.00% <0.00%> (ø)` | |
| [pynetdicom/acse.py](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHluZXRkaWNvbS9hY3NlLnB5) | `100.00% <0.00%> (ø)` | |
| [pynetdicom/status.py](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHluZXRkaWNvbS9zdGF0dXMucHk=) | `100.00% <0.00%> (ø)` | |
| [pynetdicom/\_config.py](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHluZXRkaWNvbS9fY29uZmlnLnB5) | `100.00% <0.00%> (ø)` | |
| [pynetdicom/\_\_init\_\_.py](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHluZXRkaWNvbS9fX2luaXRfXy5weQ==) | `100.00% <0.00%> (ø)` | |
| [pynetdicom/\_globals.py](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHluZXRkaWNvbS9fZ2xvYmFscy5weQ==) | `100.00% <0.00%> (ø)` | |
| [pynetdicom/sop\_class.py](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHluZXRkaWNvbS9zb3BfY2xhc3MucHk=) | `100.00% <0.00%> (ø)` | |
| [pynetdicom/association.py](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHluZXRkaWNvbS9hc3NvY2lhdGlvbi5weQ==) | `100.00% <0.00%> (ø)` | |
| ... and [1 more](https://codecov.io/gh/pydicom/pynetdicom/pull/730/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) | |


Patch:
diff --git a/.github/workflows/publish-pypi-deploy.yml b/.github/workflows/publish-pypi-deploy.yml
index 4cd253324..5839901de 100644
--- a/.github/workflows/publish-pypi-deploy.yml
+++ b/.github/workflows/publish-pypi-deploy.yml
@@ -44,8 +44,8 @@ jobs:
         pip install -i https://test.pypi.org/simple/ pynetdicom
 
     - name: Test with pytest
-      with:
-        python-version: '3.10'
+      env:
+        PYTHON_VERSION: ${{ matrix.python-version }}
       run: |
         cd ${HOME}
         python -m pynetdicom --version
diff --git a/docs/changelog/index.rst b/docs/changelog/index.rst
index 2f5bf3e74..523d43290 100644
--- a/docs/changelog/index.rst
+++ b/docs/changelog/index.rst
@@ -8,6 +8,7 @@ Release Notes
    :maxdepth: 1
 
    v2.1.0
+   v2.0.1
    v2.0.0
    v1.5.7
    v1.5.6
diff --git a/docs/changelog/v2.0.1.rst b/docs/changelog/v2.0.1.rst
new file mode 100644
index 000000000..82339bc1f
--- /dev/null
+++ b/docs/changelog/v2.0.1.rst
@@ -0,0 +1,10 @@
+.. _v2.0.1:
+
+2.0.1
+=====
+
+Changes
+.......
+
+* Revert change to default bind address
+* Don't allow passing an address tuple to T_CONNECT initialisation
diff --git a/docs/index.rst b/docs/index.rst
index 82715381e..5e2544974 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -120,6 +120,7 @@ Release Notes
 =============
 
 * :doc:`v2.1.0 </changelog/v2.1.0>`
+* :doc:`v2.0.1 </changelog/v2.0.0>`
 * :doc:`v2.0.0 </changelog/v2.0.0>`
 * :doc:`v1.5.7 </changelog/v1.5.7>`
 * :doc:`v1.5.6 </changelog/v1.5.6>`
diff --git a/pynetdicom/_globals.py b/pynetdicom/_globals.py
index d8cd60fd4..79bbef9b9 100644
--- a/pynetdicom/_globals.py
+++ b/pynetdicom/_globals.py
@@ -99,7 +99,7 @@ STATUS_UNKNOWN: str = "Unknown"
 
 
 # The default address that client sockets are bound to
-BIND_ADDRESS = ("127.0.0.1", 0)
+BIND_ADDRESS = ("", 0)
 
 
 OptionalUIDType = Optional[Union[str, bytes, UID]]
diff --git a/pynetdicom/transport.py b/pynetdicom/transport.py
index 06186e7a9..50df9d6ca 100644
--- a/pynetdicom/transport.py
+++ b/pynetdicom/transport.py
@@ -52,41 +52,64 @@ class T_CONNECT:
     """A TRANSPORT CONNECTION primitive
 
     .. versionadded:: 2.0
+
+    Attributes
+    ----------
+    request : pynetdicom.pdu_primitives.A_ASSOCIATE
+        The A-ASSOCIATE (request) primitive that generated the TRANSPORT CONNECTION
+        primitive.
     """
 
-    def __init__(self, address: Union[Tuple[str, int], "A_ASSOCIATE"]) -> None:
+    def __init__(self, request: "A_ASSOCIATE") -> None:
         """Create a new TRANSPORT CONNECTION primitive.
 
         Parameters
         ----------
-        address : Union[Tuple[str, int], pynetdicom.pdu_primitives.A_ASSOCIATE]
-            The ``(str: IP address, int: port)`` or A-ASSOCIATE (request) primitive to
-            use when making a connection with a peer.
+        request : pynetdicom.pdu_primitives.A_ASSOCIATE
+            The A-ASSOCIATE (request) primitive to use when making a connection with
+            a peer.
         """
-        self._request = None
-        self.result = ""
-
-        if isinstance(address, tuple):
-            self._address = address
-        elif isinstance(address, A_ASSOCIATE):
-            self._address = cast(Tuple[str, int], address.called_presentation_address)
-            self._request = address
-        else:
+        self._result = ""
+        self.request = request
+
+        if not isinstance(request, A_ASSOCIATE):
             raise TypeError(
-                f"'address' must be 'Tuple[str, int]' or "
-                "'pynetdicom.pdu_primitives.A_ASSOCIATE', not "
-                f"'{address.__class__.__name__}'"
+                f"'request' must be 'pynetdicom.pdu_primitives.A_ASSOCIATE', not "
+                f"'{request.__class__.__name__}'"
             )
 
     @property
     def address(self) -> Tuple[str, int]:
         """Return the peer's ``(str: IP address, int: port)``."""
-        return self._address
+        return cast(Tuple[str, int], self.request.called_presentation_address)
 
     @property
-    def request(self) -> Optional[A_ASSOCIATE]:
-        """Return the A-ASSOCIATE (request) primitive, or ``None`` if not available."""
-        return self._request
+    def result(self) -> str:
+        """Return the result of the connection attempt as :class:`str`.
+
+        Parameters
+        ----------
+        str
+            The result of the connection attempt, ``"Evt2"`` if the connection
+            succeeded, ``"Evt17"`` if it failed.
+
+        Returns
+        -------
+        str
+            The result of the connection attempt, ``"Evt2"`` if the connection
+            succeeded, ``"Evt17"`` if it failed.
+        """
+        if self._result == "":
+            raise ValueError("A connection attempt has not yet been made")
+
+        return self._result
+
+    @result.setter
+    def result(self, value: str) -> None:
+        if value not in ("Evt2", "Evt17"):
+            raise ValueError(f"Invalid connection result '{value}'")
+
+        self._result = value
 
 
 class AssociationSocket:
@@ -190,7 +213,7 @@ class AssociationSocket:
         self.event_queue.put("Evt17")
 
     def connect(self, primitive: T_CONNECT) -> None:
-        """Try and connect to a remote at `address`.
+        """Try and connect to a remote using connection details from  `primitive`.
 
         .. versionchanged:: 2.0
 


Test patch:
diff --git a/pynetdicom/tests/test_transport.py b/pynetdicom/tests/test_transport.py
index b57288951..47cb4f06f 100644
--- a/pynetdicom/tests/test_transport.py
+++ b/pynetdicom/tests/test_transport.py
@@ -62,19 +62,11 @@ class TestTConnect:
     def test_bad_addr_raises(self):
         """Test a bad init parameter raises exception"""
         msg = (
-            r"'address' must be 'Tuple\[str, int\]' or "
-            r"'pynetdicom.pdu_primitives.A_ASSOCIATE', not 'NoneType'"
+            r"'request' must be 'pynetdicom.pdu_primitives.A_ASSOCIATE', not 'NoneType'"
         )
         with pytest.raises(TypeError, match=msg):
             T_CONNECT(None)
 
-    def test_address_tuple(self):
-        """Test init with a tuple"""
-        conn = T_CONNECT(("123", 12))
-        assert conn.address == ("123", 12)
-        assert conn.request is None
-        assert conn.result == ""
-
     def test_address_request(self):
         """Test init with an A-ASSOCIATE primitive"""
         request = A_ASSOCIATE()
@@ -82,7 +74,26 @@ class TestTConnect:
         conn = T_CONNECT(request)
         assert conn.address == ("123", 12)
         assert conn.request is request
-        assert conn.result == ""
+
+        msg = r"A connection attempt has not yet been made"
+        with pytest.raises(ValueError, match=msg):
+            conn.result
+
+    def test_result_setter(self):
+        """Test setting the result value."""
+        request = A_ASSOCIATE()
+        request.called_presentation_address = ("123", 12)
+        conn = T_CONNECT(request)
+
+        msg = r"Invalid connection result 'foo'"
+        with pytest.raises(ValueError, match=msg):
+            conn.result = "foo"
+
+        assert conn._result == ""
+
+        for result in ("Evt2", "Evt17"):
+            conn.result = result
+            assert conn.result == result
 
 
 class TestAssociationSocket:
@@ -161,7 +172,9 @@ class TestAssociationSocket:
         sock.close()
         assert sock.socket is None
         # Tries to connect, sets to None if fails
-        sock.connect(T_CONNECT(("localhost", 11112)))
+        request = A_ASSOCIATE()
+        request.called_presentation_address = ("123", 12)
+        sock.connect(T_CONNECT(request))
         assert sock.event_queue.get() == "Evt17"
         assert sock.socket is None