aboutsummaryrefslogtreecommitdiffstats
path: root/bsie
diff options
context:
space:
mode:
Diffstat (limited to 'bsie')
-rw-r--r--bsie/__init__.py4
-rw-r--r--bsie/apps/__init__.py44
-rw-r--r--bsie/apps/_loader.py47
-rw-r--r--bsie/apps/default_config.yaml19
-rw-r--r--bsie/apps/index.py49
-rw-r--r--bsie/apps/info.py48
-rw-r--r--bsie/extractor/__init__.py3
-rw-r--r--bsie/extractor/base.py36
-rw-r--r--bsie/extractor/builder.py5
-rw-r--r--bsie/extractor/generic/__init__.py3
-rw-r--r--bsie/extractor/generic/constant.py4
-rw-r--r--bsie/extractor/generic/path.py9
-rw-r--r--bsie/extractor/generic/stat.py8
-rw-r--r--bsie/extractor/image/__init__.py5
-rw-r--r--bsie/extractor/image/colors_spatial.py16
-rw-r--r--bsie/extractor/image/photometrics.py211
-rw-r--r--bsie/extractor/preview.py27
-rw-r--r--bsie/lib/__init__.py5
-rw-r--r--bsie/lib/bsie.py5
-rw-r--r--bsie/lib/builder.py5
-rw-r--r--bsie/lib/naming_policy.py13
-rw-r--r--bsie/lib/pipeline.py7
-rw-r--r--bsie/reader/__init__.py8
-rw-r--r--bsie/reader/base.py9
-rw-r--r--bsie/reader/builder.py5
-rw-r--r--bsie/reader/chain.py5
-rw-r--r--bsie/reader/exif.py44
-rw-r--r--bsie/reader/image/__init__.py5
-rw-r--r--bsie/reader/image/_pillow.py5
-rw-r--r--bsie/reader/image/_raw.py5
-rw-r--r--bsie/reader/path.py4
-rw-r--r--bsie/reader/preview/__init__.py5
-rw-r--r--bsie/reader/preview/_pg.py5
-rw-r--r--bsie/reader/preview/_pillow.py7
-rw-r--r--bsie/reader/preview/_rawpy.py5
-rw-r--r--bsie/reader/preview/utils.py5
-rw-r--r--bsie/reader/stat.py4
-rw-r--r--bsie/utils/__init__.py4
-rw-r--r--bsie/utils/bsfs.py4
-rw-r--r--bsie/utils/errors.py6
-rw-r--r--bsie/utils/filematcher/__init__.py5
-rw-r--r--bsie/utils/filematcher/matcher.py5
-rw-r--r--bsie/utils/filematcher/parser.py5
-rw-r--r--bsie/utils/loading.py9
-rw-r--r--bsie/utils/namespaces.py32
-rw-r--r--bsie/utils/node.py4
46 files changed, 448 insertions, 320 deletions
diff --git a/bsie/__init__.py b/bsie/__init__.py
index c253f39..f6f2ff2 100644
--- a/bsie/__init__.py
+++ b/bsie/__init__.py
@@ -1,8 +1,4 @@
"""The BSIE module extracts triples from files for insertion into a BSFS storage.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import collections
diff --git a/bsie/apps/__init__.py b/bsie/apps/__init__.py
index 1c3d0f9..2fe4795 100644
--- a/bsie/apps/__init__.py
+++ b/bsie/apps/__init__.py
@@ -1,12 +1,13 @@
-"""
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
+#!/usr/bin/env python3
+"""BSIE tools.
"""
# standard imports
+import argparse
import typing
+# bsie imports
+import bsie
+
# inner-module imports
from .index import main as index
from .info import main as info
@@ -15,6 +16,39 @@ from .info import main as info
__all__: typing.Sequence[str] = (
'index',
'info',
+ 'main',
)
+# config
+apps = {
+ 'index' : index,
+ 'info' : info,
+ }
+
+
+## code ##
+
+def main(argv=None):
+ """Black Star File System maintenance tools."""
+ parser = argparse.ArgumentParser(description=main.__doc__, prog='bsie')
+ # version
+ parser.add_argument('--version', action='version',
+ version='%(prog)s version {}.{}.{}'.format(*bsie.version_info)) # pylint: disable=C0209
+ # application selection
+ parser.add_argument('app', choices=apps.keys(),
+ help='Select the application to run.')
+ # dangling args
+ parser.add_argument('rest', nargs=argparse.REMAINDER)
+ # parse
+ args = parser.parse_args(argv)
+ # run application
+ apps[args.app](args.rest)
+
+
+## main ##
+
+if __name__ == '__main__':
+ import sys
+ main(sys.argv[1:])
+
## EOF ##
diff --git a/bsie/apps/_loader.py b/bsie/apps/_loader.py
new file mode 100644
index 0000000..6411f10
--- /dev/null
+++ b/bsie/apps/_loader.py
@@ -0,0 +1,47 @@
+
+# standard imports
+import typing
+
+# external imports
+import yaml
+
+# bsie imports
+from bsie.extractor import ExtractorBuilder
+from bsie.lib import PipelineBuilder
+from bsie.lib.pipeline import Pipeline
+from bsie.reader import ReaderBuilder
+
+# constants
+DEFAULT_CONFIG_FILE = 'default_config.yaml'
+
+# exports
+__all__: typing.Sequence[str] = (
+ 'DEFAULT_CONFIG_FILE',
+ 'load_pipeline',
+ )
+
+
+## code ##
+
+def load_pipeline(path: str) -> Pipeline:
+ """Load a pipeline according to a config at *path*."""
+ # load config file
+ with open(path, 'rt', encoding='utf-8') as ifile:
+ cfg = yaml.safe_load(ifile)
+
+ # reader builder
+ rbuild = ReaderBuilder(cfg['ReaderBuilder'])
+ # extractor builder
+ ebuild = ExtractorBuilder(cfg['ExtractorBuilder'])
+ # pipeline builder
+ pbuild = PipelineBuilder(
+ rbuild,
+ ebuild,
+ )
+ # build pipeline
+ pipeline = pbuild.build()
+
+ # return pipeline
+ return pipeline
+
+## EOF ##
diff --git a/bsie/apps/default_config.yaml b/bsie/apps/default_config.yaml
new file mode 100644
index 0000000..a59b0f3
--- /dev/null
+++ b/bsie/apps/default_config.yaml
@@ -0,0 +1,19 @@
+
+ReaderBuilder: {}
+
+ExtractorBuilder:
+
+ - bsie.extractor.preview.Preview:
+ max_sides: [50, 100, 200,400]
+
+ - bsie.extractor.generic.path.Path: {}
+
+ - bsie.extractor.generic.stat.Stat: {}
+
+ - bsie.extractor.image.colors_spatial.ColorsSpatial:
+ width: 32
+ height: 32
+ exp: 4
+
+ - bsie.extractor.image.photometrics.Exif: {}
+
diff --git a/bsie/apps/index.py b/bsie/apps/index.py
index 8798c49..d64e8c2 100644
--- a/bsie/apps/index.py
+++ b/bsie/apps/index.py
@@ -1,20 +1,16 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import argparse
import os
import typing
# bsie imports
-from bsie.extractor import ExtractorBuilder
-from bsie.lib import BSIE, PipelineBuilder, DefaultNamingPolicy
-from bsie.reader import ReaderBuilder
+from bsie.lib import BSIE, DefaultNamingPolicy
from bsie.utils import bsfs, errors, node as node_
+# inner-module imports
+from . import _loader
+
# exports
__all__: typing.Sequence[str] = (
'main',
@@ -26,6 +22,9 @@ __all__: typing.Sequence[str] = (
def main(argv):
"""Index files or directories into BSFS."""
parser = argparse.ArgumentParser(description=main.__doc__, prog='index')
+ parser.add_argument('--config', type=str,
+ default=os.path.join(os.path.dirname(__file__), _loader.DEFAULT_CONFIG_FILE),
+ help='Path to the config file.')
parser.add_argument('--host', type=bsfs.URI, default=bsfs.URI('http://example.com'),
help='')
parser.add_argument('--user', type=str, default='me',
@@ -44,39 +43,8 @@ def main(argv):
help='')
args = parser.parse_args(argv)
- # FIXME: Read reader/extractor configs from a config file
- # reader builder
- rbuild = ReaderBuilder()
- # extractor builder
- ebuild = ExtractorBuilder([
- {'bsie.extractor.preview.Preview': {
- 'max_sides': [50],
- }},
- {'bsie.extractor.generic.path.Path': {}},
- {'bsie.extractor.generic.stat.Stat': {}},
- {'bsie.extractor.generic.constant.Constant': dict(
- tuples=[('http://bsfs.ai/schema/Entity#author', 'Me, myself, and I')],
- schema='''
- bse:author rdfs:subClassOf bsfs:Predicate ;
- rdfs:domain bsfs:Entity ;
- rdfs:range xsd:string ;
- bsfs:unique "true"^^xsd:boolean .
- ''',
- )},
- {'bsie.extractor.image.colors_spatial.ColorsSpatial': {
- 'width': 2,
- 'height': 2,
- 'exp': 2,
- }},
- ])
- # pipeline builder
- pbuild = PipelineBuilder(
- rbuild,
- ebuild,
- )
-
# build pipeline
- pipeline = pbuild.build()
+ pipeline = _loader.load_pipeline(args.config)
# build the naming policy
naming_policy = DefaultNamingPolicy(
host=args.host,
@@ -127,7 +95,6 @@ def main(argv):
return store
-
## main ##
if __name__ == '__main__':
diff --git a/bsie/apps/info.py b/bsie/apps/info.py
index 750aedc..e27b70b 100644
--- a/bsie/apps/info.py
+++ b/bsie/apps/info.py
@@ -1,20 +1,16 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import argparse
+import os
import sys
import typing
# bsie imports
-from bsie.extractor import ExtractorBuilder
-from bsie.lib import PipelineBuilder
-from bsie.reader import ReaderBuilder
from bsie.utils import bsfs, errors
+# inner-module imports
+from . import _loader
+
# exports
__all__: typing.Sequence[str] = (
'main',
@@ -26,43 +22,15 @@ __all__: typing.Sequence[str] = (
def main(argv):
"""Show information from BSIE."""
parser = argparse.ArgumentParser(description=main.__doc__, prog='info')
+ parser.add_argument('--config', type=str,
+ default=os.path.join(os.path.dirname(__file__), _loader.DEFAULT_CONFIG_FILE),
+ help='Path to the config file.')
parser.add_argument('what', choices=('predicates', 'schema'),
help='Select what information to show.')
args = parser.parse_args(argv)
- # FIXME: Read reader/extractor configs from a config file
- # reader builder
- rbuild = ReaderBuilder()
- # extractor builder
- ebuild = ExtractorBuilder([
- {'bsie.extractor.preview.Preview': {
- 'max_sides': [50, 200],
- }},
- {'bsie.extractor.generic.path.Path': {}},
- {'bsie.extractor.generic.stat.Stat': {}},
- {'bsie.extractor.generic.constant.Constant': dict(
- tuples=[('http://bsfs.ai/schema/Entity#author', 'Me, myself, and I')],
- schema='''
- bse:author rdfs:subClassOf bsfs:Predicate ;
- rdfs:domain bsfs:Entity ;
- rdfs:range xsd:string ;
- bsfs:unique "true"^^xsd:boolean .
- ''',
- )},
- {'bsie.extractor.image.colors_spatial.ColorsSpatial': {
- 'width': 2,
- 'height': 2,
- 'exp': 2,
- }},
- ])
- # pipeline builder
- pbuild = PipelineBuilder(
- rbuild,
- ebuild,
- )
-
# build pipeline
- pipeline = pbuild.build()
+ pipeline = _loader.load_pipeline(args.config)
# show info
if args.what == 'predicates':
diff --git a/bsie/extractor/__init__.py b/bsie/extractor/__init__.py
index 5f385ee..36fa9ba 100644
--- a/bsie/extractor/__init__.py
+++ b/bsie/extractor/__init__.py
@@ -2,9 +2,6 @@
Each Extractor class is linked to the Reader class whose content it requires.
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing
diff --git a/bsie/extractor/base.py b/bsie/extractor/base.py
index 89183f9..f92d7cc 100644
--- a/bsie/extractor/base.py
+++ b/bsie/extractor/base.py
@@ -1,8 +1,4 @@
"""The Extractor classes transform content into triples.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import abc
@@ -28,26 +24,32 @@ SCHEMA_PREAMBLE = '''
prefix schema: <http://schema.org/>
# common bsfs prefixes
- prefix bsfs: <http://bsfs.ai/schema/>
- prefix bse: <http://bsfs.ai/schema/Entity#>
- prefix bsp: <http://bsfs.ai/schema/Preview#>
+ prefix bsfs: <https://schema.bsfs.io/core/>
+ prefix bsl: <https://schema.bsfs.io/core/Literal/>
+ prefix bsa: <https://schema.bsfs.io/core/Literal/Array/>
+ prefix bsd: <https://schema.bsfs.io/core/distance#>
+
+ prefix bsie: <https://schema.bsfs.io/ie/>
+ prefix bsn: <https://schema.bsfs.io/ie/Node/>
+ prefix bse: <https://schema.bsfs.io/ie/Node/Entity#>
+ prefix bsp: <https://schema.bsfs.io/ie/Node/Preview#>
# default definitions
- bsfs:Array rdfs:subClassOf bsfs:Literal .
- bsfs:Number rdfs:subClassOf bsfs:Literal .
- bsfs:Time rdfs:subClassOf bsfs:Literal .
- bsfs:Feature rdfs:subClassOf bsfs:Array ;
+ bsl:Array rdfs:subClassOf bsfs:Literal .
+ bsl:Number rdfs:subClassOf bsfs:Literal .
+ bsl:Time rdfs:subClassOf bsfs:Literal .
+ bsa:Feature rdfs:subClassOf bsl:Array ;
bsfs:dimension "1"^^xsd:integer ;
- bsfs:dtype bsfs:f16 ;
- bsfs:distance bsfs:euclidean .
+ bsfs:dtype <https://schema.bsfs.io/core/dtype#f16> ;
+ bsfs:distance bsd:euclidean .
# essential nodes
- bsfs:Entity rdfs:subClassOf bsfs:Node .
- bsfs:File rdfs:subClassOf bsfs:Entity .
+ bsn:Entity rdfs:subClassOf bsfs:Node .
# common definitions
xsd:string rdfs:subClassOf bsfs:Literal .
- xsd:integer rdfs:subClassOf bsfs:Number .
+ xsd:integer rdfs:subClassOf bsl:Number .
+ xsd:float rdfs:subClassOf bsl:Number .
'''
@@ -93,7 +95,7 @@ class Extractor(abc.ABC):
@property
def principals(self) -> typing.Iterator[bsfs.schema.Predicate]:
"""Return the principal predicates, i.e., relations from/to the extraction subject."""
- ent = self.schema.node(ns.bsfs.Entity)
+ ent = self.schema.node(ns.bsn.Entity)
return (
pred
for pred
diff --git a/bsie/extractor/builder.py b/bsie/extractor/builder.py
index 0fd3685..d691b0e 100644
--- a/bsie/extractor/builder.py
+++ b/bsie/extractor/builder.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import typing
diff --git a/bsie/extractor/generic/__init__.py b/bsie/extractor/generic/__init__.py
index 4783949..46a4bd6 100644
--- a/bsie/extractor/generic/__init__.py
+++ b/bsie/extractor/generic/__init__.py
@@ -3,9 +3,6 @@ files. Examples include file system information (file name and size, mime type,
etc.) and information that is independent of the actual file (constant triples,
host platform infos, current time, etc.).
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing
diff --git a/bsie/extractor/generic/constant.py b/bsie/extractor/generic/constant.py
index 938e20c..7acbe95 100644
--- a/bsie/extractor/generic/constant.py
+++ b/bsie/extractor/generic/constant.py
@@ -1,8 +1,4 @@
"""The Constant extractor produces pre-specified triples.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing
diff --git a/bsie/extractor/generic/path.py b/bsie/extractor/generic/path.py
index c984515..00c1121 100644
--- a/bsie/extractor/generic/path.py
+++ b/bsie/extractor/generic/path.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import os
import typing
@@ -31,11 +26,11 @@ class Path(base.Extractor):
def __init__(self):
super().__init__(bsfs.schema.from_string(base.SCHEMA_PREAMBLE + '''
bse:filename rdfs:subClassOf bsfs:Predicate ;
- rdfs:domain bsfs:File ;
+ rdfs:domain bsn:Entity ;
rdfs:range xsd:string ;
rdfs:label "File name"^^xsd:string ;
schema:description "Filename of entity in some filesystem."^^xsd:string ;
- bsfs:unique "false"^^xsd:boolean .
+ bsfs:unique "true"^^xsd:boolean .
'''))
self._callmap = {
self.schema.predicate(ns.bse.filename): self.__filename,
diff --git a/bsie/extractor/generic/stat.py b/bsie/extractor/generic/stat.py
index 9394456..92b51f3 100644
--- a/bsie/extractor/generic/stat.py
+++ b/bsie/extractor/generic/stat.py
@@ -1,8 +1,4 @@
"""Extract information from the file system, such as filesize.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import os
@@ -33,11 +29,11 @@ class Stat(base.Extractor):
def __init__(self):
super().__init__(bsfs.schema.from_string(base.SCHEMA_PREAMBLE + '''
bse:filesize rdfs:subClassOf bsfs:Predicate ;
- rdfs:domain bsfs:File ;
+ rdfs:domain bsn:Entity ;
rdfs:range xsd:integer ;
rdfs:label "File size"^^xsd:string ;
schema:description "File size of entity in some filesystem."^^xsd:string ;
- bsfs:unique "false"^^xsd:boolean .
+ bsfs:unique "true"^^xsd:boolean .
'''))
self._callmap = {
self.schema.predicate(ns.bse.filesize): self.__filesize,
diff --git a/bsie/extractor/image/__init__.py b/bsie/extractor/image/__init__.py
index 75b118d..f82424a 100644
--- a/bsie/extractor/image/__init__.py
+++ b/bsie/extractor/image/__init__.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import typing
diff --git a/bsie/extractor/image/colors_spatial.py b/bsie/extractor/image/colors_spatial.py
index 15fd281..e6661a9 100644
--- a/bsie/extractor/image/colors_spatial.py
+++ b/bsie/extractor/image/colors_spatial.py
@@ -1,8 +1,4 @@
"""Spatial color features.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing
@@ -18,8 +14,7 @@ from bsie.utils import bsfs, node, ns
from .. import base
# constants
-FEATURE_NAME = ns.bsf + 'ColorsSpatial'
-PREDICATE_NAME = ns.bse + 'colors_spatial'
+FEATURE_NAME = ns.bsf.ColorsSpatial()
# exports
__all__: typing.Sequence[str] = (
@@ -62,16 +57,17 @@ class ColorsSpatial(base.Extractor):
'exp': exp,
})
# determine symbol names
- instance_name = FEATURE_NAME[uuid]
- predicate_name = PREDICATE_NAME[uuid]
+ instance_name = getattr(FEATURE_NAME, uuid)
+ predicate_name = getattr(ns.bse, 'colors_spatial_' + uuid)
# get vector dimension
dimension = self.dimension(width, height, exp)
# initialize parent with the schema
super().__init__(bsfs.schema.from_string(base.SCHEMA_PREAMBLE + f'''
- <{FEATURE_NAME}> rdfs:subClassOf bsfs:Feature ;
+ <{FEATURE_NAME}> rdfs:subClassOf bsa:Feature ;
# annotations
rdfs:label "Spatially dominant colors"^^xsd:string ;
schema:description "Domiant colors of subregions in an image."^^xsd:string ;
+ bsfs:distance <https://schema.bsfs.io/core/distance#euclidean> ;
bsfs:dtype xsd:integer .
<{instance_name}> rdfs:subClassOf <{FEATURE_NAME}> ;
@@ -82,7 +78,7 @@ class ColorsSpatial(base.Extractor):
<{FEATURE_NAME}/args#exp> "{exp}"^^xsd:float .
<{predicate_name}> rdfs:subClassOf bsfs:Predicate ;
- rdfs:domain bsfs:File ;
+ rdfs:domain bsn:Entity ;
rdfs:range <{instance_name}> ;
bsfs:unique "true"^^xsd:boolean .
diff --git a/bsie/extractor/image/photometrics.py b/bsie/extractor/image/photometrics.py
new file mode 100644
index 0000000..42eb3c8
--- /dev/null
+++ b/bsie/extractor/image/photometrics.py
@@ -0,0 +1,211 @@
+
+# standard imports
+from fractions import Fraction
+import typing
+
+# bsie imports
+from bsie.utils import bsfs, node, ns
+
+# inner-module imports
+from .. import base
+
+# exports
+__all__: typing.Sequence[str] = (
+ 'Exif',
+ )
+
+
+## code ##
+
+def _gps_to_dec(coords: typing.Tuple[float, float, float]) -> float:
+ """Convert GPS coordinates from exif to float."""
+ # unpack args
+ deg, min, sec = coords # pylint: disable=redefined-builtin # min
+ # convert to float
+ deg = float(Fraction(deg))
+ min = float(Fraction(min))
+ sec = float(Fraction(sec))
+
+ if float(sec) > 0:
+ # format is deg+min+sec
+ return (float(deg) * 3600 + float(min) * 60 + float(sec)) / 3600
+ # format is deg+min
+ return float(deg) + float(min) / 60
+
+
+class Exif(base.Extractor):
+ """Extract information from EXIF/IPTC tags of an image file."""
+
+ CONTENT_READER = 'bsie.reader.exif.Exif'
+
+ def __init__(self):
+ super().__init__(bsfs.schema.from_string(base.SCHEMA_PREAMBLE + '''
+ #bse:t_capture rdfs:subClassOf bsfs:Predicate ;
+ # rdfs:domain bsn:Entity ;
+ # rdfs:range xsd:float ;
+ # bsfs:unique "true"^^xsd:boolean .
+ bse:exposure rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:float ;
+ bsfs:unique "true"^^xsd:boolean .
+ bse:aperture rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:float ;
+ bsfs:unique "true"^^xsd:boolean .
+ bse:iso rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:integer ;
+ bsfs:unique "true"^^xsd:boolean .
+ bse:focal_length rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:float ;
+ bsfs:unique "true"^^xsd:boolean .
+ bse:width rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:integer ;
+ bsfs:unique "true"^^xsd:boolean .
+ bse:height rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:integer ;
+ bsfs:unique "true"^^xsd:boolean .
+ bse:orientation rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:integer ;
+ bsfs:unique "true"^^xsd:boolean .
+ bse:orientation_label rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:string ;
+ bsfs:unique "true"^^xsd:boolean .
+ bse:altitude rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:float ;
+ bsfs:unique "true"^^xsd:boolean .
+ bse:latitude rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:float ;
+ bsfs:unique "true"^^xsd:boolean .
+ bse:longitude rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range xsd:float ;
+ bsfs:unique "true"^^xsd:boolean .
+ '''))
+ # initialize mapping from predicate to callback
+ self._callmap = {
+ #self.schema.predicate(ns.bse.t_capture): self._date,
+ self.schema.predicate(ns.bse.exposure): self._exposure,
+ self.schema.predicate(ns.bse.aperture): self._aperture,
+ self.schema.predicate(ns.bse.iso): self._iso,
+ self.schema.predicate(ns.bse.focal_length): self._focal_length,
+ self.schema.predicate(ns.bse.width): self._width,
+ self.schema.predicate(ns.bse.height): self._height,
+ self.schema.predicate(ns.bse.orientation): self._orientation,
+ self.schema.predicate(ns.bse.orientation_label): self._orientation_label,
+ self.schema.predicate(ns.bse.altitude): self._altitude,
+ self.schema.predicate(ns.bse.latitude): self._latitude,
+ self.schema.predicate(ns.bse.longitude): self._longitude,
+ }
+
+ def extract(
+ self,
+ subject: node.Node,
+ content: dict,
+ principals: typing.Iterable[bsfs.schema.Predicate],
+ ) -> typing.Iterator[typing.Tuple[node.Node, bsfs.schema.Predicate, typing.Any]]:
+ for pred in principals:
+ # find callback
+ clbk = self._callmap.get(pred)
+ if clbk is None:
+ continue
+ # get value
+ value = clbk(content)
+ if value is None:
+ continue
+ # produce triple
+ yield subject, pred, value
+
+ #def _date(self, content: dict): # FIXME: Return type annotation
+ # date_keys = (
+ # 'Exif.Photo.DateTimeOriginal',
+ # 'Exif.Photo.DateTimeDigitized',
+ # 'Exif.Image.DateTime',
+ # )
+ # for key in date_keys:
+ # if key in content:
+ # dt = content[key].value
+ # if dt.tzinfo is None:
+ # dt = dt.replace(tzinfo=ttime.NoTimeZone)
+ # return dt
+ # return None
+
+
+ ## photometrics
+
+ def _exposure(self, content: dict) -> typing.Optional[float]:
+ if 'Exif.Photo.ExposureTime' in content:
+ return 1.0 / float(Fraction(content['Exif.Photo.ExposureTime']))
+ return None
+
+ def _aperture(self, content: dict) -> typing.Optional[float]:
+ if 'Exif.Photo.FNumber' in content:
+ return float(Fraction(content['Exif.Photo.FNumber']))
+ return None
+
+ def _iso(self, content: dict) -> typing.Optional[int]:
+ if 'Exif.Photo.ISOSpeedRatings' in content:
+ return int(content['Exif.Photo.ISOSpeedRatings'])
+ return None
+
+ def _focal_length(self, content: dict) -> typing.Optional[float]:
+ if 'Exif.Photo.FocalLength' in content:
+ return float(Fraction(content['Exif.Photo.FocalLength']))
+ return None
+
+
+ ## image dimensions
+
+ def _width(self, content: dict) -> typing.Optional[int]:
+ # FIXME: consider orientation!
+ if 'Exif.Photo.PixelXDimension' in content:
+ return int(content['Exif.Photo.PixelXDimension'])
+ return None
+
+ def _height(self, content: dict) -> typing.Optional[int]:
+ # FIXME: consider orientation!
+ if 'Exif.Photo.PixelYDimension' in content:
+ return int(content['Exif.Photo.PixelYDimension'])
+ return None
+
+ def _orientation(self, content: dict) -> typing.Optional[int]:
+ if 'Exif.Image.Orientation' in content:
+ return int(content['Exif.Image.Orientation'])
+ return None
+
+ def _orientation_label(self, content: dict) -> typing.Optional[str]:
+ width = self._width(content)
+ height = self._height(content)
+ ori = self._orientation(content)
+ if width is not None and height is not None and ori is not None:
+ if ori <= 4:
+ return 'landscape' if width >= height else 'portrait'
+ return 'portrait' if width >= height else 'landscape'
+ return None
+
+
+ ## location
+
+ def _altitude(self, content: dict) -> typing.Optional[float]:
+ if 'Exif.GPSInfo.GPSAltitude' in content:
+ return float(Fraction(content['Exif.GPSInfo.GPSAltitude']))
+ return None
+
+ def _latitude(self, content: dict) -> typing.Optional[float]:
+ if 'Exif.GPSInfo.GPSLatitude' in content:
+ return _gps_to_dec(content['Exif.GPSInfo.GPSLatitude'].split())
+ return None
+
+ def _longitude(self, content: dict) -> typing.Optional[float]:
+ if 'Exif.GPSInfo.GPSLongitude' in content:
+ return _gps_to_dec(content['Exif.GPSInfo.GPSLongitude'].split())
+ return None
+
+## EOF ##
diff --git a/bsie/extractor/preview.py b/bsie/extractor/preview.py
index 1531d62..145a01a 100644
--- a/bsie/extractor/preview.py
+++ b/bsie/extractor/preview.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# imports
import io
import typing
@@ -33,28 +28,30 @@ class Preview(base.Extractor):
def __init__(self, max_sides: typing.Iterable[int]):
super().__init__(bsfs.schema.from_string(base.SCHEMA_PREAMBLE + '''
- bsfs:Preview rdfs:subClassOf bsfs:Node .
- bsfs:BinaryBlob rdfs:subClassOf bsfs:Literal .
- bsfs:JPEG rdfs:subClassOf bsfs:BinaryBlob .
+
+
+ bsn:Preview rdfs:subClassOf bsfs:Node .
+ bsl:BinaryBlob rdfs:subClassOf bsfs:Literal .
+ <https://schema.bsfs.io/ie/Literal/BinaryBlob/JPEG> rdfs:subClassOf bsl:BinaryBlob .
bse:preview rdfs:subClassOf bsfs:Predicate ;
- rdfs:domain bsfs:File ;
- rdfs:range bsfs:Preview ;
+ rdfs:domain bsn:Entity ;
+ rdfs:range bsn:Preview ;
bsfs:unique "false"^^xsd:boolean .
bsp:width rdfs:subClassOf bsfs:Predicate ;
- rdfs:domain bsfs:Preview ;
+ rdfs:domain bsn:Preview ;
rdfs:range xsd:integer ;
bsfs:unique "true"^^xsd:boolean .
bsp:height rdfs:subClassOf bsfs:Predicate ;
- rdfs:domain bsfs:Preview ;
+ rdfs:domain bsn:Preview ;
rdfs:range xsd:integer ;
bsfs:unique "true"^^xsd:boolean .
bsp:asset rdfs:subClassOf bsfs:Predicate ;
- rdfs:domain bsfs:Preview ;
- rdfs:range bsfs:JPEG ;
+ rdfs:domain bsn:Preview ;
+ rdfs:range <https://schema.bsfs.io/ie/Literal/BinaryBlob/JPEG> ;
bsfs:unique "true"^^xsd:boolean .
'''))
@@ -85,7 +82,7 @@ class Preview(base.Extractor):
buffer = io.BytesIO()
img.save(buffer, format='jpeg')
# create a preview node
- preview = node.Node(ns.bsfs.Preview,
+ preview = node.Node(ns.bsn.Preview,
ucid=bsfs.uuid.UCID.from_bytes(buffer.getvalue()),
size=max_side,
source=subject,
diff --git a/bsie/lib/__init__.py b/bsie/lib/__init__.py
index 48379de..f44fb74 100644
--- a/bsie/lib/__init__.py
+++ b/bsie/lib/__init__.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import typing
diff --git a/bsie/lib/bsie.py b/bsie/lib/bsie.py
index a572525..b02e707 100644
--- a/bsie/lib/bsie.py
+++ b/bsie/lib/bsie.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import typing
diff --git a/bsie/lib/builder.py b/bsie/lib/builder.py
index 39da441..3a15311 100644
--- a/bsie/lib/builder.py
+++ b/bsie/lib/builder.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import logging
import typing
diff --git a/bsie/lib/naming_policy.py b/bsie/lib/naming_policy.py
index 131a70b..9b9a45d 100644
--- a/bsie/lib/naming_policy.py
+++ b/bsie/lib/naming_policy.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import abc
import os
@@ -85,9 +80,9 @@ class DefaultNamingPolicy(NamingPolicy):
def handle_node(self, node: Node) -> Node:
if node.uri is not None:
return node
- if node.node_type == ns.bsfs.File:
+ if node.node_type == ns.bsn.Entity :
return self.name_file(node)
- if node.node_type == ns.bsfs.Preview:
+ if node.node_type == ns.bsn.Preview:
return self.name_preview(node)
raise errors.ProgrammingError('no naming policy available for {node.node_type}')
@@ -97,7 +92,7 @@ class DefaultNamingPolicy(NamingPolicy):
fragment = node.hints['ucid']
else: # random name
fragment = self._uuid()
- node.uri = (self._prefix + 'file')[fragment]
+ node.uri = getattr(self._prefix.file(), fragment)
return node
def name_preview(self, node: Node) -> Node:
@@ -114,7 +109,7 @@ class DefaultNamingPolicy(NamingPolicy):
fragment = self._uuid()
if 'size' in node.hints: # append size
fragment += '_s' + str(node.hints['size'])
- node.uri = (self._prefix + 'preview')[fragment]
+ node.uri = getattr(self._prefix.preview(), fragment)
return node
## EOF ##
diff --git a/bsie/lib/pipeline.py b/bsie/lib/pipeline.py
index 0bc5109..30fd6fd 100644
--- a/bsie/lib/pipeline.py
+++ b/bsie/lib/pipeline.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
from collections import defaultdict
import logging
@@ -109,7 +104,7 @@ class Pipeline():
rdr2ext[rdr].add(ext)
# create subject for file
- subject = node.Node(ns.bsfs.File,
+ subject = node.Node(ns.bsn.Entity,
ucid=bsfs.uuid.UCID.from_path(path),
)
diff --git a/bsie/reader/__init__.py b/bsie/reader/__init__.py
index 4163d1c..a1c38a9 100644
--- a/bsie/reader/__init__.py
+++ b/bsie/reader/__init__.py
@@ -1,8 +1,8 @@
"""The Reader classes return high-level content structures from files.
The Reader fulfills two purposes:
- First, it brokers between multiple libraries and file formats.
- Second, it separates multiple aspects of a file into distinct content types.
+First, it brokers between multiple libraries and file formats.
+Second, it separates multiple aspects of a file into distinct content types.
Often, different libraries focus on reading different types of content from a
file. E.g. one would use different modules to read file system infos than to
@@ -11,9 +11,6 @@ type. Each distinct type can be implemented in a file or submodule that
provides a Reader implementation. Through utilization of submodules, different
file formats can be supported.
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing
@@ -29,4 +26,3 @@ __all__: typing.Sequence[str] = (
)
## EOF ##
-## EOF ##
diff --git a/bsie/reader/base.py b/bsie/reader/base.py
index 099a327..a775701 100644
--- a/bsie/reader/base.py
+++ b/bsie/reader/base.py
@@ -1,13 +1,4 @@
-"""The Reader classes return high-level content structures from files.
-The Reader fulfills two purposes:
- First, it brokers between multiple libraries and file formats.
- Second, it separates multiple aspects of a file into distinct content types.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import abc
import typing
diff --git a/bsie/reader/builder.py b/bsie/reader/builder.py
index 8699e75..d32700b 100644
--- a/bsie/reader/builder.py
+++ b/bsie/reader/builder.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import typing
diff --git a/bsie/reader/chain.py b/bsie/reader/chain.py
index 1dbc52b..79b44b4 100644
--- a/bsie/reader/chain.py
+++ b/bsie/reader/chain.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import logging
import typing
diff --git a/bsie/reader/exif.py b/bsie/reader/exif.py
new file mode 100644
index 0000000..2d0428b
--- /dev/null
+++ b/bsie/reader/exif.py
@@ -0,0 +1,44 @@
+
+# standard imports
+import typing
+
+# external imports
+import pyexiv2
+
+# bsie imports
+from bsie.utils import errors, filematcher
+
+# inner-module imports
+from . import base
+
+# constants
+MATCH_RULE = 'mime=image/jpeg'
+
+# exports
+__all__: typing.Sequence[str] = (
+ 'Exif',
+ )
+
+
+## code ##
+
+class Exif(base.Reader):
+ """Use pyexiv2 to read exif metadata from image files."""
+
+ def __init__(self):
+ self._match = filematcher.parse(MATCH_RULE)
+
+ def __call__(self, path: str) -> dict:
+ # perform quick checks first
+ if not self._match(path):
+ raise errors.UnsupportedFileFormatError(path)
+
+ try:
+ # open the file
+ img = pyexiv2.Image(path)
+ # read metadata
+ return img.read_exif()
+ except (TypeError, OSError, RuntimeError) as err:
+ raise errors.ReaderError(path) from err
+
+## EOF ##
diff --git a/bsie/reader/image/__init__.py b/bsie/reader/image/__init__.py
index c5d2a2a..89642f2 100644
--- a/bsie/reader/image/__init__.py
+++ b/bsie/reader/image/__init__.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import typing
diff --git a/bsie/reader/image/_pillow.py b/bsie/reader/image/_pillow.py
index 5b2bdf2..0611d3c 100644
--- a/bsie/reader/image/_pillow.py
+++ b/bsie/reader/image/_pillow.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import typing
diff --git a/bsie/reader/image/_raw.py b/bsie/reader/image/_raw.py
index 257fdb3..e5745aa 100644
--- a/bsie/reader/image/_raw.py
+++ b/bsie/reader/image/_raw.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import typing
diff --git a/bsie/reader/path.py b/bsie/reader/path.py
index 1ca05a0..45eb127 100644
--- a/bsie/reader/path.py
+++ b/bsie/reader/path.py
@@ -1,8 +1,4 @@
"""The Path reader produces a file path.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing
diff --git a/bsie/reader/preview/__init__.py b/bsie/reader/preview/__init__.py
index 3e69a4a..791a133 100644
--- a/bsie/reader/preview/__init__.py
+++ b/bsie/reader/preview/__init__.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# imports
import typing
diff --git a/bsie/reader/preview/_pg.py b/bsie/reader/preview/_pg.py
index 097c513..401b33d 100644
--- a/bsie/reader/preview/_pg.py
+++ b/bsie/reader/preview/_pg.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
from functools import partial
import contextlib
diff --git a/bsie/reader/preview/_pillow.py b/bsie/reader/preview/_pillow.py
index 174d509..2b797c6 100644
--- a/bsie/reader/preview/_pillow.py
+++ b/bsie/reader/preview/_pillow.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
from functools import partial
import typing
@@ -38,7 +33,7 @@ class PillowPreviewReader(base.Reader):
except PIL.UnidentifiedImageError as err:
# failed to open, skip file
raise errors.UnsupportedFileFormatError(path) from err
- except IOError as err:
+ except OSError as err:
raise errors.ReaderError(path) from err
# EOF ##
diff --git a/bsie/reader/preview/_rawpy.py b/bsie/reader/preview/_rawpy.py
index 2c20a48..16e8675 100644
--- a/bsie/reader/preview/_rawpy.py
+++ b/bsie/reader/preview/_rawpy.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
from functools import partial
import typing
diff --git a/bsie/reader/preview/utils.py b/bsie/reader/preview/utils.py
index 2ef1562..82ecc31 100644
--- a/bsie/reader/preview/utils.py
+++ b/bsie/reader/preview/utils.py
@@ -1,9 +1,4 @@
-"""
-Part of the tagit module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import typing
diff --git a/bsie/reader/stat.py b/bsie/reader/stat.py
index 706dc47..f42e7fb 100644
--- a/bsie/reader/stat.py
+++ b/bsie/reader/stat.py
@@ -1,8 +1,4 @@
"""The Stat reader produces filesystem stat information.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import os
diff --git a/bsie/utils/__init__.py b/bsie/utils/__init__.py
index 9cb60ed..18c8db7 100644
--- a/bsie/utils/__init__.py
+++ b/bsie/utils/__init__.py
@@ -1,8 +1,4 @@
"""Common tools and definitions.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing
diff --git a/bsie/utils/bsfs.py b/bsie/utils/bsfs.py
index ef5db31..fc045cc 100644
--- a/bsie/utils/bsfs.py
+++ b/bsie/utils/bsfs.py
@@ -1,8 +1,4 @@
"""BSFS bridge, provides BSFS bindings for BSIE.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing
diff --git a/bsie/utils/errors.py b/bsie/utils/errors.py
index 8133cd4..7c7e6ed 100644
--- a/bsie/utils/errors.py
+++ b/bsie/utils/errors.py
@@ -1,8 +1,4 @@
"""Common BSIE exceptions.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing
@@ -42,7 +38,7 @@ class UnreachableError(ProgrammingError):
class ParserError(_BSIEError):
"""Failed to parse due to invalid syntax or structures."""
-class UnsupportedFileFormatError(ReaderError):
+class UnsupportedFileFormatError(_BSIEError):
"""Failed to read a file format."""
## EOF ##
diff --git a/bsie/utils/filematcher/__init__.py b/bsie/utils/filematcher/__init__.py
index 1e23e4e..908de78 100644
--- a/bsie/utils/filematcher/__init__.py
+++ b/bsie/utils/filematcher/__init__.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import typing
diff --git a/bsie/utils/filematcher/matcher.py b/bsie/utils/filematcher/matcher.py
index a279a4b..1fa308e 100644
--- a/bsie/utils/filematcher/matcher.py
+++ b/bsie/utils/filematcher/matcher.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2021
-"""
# standard imports
from collections.abc import Callable, Collection, Hashable
import abc
diff --git a/bsie/utils/filematcher/parser.py b/bsie/utils/filematcher/parser.py
index 2f82875..dc28a0d 100644
--- a/bsie/utils/filematcher/parser.py
+++ b/bsie/utils/filematcher/parser.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2021
-"""
# standard imports
import typing
diff --git a/bsie/utils/loading.py b/bsie/utils/loading.py
index eb05c35..58202d1 100644
--- a/bsie/utils/loading.py
+++ b/bsie/utils/loading.py
@@ -1,9 +1,4 @@
-"""
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
-"""
# standard imports
import importlib
import typing
@@ -27,14 +22,14 @@ def safe_load(module_name: str, class_name: str):
module = importlib.import_module(module_name)
except Exception as err:
# cannot import module
- raise errors.LoaderError(f'cannot load module {module_name}') from err
+ raise errors.LoaderError(f'cannot load module {module_name} ({err})') from err
try:
# get the class from the module
cls = getattr(module, class_name)
except Exception as err:
# cannot find the class
- raise errors.LoaderError(f'cannot load class {class_name} from module {module_name}') from err
+ raise errors.LoaderError(f'cannot load class {class_name} from module {module_name} ({err})') from err
return cls
diff --git a/bsie/utils/namespaces.py b/bsie/utils/namespaces.py
index 0af8ece..4a66048 100644
--- a/bsie/utils/namespaces.py
+++ b/bsie/utils/namespaces.py
@@ -1,8 +1,4 @@
"""Default namespaces used throughout BSIE.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing
@@ -10,19 +6,31 @@ import typing
# inner-module imports
from . import bsfs as _bsfs
-# constants
-bse = _bsfs.Namespace('http://bsfs.ai/schema/Entity')
-bsf = _bsfs.Namespace('http://ie.bsfs.ai/schema/Feature')
-bsfs = _bsfs.Namespace('http://bsfs.ai/schema', fsep='/')
-bsm = _bsfs.Namespace('http://bsfs.ai/schema/Meta')
-bsp = _bsfs.Namespace('http://bsfs.ai/schema/Preview')
-xsd = _bsfs.Namespace('http://www.w3.org/2001/XMLSchema')
+# generic namespaces
+xsd = _bsfs.Namespace('http://www.w3.org/2001/XMLSchema')()
+
+# core bsfs/bsie namespaces
+bsfs = _bsfs.Namespace('https://schema.bsfs.io/core')
+bsie = _bsfs.Namespace('https://schema.bsfs.io/ie')
+
+# auxiliary namespaces
+bsd = bsie.distance()
+bse = bsie.Node.Entity()
+bsf = bsie.Literal.Array.Feature
+bsl = bsfs.Literal
+bsn = bsie.Node
+bsp = bsie.Node.Preview()
# export
__all__: typing.Sequence[str] = (
+ 'bsd',
'bse',
+ 'bsf',
'bsfs',
- 'bsm',
+ 'bsie',
+ 'bsl',
+ 'bsl',
+ 'bsn',
'bsp',
'xsd',
)
diff --git a/bsie/utils/node.py b/bsie/utils/node.py
index aa62c06..fa34b2e 100644
--- a/bsie/utils/node.py
+++ b/bsie/utils/node.py
@@ -1,8 +1,4 @@
"""Lighweight Node to bridge to BSFS.
-
-Part of the bsie module.
-A copy of the license is provided with the project.
-Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing