55
66import json
77import logging
8- import os
9- import uuid
10- from io import BytesIO
118from typing import Dict
129
1310import folium
14- import requests
1511from dotenv import load_dotenv
16- from google .cloud import storage
17- from sqlalchemy .orm import Session
1812
1913from reverse_geolocation_processor import reverse_geolocation_process
20- from shared .database .database import with_db_session
21- from shared .database_gen .sqlacodegen_models import Gtfsfeed , Gbfsfeed
2214from shared .helpers .locations import ReverseGeocodingStrategy
2315from shared .helpers .logger import init_logger
24- from shared .helpers .runtime_metrics import track_metrics
2516
26- HOST = "localhost"
27- PORT = 9023
28- BUCKET_NAME = "verifier"
17+ from shared .helpers .verifier_common import (
18+ download_to_local ,
19+ EMULATOR_STORAGE_BUCKET_NAME ,
20+ create_test_data ,
21+ EMULATOR_HOST ,
22+ EMULATOR_STORAGE_PORT ,
23+ setup_local_storage_emulator ,
24+ shutdown_local_storage_emulator ,
25+ start_datastore_emulator ,
26+ shutdown_datastore_emulator ,
27+ )
2928
3029feeds = [
3130 {
8079 },
8180]
8281run_with_feed_index = (
83- 1 # Set to an integer index to run with a specific feed from the list above
82+ 3 # Set to an integer index to run with a specific feed from the list above
8483)
8584
8685
9089init_logger ()
9190
9291
93- @track_metrics (metrics = ("time" , "memory" , "cpu" ))
94- def download_to_local (
95- feed_stable_id : str , url : str , filename : str , force_download : bool = False
96- ):
97- """
98- Download a file from a URL and upload it to the Google Cloud Storage emulator.
99- If the file already exists, it will not be downloaded again.
100- Args:
101- url (str): The URL to download the file from.
102- filename (str): The name of the file to save in the emulator.
103- """
104- if not url :
105- return
106- blob_path = f"{ feed_stable_id } /{ filename } "
107- client = storage .Client ()
108- bucket = client .bucket (BUCKET_NAME )
109- blob = bucket .blob (blob_path )
110-
111- # Check if the blob already exists in the emulator
112- if not blob .exists () or force_download :
113- logging .info (f"Downloading and uploading: { blob_path } " )
114- with requests .get (url , stream = True ) as response :
115- response .raise_for_status ()
116- blob .content_type = "application/json"
117- # The file is downloaded into memory before uploading to ensure it's seekable.
118- # Be careful with large files.
119- data = BytesIO (response .content )
120- blob .upload_from_file (data , rewind = True )
121- else :
122- logging .info (f"Blob already exists: gs://{ BUCKET_NAME } /{ blob_path } " )
123-
124-
12592def verify_reverse_geolocation_process (
12693 feed_stable_id : str ,
12794 feed_dict : Dict ,
@@ -183,7 +150,10 @@ def verify_reverse_geolocation_process(
183150 reverse_geolocation_process (request )
184151
185152 # Visualize the resulting geojson file
186- url = f"http://{ HOST } :{ PORT } /{ BUCKET_NAME } /{ feed_stable_id } /geolocation.geojson"
153+ url = (
154+ f"http://{ EMULATOR_HOST } :{ EMULATOR_STORAGE_PORT } /{ EMULATOR_STORAGE_BUCKET_NAME } "
155+ f"/{ feed_stable_id } /geolocation.geojson"
156+ )
187157 gdf = gpd .read_file (url )
188158
189159 # Calculate centroid for map center
@@ -203,37 +173,8 @@ def verify_reverse_geolocation_process(
203173 )
204174
205175
206- @with_db_session
207- def create_test_data (feed_stable_id : str , feed_dict : Dict , db_session : Session = None ):
208- """
209- Create test data in the database if it does not exist.
210- This function is used to ensure that the reverse geolocation process has the necessary data to work with.
211- """
212- # Here you would typically interact with your database to create the necessary test data
213- # For this example, we will just log the action
214- logging .info (f"Creating test data for { feed_stable_id } with data: { feed_dict } " )
215- model = Gtfsfeed if feed_dict ["data_type" ] == "gtfs" else Gbfsfeed
216- local_feed = (
217- db_session .query (model ).filter (model .stable_id == feed_stable_id ).one_or_none ()
218- )
219- if not local_feed :
220- local_feed = model (
221- id = uuid .uuid4 (),
222- stable_id = feed_stable_id ,
223- data_type = feed_dict ["data_type" ],
224- feed_name = "Test Feed" ,
225- note = "This is a test feed created for reverse geolocation verification." ,
226- producer_url = "https://files.mobilitydatabase.org/mdb-2014/mdb-2014-202508120303/mdb-2014-202508120303.zip" ,
227- authentication_type = "0" ,
228- status = "active" ,
229- )
230- db_session .add (local_feed )
231- db_session .commit ()
232-
233-
234176if __name__ == "__main__" :
235177 import geopandas as gpd
236- from gcp_storage_emulator .server import create_server
237178 from flask import Flask , Request
238179
239180 strategy = ReverseGeocodingStrategy .PER_POINT
@@ -245,16 +186,20 @@ def create_test_data(feed_stable_id: str, feed_dict: Dict, db_session: Session =
245186 data = {
246187 "stable_id" : feed_stable_id ,
247188 "dataset_id" : feed_dict ["dataset_id" ] if "dataset_id" in feed_dict else None ,
248- "station_information_url" : f"http://{ HOST } :{ PORT } /{ BUCKET_NAME } /{ feed_stable_id } /station_information.json"
189+ "station_information_url" : f"http://{ EMULATOR_HOST } :{ EMULATOR_STORAGE_PORT } /{ EMULATOR_STORAGE_BUCKET_NAME } "
190+ f"/{ feed_stable_id } /station_information.json"
249191 if "station_information_url" in feed_dict
250192 else None ,
251- "vehicle_status_url" : f"http://{ HOST } :{ PORT } /{ BUCKET_NAME } /{ feed_stable_id } /vehicle_status.json"
193+ "vehicle_status_url" : f"http://{ EMULATOR_HOST } :{ EMULATOR_STORAGE_PORT } /{ EMULATOR_STORAGE_BUCKET_NAME } "
194+ f"/{ feed_stable_id } /vehicle_status.json"
252195 if "vehicle_status_url" in feed_dict
253196 else None ,
254- "free_bike_status_url" : f"http://{ HOST } :{ PORT } /{ BUCKET_NAME } /{ feed_stable_id } /free_bike_status.json"
197+ "free_bike_status_url" : f"http://{ EMULATOR_HOST } :{ EMULATOR_STORAGE_PORT } /{ EMULATOR_STORAGE_BUCKET_NAME } "
198+ f"/{ feed_stable_id } /free_bike_status.json"
255199 if "free_bike_status_url" in feed_dict
256200 else None ,
257- "stops_url" : f"http://{ HOST } :{ PORT } /{ BUCKET_NAME } /{ feed_stable_id } /stops.txt" ,
201+ "stops_url" : f"http://{ EMULATOR_HOST } :{ EMULATOR_STORAGE_PORT } /{ EMULATOR_STORAGE_BUCKET_NAME } "
202+ f"/{ feed_stable_id } /stops.txt" ,
258203 "strategy" : str (strategy .value ),
259204 "data_type" : feed_dict ["data_type" ],
260205 # "use_cache": False,
@@ -263,14 +208,8 @@ def create_test_data(feed_stable_id: str, feed_dict: Dict, db_session: Session =
263208 }
264209
265210 try :
266- os .environ ["STORAGE_EMULATOR_HOST" ] = f"http://{ HOST } :{ PORT } "
267- os .environ ["DATASETS_BUCKET_NAME_GBFS" ] = BUCKET_NAME
268- os .environ ["DATASETS_BUCKET_NAME_GTFS" ] = BUCKET_NAME
269- os .environ ["DATASTORE_EMULATOR_HOST" ] = "localhost:8081"
270- server = create_server (
271- host = HOST , port = PORT , in_memory = False , default_bucket = BUCKET_NAME
272- )
273- server .start ()
211+ server = setup_local_storage_emulator ()
212+ datastore_process = start_datastore_emulator ()
274213 verify_reverse_geolocation_process (
275214 feed_stable_id = feed_stable_id ,
276215 feed_dict = feed_dict ,
@@ -280,4 +219,5 @@ def create_test_data(feed_stable_id: str, feed_dict: Dict, db_session: Session =
280219 except Exception as e :
281220 logging .error (f"Error verifying download content: { e } " )
282221 finally :
283- server .stop ()
222+ shutdown_local_storage_emulator (server )
223+ shutdown_datastore_emulator (datastore_process )
0 commit comments