aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Baumgartner <dev@igsor.net>2023-03-02 08:58:29 +0100
committerMatthias Baumgartner <dev@igsor.net>2023-03-02 08:58:29 +0100
commitba6329bbe14c832d42773dee2fe30bd7669ca255 (patch)
tree4cd2771d95adaba0663fd7879b1666ebd3ef3cb9
parent70d77819a84c73292825b81f952e162bb30753d7 (diff)
downloadbsie-ba6329bbe14c832d42773dee2fe30bd7669ca255.tar.gz
bsie-ba6329bbe14c832d42773dee2fe30bd7669ca255.tar.bz2
bsie-ba6329bbe14c832d42773dee2fe30bd7669ca255.zip
various minor fixes
-rw-r--r--.pylintrc17
-rw-r--r--bsie/apps/__init__.py2
-rw-r--r--bsie/apps/_loader.py4
-rw-r--r--bsie/extractor/image/photometrics.py37
-rw-r--r--doc/source/installation.rst2
-rw-r--r--test/apps/test_main.py57
-rw-r--r--test/extractor/image/test_photometrics.py10
-rw-r--r--test/reader/preview/test_pg.py1
8 files changed, 105 insertions, 25 deletions
diff --git a/.pylintrc b/.pylintrc
index 1b34854..576e81a 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -145,6 +145,21 @@ logging-format-style=old
+[MESSAGES CONTROL]
+
+# disable similarities check
+disable=raw-checker-failed,
+ bad-inline-option,
+ locally-disabled,
+ file-ignored,
+ suppressed-message,
+ useless-suppression,
+ deprecated-pragma,
+ use-symbolic-message-instead,
+ duplicate-code
+
+
+
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
@@ -188,6 +203,4 @@ ignore-none=no
callbacks=clbk,callback
-
-
# Disable: R1735 (use-dict-literal)
diff --git a/bsie/apps/__init__.py b/bsie/apps/__init__.py
index cec8f84..2fe4795 100644
--- a/bsie/apps/__init__.py
+++ b/bsie/apps/__init__.py
@@ -33,7 +33,7 @@ def main(argv=None):
parser = argparse.ArgumentParser(description=main.__doc__, prog='bsie')
# version
parser.add_argument('--version', action='version',
- version='%(prog)s version {}.{}.{}'.format(*bsie.version_info))
+ 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.')
diff --git a/bsie/apps/_loader.py b/bsie/apps/_loader.py
index 36dd8a6..6411f10 100644
--- a/bsie/apps/_loader.py
+++ b/bsie/apps/_loader.py
@@ -16,8 +16,8 @@ DEFAULT_CONFIG_FILE = 'default_config.yaml'
# exports
__all__: typing.Sequence[str] = (
- 'load',
'DEFAULT_CONFIG_FILE',
+ 'load_pipeline',
)
@@ -26,7 +26,7 @@ __all__: typing.Sequence[str] = (
def load_pipeline(path: str) -> Pipeline:
"""Load a pipeline according to a config at *path*."""
# load config file
- with open(path, 'rt') as ifile:
+ with open(path, 'rt', encoding='utf-8') as ifile:
cfg = yaml.safe_load(ifile)
# reader builder
diff --git a/bsie/extractor/image/photometrics.py b/bsie/extractor/image/photometrics.py
index 525f207..c5254ab 100644
--- a/bsie/extractor/image/photometrics.py
+++ b/bsie/extractor/image/photometrics.py
@@ -20,7 +20,7 @@ __all__: typing.Sequence[str] = (
def _gps_to_dec(coords: typing.Tuple[float, float, float]) -> float:
"""Convert GPS coordinates from exif to float."""
# unpack args
- deg, min, sec = coords
+ deg, min, sec = coords # pylint: disable=redefined-builtin # min
# convert to float
deg = float(Fraction(deg))
min = float(Fraction(min))
@@ -29,9 +29,8 @@ def _gps_to_dec(coords: typing.Tuple[float, float, float]) -> float:
if float(sec) > 0:
# format is deg+min+sec
return (float(deg) * 3600 + float(min) * 60 + float(sec)) / 3600
- else:
- # format is deg+min
- return float(deg) + float(min) / 60
+ # format is deg+min
+ return float(deg) + float(min) / 60
class Exif(base.Extractor):
@@ -124,20 +123,19 @@ class Exif(base.Extractor):
# produce triple
yield subject, pred, value
- def _date(self, content: dict): # FIXME: Return type annotation
- raise NotImplementedError()
- #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
+ #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
@@ -189,8 +187,7 @@ class Exif(base.Extractor):
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'
- else:
- return 'portrait' if width >= height else 'landscape'
+ return 'portrait' if width >= height else 'landscape'
return None
diff --git a/doc/source/installation.rst b/doc/source/installation.rst
index 42b1e4e..b634457 100644
--- a/doc/source/installation.rst
+++ b/doc/source/installation.rst
@@ -40,6 +40,8 @@ For development, you also need to install some additional dependencies::
# code style discipline
pip install mypy coverage pylint
+ # external type annotations for pyyaml
+ pip install types-PyYAML
# documentation
pip install sphinx sphinx-copybutton furo
diff --git a/test/apps/test_main.py b/test/apps/test_main.py
new file mode 100644
index 0000000..a1d8a49
--- /dev/null
+++ b/test/apps/test_main.py
@@ -0,0 +1,57 @@
+
+# standard imports
+import contextlib
+import io
+import json
+import os
+import tempfile
+import unittest
+import yaml
+
+# objects to test
+from bsie.apps import main
+
+
+## code ##
+
+class TestMain(unittest.TestCase):
+ def setUp(self):
+ config = {
+ 'ReaderBuilder': {},
+ 'ExtractorBuilder': [
+ {'bsie.extractor.generic.stat.Stat': {}},
+ {'bsie.extractor.generic.path.Path': {}},
+ ]
+ }
+ # create config file
+ _, self.config_path = tempfile.mkstemp(prefix='bsie-test-', suffix='.yaml')
+ with open(self.config_path, 'wt') as cfile:
+ yaml.dump(config, cfile)
+
+ def tearDown(self):
+ if os.path.exists(self.config_path):
+ os.unlink(self.config_path)
+
+ def test_main(self):
+ # must at least pass an app
+ with contextlib.redirect_stderr(io.StringIO()):
+ self.assertRaises(SystemExit, main, [])
+ # app takes over
+ with contextlib.redirect_stderr(io.StringIO()):
+ self.assertRaises(SystemExit, main, ['info'])
+ outbuf = io.StringIO()
+ with contextlib.redirect_stdout(outbuf):
+ main(['info', '--config', self.config_path, 'predicates'])
+ self.assertEqual(set(outbuf.getvalue().strip().split('\n')), {
+ 'http://bsfs.ai/schema/Entity#filename',
+ 'http://bsfs.ai/schema/Entity#filesize',
+ 'http://bsfs.ai/schema/Predicate',
+ })
+
+
+## main ##
+
+if __name__ == '__main__':
+ unittest.main()
+
+## EOF ##
diff --git a/test/extractor/image/test_photometrics.py b/test/extractor/image/test_photometrics.py
index 0e0261b..fb219e2 100644
--- a/test/extractor/image/test_photometrics.py
+++ b/test/extractor/image/test_photometrics.py
@@ -95,6 +95,16 @@ class TestExif(unittest.TestCase):
self.assertSetEqual(set(ext.extract(node, content, {ext.schema.predicate(ns.bse.longitude)})),
{(node, ext.schema.predicate(ns.bse.longitude), 7.875)})
+ # check orientation label
+ self.assertSetEqual(set(ext.extract(
+ node, {
+ 'Exif.Photo.PixelXDimension': '4288',
+ 'Exif.Photo.PixelYDimension': '2848',
+ 'Exif.Image.Orientation': '5',
+ },
+ {ext.schema.predicate(ns.bse.orientation_label)})),
+ {(node, ext.schema.predicate(ns.bse.orientation_label), 'portrait')})
+
# can pass multiple principals
self.assertSetEqual(set(ext.extract(node, content, {
ext.schema.predicate(ns.bse.exposure),
diff --git a/test/reader/preview/test_pg.py b/test/reader/preview/test_pg.py
index 381344f..30095c5 100644
--- a/test/reader/preview/test_pg.py
+++ b/test/reader/preview/test_pg.py
@@ -52,6 +52,7 @@ class TestPreviewGeneratorReader(unittest.TestCase):
self.assertEqual(sum(img.getdata()), 20258)
# cleanup
img.close()
+ del rdr
# can define a cache dir
pg_dir = tempfile.mkdtemp(prefix='bsie-test')