Next alpha stage commit

This commit is contained in:
2026-07-06 20:54:46 +02:00
parent e23387738b
commit 1d7ec956d2
42 changed files with 11603 additions and 2837 deletions

View File

@@ -5,8 +5,11 @@ import csv
from app import feed_discovery
from app.feed_discovery import (
FeedCandidate,
apply_source_hierarchy,
build_gtfs_discovery_manifests,
enrich_ptna_candidate_from_details,
parse_opendata_oepnv_dataset_links,
parse_opendata_oepnv_detail_page,
parse_ptna_country_page,
parse_ptna_detail_fields,
select_test_run_candidates,
@@ -105,6 +108,7 @@ def test_build_gtfs_discovery_manifests_from_stubbed_sources(tmp_path, monkeypat
monkeypatch.setattr(feed_discovery, "fetch_mobility_database_candidates", lambda **_: mobility)
monkeypatch.setattr(feed_discovery, "fetch_mobility_acceptance_candidates", lambda **_: [])
monkeypatch.setattr(feed_discovery, "fetch_ptna_candidates", lambda **_: ptna)
monkeypatch.setattr(feed_discovery, "fetch_opendata_oepnv_candidates", lambda **_: [])
monkeypatch.setattr(feed_discovery, "load_curated_ingestable_seed", lambda **_: curated)
report = build_gtfs_discovery_manifests(output_dir=tmp_path, countries=["DE", "CH"], test_limit=10)
@@ -116,6 +120,83 @@ def test_build_gtfs_discovery_manifests_from_stubbed_sources(tmp_path, monkeypat
assert "ptna" in next(row for row in ingestable_rows if row["url"] == "https://example.test/rnv.zip")["source_basis"]
def test_parse_opendata_oepnv_catalog_and_details():
catalog_html = """
<a href="/ht/de/organisation/verkehrsunternehmen/rnv/startseite?tx_vrrkit_view%5Baction%5D=details&amp;tx_vrrkit_view%5Bcontroller%5D=View&amp;tx_vrrkit_view%5Bdataset_name%5D=soll-fahrplandaten-rnv">
<span itemprop="headline">Soll-Fahrplandaten (GTFS - General Transit Feed Specification)</span>
</a>
"""
links = parse_opendata_oepnv_dataset_links(catalog_html, "https://www.opendata-oepnv.de/ht/de/datensaetze")
assert len(links) == 1
assert links[0].slug == "soll-fahrplandaten-rnv"
assert links[0].title.startswith("Soll-Fahrplandaten")
detail_html = """
<div class="element-header">Soll-Fahrplandaten (GTFS - General Transit Feed Specification)</div>
<p>In dieser Ressource hinterlegen wir stets den aktuellsten GTFS-Datensatz.</p>
<a href="https://gtfs-sandbox-dds.rnv-online.de/latest/gtfs.zip">Download [ZIP]</a>
<td id="dodp_license"><a href="/?id=20">Creative Commons</a></td>
"""
candidate = parse_opendata_oepnv_detail_page(
detail_html,
detail_url=links[0].url,
slug=links[0].slug,
title_hint=links[0].title,
)
assert candidate.discovery_source == "opendata_oepnv"
assert candidate.provider == "Rhein-Neckar-Verkehr"
assert candidate.selected_url == "https://gtfs-sandbox-dds.rnv-online.de/latest/gtfs.zip"
assert candidate.data_type == "gtfs"
assert candidate.authority_level == "operator_feed"
assert candidate.import_policy == "qa_or_override_not_additive"
def test_opendata_oepnv_registration_required_is_not_direct_ingestable():
detail_html = """
<div class="element-header">Deutschlandweite Sollfahrplandaten (GTFS)</div>
<p>This Download is only available for registered Users.</p>
<td id="dodp_license"><a href="http://www.opendefinition.org/licenses/cc-by">Creative Commons Attribution</a></td>
"""
candidate = parse_opendata_oepnv_detail_page(
detail_html,
detail_url="https://www.opendata-oepnv.de/ht/de/organisation/delfi/startseite?tx_vrrkit_view%5Bdataset_name%5D=deutschlandweite-sollfahrplandaten-gtfs",
slug="deutschlandweite-sollfahrplandaten-gtfs",
)
assert candidate.status == "registration_required"
assert candidate.selected_url == ""
assert candidate.authority_level == "national_official"
assert candidate.overlap_role == "review_baseline"
assert candidate.import_policy == "review_before_import"
def test_source_hierarchy_marks_mirrors_and_regional_feeds():
mirror = FeedCandidate(
discovery_source="curated_seed",
country="DE",
provider="DE generated national",
selected_url="https://scraped.data.public-transport.earth/de/gtfs.zip",
source_basis="European transport feeds mirror",
)
regional = FeedCandidate(
discovery_source="mobility_database",
country="DE",
provider="Verkehrsverbund Berlin-Brandenburg",
selected_url="https://www.vbb.de/vbbgtfs",
is_official="True",
)
apply_source_hierarchy(mirror)
apply_source_hierarchy(regional)
assert mirror.authority_level == "mirror"
assert mirror.import_policy == "bootstrap_only"
assert regional.authority_level == "regional_authority"
assert regional.import_policy == "qa_or_override_not_additive"
def test_select_test_run_candidates_keeps_overlapping_german_feeds():
candidates = [
FeedCandidate(