python-openpublictransport 0.1.16__tar.gz → 0.1.17__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/PKG-INFO +1 -1
  2. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/pyproject.toml +1 -1
  3. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/efa_base.py +6 -2
  4. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/python_openpublictransport.egg-info/PKG-INFO +1 -1
  5. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/python_openpublictransport.egg-info/SOURCES.txt +1 -0
  6. python_openpublictransport-0.1.17/tests/test_efa_mimetype.py +87 -0
  7. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/setup.cfg +0 -0
  8. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/__init__.py +0 -0
  9. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/const.py +0 -0
  10. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/data/uk_stations.json +0 -0
  11. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/exceptions.py +0 -0
  12. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/models.py +0 -0
  13. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/parsers.py +0 -0
  14. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/__init__.py +0 -0
  15. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/avv.py +0 -0
  16. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/bart.py +0 -0
  17. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/base.py +0 -0
  18. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/beg.py +0 -0
  19. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/bsvg.py +0 -0
  20. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/bvg.py +0 -0
  21. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/dart.py +0 -0
  22. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/db.py +0 -0
  23. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/ding.py +0 -0
  24. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/entur.py +0 -0
  25. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/fptf_base.py +0 -0
  26. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/gtfsde.py +0 -0
  27. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/hafas_base.py +0 -0
  28. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/hafas_mgate_base.py +0 -0
  29. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/hvv.py +0 -0
  30. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/hvv_gti.py +0 -0
  31. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/irishrail.py +0 -0
  32. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/kvv.py +0 -0
  33. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/mobiliteit_lu.py +0 -0
  34. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/mvv.py +0 -0
  35. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/national_rail.py +0 -0
  36. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/ns.py +0 -0
  37. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/nta.py +0 -0
  38. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/nvbw.py +0 -0
  39. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/nwl.py +0 -0
  40. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/oebb.py +0 -0
  41. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/otp.py +0 -0
  42. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/otp_base.py +0 -0
  43. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/otp_custom.py +0 -0
  44. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/rejseplanen.py +0 -0
  45. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/rmv.py +0 -0
  46. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/rvv.py +0 -0
  47. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/sbb.py +0 -0
  48. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/tpg.py +0 -0
  49. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/trafiklab.py +0 -0
  50. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/transitous.py +0 -0
  51. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/trias_base.py +0 -0
  52. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/vagfr.py +0 -0
  53. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/vbn.py +0 -0
  54. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/vgn.py +0 -0
  55. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/vrn.py +0 -0
  56. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/vrr.py +0 -0
  57. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/vvo.py +0 -0
  58. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/providers/vvs.py +0 -0
  59. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/openpublictransport/py.typed +0 -0
  60. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/python_openpublictransport.egg-info/dependency_links.txt +0 -0
  61. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/python_openpublictransport.egg-info/requires.txt +0 -0
  62. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/src/python_openpublictransport.egg-info/top_level.txt +0 -0
  63. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/tests/test_efa_platform.py +0 -0
  64. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/tests/test_entur.py +0 -0
  65. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/tests/test_hafas_base.py +0 -0
  66. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/tests/test_hafas_mgate.py +0 -0
  67. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/tests/test_hvv_gti.py +0 -0
  68. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/tests/test_national_rail.py +0 -0
  69. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/tests/test_national_rail_parse.py +0 -0
  70. {python_openpublictransport-0.1.16 → python_openpublictransport-0.1.17}/tests/test_national_rail_static.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-openpublictransport
3
- Version: 0.1.16
3
+ Version: 0.1.17
4
4
  Summary: Python library for public transport APIs (EFA, OTP2, TRIAS, FPTF, HAFAS, GTFS-RT)
5
5
  License: MIT
6
6
  Requires-Python: >=3.11
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-openpublictransport"
7
- version = "0.1.16"
7
+ version = "0.1.17"
8
8
  description = "Python library for public transport APIs (EFA, OTP2, TRIAS, FPTF, HAFAS, GTFS-RT)"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -154,7 +154,9 @@ class EFABaseProvider(BaseProvider):
154
154
  async with self.session.get(url, headers=headers, timeout=aiohttp.ClientTimeout(total=10)) as response:
155
155
  if response.status == 200:
156
156
  try:
157
- json_data = await response.json()
157
+ # content_type=None: some deployments (VGN) send RapidJSON
158
+ # payloads with a "text/xml;;charset=utf-8" header (issue #79).
159
+ json_data = await response.json(content_type=None)
158
160
  if not isinstance(json_data, dict):
159
161
  _LOGGER.warning("%s API returned non-dict response: %s", name, type(json_data))
160
162
  return None
