python-openpublictransport 0.3.2__tar.gz → 0.3.3__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 (108) hide show
  1. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/PKG-INFO +1 -1
  2. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/pyproject.toml +1 -1
  3. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/models.py +7 -0
  4. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/parsers.py +12 -0
  5. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/python_openpublictransport.egg-info/PKG-INFO +1 -1
  6. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/python_openpublictransport.egg-info/SOURCES.txt +1 -0
  7. python_openpublictransport-0.3.3/tests/test_disruptions.py +101 -0
  8. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/setup.cfg +0 -0
  9. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/__init__.py +0 -0
  10. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/const.py +0 -0
  11. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/data/uk_stations.json +0 -0
  12. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/exceptions.py +0 -0
  13. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/__init__.py +0 -0
  14. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/avv.py +0 -0
  15. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/bart.py +0 -0
  16. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/base.py +0 -0
  17. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/beg.py +0 -0
  18. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/bsvg.py +0 -0
  19. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/bvg.py +0 -0
  20. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/cta.py +0 -0
  21. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/dart.py +0 -0
  22. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/db.py +0 -0
  23. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/digitransit.py +0 -0
  24. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/ding.py +0 -0
  25. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/efa_base.py +0 -0
  26. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/entur.py +0 -0
  27. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/fptf_base.py +0 -0
  28. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/golemio.py +0 -0
  29. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/gvh.py +0 -0
  30. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/hafas_base.py +0 -0
  31. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/hafas_mgate_base.py +0 -0
  32. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/hongkong.py +0 -0
  33. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/hvv.py +0 -0
  34. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/hvv_gti.py +0 -0
  35. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/insa.py +0 -0
  36. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/irail.py +0 -0
  37. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/irishrail.py +0 -0
  38. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/kvv.py +0 -0
  39. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/mobiliteit_lu.py +0 -0
  40. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/mvv.py +0 -0
  41. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/nahsh.py +0 -0
  42. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/national_rail.py +0 -0
  43. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/nextbus_base.py +0 -0
  44. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/ns.py +0 -0
  45. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/nta.py +0 -0
  46. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/nvbw.py +0 -0
  47. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/nvv.py +0 -0
  48. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/nwl.py +0 -0
  49. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/oebb.py +0 -0
  50. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/otp.py +0 -0
  51. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/otp_base.py +0 -0
  52. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/otp_custom.py +0 -0
  53. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/rejseplanen.py +0 -0
  54. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/rmv.py +0 -0
  55. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/rvv.py +0 -0
  56. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/saarvv.py +0 -0
  57. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/sbb.py +0 -0
  58. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/sl.py +0 -0
  59. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/tfl.py +0 -0
  60. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/tfnsw.py +0 -0
  61. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/tpg.py +0 -0
  62. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/trafiklab.py +0 -0
  63. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/transitous.py +0 -0
  64. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/trias_base.py +0 -0
  65. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/trimet.py +0 -0
  66. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/ttc.py +0 -0
  67. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vagfr.py +0 -0
  68. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vao.py +0 -0
  69. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vbn.py +0 -0
  70. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vbn_hafas.py +0 -0
  71. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vgn.py +0 -0
  72. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vmt.py +0 -0
  73. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vmv.py +0 -0
  74. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vos.py +0 -0
  75. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vrn.py +0 -0
  76. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vrr.py +0 -0
  77. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vsn.py +0 -0
  78. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vvo.py +0 -0
  79. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/vvs.py +0 -0
  80. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/providers/wienerlinien.py +0 -0
  81. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/openpublictransport/py.typed +0 -0
  82. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/python_openpublictransport.egg-info/dependency_links.txt +0 -0
  83. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/python_openpublictransport.egg-info/requires.txt +0 -0
  84. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/src/python_openpublictransport.egg-info/top_level.txt +0 -0
  85. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_cta.py +0 -0
  86. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_digitransit.py +0 -0
  87. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_efa_mimetype.py +0 -0
  88. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_efa_platform.py +0 -0
  89. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_entur.py +0 -0
  90. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_german_regional_providers.py +0 -0
  91. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_golemio.py +0 -0
  92. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_hafas_base.py +0 -0
  93. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_hafas_mgate.py +0 -0
  94. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_hongkong.py +0 -0
  95. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_http_errors.py +0 -0
  96. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_hvv_gti.py +0 -0
  97. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_irail.py +0 -0
  98. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_issue_fixes_0_3_1.py +0 -0
  99. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_national_rail.py +0 -0
  100. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_national_rail_parse.py +0 -0
  101. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_national_rail_static.py +0 -0
  102. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_provider_expansion.py +0 -0
  103. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_sbb.py +0 -0
  104. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_sl.py +0 -0
  105. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_tfl.py +0 -0
  106. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_tfnsw.py +0 -0
  107. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_ttc.py +0 -0
  108. {python_openpublictransport-0.3.2 → python_openpublictransport-0.3.3}/tests/test_wienerlinien.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-openpublictransport
