""""Contains the class needed to thaw the distribution."""from__future__importannotations__author__='Paul Landes'fromtypingimportDict,Any,IterableimportloggingfrompathlibimportPathimportplatformimportzipfileimportjsonfromzensols.persistimportpersisted,PersistedWorkfromzensols.grsyncimport(FrozenRepo,FileEntry,LinkEntry,PathTranslator,Discoverer,)logger=logging.getLogger(__name__)
[docs]classDistribution(object):"""Represents a frozen distribution. """
[docs]def__init__(self,path:Path,defs_file:Path,target_dir:Path,path_translator:PathTranslator):"""Initialize the distribution instance. :param path: points to the distribution file itself :param target_dir: points to the directory where we thaw the distribution :param path_translator: translates relative paths to the thaw directory """self.path=pathself.defs_file=defs_fileself.target_dir=target_dirself.path_translator=path_translatorself.params={'os':platform.system().lower()}
[docs]@classmethoddeffrom_struct(cls:type,struct:Dict[str,Any],target_dir:Path)->Distribution:"""Return a distrbution directly from the data structure created from :class:`.Discoverer`. :param struct: the data structure given by :meth:`.Discoverer.freeze` using ``flatten=True`` :param target_dir: where the distribution will be *thawed* """self=cls(None,None,target_dir,PathTranslator(target_dir))self._struct=PersistedWork('_struct',self,initial_value=struct)returnself
[docs]@classmethoddeffrom_discoverer(cls:type,discoverer:Discoverer,target_dir:Path)->Distribution:"""Return a distrbution directly from the data structure created from :class:`.Discoverer`. :param discoverer: a discoverer instance created by the *freeze* state :param target_dir: where the distribution will be *thawed* """fspec=discoverer.freeze(True)returncls.from_struct(fspec,target_dir)
@property@persisted('_struct')defstruct(self)->Dict[str,Any]:"""Return the JSON deserialized (meta data) of the distribution. """withzipfile.ZipFile(str(self.path.resolve()))aszf:withzf.open(self.defs_file)asf:jstr=f.read().decode('utf-8')struct=json.loads(jstr)returnstruct@propertydefversion(self)->str:"""Get the distribution format version, which for now, is just the application version. """if'app_version'inself.struct:returnself.struct['app_version']@property@persisted('_files')deffiles(self)->Iterable[FileEntry]:"""Get the files in the distribution. """returnmap(lambdafi:FileEntry(self,fi),self.struct['files'])@property@persisted('_empty_dirs')defempty_dirs(self)->Iterable[FileEntry]:"""Get empty directories defined in the dist configuration. """returnmap(lambdafi:FileEntry(self,fi),self.struct['empty_dirs'])@property@persisted('_links')deflinks(self)->Iterable[LinkEntry]:"""Pattern links and symbolic links not pointing to repositories. """returnmap(lambdafi:LinkEntry(self,fi),self.struct['links'])@property@persisted('_repos')defrepos(self)->Iterable[FrozenRepo]:"""Repository specifications. """repos=[]repo_pref=self.struct['repo_pref']forrdefinself.struct['repo_specs']:links=tuple(map(lambdafi:LinkEntry(self,fi),rdef['links']))repo=FrozenRepo(rdef['remotes'],links,self.target_dir,self.path_translator.expand(rdef['path']),repo_pref,self.path_translator)repos.append(repo)returnrepos