@@ -251,7 +253,9 @@ class EFABaseProvider(BaseProvider):
251
253
  async with self.session.get(url, timeout=aiohttp.ClientTimeout(total=10)) as response:
252
254
  if response.status == 200:
253
255
  try:
254
- data = await response.json()
256
+ # content_type=None: some deployments (VGN) send RapidJSON
257
+ # payloads with a "text/xml;;charset=utf-8" header (issue #79).
258
+ data = await response.json(content_type=None)
255
259
  except (ValueError, aiohttp.ContentTypeError) as e:
256
260
  _LOGGER.error("Invalid JSON response from %s API: %s", name, e)
257
261
  return []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-openpublictransport
3
- Version: 0.1.16
3
+ Version: 0.1.17
4
4
  Summary: Python library for public transport APIs (EFA, OTP2, TRIAS, FPTF, HAFAS, GTFS-RT)
5
5
  License: MIT
6
6
  Requires-Python: >=3.11
@@ -57,6 +57,7 @@ src/python_openpublictransport.egg-info/SOURCES.txt
57
57
  src/python_openpublictransport.egg-info/dependency_links.txt
58
58
  src/python_openpublictransport.egg-info/requires.txt
59
59
  src/python_openpublictransport.egg-info/top_level.txt
60
+ tests/test_efa_mimetype.py
60
61
  tests/test_efa_platform.py
61
62
  tests/test_entur.py
62
63
  tests/test_hafas_base.py
@@ -0,0 +1,87 @@
1
+ """EFA endpoints that mislabel their JSON payload (issue #79).
2
+
3
+ VGN answers ``outputFormat=RapidJSON`` requests with
4
+ ``Content-Type: text/xml;;charset=utf-8``. aiohttp raises ``ContentTypeError``
5
+ for that unless the caller passes ``content_type=None``, so station search
6
+ returned "no results found" even though the body was valid JSON.
7
+
8
+ The fake response below mimics aiohttp: it raises unless the strict content
9
+ type check is disabled — a mock that accepts the kwarg either way cannot catch
10
+ this regression.
11
+ """
12
+
13
+ import aiohttp
14
+ import pytest
15
+
16
+ from openpublictransport.providers.vgn import VGNProvider
17
+
18
+ STOPFINDER_PAYLOAD = {
19
+ "locations": [
20
+ {
21
+ "id": "de:09564:704",
22
+ "name": "Nürnberg, Rathenauplatz",
23
+ "disassembledName": "Rathenauplatz, Nürnberg",
24
+ "type": "stop",
25
+ }
26
+ ]
27
+ }
28
+
29
+ DM_PAYLOAD = {
30
+ "stopEvents": [
31
+ {
32
+ "departureTimePlanned": "2026-08-08T10:00:00Z",
33
+ "transportation": {"number": "U2", "product": {"class": 2, "name": "U-Bahn"}},
34
+ }
35
+ ]
36
+ }
37
+
38
+
39
+ class _XmlMimeResponse:
40
+ """Response whose body is JSON but whose header claims text/xml."""
41
+
42
+ def __init__(self, payload, status=200):
43
+ self.status = status
44
+ self._payload = payload
45
+
46
+ async def json(self, content_type="application/json"):
47
+ if content_type is not None:
48
+ raise aiohttp.ContentTypeError(
49
+ None,
50
+ (),
51
+ message=("Attempt to decode JSON with unexpected mimetype: text/xml;;charset=utf-8"),
52
+ )
53
+ return self._payload
54
+
55
+ async def __aenter__(self):
56
+ return self
57
+
58
+ async def __aexit__(self, *exc):
59
+ return False
60
+
61
+
62
+ class _FakeSession:
63
+ def __init__(self, payload):
64
+ self._payload = payload
65
+ self.urls = []
66
+
67
+ def get(self, url, headers=None, timeout=None):
68
+ self.urls.append(url)
69
+ return _XmlMimeResponse(self._payload)
70
+
71
+
72
+ @pytest.mark.asyncio
73
+ async def test_search_stops_accepts_xml_mimetype():
74
+ session = _FakeSession(STOPFINDER_PAYLOAD)
75
+ results = await VGNProvider(session).search_stops("Rathenauplatz, Nürnberg")
76
+
77
+ assert [r["id"] for r in results] == ["de:09564:704"]
78
+ assert results[0]["place"] == "Nürnberg"
79
+
80
+
81
+ @pytest.mark.asyncio
82
+ async def test_fetch_departures_accepts_xml_mimetype():
83
+ session = _FakeSession(DM_PAYLOAD)
84
+ data = await VGNProvider(session).fetch_departures("de:09564:704", "", "", 10)
85
+
86
+ assert data is not None
87
+ assert len(data["stopEvents"]) == 1