11import json
22import os
33from json .decoder import JSONDecodeError
4- from typing import List , Optional
4+ from typing import Optional
55from urllib .error import HTTPError , URLError
66
77import click # type: ignore
2222class StacValidate :
2323 def __init__ (
2424 self ,
25- stac_file : str = None ,
25+ stac_file : Optional [str ] = None ,
26+ item_collection : bool = False ,
27+ pages : Optional [int ] = None ,
2628 recursive : bool = False ,
2729 max_depth : Optional [int ] = None ,
2830 core : bool = False ,
@@ -35,6 +37,8 @@ def __init__(
3537 log : str = "" ,
3638 ):
3739 self .stac_file = stac_file
40+ self .item_collection = item_collection
41+ self .pages = pages
3842 self .message : list = []
3943 self .custom = custom
4044 self .links = links
@@ -64,10 +68,10 @@ def create_err_msg(self, err_type: str, err_msg: str) -> dict:
6468 }
6569
6670 def create_links_message (self ):
67- format_valid : List [ str ] = []
68- format_invalid : List [ str ] = []
69- request_valid : List [ str ] = []
70- request_invalid : List [ str ] = []
71+ format_valid = []
72+ format_invalid = []
73+ request_valid = []
74+ request_invalid = []
7175 return {
7276 "format_valid" : format_valid ,
7377 "format_invalid" : format_invalid ,
@@ -267,75 +271,106 @@ def recursive_validator(self, stac_type: str) -> bool:
267271 click .echo (json .dumps (message , indent = 4 ))
268272 return True
269273
270- def validate_dict (cls , stac_content ):
271- cls .stac_content = stac_content
272- return cls .run ()
274+ def validate_dict (self , stac_content ):
275+ self .stac_content = stac_content
276+ return self .run ()
273277
274- def run (cls ):
278+ def validate_item_collection_dict (self , item_collection ):
279+ for item in item_collection ["features" ]:
280+ self .custom = ""
281+ self .validate_dict (item )
282+
283+ def validate_item_collection (self ):
284+ page = 1
285+ print (f"processing page { page } " )
286+ item_collection = fetch_and_parse_file (self .stac_file )
287+ self .validate_item_collection_dict (item_collection )
288+ try :
289+ if self .pages is not None :
290+ for _ in range (self .pages - 1 ):
291+ if "links" in item_collection :
292+ for link in item_collection ["links" ]:
293+ if link ["rel" ] == "next" :
294+ page = page + 1
295+ print (f"processing page { page } " )
296+ next_link = link ["href" ]
297+ self .stac_file = next_link
298+ item_collection = fetch_and_parse_file (self .stac_file )
299+ self .validate_item_collection_dict (item_collection )
300+ break
301+ except Exception as e :
302+ message = {}
303+ message ["pagination_error" ] = (
304+ f"Validating the item collection failed on page { page } : " ,
305+ str (e ),
306+ )
307+ self .message .append (message )
308+
309+ def run (self ):
275310 message = {}
276311 try :
277- if cls .stac_file is not None :
278- cls .stac_content = fetch_and_parse_file (cls .stac_file )
279- stac_type = get_stac_type (cls .stac_content ).upper ()
280- cls .version = cls .stac_content ["stac_version" ]
312+ if self .stac_file is not None and self . item_collection is False :
313+ self .stac_content = fetch_and_parse_file (self .stac_file )
314+ stac_type = get_stac_type (self .stac_content ).upper ()
315+ self .version = self .stac_content ["stac_version" ]
281316
282- if cls .core is True :
283- message = cls .create_message (stac_type , "core" )
284- cls .core_validator (stac_type )
285- message ["schema" ] = [cls .custom ]
286- cls .valid = True
287- elif cls .custom != "" :
288- message = cls .create_message (stac_type , "custom" )
289- message ["schema" ] = [cls .custom ]
290- cls .custom_validator ()
291- cls .valid = True
292- elif cls .recursive :
293- cls .valid = cls .recursive_validator (stac_type )
294- elif cls .extensions is True :
295- message = cls .extensions_validator (stac_type )
317+ if self .core is True :
318+ message = self .create_message (stac_type , "core" )
319+ self .core_validator (stac_type )
320+ message ["schema" ] = [self .custom ]
321+ self .valid = True
322+ elif self .custom != "" :
323+ message = self .create_message (stac_type , "custom" )
324+ message ["schema" ] = [self .custom ]
325+ self .custom_validator ()
326+ self .valid = True
327+ elif self .recursive :
328+ self .valid = self .recursive_validator (stac_type )
329+ elif self .extensions is True :
330+ message = self .extensions_validator (stac_type )
296331 else :
297- cls .valid = True
298- message = cls .default_validator (stac_type )
332+ self .valid = True
333+ message = self .default_validator (stac_type )
299334
300335 except URLError as e :
301- message .update (cls .create_err_msg ("URLError" , str (e )))
336+ message .update (self .create_err_msg ("URLError" , str (e )))
302337 except JSONDecodeError as e :
303- message .update (cls .create_err_msg ("JSONDecodeError" , str (e )))
338+ message .update (self .create_err_msg ("JSONDecodeError" , str (e )))
304339 except ValueError as e :
305- message .update (cls .create_err_msg ("ValueError" , str (e )))
340+ message .update (self .create_err_msg ("ValueError" , str (e )))
306341 except TypeError as e :
307- message .update (cls .create_err_msg ("TypeError" , str (e )))
342+ message .update (self .create_err_msg ("TypeError" , str (e )))
308343 except FileNotFoundError as e :
309- message .update (cls .create_err_msg ("FileNotFoundError" , str (e )))
344+ message .update (self .create_err_msg ("FileNotFoundError" , str (e )))
310345 except ConnectionError as e :
311- message .update (cls .create_err_msg ("ConnectionError" , str (e )))
346+ message .update (self .create_err_msg ("ConnectionError" , str (e )))
312347 except exceptions .SSLError as e :
313- message .update (cls .create_err_msg ("SSLError" , str (e )))
348+ message .update (self .create_err_msg ("SSLError" , str (e )))
314349 except OSError as e :
315- message .update (cls .create_err_msg ("OSError" , str (e )))
350+ message .update (self .create_err_msg ("OSError" , str (e )))
316351 except jsonschema .exceptions .ValidationError as e :
317352 if e .absolute_path :
318353 err_msg = f"{ e .message } . Error is in { ' -> ' .join ([str (i ) for i in e .absolute_path ])} "
319354 else :
320355 err_msg = f"{ e .message } of the root of the STAC object"
321- message .update (cls .create_err_msg ("JSONSchemaValidationError" , err_msg ))
356+ message .update (self .create_err_msg ("JSONSchemaValidationError" , err_msg ))
322357 except KeyError as e :
323- message .update (cls .create_err_msg ("KeyError" , str (e )))
358+ message .update (self .create_err_msg ("KeyError" , str (e )))
324359 except HTTPError as e :
325- message .update (cls .create_err_msg ("HTTPError" , str (e )))
360+ message .update (self .create_err_msg ("HTTPError" , str (e )))
326361 except Exception as e :
327- message .update (cls .create_err_msg ("Exception" , str (e )))
362+ message .update (self .create_err_msg ("Exception" , str (e )))
328363
329364 if len (message ) > 0 :
330- message ["valid_stac" ] = cls .valid
331- cls .message .append (message )
365+ message ["valid_stac" ] = self .valid
366+ self .message .append (message )
332367
333- if cls .log != "" :
334- f = open (cls .log , "w" )
335- f .write (json .dumps (cls .message , indent = 4 ))
368+ if self .log != "" :
369+ f = open (self .log , "w" )
370+ f .write (json .dumps (self .message , indent = 4 ))
336371 f .close ()
337372
338- if cls .valid :
373+ if self .valid :
339374 return True
340375 else :
341376 return False
0 commit comments