3
- Version: 0.3.2
3
+ Version: 0.3.3
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.3.2"
7
+ version = "0.3.3"
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" }
@@ -36,6 +36,10 @@ class UnifiedDeparture:
36
36
  description: Optional[str] = None
37
37
  agency: Optional[str] = None
38
38
  notices: Optional[list[str]] = None
39
+ # The subset of ``notices`` that reports an actual disruption, as opposed
40
+ # to routine information such as bicycle rules or on-board facilities.
41
+ # None means the provider does not tell them apart: every notice counts.
42
+ disruptions: Optional[list[str]] = None
39
43
  planned_platform: Optional[str] = None
40
44
  platform_changed: bool = False
41
45
  # Human-readable form of `platform` when the provider offers one
@@ -63,6 +67,9 @@ class UnifiedDeparture:
63
67
  result["agency"] = self.agency
64
68
  if self.notices:
65
69
  result["notices"] = self.notices
70
+ # Always present next to the notices, even when empty, so consumers
71
+ # can tell "no disruption" apart from an older payload without it.
72
+ result["disruptions"] = self.notices if self.disruptions is None else self.disruptions
66
73
  if self.platform_name and self.platform_name != self.platform:
67
74
  result["platform_name"] = self.platform_name
68
75
  if self.platform_changed:
@@ -34,6 +34,13 @@ def rail_line_label(number: str, name: str) -> str:
34
34
  return number
35
35
 
36
36
 
37
+ # EFA hint types that carry routine timetable or vehicle information ("bicycles
38
+ # limited", "wheelchair accessible", "on-board restaurant") rather than a
39
+ # disruption. Infos (lineInfo, stopBlocking, …) and real-time hints such as
40
+ # RTIncidentCall ("delay of a preceding train") are disruptions.
41
+ EFA_ROUTINE_HINT_TYPES = frozenset({"Timetable", "VehicleType"})
42
+
43
+
37
44
  # Human-readable platform labels APIs prefix onto the bare track identifier:
38
45
  # "Gleis 3", "Bstg. 12", "Steig B", "Platform 4", "Pl. 2", "Track 1".
