22# -*- coding: utf-8 -*-
33
44# SPDX-License-Identifier: Apache-2.0
5- # Copyright (C) 2024 Barcelona Supercomputing Center, José M. Fernández
5+ # Copyright (C) 2025 Barcelona Supercomputing Center, José M. Fernández
66#
77# Licensed under the Apache License, Version 2.0 (the "License");
88# you may not use this file except in compliance with the License.
2424import json
2525import os
2626import os .path
27+ import pathlib
2728from typing import (
2829 cast ,
2930 TYPE_CHECKING ,
@@ -157,6 +158,7 @@ def create_groovy_parser() -> "Lark":
157158 # parser='lalr',
158159 # debug=True,
159160 start = "compilation_unit" ,
161+ # ambiguity='explicit',
160162 # lexer_callbacks={
161163 # 'square_bracket_block': jarlmethod
162164 # }
@@ -217,13 +219,21 @@ def digest_lark_tree(
217219
218220def parse_and_digest_groovy_content (
219221 content : "str" ,
220- cache_directory : "Optional[str]" = None ,
222+ ro_cache_directories : "Optional[Sequence[Union[str, os.PathLike[str]]]]" = None ,
223+ cache_directory : "Optional[Union[str, os.PathLike[str]]]" = None ,
221224 prune : "Sequence[str]" = ["sep" , "nls" ],
222225 noflat : "Sequence[str]" = ["script_statement" ],
223226) -> "Union[RuleNode, LeafNode, EmptyNode]" :
224227 t_tree : "Optional[Union[RuleNode, LeafNode, EmptyNode]]" = None
225- hashfile : "Optional[str]" = None
226- if cache_directory is not None and os .path .isdir (cache_directory ):
228+ hashpath : "Optional[pathlib.Path]" = None
229+ cache_path : "Optional[pathlib.Path]" = None
230+ if cache_directory is not None :
231+ if isinstance (cache_directory , pathlib .Path ):
232+ cache_path = cache_directory
233+ else :
234+ cache_path = pathlib .Path (cache_directory )
235+
236+ if cache_path is not None and cache_path .is_dir ():
227237 h = hashlib .sha256 ()
228238 buff = bytearray (BLOCK_SIZE )
229239
@@ -246,31 +256,57 @@ def parse_and_digest_groovy_content(
246256 # Now we can obtain the relative directory, unique to this
247257 # version of the software and its dependencies
248258 hreldir = h .copy ().hexdigest ()
249- this_cache_directory = os .path .join (cache_directory , hreldir )
250- os .makedirs (this_cache_directory , exist_ok = True )
251259
252- # Now, let's go for the content signature
253- h .update (content .encode ("utf-8" ))
254- hashfile = os .path .join (this_cache_directory , h .hexdigest () + ".json.gz" )
260+ ro_cache_paths : "MutableSequence[pathlib.Path]" = []
261+ if ro_cache_directories is not None :
262+ for ro_cache_directory in ro_cache_directories :
263+ if isinstance (ro_cache_directory , pathlib .Path ):
264+ ro_cache_path = ro_cache_directory
265+ else :
266+ ro_cache_path = pathlib .Path (ro_cache_directory )
267+
268+ # Include only existing cache paths
269+ this_ro_cache_path = ro_cache_path / hreldir
270+ if this_ro_cache_path .is_dir ():
271+ ro_cache_paths .append (this_ro_cache_path )
255272
256- if os .path .isfile (hashfile ):
257- try :
258- with gzip .open (hashfile , mode = "rt" , encoding = "utf-8" ) as jH :
259- t_tree = json .load (jH )
260- except :
261- # If it is unreadable, re-create
262- pass
273+ this_cache_path = cache_path / hreldir
274+ this_cache_path .mkdir (parents = True , exist_ok = True )
263275
264- if t_tree is None :
276+ ro_cache_paths .append (this_cache_path )
277+
278+ # Now, let's go for the content signature
279+ h .update (content .encode ("utf-8" ))
280+ rel_hashpath = h .hexdigest () + ".json.gz"
281+
282+ # This is needed in case nothing was available
283+ hashpath = this_cache_path / rel_hashpath
284+ for ro_cache_path in ro_cache_paths :
285+ ro_hashpath = ro_cache_path / rel_hashpath
286+ if ro_hashpath .is_file ():
287+ try :
288+ with gzip .open (
289+ ro_hashpath .as_posix (), mode = "rt" , encoding = "utf-8"
290+ ) as jH :
291+ t_tree = json .load (jH )
292+ hashpath = None
293+ break
294+ except :
295+ # If it is unreadable, re-create
296+ pass
297+
298+ if t_tree is None and (hashpath is not None or cache_path is None ):
265299 tree = parse_groovy_content (content )
266300 t_tree = LarkFilteringTreeEncoder ().default (
267301 tree ,
268302 prune = prune ,
269303 noflat = noflat ,
270304 )
271305
272- if hashfile is not None :
273- with gzip .open (hashfile , mode = "wt" , encoding = "utf-8" ) as jH :
274- json .dump (t_tree , jH , sort_keys = True )
306+ assert t_tree is not None
307+
308+ if hashpath is not None :
309+ with gzip .open (hashpath .as_posix (), mode = "wt" , encoding = "utf-8" ) as jH :
310+ json .dump (t_tree , jH , sort_keys = True )
275311
276312 return t_tree
0 commit comments