Repository: astropy/astropy

Issue:
Latitude/Longitude parsing accepts wrong cardinality
### Description

`Longitude` / `Latitude` string parsing accepts the wrong cardinalities without complaining (warning or error).

### Expected behavior

Issue an error or at least a warning.

### How to Reproduce

```
In [10]: Longitude("45°21'48.7\"N")
Out[10]: <Longitude 45.36352778 deg>

In [11]: Longitude("45°21'48.7\"S")
Out[11]: <Longitude 314.63647222 deg>

In [12]: Latitude("14°24'48.9\"E")
Out[12]: <Latitude 14.41358333 deg>

In [13]: Latitude("14°24'48.9\"W")
Out[13]: <Latitude -14.41358333 deg>
```

### Versions

```
Linux-6.10.10-arch1-1-x86_64-with-glibc2.40
Python 3.11.10 | packaged by conda-forge | (main, Sep 22 2024, 14:10:38) [GCC 13.3.0]
astropy 6.1.4
Numpy 2.0.2
pyerfa 2.0.1.4
Scipy 1.14.1
Matplotlib 3.9.2
```

Discussion:
github-actions[bot]: Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.

  - [ ] Do the proposed changes actually accomplish desired goals?
  - [ ] Do the proposed changes follow the [Astropy coding guidelines](https://docs.astropy.org/en/latest/development/codeguide.html)?
  - [ ] Are tests added/updated as required? If so, do they follow the [Astropy testing guidelines](https://docs.astropy.org/en/latest/development/testguide.html)?
  - [ ] Are docs added/updated as required? If so, do they follow the [Astropy documentation guidelines](https://docs.astropy.org/en/latest/development/docguide.html)?
  - [ ] Is rebase and/or squash necessary? If so, please provide the author with appropriate instructions. Also see instructions for [rebase](https://docs.astropy.org/en/latest/development/development_details.html#rebase-if-necessary) and [squash](https://docs.astropy.org/en/latest/development/development_details.html#squash-if-necessary).
  - [ ] Did the CI pass? If no, are the failures related? If you need to run daily and weekly cron jobs as part of the PR, please apply the "Extra CI" label. Codestyle issues can be fixed by the [bot](https://docs.astropy.org/en/latest/development/development_details.html#pre-commit).
  - [ ] Is a change log needed? If yes, did the change log check pass? If no, add the "no-changelog-entry-needed" label. If this is a manual backport, use the "skip-changelog-checks" label unless special changelog handling is necessary.
  - [ ] Is this a big PR that makes a "What's new?" entry worthwhile and if so, is (1) a "what's new" entry included in this PR and (2) the "whatsnew-needed" label applied?
  - [ ] At the time of adding the milestone, if the milestone set requires a backport to release branch(es), apply the appropriate "backport-X.Y.x" label(s) *before* merge.
mhvk: @eerovaher - I agree that this is not really a great solution, and am fine with just keeping this up our sleeve just in case someone has time to think of a more elegant one.

Patch:
diff --git a/astropy/coordinates/angles/core.py b/astropy/coordinates/angles/core.py
index 36508ee91d..6d2ff95859 100644
--- a/astropy/coordinates/angles/core.py
+++ b/astropy/coordinates/angles/core.py
@@ -183,7 +183,7 @@ class Angle(SpecificTypeQuantity):
             elif isiterable(angle) and not (
                 isinstance(angle, np.ndarray) and angle.dtype.kind not in "SUVO"
             ):
-                angle = [Angle(x, unit, copy=COPY_IF_NEEDED) for x in angle]
+                angle = [cls(x, unit, copy=COPY_IF_NEEDED) for x in angle]
 
         return super().__new__(cls, angle, unit, dtype=dtype, copy=copy, **kwargs)
 
@@ -582,7 +582,9 @@ class Latitude(Angle):
 
     def __new__(cls, angle, unit=None, **kwargs):
         # Forbid creating a Lat from a Long.
-        if isinstance(angle, Longitude):
+        if isinstance(angle, Longitude) or (
+            isinstance(angle, str) and angle.endswith(("E", "W"))
+        ):
             raise TypeError("A Latitude angle cannot be created from a Longitude angle")
         self = super().__new__(cls, angle, unit=unit, **kwargs)
         self._validate_angles()
@@ -707,7 +709,9 @@ class Longitude(Angle):
 
     def __new__(cls, angle, unit=None, wrap_angle=None, **kwargs):
         # Forbid creating a Long from a Lat.
-        if isinstance(angle, Latitude):
+        if isinstance(angle, Latitude) or (
+            isinstance(angle, str) and angle.endswith(("N", "S"))
+        ):
             raise TypeError(
                 "A Longitude angle cannot be created from a Latitude angle."
             )
diff --git a/docs/changes/coordinates/17132.bugfix.rst b/docs/changes/coordinates/17132.bugfix.rst
new file mode 100644
index 0000000000..c768a96de9
--- /dev/null
+++ b/docs/changes/coordinates/17132.bugfix.rst
@@ -0,0 +1,3 @@
+``Longitude`` and ``Latitude`` can no longer be initialized with strings
+ending in "N" or "S", and "E" or "W", respectively, since those suggest
+the other type.


Test patch:
diff --git a/astropy/coordinates/tests/test_angles.py b/astropy/coordinates/tests/test_angles.py
index 2b5eb7a56c..0ee290877b 100644
--- a/astropy/coordinates/tests/test_angles.py
+++ b/astropy/coordinates/tests/test_angles.py
@@ -698,7 +698,7 @@ def test_latitude():
 
     lim_exc = r"Latitude angle\(s\) must be within -90 deg <= angle <= 90 deg, got"
     with pytest.raises(ValueError, match=rf"{lim_exc} \[91. 89.\] deg"):
-        Latitude(["91d", "89d"])
+        Latitude([91, 89] * u.deg)
     with pytest.raises(ValueError, match=f"{lim_exc} -91.0 deg"):
         Latitude("-91d")
 
@@ -777,6 +777,18 @@ def test_lon_as_lat():
     assert lat.value[0] == 10.0
 
 
+@pytest.mark.parametrize("lon", ["12.3dW", "12h13m12sE", ["1d", "1dW"]])
+def test_lon_as_lat_str(lon):
+    with pytest.raises(TypeError, match="Latitude.*cannot be created from a Longitude"):
+        Latitude(lon)
+
+
+@pytest.mark.parametrize("lat", ["12.3dN", "12d13m12sS", ["1d", "1dS"]])
+def test_lat_as_lon_str(lat):
+    with pytest.raises(TypeError, match="Longitude.*cannot be created from a Latitude"):
+        Longitude(lat)
+
+
 def test_longitude():
     """Test setting and manipulation operations on Longitude angles."""