From bc08757977c80f65f1610a330c293a28b74ce2d2 Mon Sep 17 00:00:00 2001 From: John Evans Date: Fri, 21 Jun 2013 08:22:35 -0400 Subject: [PATCH 1/5] Use absolute rather than relative "up-the-ladder" imports. This eases the problem of running the unittests via the command line with "python -m unittest discover -s /start/path". #53 --- glymur/test/test_opj_suite_neg.py | 2 +- glymur/test/test_opj_suite_write.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 03cb437..5754e16 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -11,7 +11,7 @@ import warnings import numpy as np import pkg_resources -from ..lib import openjp2 as opj2 +from glymur.lib import openjp2 as opj2 # Need some combination of matplotlib, PIL, or scikits-image for reading # other image formats. diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 0526fc3..74237c2 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -11,7 +11,7 @@ import warnings import numpy as np -from ..lib import openjp2 as opj2 +from glymur.lib import openjp2 as opj2 # Need some combination of matplotlib, PIL, or scikits-image for reading # other image formats. From 146dffc5dc05213d37e5f8f07cba9fc286b510c1 Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 24 Jun 2013 08:23:58 -0400 Subject: [PATCH 2/5] Refactored configuration tests into new file. --- glymur/test/test_config.py | 101 +++++++++++++++++++++++++++++++++++++ glymur/test/test_jp2k.py | 79 +---------------------------- 2 files changed, 102 insertions(+), 78 deletions(-) create mode 100644 glymur/test/test_config.py diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py new file mode 100644 index 0000000..1abf02f --- /dev/null +++ b/glymur/test/test_config.py @@ -0,0 +1,101 @@ +import imp +import os +import sys +import tempfile +import unittest +if sys.hexversion <= 0x03030000: + from mock import patch +else: + from unittest.mock import patch +import warnings + +import pkg_resources + +import glymur +from glymur import Jp2k +from glymur.lib import openjp2 as opj2 + + +@unittest.skipIf(sys.hexversion < 0x03020000, + "Uses features introduced in 3.2.") +class TestJp2k(unittest.TestCase): + def setUp(self): + self.jp2file = pkg_resources.resource_filename(glymur.__name__, + "data/nemo.jp2") + imp.reload(glymur) + imp.reload(glymur.lib.openjp2) + + def tearDown(self): + imp.reload(glymur) + imp.reload(glymur.lib.openjp2) + + def test_config_file_via_environ(self): + """Verify that we can read a configuration file set via environ var.""" + with tempfile.TemporaryDirectory() as tdir: + configdir = os.path.join(tdir, 'glymur') + os.mkdir(configdir) + filename = os.path.join(configdir, 'glymurrc') + with open(filename, 'wb') as tfile: + tfile.write('[library]\n'.encode()) + libloc = glymur.lib.openjp2._OPENJP2._name + line = 'openjp2: {0}\n'.format(libloc) + tfile.write(line.encode()) + tfile.flush() + with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): + imp.reload(glymur.lib.openjp2) + j = Jp2k(self.jp2file) + + def test_config_file_via_environ_is_wrong(self): + # A non-existant library location should be rejected. + with tempfile.TemporaryDirectory() as tdir: + configdir = os.path.join(tdir, 'glymur') + os.mkdir(configdir) + fname = os.path.join(configdir, 'glymurrc') + with open(fname, 'w') as fp: + with tempfile.NamedTemporaryFile(suffix='.dylib') as tfile: + fp.write('[library]\n') + fp.write('openjp2: {0}.not.there\n'.format(tfile.name)) + fp.flush() + with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): + # Misconfigured new configuration file should + # be rejected. + with self.assertWarns(UserWarning) as cw: + imp.reload(glymur.lib.openjp2) + + def test_missing_config_file_via_environ(self): + # Verify that we error out properly if the configuration file + # specified via environment variable is not found. + with tempfile.TemporaryDirectory() as tdir: + with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): + # Misconfigured new configuration file should + # be rejected. + with self.assertWarns(UserWarning) as cw: + imp.reload(glymur.lib.openjp2) + + def test_home_dir_missing_config_dir(self): + # Verify no exception is raised if $HOME is missing .config directory. + with tempfile.TemporaryDirectory() as tdir: + with patch.dict('os.environ', {'HOME': tdir}): + # Misconfigured new configuration file should + # be rejected. + with self.assertWarns(UserWarning) as cw: + imp.reload(glymur.lib.openjp2) + + def test_home_dir_missing_glymur_rc_dir(self): + # Should warn but not error if $HOME/.config but no glymurrc dir. + with tempfile.TemporaryDirectory() as tdir: + # We need the subdirectory to be specifically named as ".config" + # in order for this test to work. A specifically-named temporary + # directory does not seem to be possible, so try to symlink it. + # Supposedly the symlink gets cleaned up with tdir gets cleaned up. + with tempfile.TemporaryDirectory(suffix=".config", dir=tdir) \ + as tdir_config: + os.symlink(tdir_config, os.path.join(tdir, '.config')) + with patch.dict('os.environ', {'HOME': tdir}): + # Misconfigured new configuration file should + # be rejected. + with self.assertWarns(UserWarning) as cw: + imp.reload(glymur.lib.openjp2) + +if __name__ == "__main__": + unittest.main() diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 3c25cca..031b989 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -20,9 +20,9 @@ from xml.etree import cElementTree as ET import numpy as np import pkg_resources +import glymur from glymur import Jp2k from glymur.lib import openjp2 as opj2 -import glymur try: data_root = os.environ['OPJ_DATA_ROOT'] @@ -594,83 +594,6 @@ class TestJp2k(unittest.TestCase): with self.assertRaisesRegex(IOError, regexp) as ce: d = j.read(reduce=3) - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_config_file_via_environ(self): - """Verify that we can read a configuration file set via environ var.""" - with tempfile.TemporaryDirectory() as tdir: - configdir = os.path.join(tdir, 'glymur') - os.mkdir(configdir) - filename = os.path.join(configdir, 'glymurrc') - with open(filename, 'wb') as tfile: - tfile.write('[library]\n'.encode()) - line = 'openjp2: {0}\n'.format(glymur._OPENJP2._name) - tfile.write(line.encode()) - tfile.flush() - with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): - imp.reload(glymur) - j = Jp2k(self.jp2file) - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_config_file_via_environ_is_wrong(self): - # A non-existant library location should be rejected. - with tempfile.TemporaryDirectory() as tdir: - configdir = os.path.join(tdir, 'glymur') - os.mkdir(configdir) - fname = os.path.join(configdir, 'glymurrc') - with open(fname, 'w') as fp: - with tempfile.NamedTemporaryFile(suffix='.dylib') as tfile: - fp.write('[library]\n') - fp.write('openjp2: {0}.not.there\n'.format(tfile.name)) - fp.flush() - with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): - # Misconfigured new configuration file should - # be rejected. - with self.assertWarns(UserWarning) as cw: - imp.reload(glymur) - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_missing_config_file_via_environ(self): - # Verify that we error out properly if the configuration file - # specified via environment variable is not found. - with tempfile.TemporaryDirectory() as tdir: - with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}): - # Misconfigured new configuration file should - # be rejected. - with self.assertWarns(UserWarning) as cw: - imp.reload(glymur) - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_home_dir_missing_config_dir(self): - # Verify no exception is raised if $HOME is missing .config directory. - with tempfile.TemporaryDirectory() as tdir: - with patch.dict('os.environ', {'HOME': tdir}): - # Misconfigured new configuration file should - # be rejected. - with self.assertWarns(UserWarning) as cw: - imp.reload(glymur) - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_home_dir_missing_glymur_rc_dir(self): - # Should warn but not error if $HOME/.config but no glymurrc dir. - with tempfile.TemporaryDirectory() as tdir: - # We need the subdirectory to be specifically named as ".config" - # in order for this test to work. A specifically-named temporary - # directory does not seem to be possible, so try to symlink it. - # Supposedly the symlink gets cleaned up with tdir gets cleaned up. - with tempfile.TemporaryDirectory(suffix=".config", dir=tdir) \ - as tdir_config: - os.symlink(tdir_config, os.path.join(tdir, '.config')) - with patch.dict('os.environ', {'HOME': tdir}): - # Misconfigured new configuration file should - # be rejected. - with self.assertWarns(UserWarning) as cw: - imp.reload(glymur) - def test_xmp_attribute(self): # Verify that we can read the XMP packet in our shipping example file. j = Jp2k(self.jp2file) From bb1d18c2a04780d1e80720a9ed72803c3962e47b Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 24 Jun 2013 08:24:15 -0400 Subject: [PATCH 3/5] Moved configuration file parsing back to lib.openjp2 --- glymur/__init__.py | 83 --------------------------------------- glymur/lib/openjp2.py | 91 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 85 deletions(-) diff --git a/glymur/__init__.py b/glymur/__init__.py index 473bb65..79fcc5e 100644 --- a/glymur/__init__.py +++ b/glymur/__init__.py @@ -2,89 +2,6 @@ """ -def _glymurrc_fname(): - """Return the path to the configuration file. - - Search order: - 1) current working directory - 2) environ var XDG_CONFIG_HOME - 3) $HOME/.config/glymur/glymurrc - """ - - # Current directory. - fname = os.path.join(os.getcwd(), 'glymurrc') - if os.path.exists(fname): - return fname - - # Either GLYMURCONFIGDIR/glymurrc or $HOME/.glymur/glymurrc - confdir = _get_configdir() - if confdir is not None: - fname = os.path.join(confdir, 'glymurrc') - if os.path.exists(fname): - return fname - else: - msg = "Configuration file '{0}' does not exist.".format(confdir) - warnings.warn(msg, UserWarning) - - # didn't find a configuration file. - return None - - -def _config(): - """Read configuration file. - - Based on matplotlib. - """ - filename = _glymurrc_fname() - if filename is not None: - # Read the configuration file for the library location. - parser = ConfigParser() - parser.read(filename) - libopenjp2_path = parser.get('library', 'openjp2') - else: - # No help from the config file, try to find it ourselves. - from ctypes.util import find_library - libopenjp2_path = find_library('openjp2') - - if libopenjp2_path is None: - return None - - try: - _OPENJP2 = ctypes.CDLL(libopenjp2_path) - except OSError: - msg = '"Library {0}" could not be loaded. Operating in degraded mode.' - msg = msg.format(libopenjp2_path) - warnings.warn(msg, UserWarning) - _OPENJP2 = None - return _OPENJP2 - - -def _get_configdir(): - """Return string representing the configuration directory. - - Default is $HOME/.config/glymur. You can override this with the - XDG_CONFIG_HOME environment variable. - """ - - if 'XDG_CONFIG_HOME' in os.environ: - return os.path.join(os.environ['XDG_CONFIG_HOME'], 'glymur') - - if 'HOME' in os.environ: - return os.path.join(os.environ['HOME'], '.config', 'glymur') - -import warnings -import sys -if sys.hexversion <= 0x03000000: - from ConfigParser import SafeConfigParser as ConfigParser - from ConfigParser import NoOptionError -else: - from configparser import ConfigParser - from configparser import NoOptionError -import ctypes -import os - -_OPENJP2 = _config() - from .jp2k import Jp2k from .jp2dump import jp2dump diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index 798f23d..d7578d0 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -2,12 +2,99 @@ Wraps individual functions in openjp2 library. """ + +def _glymurrc_fname(): + """Return the path to the configuration file. + + Search order: + 1) current working directory + 2) environ var XDG_CONFIG_HOME + 3) $HOME/.config/glymur/glymurrc + """ + + # Current directory. + fname = os.path.join(os.getcwd(), 'glymurrc') + if os.path.exists(fname): + return fname + + # Either GLYMURCONFIGDIR/glymurrc or $HOME/.glymur/glymurrc + confdir = _get_configdir() + if confdir is not None: + fname = os.path.join(confdir, 'glymurrc') + if os.path.exists(fname): + return fname + else: + msg = "Configuration file '{0}' does not exist.".format(confdir) + warnings.warn(msg, UserWarning) + + # didn't find a configuration file. + return None + + +def _config(): + """Read configuration file. + + Based on matplotlib. + """ + filename = _glymurrc_fname() + if filename is not None: + # Read the configuration file for the library location. + parser = ConfigParser() + parser.read(filename) + libopenjp2_path = parser.get('library', 'openjp2') + else: + # No help from the config file, try to find it ourselves. + from ctypes.util import find_library + libopenjp2_path = find_library('openjp2') + + if libopenjp2_path is None: + return None + + try: + _OPENJP2 = ctypes.CDLL(libopenjp2_path) + except OSError: + msg = '"Library {0}" could not be loaded. Operating in degraded mode.' + msg = msg.format(libopenjp2_path) + warnings.warn(msg, UserWarning) + _OPENJP2 = None + return _OPENJP2 + + +def _get_configdir(): + """Return string representing the configuration directory. + + Default is $HOME/.config/glymur. You can override this with the + XDG_CONFIG_HOME environment variable. + """ + + if 'XDG_CONFIG_HOME' in os.environ: + return os.path.join(os.environ['XDG_CONFIG_HOME'], 'glymur') + + if 'HOME' in os.environ: + return os.path.join(os.environ['HOME'], '.config', 'glymur') + import ctypes +import os +import warnings + +import sys +if sys.hexversion <= 0x03000000: + from ConfigParser import SafeConfigParser as ConfigParser + from ConfigParser import NoOptionError +else: + from configparser import ConfigParser + from configparser import NoOptionError + +_OPENJP2 = _config() import numpy as np -from .. import _OPENJP2 -from ..core import LRCP, RLCP, RPCL, PCRL, CPRL +# Progression order +LRCP = 0 +RLCP = 1 +RPCL = 2 +PCRL = 3 +CPRL = 4 _ERROR_MSG_LST = [] From 6eafc2ad3dc02b9586bee78c5de84d289d70b3c2 Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 24 Jun 2013 08:54:08 -0400 Subject: [PATCH 4/5] Added runtests function to discover and run tests from within python. --- glymur/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/glymur/__init__.py b/glymur/__init__.py index 79fcc5e..43ca2b3 100644 --- a/glymur/__init__.py +++ b/glymur/__init__.py @@ -1,9 +1,15 @@ """glymur - read, write, and interrogate JPEG 2000 files """ - from .jp2k import Jp2k from .jp2dump import jp2dump from . import data from . import test + +def runtests(): + """Discover and run all tests for the glymur package. + """ + import unittest + suite = unittest.defaultTestLoader.discover(__path__[0]) + unittest.TextTestRunner(verbosity=2).run(suite) From 08eec3d82bd36216f6aea097c3daaae400723d9d Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 24 Jun 2013 08:54:29 -0400 Subject: [PATCH 5/5] Updated docs to reflect running tests from within python. --- docs/source/detailed_installation.rst | 8 +++++++- docs/source/introduction.rst | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst index 1771722..0037ccf 100644 --- a/docs/source/detailed_installation.rst +++ b/docs/source/detailed_installation.rst @@ -96,7 +96,13 @@ Not currently supported. Testing ''''''' -If you wish to run the tests (strongly suggested :-), try the following +If you wish to run the tests (strongly suggested :-), you can either run them +from within python as follows ... :: + + >>> import glymur + >>> glymur.runtests() + +or from the unix command line. :: $ cd /to/where/you/unpacked/glymur $ python -m unittest discover diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index d21d7eb..834ecc7 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -70,3 +70,11 @@ to take advantage of it. For example, if you install with pip's $ export PYTHONPATH=$HOME/.local/lib/python3.3/site-packages $ export PATH=$HOME/.local/bin:$PATH + +You can run the tests from within python as follows:: + + >>> import glymur + >>> glymur.runtests() + +Many tests are currently skipped; the important thing is whether or not any +tests fail.