@@ -61,7 +61,9 @@ def unmasked(cls) -> "Mask":
6161@dataclasses .dataclass
6262class BaseSpec (Generic [T ]):
6363 file_root : Path
64+ """The search path contiaining the generated spec; typically the some version-control root"""
6465 file_path : Path
66+ """The path to the test file relative to `file_root`"""
6567 family : str = ""
6668 stdout : str = "canary-out.txt"
6769 stderr : str | None = None # combine stdout/stderr by default
@@ -132,6 +134,7 @@ def from_dict(cls: Type[T], d: dict, lookup: dict[str, T]) -> T:
132134
133135 @cached_property
134136 def file (self ) -> Path :
137+ """Path to the test specification file"""
135138 return self .file_root / self .file_path
136139
137140 @property
@@ -485,40 +488,56 @@ def _generate_dependency_patterns(
485488
486489
487490class _GlobalSpecCache :
488- _file_hash : dict [Path , str ] = {}
489- _repo_root : dict [Path , Path ] = {}
490- _lock = threading .Lock ()
491+ """Simple cache for storing re-used data feeding the spec ID"""
491492
492- @classmethod
493- def file_hash (cls , path : Path ) -> str :
494- path = path .absolute ()
495- try :
496- return cls ._file_hash [path ]
497- except KeyError :
498- pass
499- h = hashlib .blake2b (digest_size = 16 )
500- h .update (path .read_bytes ())
501- digest = h .hexdigest ()
502- with cls ._lock :
503- return cls ._file_hash .setdefault (path , digest )
493+ _key : dict [Path , Path ] = {}
494+ """Maps the input file path to a key index (absolute path)"""
495+
496+ _file_hash : dict [Path , bytes ] = {}
497+ _repo_root : dict [Path , bytes ] = {}
498+ _rel_repo : dict [Path , bytes ] = {}
499+ _lock = threading .Lock ()
504500
505501 @classmethod
506- def repo_root (cls , path : Path ) -> Path :
507- path = path .absolute ()
508- try :
509- return cls ._repo_root [path ]
510- except KeyError :
511- pass
502+ def _compute_repo_root (cls , path : Path ) -> Path :
512503 d = path .parent
513504 while d .parent != d :
514505 if (d / ".git" ).exists () or (d / ".repo" ).exists ():
515506 root = d
516507 break
517508 d = d .parent
518509 else :
519- root = path .parent
510+ root = d
511+ return root
512+
513+ @classmethod
514+ def populate_cache (cls , path : Path ) -> Path :
515+ try :
516+ return cls ._key [path ]
517+ except KeyError :
518+ pass
519+
520+ key = path .absolute ()
521+ h = hashlib .blake2b (digest_size = 16 )
522+ h .update (key .read_bytes ())
523+ root = cls ._compute_repo_root (key )
524+ rel = key .relative_to (root )
525+
520526 with cls ._lock :
521- return cls ._repo_root .setdefault (path , root )
527+ cls ._repo_root [key ] = str (root ).encode ()
528+ cls ._rel_repo [key ] = str (rel ).encode ()
529+ cls ._file_hash [key ] = h .hexdigest ().encode ()
530+ return cls ._key .setdefault (path , key )
531+
532+ @classmethod
533+ def file_hash (cls , path : Path ) -> bytes :
534+ key = cls .populate_cache (path )
535+ return cls ._file_hash [key ]
536+
537+ @classmethod
538+ def rel_repo (cls , path : Path ) -> bytes :
539+ key = cls .populate_cache (path )
540+ return cls ._rel_repo [key ]
522541
523542
524543def build_spec_id (spec : BaseSpec ) -> str :
@@ -529,8 +548,8 @@ def build_spec_id(spec: BaseSpec) -> str:
529548 if parameters :
530549 for p in sorted (parameters ):
531550 hasher .update (f"{ p } ={ stringify (parameters [p ], float_fmt = '%.16e' )} " .encode ())
532- hasher .update (_GlobalSpecCache .file_hash (spec .file ). encode () )
533- hasher .update (str ( _GlobalSpecCache .repo_root (spec .file )). encode ( ))
551+ hasher .update (_GlobalSpecCache .file_hash (spec .file ))
552+ hasher .update (_GlobalSpecCache .rel_repo (spec .file ))
534553 return hasher .hexdigest ()
535554
536555
0 commit comments