From 75509b5f1727dccd8a749823d74e94365a42b201 Mon Sep 17 00:00:00 2001 From: GD Date: Tue, 8 Mar 2022 16:20:44 +0100 Subject: [PATCH 01/12] remove useless installation of test, data and remaining doc files (potential fix for github issue #10 ) --- setup.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/setup.py b/setup.py index 8344486..6c96b2a 100644 --- a/setup.py +++ b/setup.py @@ -196,15 +196,6 @@ def get_extension(): packages=find_packages(), cmdclass={'build_ext': CustomBuildExtCommand}, ext_modules=get_extension(), - data_files=[('tests', ['tests/test_spams.py', - 'tests/test_decomp.py', - 'tests/test_dictLearn.py', - 'tests/test_linalg.py', - 'tests/test_prox.py', - 'tests/test_utils.py']), - ('doc', ['doc/doc_spams.pdf']), - ('tests', ['data/boat.png', 'data/lena.png'])], - include_package_data=True, zip_safe=True ) From 3eb87025ba4d46dba5723d71b87f83678529abdb Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 10:23:12 +0100 Subject: [PATCH 02/12] re-include test and data files in the installation following setuptools recommandation (c.f. https://setuptools.pypa.io/en/latest/userguide/datafiles.html) --- MANIFEST.in | 4 ++-- README.md | 4 ++-- setup.py | 3 +++ {data => spams/data}/boat.png | Bin {data => spams/data}/lena.png | Bin {tests => spams/tests}/test_decomp.py | 0 {tests => spams/tests}/test_dictLearn.py | 0 {tests => spams/tests}/test_linalg.py | 0 {tests => spams/tests}/test_prox.py | 0 {tests => spams/tests}/test_spams.py | 0 {tests => spams/tests}/test_utils.py | 0 11 files changed, 7 insertions(+), 4 deletions(-) rename {data => spams/data}/boat.png (100%) rename {data => spams/data}/lena.png (100%) rename {tests => spams/tests}/test_decomp.py (100%) rename {tests => spams/tests}/test_dictLearn.py (100%) rename {tests => spams/tests}/test_linalg.py (100%) rename {tests => spams/tests}/test_prox.py (100%) rename {tests => spams/tests}/test_spams.py (100%) rename {tests => spams/tests}/test_utils.py (100%) diff --git a/MANIFEST.in b/MANIFEST.in index 944ebba..6eb3dd9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,6 +5,6 @@ include version recursive-include spams_wrap *.h recursive-include spams_wrap *.cpp -recursive-include tests *.py -recursive-include data *.png +recursive-include spams/tests *.py +recursive-include spams/data *.png recursive-include doc * diff --git a/README.md b/README.md index a04c1b8..ca55eac 100644 --- a/README.md +++ b/README.md @@ -50,8 +50,8 @@ Manipulated objects are imported from numpy and scipy. Matrices should be stored ### Testing the interface ```bash -python tests/test_spams.py -h # to get help -python tests/test_spams.py # will run all the tests +python spams/tests/test_spams.py -h # to get help +python spams/tests/test_spams.py # will run all the tests ``` --- diff --git a/setup.py b/setup.py index 6c96b2a..9c2991f 100644 --- a/setup.py +++ b/setup.py @@ -196,6 +196,9 @@ def get_extension(): packages=find_packages(), cmdclass={'build_ext': CustomBuildExtCommand}, ext_modules=get_extension(), + package_data={ + "spams": ["data/*.png", "tests/*.py"] + }, zip_safe=True ) diff --git a/data/boat.png b/spams/data/boat.png similarity index 100% rename from data/boat.png rename to spams/data/boat.png diff --git a/data/lena.png b/spams/data/lena.png similarity index 100% rename from data/lena.png rename to spams/data/lena.png diff --git a/tests/test_decomp.py b/spams/tests/test_decomp.py similarity index 100% rename from tests/test_decomp.py rename to spams/tests/test_decomp.py diff --git a/tests/test_dictLearn.py b/spams/tests/test_dictLearn.py similarity index 100% rename from tests/test_dictLearn.py rename to spams/tests/test_dictLearn.py diff --git a/tests/test_linalg.py b/spams/tests/test_linalg.py similarity index 100% rename from tests/test_linalg.py rename to spams/tests/test_linalg.py diff --git a/tests/test_prox.py b/spams/tests/test_prox.py similarity index 100% rename from tests/test_prox.py rename to spams/tests/test_prox.py diff --git a/tests/test_spams.py b/spams/tests/test_spams.py similarity index 100% rename from tests/test_spams.py rename to spams/tests/test_spams.py diff --git a/tests/test_utils.py b/spams/tests/test_utils.py similarity index 100% rename from tests/test_utils.py rename to spams/tests/test_utils.py From 7077ab7919becda513bdfe32861b5906ea91f709 Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 10:33:35 +0100 Subject: [PATCH 03/12] keep data dir in root directory and add a symlink in spams package dir --- {spams/data => data}/boat.png | Bin {spams/data => data}/lena.png | Bin spams/data | 1 + 3 files changed, 1 insertion(+) rename {spams/data => data}/boat.png (100%) rename {spams/data => data}/lena.png (100%) create mode 120000 spams/data diff --git a/spams/data/boat.png b/data/boat.png similarity index 100% rename from spams/data/boat.png rename to data/boat.png diff --git a/spams/data/lena.png b/data/lena.png similarity index 100% rename from spams/data/lena.png rename to data/lena.png diff --git a/spams/data b/spams/data new file mode 120000 index 0000000..4909e06 --- /dev/null +++ b/spams/data @@ -0,0 +1 @@ +../data \ No newline at end of file From 00c07c248c71fa92d68196d32ff1e27341a3aeda Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 10:34:20 +0100 Subject: [PATCH 04/12] keep test dir in root directory and add a symlink in spams package dir --- {spams/tests => tests}/test_decomp.py | 0 {spams/tests => tests}/test_dictLearn.py | 0 {spams/tests => tests}/test_linalg.py | 0 {spams/tests => tests}/test_prox.py | 0 {spams/tests => tests}/test_spams.py | 0 {spams/tests => tests}/test_utils.py | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {spams/tests => tests}/test_decomp.py (100%) rename {spams/tests => tests}/test_dictLearn.py (100%) rename {spams/tests => tests}/test_linalg.py (100%) rename {spams/tests => tests}/test_prox.py (100%) rename {spams/tests => tests}/test_spams.py (100%) rename {spams/tests => tests}/test_utils.py (100%) diff --git a/spams/tests/test_decomp.py b/tests/test_decomp.py similarity index 100% rename from spams/tests/test_decomp.py rename to tests/test_decomp.py diff --git a/spams/tests/test_dictLearn.py b/tests/test_dictLearn.py similarity index 100% rename from spams/tests/test_dictLearn.py rename to tests/test_dictLearn.py diff --git a/spams/tests/test_linalg.py b/tests/test_linalg.py similarity index 100% rename from spams/tests/test_linalg.py rename to tests/test_linalg.py diff --git a/spams/tests/test_prox.py b/tests/test_prox.py similarity index 100% rename from spams/tests/test_prox.py rename to tests/test_prox.py diff --git a/spams/tests/test_spams.py b/tests/test_spams.py similarity index 100% rename from spams/tests/test_spams.py rename to tests/test_spams.py diff --git a/spams/tests/test_utils.py b/tests/test_utils.py similarity index 100% rename from spams/tests/test_utils.py rename to tests/test_utils.py From 902b4cd35af1904bf5873e274669a2cb937d325d Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 11:48:33 +0100 Subject: [PATCH 05/12] fix image file usage after modifying the test dir installation --- tests/test_dictLearn.py | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/tests/test_dictLearn.py b/tests/test_dictLearn.py index 88714a0..c6ea44a 100644 --- a/tests/test_dictLearn.py +++ b/tests/test_dictLearn.py @@ -1,6 +1,7 @@ from __future__ import absolute_import, division, print_function import sys +import os import numpy as np import scipy import scipy.sparse as ssp @@ -15,6 +16,33 @@ ssprand = myscipy_rand.rand else: ssprand = ssp.rand + + +def get_img_file_path(img): + """Return path to an image file + + Arguments: + img (string): image filename without path among 'boat.png' or + 'lena.png'. + + Output: + img_file (string): normalized path to image input filename. + + """ + # check input + if not img in ["boat.png", "lena.png"]: + raise ValueError("bad input, `img` should be 'boat.png' or 'lena.png'") + # try local file + img_file = os.path.join("data", img) + if os.path.isfile(img_file): + img_file = os.path.abspath(img_file) + else: + # file from install + img_file = os.path.join( + os.path.dirname(os.path.abspath(spams.__file__)), img_file + ) + # output + return img_file def _extract_lasso_param(f_param): @@ -46,8 +74,8 @@ def _objective(X, D, param, imgname=None): def test_trainDL(): - img_file = 'data/boat.png' try: + img_file = get_img_file_path("boat.png") img = Image.open(img_file) except: print("Cannot load image %s : skipping test" % img_file) @@ -140,8 +168,8 @@ def test_trainDL(): def test_trainDL_Memory(): - img_file = 'data/lena.png' try: + img_file = get_img_file_path("lena.png") img = Image.open(img_file) except: print("Cannot load image %s : skipping test" % img_file) @@ -202,8 +230,8 @@ def test_trainDL_Memory(): def test_structTrainDL(): - img_file = 'data/lena.png' try: + img_file = get_img_file_path("lena.png") img = Image.open(img_file) except Exception as e: print("Cannot load image %s (%s) : skipping test" % (img_file, e)) @@ -376,8 +404,8 @@ def test_structTrainDL(): def test_nmf(): - img_file = 'data/boat.png' try: + img_file = get_img_file_path("boat.png") img = Image.open(img_file) except: print("Cannot load image %s : skipping test" % img_file) @@ -413,8 +441,8 @@ def test_nmf(): # Archetypal Analysis, run first steps with FISTA and run last steps with activeSet, def test_archetypalAnalysis(): - img_file = 'data/lena.png' try: + img_file = get_img_file_path("lena.png") img = Image.open(img_file) except Exception as e: print("Cannot load image %s (%s) : skipping test" % (img_file, e)) From aba0b7f5810b1d9bfe434ba0bee6160d51685cf8 Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 11:49:40 +0100 Subject: [PATCH 06/12] include tests dir from root directory and from spams directory in distribution --- MANIFEST.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index 6eb3dd9..b81f4ed 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,4 +7,6 @@ recursive-include spams_wrap *.cpp recursive-include spams/tests *.py recursive-include spams/data *.png +recursive-include tests *.py +recursive-include data *.png recursive-include doc * From adbb6dee96682a628e064f7af726747dc24ef505 Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 11:50:47 +0100 Subject: [PATCH 07/12] document the new test call from Python --- README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ca55eac..4db3155 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,20 @@ Manipulated objects are imported from numpy and scipy. Matrices should be stored ### Testing the interface +- From the command line (in the project root directory): ```bash -python spams/tests/test_spams.py -h # to get help -python spams/tests/test_spams.py # will run all the tests +python tests/test_spams.py -h # print the man page +python tests/test_spams.py # run all the tests +``` + +- From Python (assuming `spams` package is installed): +```python +from spams.tests import test_spams + +test_spams('-h') # print the man page +test_spams() # run all tests +test_spams(['sort', 'calcAAt']) # run specific tests +test_spams(python_exec='python3') # specify the python exec ``` --- From 95c2f9d18d1ad9c6031f521e7762c132ed6c749c Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 11:56:25 +0100 Subject: [PATCH 08/12] document test run from command line using installed package --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4db3155..3f49b09 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Manipulated objects are imported from numpy and scipy. Matrices should be stored ### Testing the interface -- From the command line (in the project root directory): +- From the command line (to be called from the project root directory): ```bash python tests/test_spams.py -h # print the man page python tests/test_spams.py # run all the tests @@ -65,6 +65,12 @@ test_spams(['sort', 'calcAAt']) # run specific tests test_spams(python_exec='python3') # specify the python exec ``` +- From the command line (assuming `spams` package is installed): +```bash +# c.f. previous point for the different options +python -c "from spams.tests import test_spams; test_spams()" +``` + --- ## Links From 8b74e7068b7db11743d30b4dd203859026df308c Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 14:19:23 +0100 Subject: [PATCH 09/12] setup test run from Python --- spams/tests | 1 + tests/__init__.py | 1 + tests/run.py | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 120000 spams/tests create mode 100644 tests/__init__.py create mode 100644 tests/run.py diff --git a/spams/tests b/spams/tests new file mode 120000 index 0000000..6dd24e0 --- /dev/null +++ b/spams/tests @@ -0,0 +1 @@ +../tests \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..23aa219 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +from .run import test_spams diff --git a/tests/run.py b/tests/run.py new file mode 100644 index 0000000..1838ac7 --- /dev/null +++ b/tests/run.py @@ -0,0 +1,59 @@ +import subprocess +import os + +def test_spams(args=None, python_exec = 'python'): + """Run spams-python tests from python + + To run the tests, from the command line, please check the README.md file + + Input: + args (string|string list): argument to pass to the the main test script, + use `args='-h'` for more details. If None (default), all tests are + run. + python_exec (string): python executable. By default, it is `'python'`. + Python 3+ is required. On some system, you may have to set + `python_exec = 'python3'`. + """ + + # check spams availability + try: + import spams + except: + raise ModuleNotFoundError("No module named 'spams'") + + # main test file + test_file = os.path.join("tests", "test_spams.py") + if os.path.isfile(test_file): + test_file = os.path.abspath(test_file) + else: + test_file = os.path.join( + os.path.dirname(os.path.abspath(spams.__file__)), test_file + ) + + # test dir + test_dir = os.path.dirname(test_file) + + # check python executable + try: + python_version = subprocess.run([python_exec, "-V"], capture_output=True) + except: + raise SystemError(f"{python_exec} is not a valid python executable") + # check python version + if not "Python 3." in python_version.stdout.decode('UTF-8'): + raise SystemError("Python 3+ is required, try using python_exec = 'python3'") + + # check args + if args is None: + args = [] + elif not (isinstance(args, str) or \ + (isinstance(args, list) and \ + all(isinstance(arg, str) for arg in args))): + raise TypeError("'args' input should be a string or a list of strings.") + + if isinstance(args, str): + args = [args] + + # run + subprocess.run([python_exec, 'test_spams.py'] + args, cwd = test_dir) + + From cf967a3c910f01e13f95a16876b46060561048f9 Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 14:40:01 +0100 Subject: [PATCH 10/12] include version file in installation --- MANIFEST.in | 2 ++ setup.py | 2 +- spams/version | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) create mode 120000 spams/version diff --git a/MANIFEST.in b/MANIFEST.in index b81f4ed..400dae6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,6 +5,8 @@ include version recursive-include spams_wrap *.h recursive-include spams_wrap *.cpp +include spams/version + recursive-include spams/tests *.py recursive-include spams/data *.png recursive-include tests *.py diff --git a/setup.py b/setup.py index 9c2991f..60ef7ac 100644 --- a/setup.py +++ b/setup.py @@ -197,7 +197,7 @@ def get_extension(): cmdclass={'build_ext': CustomBuildExtCommand}, ext_modules=get_extension(), package_data={ - "spams": ["data/*.png", "tests/*.py"] + "spams": ["data/*.png", "tests/*.py", "version"] }, zip_safe=True ) diff --git a/spams/version b/spams/version new file mode 120000 index 0000000..1748d5b --- /dev/null +++ b/spams/version @@ -0,0 +1 @@ +../version \ No newline at end of file From 45feb72d83b24d4bc4e96230408b3ee360d2f237 Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 14:40:41 +0100 Subject: [PATCH 11/12] update version number --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 0ce6c9d..dacc32b 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.6.5.1 +2.6.5.2 From 3de75e7199b1da4609225709382c713c92e8467c Mon Sep 17 00:00:00 2001 From: GD Date: Wed, 9 Mar 2022 15:35:28 +0100 Subject: [PATCH 12/12] cleanup setup to avoid test module installation duplicate --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 60ef7ac..561409a 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ # import platform import sys -from setuptools import setup, Extension, find_packages +from setuptools import setup, Extension from setuptools.command.build_ext import build_ext from distutils.sysconfig import get_python_inc @@ -193,11 +193,11 @@ def get_extension(): python_requires='>=3', install_requires=['Cython>=0.29', 'numpy>=1.12', 'Pillow>=6.0', 'scipy>=1.0', 'six>=1.12'], - packages=find_packages(), + packages=['myscipy_rand', 'spams_wrap', 'spams', 'spams.tests'], cmdclass={'build_ext': CustomBuildExtCommand}, ext_modules=get_extension(), package_data={ - "spams": ["data/*.png", "tests/*.py", "version"] + "spams": ["data/*.png", "version"] }, zip_safe=True )