55from pathlib import Path
66from typing import Union , Any
77from .config import Settings
8-
9- from tcat_gtfs_csv_validator import gcv_test_release
10- from tcat_gtfs_csv_validator import exceptions as gcvex
8+ from gtfs_canonical_validator import CanonicalValidator
9+ from .flex_config import CHANGE_ERROR_TO_WARNING , FLEX_FATAL_ERROR_CODES , FLEX_FIELDS , FLEX_FILES
1110
1211ROOT_DIR = os .path .dirname (os .path .abspath (__file__ ))
1312# Path used for download file generation.
1716logger = logging .getLogger ('FLEX_VALIDATION' )
1817logger .setLevel (logging .INFO )
1918
20- DATA_TYPE = 'gtfs_flex'
21- SCHEMA_VERSION = 'v2.0'
22-
2319
2420class GTFSFlexValidation :
25- def __init__ (self , file_path = None , storage_client = None ):
21+ def __init__ (self , file_path = None , storage_client = None , prefix = None ):
2622 self .settings = Settings ()
2723 self .container_name = self .settings .storage_container_name
2824 self .storage_client = storage_client
2925 self .file_path = file_path
3026 self .file_relative_path = file_path .split ('/' )[- 1 ]
3127 self .client = self .storage_client .get_container (container_name = self .container_name )
28+ if prefix :
29+ self .prefix = prefix
30+ else :
31+ self .prefix = self .settings .get_unique_id ()
3232
3333 # Facade function to validate the file
3434 # Focuses on the file name with file name validation
@@ -46,31 +46,69 @@ def is_gtfs_flex_valid(self) -> tuple[Union[bool, Any], Union[str, Any]]:
4646 if ext and ext .lower () == '.zip' :
4747 downloaded_file_path = self .download_single_file (self .file_path )
4848 logger .info (f' Downloaded file path: { downloaded_file_path } ' )
49- try :
50- gcv_test_release .test_release (DATA_TYPE , SCHEMA_VERSION , downloaded_file_path )
51- is_valid = True
52- except Exception as err :
53- traceback .print_exc ()
54- validation_message = str (err )
55- logger .error (f' Error While Validating File: { str (err )} ' )
49+ flex_validator = CanonicalValidator (zip_file = downloaded_file_path )
50+ result = flex_validator .validate ()
51+
52+ is_valid = result .status
53+ if isinstance (result .error , list ) and result .error is not None :
54+ for error in result .error [:]:
55+ # change some smaller errors to warnings instead to relax the strict validation MD gives us
56+ if error ['code' ] in CHANGE_ERROR_TO_WARNING :
57+ if result .info is None : result .info = []
58+ result .info .append (error )
59+ result .error .remove (error )
60+ continue
61+
62+ # these are error codes from MD that relate to pathways that are fatal
63+ if error ['code' ] in FLEX_FATAL_ERROR_CODES :
64+ is_valid = False
65+ continue
66+
67+ # some of the notices relate to pathways, but there's no way to tell except with this logic:
68+ for notice in error ['sampleNotices' ]:
69+ # one of the fields in a given file is a pathway-spec field--if it's flagged, fail
70+ if "fieldName" in notice and "filename" in notice :
71+ if notice ['filename' ] in FLEX_FIELDS and \
72+ notice ['fieldName' ] in FLEX_FIELDS [notice ['filename' ]]:
73+ is_valid = False
74+ continue
75+
76+ # one of the pathways spec'd files has an error--if so, fail
77+ if "filename" in notice :
78+ if notice ['filename' ] in FLEX_FILES :
79+ is_valid = False
80+ continue
81+
82+ # similar to the above, but the field for the filename is parent/child
83+ if "childFilename" in notice :
84+ if notice ['childFilename' ] in FLEX_FILES :
85+ is_valid = False
86+ continue
87+
88+ # if all errors have been downgraded to warnings, mark us as a success
89+ if len (result .error ) == 0 :
90+ is_valid = True
91+
92+ if result .error is not None :
93+ validation_message = str (result .error )
94+ logger .error (f' Error While Validating File: { str (result .error )} ' )
95+
5696 GTFSFlexValidation .clean_up (downloaded_file_path )
5797 else :
5898 logger .error (f' Failed to validate because unknown file format' )
5999
60100 return is_valid , validation_message
61101
62102 # Downloads the file to local folder of the server
63- # file_upload_path is the fullUrl of where the
103+ # file_upload_path is the fullUrl of where the
64104 # file is uploaded.
65105 def download_single_file (self , file_upload_path = None ) -> str :
66106 is_exists = os .path .exists (DOWNLOAD_FILE_PATH )
67107 if not is_exists :
68108 os .makedirs (DOWNLOAD_FILE_PATH )
69-
70- unique_folder = self .settings .get_unique_id ()
109+ unique_folder = self .prefix
71110 dl_folder_path = os .path .join (DOWNLOAD_FILE_PATH , unique_folder )
72111
73- # Ensure the unique folder path is created
74112 os .makedirs (dl_folder_path , exist_ok = True )
75113
76114 file = self .storage_client .get_file_from_url (self .container_name , file_upload_path )
@@ -95,6 +133,5 @@ def clean_up(path):
95133 logger .info (f' Removing File: { path } ' )
96134 os .remove (path )
97135 else :
98- folder = os .path .join (DOWNLOAD_FILE_PATH , path )
99- logger .info (f' Removing Folder: { folder } ' )
100- shutil .rmtree (folder , ignore_errors = False )
136+ logger .info (f' Removing Folder: { path } ' )
137+ shutil .rmtree (path , ignore_errors = False )
0 commit comments