def closure(self)->Closure: """ Check that the current value of Lens is an `RRef` and return it """ r=lens_repr(self,'closure') v=traverse(self, r) assert isdref(v), f"Lens {r} expected closure, but got '{v}'" assert self.ctx.closure is not None return Closure(v, self.ctx.closure.derivations, self.ctx.storage)
def dref(self)->DRef: """ Check that the current value of Lens is a `DRef` and return it """ r=lens_repr(self,'dref') v=traverse(self, r) if isdref(v): return DRef(v) elif isrref(v): return rref2dref(v) else: assert False, f"Lens {r} expected a DRef-like object, got '{v}'"
def store_config(r: Union[DRef, RRef], S=None) -> RConfig: """ Read the [Config](#pylightnix.types.Config) of the derivation and [resolve](#pylightnix.core.config_substitutePromises) it from promises and claims. """ assert isrref(r) or isdref(r), ( f"Invalid reference '{r}'. Expected either RRef or DRef.") if isrref(r): dref = rref2dref(RRef(r)) else: dref = DRef(r) return config_substitutePromises(store_config_(dref, S), dref)
def path2dref(p: Path) -> Optional[DRef]: """ Takes either a system path of some realization in the Pylightnix storage or a symlink pointing to such path. Return a `DRef` which corresponds to this path. Note: `path2dref` operates on `p` symbolically. It doesn't actually check the presence of such an object in storage """ if islink(p): p = Path(readlink(p)) _, dref_part = split(p) dref = DRef('dref:' + dref_part) return dref if isdref(dref) else None
def path2rref(p: Path) -> Optional[RRef]: """ Takes either a system path of some realization in the Pylightnix storage or a symlink pointing to such path. Return `RRef` which corresponds to this path. Note: `path2rref` operates on `p` symbolically. It doesn't actually check the presence of such an object in storage """ if islink(p): p = Path(readlink(p)) head, h1 = split(p) _, dref_part = split(head) dref = DRef('dref:' + dref_part) if not isdref(dref): return None h2, nm = undref(dref) return mkrref(HashPart(h1), HashPart(h2), mkname(nm))
def val2rref(v:Any, ctx:LensContext)->RRef: S=ctx.storage if isdref(v): dref=DRef(v) context=ctx.context if context is not None: if dref in context: rgs=context_deref(context, dref, S) assert len(rgs)==1, "Lens doesn't support multirealization dependencies" return rgs[0][Tag('out')] else: assert False, f"Can't convert {dref} into RRef because it is not in context" else: assert False, f"Lens couldn't resolve '{dref}' without a context" elif isinstance(v,Closure): return val2rref(v.dref, ctx) else: assert isrref(v), f"Lens expected RRef, but got '{v}'" return RRef(v)
def val2dict(v:Any, ctx:LensContext)->Optional[dict]: """ Return the `dict` representation of the Lens value, if possible. Getting the dictionary allows for creating new lenses """ S:SPath=ctx.storage if isdref(v): return config_dict(store_config(DRef(v), S)) elif isrref(v): return config_dict(store_config(rref2dref(RRef(v)),S)) elif isrefpath(v): j=tryreadjson(val2path(v, ctx)) assert j is not None, f"RefPath {v} doesn't belong to a valid JSON file" assert isinstance(j, dict), f"A file with RefPath {v} doesn't contain valid JSON dict" return j elif isinstance(v,Build): return config_dict(build_config(v)) elif isinstance(v,dict): return v elif isinstance(v,Closure): return val2dict(v.dref, ctx) else: return None
def val2path(v:Any, ctx:LensContext)->Path: """ Resolve the current value of Lens into system path. Assert if it is not possible or if the result is associated with multiple paths.""" S:SPath=ctx.storage if isdref(v): dref=DRef(v) context=ctx.context if context is not None: if dref in context: rgs=context_deref(context, dref) assert len(rgs)==1, "Lens doesn't support multirealization dependencies" return Path(store_rref2path(rgs[0][tag_out()])) return store_dref2path(dref) elif isrref(v): return store_rref2path(RRef(v),S) elif isrefpath(v): refpath=list(v) # RefPath is list bpath=ctx.build_path context=ctx.context if context is not None: if refpath[0] in context: rgs=context_deref(context,refpath[0],S) assert len(rgs)==1, "Lens doesn't support multirealization dependencies" return Path(join(store_rref2path(rgs[0][Tag('out')],S), *refpath[1:])) else: if bpath is not None: # FIXME: should we assert on refpath[0]==build.dref ? return Path(join(bpath, *refpath[1:])) else: assert False, f"Can't dereference refpath {refpath}" else: assert False, f"Lens couldn't resolve '{refpath}' without a context" elif isinstance(v, Closure): return val2path(v.dref, ctx) elif isinstance(v, Build): assert ctx.build_path is not None, f"Lens can't access build path of '{v}'" return ctx.build_path else: assert False, f"Lens doesn't know how to resolve '{v}'"
def assert_valid_dref(ref: str) -> None: error_msg = ( f'Value "{ref}" is not a valid derivation reference! Expected ' f'a string of form \'dref:HASH-name\'') assert isdref(ref), error_msg