diff --git a/lib/Bastion/Common.py b/lib/Bastion/Common.py index 87ad283..2f0b04d 100644 --- a/lib/Bastion/Common.py +++ b/lib/Bastion/Common.py @@ -269,10 +269,13 @@ def path(self): return pathlib.PurePosixPath(self[1]) def __str__(self): - if self.args: - return "[{}:{}?{}]".format(self.itype, str(self.path), self.args) + if self.path: + if self.args: + return "[{}:{}?{}]".format(self.itype, str(self.path), self.args) + else: + return "[{}:{}]".format(self.itype, str(self.path)) else: - return "[{}:{}]".format(self.itype, str(self.path)) + return "[{}:]".format(self.itype) def __repr__(self): return str(self) @@ -309,6 +312,8 @@ def parse(c): query = None return (itype, path, query) + else: + return (itype, None, None) raise ValueError diff --git a/lib/Bastion/Model.py b/lib/Bastion/Model.py index 707af6c..275e7f2 100644 --- a/lib/Bastion/Model.py +++ b/lib/Bastion/Model.py @@ -18,6 +18,10 @@ def __new__(cls, *args): if isinstance(arg, ARK): return arg + #-- The given object knows how to create an ARK for itself.... + if hasattr(arg, 'ARK'): + return arg.ARK + if isinstance(arg, CURIE): site = arg.space if site[0] == '@': @@ -28,12 +32,9 @@ def __new__(cls, *args): asset = None return ARK(site, zone, asset) - elif isinstance(arg, str): + if isinstance(arg, str): return ARK(CURIE(arg)) - elif isinstance(arg, isAsset): - return ARK( RDN(arg.site), RDN(arg.zone), RDN(arg.asset) ) - if len(args) == 2: #-- site, zone, / site = args[0] @@ -44,7 +45,7 @@ def __new__(cls, *args): site, zone, asset = args s = RDN(site) z = RDN(zone) - a = asset + a = asset.name if isinstance(isAsset) else str(asset) st = s if (s[0] == '@') else "@{}".format(s) return tuple.__new__(cls, [st, z, a]) @@ -70,10 +71,14 @@ def zolo(self): """ zolo ("zone location") is the logical path to this including its zone. """ - if self.asset: - return pathlib.PurePosixPath(self.zone) / self.asset + if self.zone: + if self.asset: + return pathlib.PurePosixPath(self.zone) / self.asset + else: + return pathlib.PurePosixPath(self.zone) else: - return pathlib.PurePosixPath(self.zone) + #-- There is no zone location for this ARK. + return None @property def CURIE(self): @@ -142,7 +147,7 @@ def sites(self): @property def ARKs(self): - raise NotImplementedError + raise NotImplementedError(".ARKs is subclass responsibility") def zones(self, site): """ @@ -284,7 +289,25 @@ def handling(protocol): Vault = isVault -class isAsset: +class isProtectedResource: + """ + The superclass of sites, zones, and assets. + Basically, any entity that can be banked (backed up) for preservation and protection. + """ + @property + def CURIE(self): + """ + My CURIE (Compact URI) form is [{site}:{zone}/{asset}] + """ + return self.ARK.CURIE + + @property + def ARK(self): + #-- must override in subclass + raise NotImplementedError(".ARK is subclass responsibility") + + +class isAsset(isProtectedResource): """ abstract Asset type, describes a local file in both the host file system and the logical (zone) space. """ @@ -307,13 +330,6 @@ def RDN(self): self._RDN = self.badge return self._RDN - @property - def CURIE(self): - """ - My CURIE (Compact URI) form is [{site}:{zone}/{asset}] - """ - return self.ARK.CURIE - @property def ARK(self): return ARK(RDN(self.zone.site), RDN(self.zone), self.name) @@ -341,7 +357,7 @@ def zolo(self): return self.ARK.zolo -class isZone: +class isZone(isProtectedResource): """ abstract resource zone. """ @@ -351,6 +367,10 @@ def __init__(self, site, name, root): self.name = name self.root = root if (root is None) else pathlib.Path(root) + @property + def ARK(self): + return ARK(RDN(self.site), RDN(self), None) + @property def halo(self): """ @@ -370,11 +390,23 @@ def __div__(self, name): return self.ASSET_CLS(self, name) -class isSite: +class isSite(isProtectedResource): """ asbtract site class; forward declaration of Site class(es). """ - pass + def __init__(self, name): + self.name = name + + @property + def ARK(self): + return ARK(RDN(self), None, None) + + @property + def RDN(self): + """ + I am the relatively distinguishing name for this object. + """ + return self.name class isClerk(isPerformer): @@ -455,7 +487,6 @@ class isPlanner(isPerformer): """ Abstract class for planning archival operations on assets. Planning is the process of determining what needs to be done to a given asset. - """ def __init__(self, app): self.app = app #-- I need a handle to the application object. diff --git a/lib/Bastion/Site.py b/lib/Bastion/Site.py index 3d80106..cc4cee8 100644 --- a/lib/Bastion/Site.py +++ b/lib/Bastion/Site.py @@ -44,10 +44,11 @@ def __new__(cls, site): def __init__(self, name): if isinstance(name, str): + isSite.__init__(self, name) + if name not in Site.SITES: Site.SITES[name] = self - self.name = name self.host = "127.0.0.1" self.logging = Thing() @@ -81,13 +82,6 @@ def zone(self, z): else: raise ValueError("zone expects an ARK or a name") - @property - def RDN(self): - """ - I am the relatively distinguishing name for this object. - """ - return self.name - def configured(self, conf): if not self._configured: if conf: