aboutsummaryrefslogtreecommitdiffstats
path: root/bsfs/namespace/namespace.py
diff options
context:
space:
mode:
authorMatthias Baumgartner <dev@igsor.net>2023-03-05 19:25:29 +0100
committerMatthias Baumgartner <dev@igsor.net>2023-03-05 19:25:29 +0100
commit48b6081d0092e9c5a1b0ad79bdde2e51649bf61a (patch)
tree634198c34aae3c0306ce30ac7452abd7b53a14e8 /bsfs/namespace/namespace.py
parent91437ba89d35bf482f3d9671bb99ef2fc69f5985 (diff)
parente4845c627e97a6d125bf33d9e7a4a8d373d7fc4a (diff)
downloadbsfs-48b6081d0092e9c5a1b0ad79bdde2e51649bf61a.tar.gz
bsfs-48b6081d0092e9c5a1b0ad79bdde2e51649bf61a.tar.bz2
bsfs-48b6081d0092e9c5a1b0ad79bdde2e51649bf61a.zip
Merge branch 'develop'v0.23.03
Diffstat (limited to 'bsfs/namespace/namespace.py')
-rw-r--r--bsfs/namespace/namespace.py102
1 files changed, 26 insertions, 76 deletions
diff --git a/bsfs/namespace/namespace.py b/bsfs/namespace/namespace.py
index f652dcd..b388f53 100644
--- a/bsfs/namespace/namespace.py
+++ b/bsfs/namespace/namespace.py
@@ -1,104 +1,54 @@
-"""
-Part of the BlackStar filesystem (bsfs) module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# imports
import typing
# bsfs imports
-from bsfs.utils import URI, typename
+from bsfs.utils import URI
# exports
__all__: typing.Sequence[str] = (
- 'ClosedNamespace',
'Namespace',
+ 'FinalNamespace',
)
## code ##
-class Namespace():
- """A namespace consists of a common prefix that is used in a set of URIs.
- Note that the prefix must include the separator between
- path and fragment (typically a '#' or a '/').
- """
-
- # namespace prefix.
- prefix: URI
-
- # fragment separator.
- fsep: str
-
- # path separator.
- psep: str
-
- def __init__(self, prefix: URI, fsep: str = '#', psep: str = '/'):
- # ensure prefix type
- prefix = URI(prefix)
- # truncate fragment separator
- while prefix.endswith(fsep):
- prefix = URI(prefix[:-1])
- # truncate path separator
- while prefix.endswith(psep):
- prefix = URI(prefix[:-1])
- # store members
- self.prefix = prefix
- self.fsep = fsep
- self.psep = psep
-
- def __eq__(self, other: typing.Any) -> bool:
- return isinstance(other, type(self)) \
- and self.prefix == other.prefix \
- and self.fsep == other.fsep \
- and self.psep == other.psep
+class Namespace(URI):
+ """The Namespace allows you to incrementally append path segments to an URI.
- def __hash__(self) -> int:
- return hash((type(self), self.prefix, self.fsep, self.psep))
+ Segments are separated by `Namespace.sep` ('/').
+ The `__call__` method signals that the URI is complete until the query part.
- def __str__(self) -> str:
- return f'{typename(self)}({self.prefix})'
-
- def __repr__(self) -> str:
- return f'{typename(self)}({self.prefix}, {self.fsep}, {self.psep})'
-
- def __getattr__(self, fragment: str) -> URI:
- """Return prefix + fragment."""
- return URI(self.prefix + self.fsep + fragment)
-
- def __getitem__(self, fragment: str) -> URI:
- """Alias for getattr(self, fragment)."""
- return self.__getattr__(fragment)
+ """
- def __add__(self, value: typing.Any) -> 'Namespace':
- """Concatenate another namespace to this one."""
- if not isinstance(value, str):
- return NotImplemented
- return Namespace(self.prefix + self.psep + value, self.fsep, self.psep)
+ # path separator
+ sep: str = '/'
+ def __getattr__(self, query: str) -> 'Namespace':
+ """Append the *query* to the current value and return as Namespace."""
+ return Namespace(self + self.sep + query)
-class ClosedNamespace(Namespace):
- """Namespace that covers a restricted set of URIs."""
+ def __call__(self, sep: str = '#') -> 'FinalNamespace':
+ """Finalize the namespace."""
+ return FinalNamespace(self, sep)
- # set of permissible fragments.
- fragments: typing.Set[str]
- def __init__(self, prefix: URI, *args: str, fsep: str = '#', psep: str = '/'):
- super().__init__(prefix, fsep, psep)
- self.fragments = set(args)
+# FIXME: Integrate FinalNamespace into Namespace? Do we need to have both?
+class FinalNamespace(URI):
+ """The FinalNamespace allows you to append a fragment to an URI."""
- def __eq__(self, other: typing.Any) -> bool:
- return super().__eq__(other) and self.fragments == other.fragments
+ # fragment separator
+ sep: str
- def __hash__(self) -> int:
- return hash((type(self), self.prefix, tuple(sorted(self.fragments))))
+ def __new__(cls, value: str, sep: str = '#'):
+ inst = URI.__new__(cls, value)
+ inst.sep = sep
+ return inst
def __getattr__(self, fragment: str) -> URI:
- """Return prefix + fragment or raise a KeyError if the fragment is not part of this namespace."""
- if fragment not in self.fragments:
- raise KeyError(f'{fragment} is not a valid fragment of namespace {self.prefix}')
- return super().__getattr__(fragment)
+ """Append the *fragment* to the current value and return as URI."""
+ return URI(self + self.sep + fragment)
## EOF ##