39
46
  _PLATFORM_LABEL_RE = re.compile(
@@ -140,16 +147,20 @@ def parse_departure_generic(
140
147
  is_realtime = get_realtime_fn(stop, estimated_time_str, planned_time_str)
141
148
 
142
149
  notices = []
150
+ disruptions = []
143
151
  for info in stop.get("infos", []):
144
152
  if isinstance(info, dict):
145
153
  text = info.get("subtitle") or info.get("title") or info.get("content", "")
146
154
  if text and isinstance(text, str):
147
155
  notices.append(text.strip())
156
+ disruptions.append(text.strip())
148
157
  for hint in stop.get("hints", []):
149
158
  if isinstance(hint, dict):
150
159
  text = hint.get("content") or hint.get("text", "")
151
160
  if text and isinstance(text, str):
152
161
  notices.append(text.strip())
162
+ if hint.get("type") not in EFA_ROUTINE_HINT_TYPES:
163
+ disruptions.append(text.strip())
153
164
 
154
165
  planned_fn = get_planned_platform_fn or _default_planned_platform_fn
155
166
  planned_platform = planned_fn(stop)
@@ -174,6 +185,7 @@ def parse_departure_generic(
174
185
  description=description if description else None,
175
186
  agency=agency if agency else None,
176
187
  notices=notices if notices else None,
188
+ disruptions=disruptions if notices else None,
177
189
  planned_platform=str(planned_platform).strip() if planned_platform and platform_changed else None,
178
190
  platform_changed=platform_changed,
179
191
  platform_name=str(platform_name).strip() or None,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-openpublictransport
3
- Version: 0.3.2
3
+ Version: 0.3.3
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
@@ -81,6 +81,7 @@ src/python_openpublictransport.egg-info/requires.txt
81
81
  src/python_openpublictransport.egg-info/top_level.txt
82
82
  tests/test_cta.py
83
83
  tests/test_digitransit.py
84
+ tests/test_disruptions.py
84
85
  tests/test_efa_mimetype.py
85
86
  tests/test_efa_platform.py
86
87
  tests/test_entur.py
@@ -0,0 +1,101 @@
1
+ """Tests for telling disruptions apart from routine notices.
2
+
3
+ EFA mixes routine timetable and vehicle information ("bicycles limited",
4
+ "wheelchair accessible vehicle", "on-board restaurant") with real disruptions
5
+ in the same ``hints`` list, so everything ended up in a red warning banner.
6
+ See https://github.com/NerdySoftPaw/openpublictransport-card/issues/15.
7
+ """
8
+
9
+ from datetime import datetime
10
+ from zoneinfo import ZoneInfo
11
+
12
+ from openpublictransport.models import UnifiedDeparture
13
+ from openpublictransport.providers.gvh import GVHProvider
14
+
15
+ TZ = ZoneInfo("Europe/Berlin")
16
+ NOW = datetime(2026, 10, 16, 20, 0, tzinfo=TZ)
17
+
18
+
19
+ def _stop_event(hints=None, infos=None) -> dict:
20
+ """A GVH departure from Hannover Hbf as the live API returns it."""
21
+ event = {
22
+ "location": {"id": "de:03241:31", "name": "Hauptbahnhof", "properties": {"platform": "8"}},
23
+ "departureTimePlanned": "2026-10-16T18:10:00Z",
24
+ "departureTimeEstimated": "2026-10-16T18:12:00Z",
25
+ "transportation": {
26
+ "name": "ICE 550 InterCityExpress",
27
+ "number": "550",
28
+ "destination": {"name": "Köln Hbf"},
29
+ "product": {"class": 0, "name": "ICE"},
30
+ },
31
+ }
32
+ if hints is not None:
33
+ event["hints"] = hints
34
+ if infos is not None:
35
+ event["infos"] = infos
36
+ return event
37
+
38
+
39
+ def test_routine_hints_are_notices_but_not_disruptions():
40
+ """Timetable and VehicleType hints stay notices without becoming disruptions."""
41
+ event = _stop_event(hints=[
42
+ {"content": "behindertengerechtes Fahrzeug", "providerCode": "13", "type": "VehicleType"},
43
+ {"content": "Bordrestaurant", "providerCode": "BR", "type": "Timetable"},
44
+ ])
45
+ dep = GVHProvider(None).parse_departure(event, TZ, NOW)
46
+
47
+ assert dep.notices == ["behindertengerechtes Fahrzeug", "Bordrestaurant"]
48
+ assert dep.disruptions == []
49
+ result = dep.to_dict()
50
+ assert result["notices"] == ["behindertengerechtes Fahrzeug", "Bordrestaurant"]
51
+ assert result["disruptions"] == []
52
+
53
+
54
+ def test_realtime_hints_and_infos_are_disruptions():
55
+ """Real-time incident hints and infos are disruptions; routine hints are not."""
56
+ event = _stop_event(
57
+ hints=[
58
+ {"content": "Bordrestaurant", "providerCode": "BR", "type": "Timetable"},
59
+ {"content": "Technische Störung am Zug", "providerCode": "x", "type": "RTIncidentCall"},
60
+ ],
61
+ infos=[{"type": "lineInfo", "priority": "normal", "title": "Bauarbeiten S1, S2, S5"}],
62
+ )
63
+ dep = GVHProvider(None).parse_departure(event, TZ, NOW)
64
+
65
+ assert dep.notices == ["Bauarbeiten S1, S2, S5", "Bordrestaurant", "Technische Störung am Zug"]
66
+ assert dep.disruptions == ["Bauarbeiten S1, S2, S5", "Technische Störung am Zug"]
67
+
68
+
69
+ def test_hint_without_type_is_a_disruption():
70
+ """An unknown or missing hint type is kept as a disruption, never hidden."""
71
+ dep = GVHProvider(None).parse_departure(_stop_event(hints=[{"content": "Ersatzverkehr"}]), TZ, NOW)
72
+
73
+ assert dep.disruptions == ["Ersatzverkehr"]
74
+
75
+
76
+ def test_no_notices_no_keys():
77
+ """Without notices, neither key appears in the attributes."""
78
+ dep = GVHProvider(None).parse_departure(_stop_event(), TZ, NOW)
79
+
80
+ assert dep.notices is None and dep.disruptions is None
81
+ assert "notices" not in dep.to_dict()
82
+ assert "disruptions" not in dep.to_dict()
83
+
84
+
85
+ def test_unclassified_notices_all_count_as_disruptions():
86
+ """Providers that do not classify their notices report all of them as disruptions."""
87
+ dep = UnifiedDeparture(
88
+ line="U1",
89
+ destination="Somewhere",
90
+ departure_time="20:10",
91
+ planned_time="20:10",
92
+ delay=0,
93
+ platform=None,
94
+ transportation_type="subway",
95
+ is_realtime=True,
96
+ minutes_until_departure=10,
97
+ departure_time_obj=NOW,
98
+ notices=["Cancelled"],
99
+ )
100
+
101
+ assert dep.to_dict()["disruptions"] == ["Cancelled"]