diff options
1731 files changed, 192947 insertions, 193136 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3556fbb..160243a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,261 @@ Change Log ========== +1.1.0: 2022/10/27 +----------------- + +This is the last version of `silx` supporting Python 3.6 and `PySide2`. +Next version will require Python >= 3.7 + +This is the first version of `silx` supporting `PyQt6` (for `Qt6`). +Please note that `PyQt6` >= v6.3.0 is required. + +* `silx view`: + + * Improved wildcard support in filename and data path (PR #3663) + * Enabled plot grid by default for curve plots (PR #3667) + * Fixed refresh for content opened as `file.h5::/path` (PR #3665) + +* `silx.gui`: + + * Added support of `PyQt6` >= 6.3.0 (PR #3655) + * Fixed `matplotlib`>=3.6.0 and `PySide6` support (PR #3639) + * Fixed `PySide6` >=6.2.2 support (PR #3581) + * Fixed Python 3.10 with `PyQt5` support (PR #3591) + * Fixed crashes on exit when deriving `QApplication` (PR #3588) + * Deprecated `PySide2` support (PR #3648) + * Fixed: raise exception early when using a version of `PyQt5` incompatible with Python 3.10 (PR #3694) + + * `silx.gui.data`: + + * Updated: Do not keep aspect ratio in `NXdata` image views when axes `@units` are different (PR #3660) + * `silx.gui.data.ArrayTableWidget`: Updated to edit without clearing previous data (PR #3686) + * `silx.gui.data.DataViewer`: Added `selectionChanged` signal (PR #3646) + * `silx.gui.data.Hdf5TableView`: Fixed for virtual datasets in the same file (PR #3572) + + * `silx.gui.dialog.ColormapDialog`: Updated layout and presentation of the features (PR #3671, #3609) + + * `silx.gui.hdf5`: Fixed issue with unsupported hdf5 entity (e.g. datatype) (PR #3643) + + * `silx.gui.plot`: + + * `silx.gui.plot.items`: + + * Added `BandROI` item (PR #3680, #3702, #3707) + * Updated to take errorbars into account for item bounds (PR #3647) + * Fixed `ArcROI` display (PR #3617) + * Fixed error logs for scatter triangle visualisation with aligned points (PR #3644) + + * `silx.gui.plot.MaskToolsWidget`: Changed mask load/save default directory (PR #3704) + + * `silx.gui.plot.PlotWidget`: + + * Fixed time axis with values outside of supported range ]0, 10000[ years (PR 3597) + * Fixed matplotlib backend replot failure under specific conditions (PR #3590) + + * `silx.gui.PlotWidget`'s OpenGL backend: + + * Added support of LaTex-like math syntax to text display (PR #3600) + * Updated text label background to be less transparent (PR #3593) + * Fixed dashed curve rendering (PR #3596) + * Fixed image rendering of arcsinh colormap for uint8 and uint16 data (PR #3604) + * Fixed rendering on some GPU (PR #3695) + * Fixed empty text support (PR #3701) + * Fixed: Avoid rendering when OpenGL version/extension check fails (PR #3707) + + * `silx.gui.plot.PlotWindow`: Fixed management of DockWidgets when showing/hiding the `PlotWindow` (PR #3631) + * `silx.gui.plot.PositionInfo`: Improved picking (PR #3640) + * `silx.gui.plot.StackView`: Updated toolbar implementation (PR #3697) + + * `silx.gui.plot.stats`: Fixed warnings when all data is outside the selected stats region (PR #3659) + * `silx.gui.plot.tools`: + + * Added snapping to profile curve (PR #3640) + * Fixed handling of `disconnect` exception (PR #3692) + * Fixed label formatting for 2D profile tool (PR #3698) + * Fixed computation of the slice profile (PR #3708) + + * `silx.gui.utils.glutils.isOpenGLAvailable`: Added possibility to check `AA_ShareOpenGLContexts` (PR #3688) + * `silx.gui.widgets.ElidedLabel`: Fixed API inherited from `QLabel` (PR #3650, #3707) + +* `silx.io`: + + * `silx.io.dictdump`: + + * Added "info" logs when an entity is not copied to the output HDF5 file `dicttoh5` (PR #3664) + * Added support of `pint` in `dicttoh5` and `dicttonx` (PR #3683) + + * `silx.io.nxdata`: + + * Updated `get_default` to be more permissive and follow `@default` recursively (PR #3662) + * Updated error dataset retrieval (PR #3657, #3672) + + * `silx.io.specfile`: + + * Fixed buffer overflow for too long motor or label (PR #3622) + * Fixed missing data if there is a trailing space in the mca array (PR #3612) + + * `silx.io.utils.retry`: Added retry for generator functions (PR #3679) + +* `silx.math`: + + * `silx.math.histogram`: + + * Added support of `uint16` weights for LUT histogram (PR #3670) + * Fixed `Histogramnd` computation on arrays with more than 2**31-1 samples (PR #3599) + + * `silx.math.fft`: + + * Added `export_wisdom()` and `import_wisdom()` (PR #3623) + * Fixed normalization modes, notably account for regression in `pyfftw` normalization (PR #3625) + * Fixed avoid creating OpenCL/Cuda contexts when not needed (PR #3587) + + * `silx.math.fit`: Updated documentation (PR #3582) + +* `silx.opencl`: Updated OpenCL profiling, fixed memory leak (PR #3690) + +* `silx.utils.ExternalResources`: Stored downloaded data checksum (PR #3580) + +* Miscellaneous: + + * Added `SILX_INSTALL_REQUIRES_STRIP` build configuration environment variable (PR #3602) + * Added optional use of `sphinx_autodoc_typehints` to generate the documentation (PR #3668) + * Updated build and development tools to remove dependency to `distutils` and `numpy.distutils` (PR #3583, #3585, #3613, #3649, #3651, #3653, #3658, #3661, #3678) + * Updated Windows installer (PR #3642) + * Updated documentation (PR #3699, #3709) + * Updated after 1.0.0 release (PR #3560, #3569) + * Fixed tests and continuous integration (PR #3632, #3637, #3639, #3685) + * Fixed Debian/Ubuntu packaging (PR #3693) + * Cleaned-up Python 2 compatibility code (PR #3673) + +1.0.0: 2021/12/06 +----------------- + +This is the first version of `silx` supporting `PySide6` (for `Qt6`) and using `pytest` to run the tests. + +* `silx view`: + + * Added Windows installer generation (PR #3548) + * Updated 'About' dialog (#3547, #3475) + * Fixed: Keep curve legend selection with changing dimensions (PR #3529) + * Fixed: Increase max number of opened file at start-up (PR #3545) + +* `silx.gui`: + + * Added PySide6 support (PR #3486, #3528, #3479, #3542, #3549, #3478, #3481): + * Removed support of PyQt4 / Pyside (PR #3423, #3424, #3480, #3482) + * `silx.gui.colors`: + + * Fixed duplicated logs when colormap vmin/vmax are not valid (PR #3471) + + * `silx.gui.plot`: + + * `silx.gui.plot.actions`: + + * `silx.gui.plot.actions.fit`: + + * Updated behaviour of fitted item auto update (PR #3532) + + * `silx.gui.plot.actions.histogram`: + + * Enhanced: Allow user to change histogram nbins and range (PR #3514, #3514) + * Updated `PixelIntensitiesHistoAction` to use `PlotWidget.selection` (PR #3408) + * Fixed issue when the whole image is masked (PR #3544) + * Fixed error on macOS 11 with 3D display in `silx view` (PR #3544) + + * `silx.gui.plot.CompareImages`: + + * Fixed `colormap`: avoid forcing vmin and vmax when not in 'HORIZONTAL_LINE' or 'VERTICAL_LINE' mode (PR #3510) + + * `silx.gui.plot.items`: + + * Added 'image_aggregated.ImageDataAggregated': item allowing to aggregate image data before display (PR #3503) + * Fixed `ArcROI.setGeometry` (fix #3492) + + * `silx.gui.plot.ImageStack`: + + * Enhanced management of the `animation thread` (PR #3440, PR #3441) + + * `silx.gui.plot.ImageView`: + + * Added action to show/hide the side histogram (PR #3488) + * Added 'resetzoom' parameter to 'ImageView.setImage' (PR #3488) + * Added empty array support to 'ImageView.setImage' (PR #3530) + * Added aggregation mode action (PR #3536) + * Added support of RGB and RGBA images (PR #3487) + * Updated 'imageview' example with a '--live' option (PR #3488) + * Fixed profile window, added `setProfileWindowBehavior` method (PR #3457) + * Fixed issue with profile window size (PR #3455) + + * `silx.gui.plot.PlotWidget`: + + * Fixed update of `Scatter` item binned statistics visualization (PR #3452) + * Fixed OpenGL backend memory leak (PR #3453) + * Enhanced: Optimized scatter when rendered as regular grid with the OpenGL backend (PR #3447) + * Enhanced axis limits management by the OpenGL backend (PR #3504) + * Enhanced control of repaint (PR #3449) + * Enhanced text label background rendering with OpenGL backend (PR #3565) + + * `silx.gui.plot.PlotWindow`: + + * Fixed returned action from 'getKeepDataAspectRatioAction' (PR #3500) + + * `silx.gui.plot3d`: + + * Fixed picking on highdpi screen (PR #3550) + * Fixed issue in parameter tree (PR #3550) + +* `silx.io`: + + * Added read support for FIO files (PR #3539) thanks to tifuchs contribution + * `silx.io.dictdump`: + + * Fixed missing conversion of the key (PR #3505) thanks to rnwatanabe contribution + * Extract update modes list to a constant global variable (PR #3460) thanks to jpcbertoldo + + * `silx.io.convert`: + + * Enhanced `write_to_h5`: `infile` parameter can now also be a HDF5 file as input (PR #3511) + + * `silx.io.h5py_utils`: + + * Added support of `locking` argument from the h5py.File when possible (PR #3554) + * Added log a critical message for unsupported versions of libhdf5 (PR #3533) + + * `silx.io.spech5`: + + * Enhanced: Improve robustness (PR #3507, #3463) + + * `silx.io.url`: + + * Fixed `is_absolute` in the case the `file_path()` returns None (PR #3437) + + * `silx.io.utils`: + + * Added 'silx.io.utils.visitall': provides a visitor of all items including links that works for both `commonh5` and `h5py` (PR #3511) + +* `silx.math`: + + * `silx.math.colormap`: + + * Added `apply_colormap` function (PR #3525) + * Enhanced `cmap` error messages (PR #3522) + +* `silx.opencl`: + + * Added description of compute capabilities for Ampere generation GPU from Nvidia (PR #3535) + * Added doubleword OpenCL library (PR #3466, PR #3472) + +* Miscellaneous: + + * Enhanced: Setup the project to use `pytest` (PR #3431, #3516, #3526) + * Enhanced: Minor test clean up (PR #3515, #3508) + * Updated project structure: move `silx` sources in `src/silx` (PR #3412) + * Fixed 'run_test.py --qt-binding' option (PR #3527) + * Fixed support of numpy 1.21rc1 (PR ##3476) + * Removed `six` dependency (PR #3483) + + 0.15.2: 2021/06/21 ------------------ @@ -31,7 +286,6 @@ Minor release: * Fixed profile window default behavior (PR #3458) * Added `setProfileWindowBehavior` method (PR #3458) - 0.15.0: 2021/03/18 ------------------ @@ -101,7 +355,6 @@ Main new features are the `silx.io.h5py_utils` module which provides `h5py` conc * Fixed debian packaging (PR #3362) * Fixed `silx test` application on Windows (PR #3411) - 0.14.1: 2021/04/30 ------------------ @@ -110,7 +363,6 @@ This is a bug-fix version of silx. * silx.gui.plot: Fixed `PlotWidget` OpenGL backend memory leak (PR #3445) * silx.gui.utils.glutils: Fixed `isOpenGLAvailable` (PR #3356) - 0.14.0: 2020/12/11 ------------------ @@ -1,14 +1,3 @@ -The silx toolkit is a software library and one of its goals is not to impose any license to the end user. - -Silx follows the permissive MIT license although it may include contributions following other licenses not interfering with the previous goal. Detailed information can be found in the copyright file. - -Silx uses the Qt library for its graphical user interfaces. -A word of caution is to be provided. -If users develop and distribute software using modules accessing Qt by means of Riverbank Computing Qt bindings PyQt4 or PyQt5, those users will be conditioned by the license of their PyQt4/5 software (GPL or commercial). -If the end user does not own a commercial license of PyQt4 or PyQt5 and wishes to be free of any distribution condition, (s)he should be able to use PySide2 because it uses the LGPL license. - -The MIT license follows: - Copyright (c) European Synchrotron Radiation Facility (ESRF) Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/MANIFEST.in b/MANIFEST.in index da024c2..5ee9a8d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,18 +4,17 @@ include copyright include LICENSE include MANIFEST.in include run_tests.py -include version.py include stdeb.cfg include build-deb.sh include requirements.txt include requirements-dev.txt include pyproject.toml -recursive-include silx *.pyx *.pxd *.pxi -recursive-include silx *.h *.c *.hpp *.cpp +recursive-include src/silx *.pyx *.pxd *.pxi +recursive-include src/silx *.h *.c *.hpp *.cpp recursive-include doc/source *.py *.rst *.png *.ico *.ipynb global-exclude .ipynb_checkpoints/* recursive-include qtdesigner_plugins *.py *.rst -recursive-include silx/resources * +recursive-include src/silx/resources * recursive-include examples * recursive-include package * @@ -1,13 +1,13 @@ Metadata-Version: 2.1 Name: silx -Version: 0.15.2 +Version: 1.1.0 Summary: Software library for X-ray data analysis Home-page: http://www.silx.org/ Author: data analysis unit Author-email: silx@esrf.fr -License: UNKNOWN +License: MIT Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta +Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Environment :: MacOS X Classifier: Environment :: Win32 (MS Windows) @@ -26,12 +26,16 @@ Classifier: Topic :: Scientific/Engineering :: Physics Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.5 Provides-Extra: full +Provides-Extra: test License-File: LICENSE silx toolkit ============ +.. |silxView| image:: http://www.silx.org/doc/silx/img/silx-view-v1-0.gif + :height: 480px + The purpose of the *silx* project is to provide a collection of Python packages to support the development of data assessment, reduction and analysis applications at synchrotron radiation facilities. @@ -59,8 +63,12 @@ The current version features: * a set of applications: * a unified viewer (*silx view filename*) for HDF5, SPEC and image file formats + + |silxView| + * a unified converter to HDF5 format (*silx convert filename*) + Installation ------------ @@ -2,6 +2,9 @@ silx toolkit ============ +.. |silxView| image:: http://www.silx.org/doc/silx/img/silx-view-v1-0.gif + :height: 480px + The purpose of the *silx* project is to provide a collection of Python packages to support the development of data assessment, reduction and analysis applications at synchrotron radiation facilities. @@ -29,8 +32,12 @@ The current version features: * a set of applications: * a unified viewer (*silx view filename*) for HDF5, SPEC and image file formats + + |silxView| + * a unified converter to HDF5 format (*silx convert filename*) + Installation ------------ diff --git a/build-deb.sh b/build-deb.sh index 25718f3..23b0a86 100755 --- a/build-deb.sh +++ b/build-deb.sh @@ -3,7 +3,7 @@ # Project: Silx # https://github.com/silx-kit/silx # -# Copyright (C) 2015-2020 European Synchrotron Radiation Facility, Grenoble, France +# Copyright (C) 2015-2021 European Synchrotron Radiation Facility, Grenoble, France # # Principal author: Jérôme Kieffer (Jerome.Kieffer@ESRF.eu) # @@ -29,9 +29,6 @@ project=silx source_project=silx -version=$(python3 -c"import version; print(version.version)") -strictversion=$(python3 -c"import version; print(version.strictversion)") -debianversion=$(python3 -c"import version; print(version.debianversion)") deb_name=$(echo "$source_project" | tr '[:upper:]' '[:lower:]') @@ -66,6 +63,13 @@ project_directory="`( cd \"$project_directory\" && pwd )`" # absolutized dist_directory=${project_directory}/dist/${target_system} build_directory=${project_directory}/build/${target_system} +# Get version info +cd ${project_directory}/src/${project} +version=$(python3 -c"import _version; print(_version.version)") +strictversion=$(python3 -c"import _version; print(_version.strictversion)") +debianversion=$(python3 -c"import _version; print(_version.debianversion)") +cd ${project_directory} + if [ -d /usr/lib/ccache ]; then export PATH=/usr/lib/ccache:$PATH diff --git a/debian/changelog b/debian/changelog index 5898d9b..b55b37e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,60 @@ +silx (1.1.0+dfsg-3) unstable; urgency=medium + + * do not run test which use lot's of memory + + -- Picca Frédéric-Emmanuel <picca@debian.org> Fri, 04 Nov 2022 16:54:24 +0100 + +silx (1.1.0+dfsg-2) unstable; urgency=medium + + * fix a typo to avoid running test which use lot's of memory. + + -- Picca Frédéric-Emmanuel <picca@debian.org> Fri, 04 Nov 2022 15:42:11 +0100 + +silx (1.1.0+dfsg-1) unstable; urgency=medium + + * New upstream version 1.1.0+dfsg + * do not install the scipy_spatial COPYING file + + -- Picca Frédéric-Emmanuel <picca@debian.org> Thu, 03 Nov 2022 10:38:19 +0100 + +silx (1.0.0+dfsg-4) unstable; urgency=medium + + * Team Upload. + * d/salsa-ci.yml: Disable reprotest + * d/t/control: Skip testing on i386 + + -- Nilesh Patra <nilesh@debian.org> Mon, 14 Mar 2022 12:56:01 +0530 + +silx (1.0.0+dfsg-3) unstable; urgency=medium + + * Team Upload. + * d/t/control: Add test dep on python3-pytest (Closes: #1006690) + * d/t/control: Make test "not" no-op so as to wxit with + non-zero exit code when it fails + * Add patch to fix test with python3.10 + * Add d/salsa-ci.yml + + -- Nilesh Patra <nilesh@debian.org> Mon, 14 Mar 2022 02:04:04 +0530 + +silx (1.0.0+dfsg-2) unstable; urgency=medium + + * d/patches/0005-removed-hdf5plugin-from-full-dependencies.patch + + -- Picca Frédéric-Emmanuel <picca@debian.org> Thu, 10 Feb 2022 15:15:16 +0100 + +silx (1.0.0+dfsg-1) unstable; urgency=medium + + * New upstream version 1.0.0+dfsg + + -- Picca Frédéric-Emmanuel <picca@debian.org> Wed, 02 Feb 2022 14:43:11 +0100 + +silx (0.15.2+dfsg-3) unstable; urgency=medium + + * fix FTBFS by skipping two tests + https://github.com/silx-kit/silx/issues/3523 + + -- Picca Frédéric-Emmanuel <picca@debian.org> Sun, 19 Sep 2021 16:05:34 +0200 + silx (0.15.2+dfsg-2) unstable; urgency=medium * Bug fix: "Removal of the python3-*-dbg packages in sid/bookworm", diff --git a/debian/control b/debian/control index 0e40824..c11ab6d 100644 --- a/debian/control +++ b/debian/control @@ -1,41 +1,44 @@ Source: silx Maintainer: Debian Science Maintainers <debian-science-maintainers@lists.alioth.debian.org> -Uploaders: Jerome Kieffer <jerome.kieffer@esrf.fr>, - Picca Frédéric-Emmanuel <picca@debian.org>, - Alexandre Marie <alexandre.marie@synchrotron-soleil.fr> +Uploaders: + Jerome Kieffer <jerome.kieffer@esrf.fr>, + Picca Frédéric-Emmanuel <picca@debian.org>, + Alexandre Marie <alexandre.marie@synchrotron-soleil.fr>, Section: science Priority: optional -Build-Depends: cython3, - debhelper-compat (= 13), - dh-python, - dh-sequence-numpy3, - dh-sequence-python3, - help2man, - ipython3, - python3-all-dev, - python3-fabio, - python3-h5py, - python3-mako, - python3-matplotlib, - python3-numpy, - python3-opengl, - python3-pil, - python3-pyopencl, - python3-pyqt5, - python3-pyqt5.qtopengl, - python3-pyqt5.qtsvg, - python3-qtconsole, - python3-scipy, - python3-setuptools, - xauth, - xvfb +Build-Depends: + cython3, + debhelper-compat (= 13), + dh-python, + dh-sequence-numpy3, + dh-sequence-python3, + help2man, + ipython3, + python3-all-dev, + python3-fabio, + python3-h5py, + python3-mako, + python3-matplotlib, + python3-numpy, + python3-opengl, + python3-pil, + python3-pyopencl, + python3-pyqt5, + python3-pyqt5.qtopengl, + python3-pyqt5.qtsvg, + python3-pytest <!nocheck>, + python3-qtconsole, + python3-scipy, + python3-setuptools, + xauth, + xvfb, Build-Depends-Indep: - dh-sequence-sphinxdoc <!nodoc>, - pandoc <!nodoc>, - python3-nbsphinx <!nodoc>, - python3-sphinx, - python3-sphinxcontrib.programoutput, -Standards-Version: 4.5.1 + dh-sequence-sphinxdoc <!nodoc>, + pandoc <!nodoc>, + python3-nbsphinx <!nodoc>, + python3-sphinx, + python3-sphinxcontrib.programoutput, +Standards-Version: 4.6.0 Vcs-Browser: https://salsa.debian.org/science-team/silx Vcs-Git: https://salsa.debian.org/science-team/silx.git Homepage: https://github.com/silx-kit/silx @@ -43,10 +46,11 @@ Rules-Requires-Root: no Package: silx Architecture: all -Depends: python3-silx (>= ${source:Version}), - ${misc:Depends}, - ${python3:Depends}, - ${shlibs:Depends} +Depends: + python3-silx (>= ${source:Version}), + ${misc:Depends}, + ${python3:Depends}, + ${shlibs:Depends}, Description: Toolbox for X-Ray data analysis - Executables The silx project aims at providing a collection of Python packages to support the development of data assessment, reduction and analysis @@ -72,7 +76,10 @@ Description: Toolbox for X-Ray data analysis - Executables Package: python3-silx Architecture: any Section: python -Depends: ${misc:Depends}, ${python3:Depends}, ${shlibs:Depends} +Depends: + ${misc:Depends}, + ${python3:Depends}, + ${shlibs:Depends}, Description: Toolbox for X-Ray data analysis - Python3 The silx project aims at providing a collection of Python packages to support the development of data assessment, reduction and analysis @@ -98,7 +105,10 @@ Description: Toolbox for X-Ray data analysis - Python3 Package: python-silx-doc Architecture: all Section: doc -Depends: libjs-mathjax, ${misc:Depends}, ${sphinxdoc:Depends} +Depends: + libjs-mathjax, + ${misc:Depends}, + ${sphinxdoc:Depends}, Multi-Arch: foreign Description: Toolbox for X-Ray data analysis - Documentation The silx project aims at providing a collection of Python packages to diff --git a/debian/copyright b/debian/copyright index f0510f5..548070c 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,12 +1,12 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: silx Source: https://github.com/silx-kit/silx -Files-Excluded: silx/opencl/sift - silx/resources/opencl/sift - silx/third_party/_local +Files-Excluded: src/silx/opencl/sift + src/silx/resources/opencl/sift + src/silx/third_party/_local Files: * -Copyright: 2004-2017 European Synchrotron Radiation Facility +Copyright: 2004-2017, 2022 European Synchrotron Radiation Facility Data analysis unit (silx@esrf.fr) License: Expat diff --git a/debian/patches/0002-use-the-system-mathjax-privacy-breach.patch b/debian/patches/0002-use-the-system-mathjax-privacy-breach.patch index 5c52c11..e6ff374 100644 --- a/debian/patches/0002-use-the-system-mathjax-privacy-breach.patch +++ b/debian/patches/0002-use-the-system-mathjax-privacy-breach.patch @@ -8,10 +8,10 @@ Subject: use the system mathjax (privacy breach) 1 file changed, 5 insertions(+) diff --git a/doc/source/conf.py b/doc/source/conf.py -index 7e173f3..86e7bfa 100644 +index 2d242e9..38b531d 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py -@@ -144,6 +144,11 @@ pygments_style = 'sphinx' +@@ -138,6 +138,11 @@ pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] diff --git a/debian/patches/0003-do-not-modify-PYTHONPATH-from-setup.py.patch b/debian/patches/0003-do-not-modify-PYTHONPATH-from-setup.py.patch index 2a43553..6453274 100644 --- a/debian/patches/0003-do-not-modify-PYTHONPATH-from-setup.py.patch +++ b/debian/patches/0003-do-not-modify-PYTHONPATH-from-setup.py.patch @@ -7,10 +7,10 @@ Subject: do not modify PYTHONPATH from setup.py 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py -index 771374c..bc43c32 100644 +index 527c072..04599d9 100644 --- a/setup.py +++ b/setup.py -@@ -313,7 +313,8 @@ class BuildMan(Command): +@@ -229,7 +229,8 @@ class BuildMan(Command): path.insert(0, os.path.abspath(build.build_lib)) env = dict((str(k), str(v)) for k, v in os.environ.items()) diff --git a/debian/patches/0004-skip-two-tests.patch b/debian/patches/0004-skip-two-tests.patch new file mode 100644 index 0000000..fbef5d1 --- /dev/null +++ b/debian/patches/0004-skip-two-tests.patch @@ -0,0 +1,29 @@ +From: =?utf-8?q?Picca_Fr=C3=A9d=C3=A9ric-Emmanuel?= <picca@debian.org> +Date: Sun, 19 Sep 2021 16:03:58 +0200 +Subject: skip two tests + +"https://github.com/silx-kit/silx/issues/3523" +--- + src/silx/io/test/test_h5py_utils.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/silx/io/test/test_h5py_utils.py b/src/silx/io/test/test_h5py_utils.py +index 0d10a78..f6405c6 100644 +--- a/src/silx/io/test/test_h5py_utils.py ++++ b/src/silx/io/test/test_h5py_utils.py +@@ -248,6 +248,7 @@ class TestH5pyUtils(unittest.TestCase): + "Versions of libhdf5 and h5py use incompatible file locking behaviour", + ) + @subtests ++ @unittest.skipIf(True, "https://github.com/silx-kit/silx/issues/3523") + def test_modes_multi_process(self): + """Test concurrent access to the same file from different processes""" + filename = self._new_filename() +@@ -322,6 +323,7 @@ class TestH5pyUtils(unittest.TestCase): + + @subtests + @unittest.skipIf(not h5py_utils.HAS_SWMR, "SWMR not supported") ++ @unittest.skipIf(True, "https://github.com/silx-kit/silx/issues/3523") + def test_modes_multi_process_swmr(self): + filename = self._new_filename() + diff --git a/debian/patches/0005-removed-hdf5plugin-from-full-dependencies.patch b/debian/patches/0005-removed-hdf5plugin-from-full-dependencies.patch new file mode 100644 index 0000000..d1965e0 --- /dev/null +++ b/debian/patches/0005-removed-hdf5plugin-from-full-dependencies.patch @@ -0,0 +1,20 @@ +From: =?utf-8?q?Picca_Fr=C3=A9d=C3=A9ric-Emmanuel?= <picca@debian.org> +Date: Thu, 10 Feb 2022 15:14:41 +0100 +Subject: removed hdf5plugin from full dependencies + +--- + setup.py | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/setup.py b/setup.py +index 04599d9..18e10cc 100644 +--- a/setup.py ++++ b/setup.py +@@ -516,7 +516,6 @@ def get_project_configuration(): + 'python-dateutil', + 'PyQt5', + # extra +- 'hdf5plugin', + 'scipy', + 'Pillow'] + diff --git a/debian/patches/0006-Tests-if-openCL-can-be-used.patch b/debian/patches/0006-Tests-if-openCL-can-be-used.patch index 23bbcc6..6fd8a20 100644 --- a/debian/patches/0006-Tests-if-openCL-can-be-used.patch +++ b/debian/patches/0006-Tests-if-openCL-can-be-used.patch @@ -3,14 +3,14 @@ Date: Fri, 5 Jul 2019 16:52:20 +0200 Subject: Tests if openCL can be used --- - silx/opencl/common.py | 2 ++ + src/silx/opencl/common.py | 2 ++ 1 file changed, 2 insertions(+) -diff --git a/silx/opencl/common.py b/silx/opencl/common.py -index b66b7b7..da966f6 100644 ---- a/silx/opencl/common.py -+++ b/silx/opencl/common.py -@@ -74,6 +74,8 @@ if pyopencl is None: +diff --git a/src/silx/opencl/common.py b/src/silx/opencl/common.py +index cf51406..5702f74 100644 +--- a/src/silx/opencl/common.py ++++ b/src/silx/opencl/common.py +@@ -73,6 +73,8 @@ if pyopencl is None: WRITE_ONLY = 1 READ_ONLY = 1 READ_WRITE = 1 diff --git a/debian/patches/0007-do-not-install-scipy_spatial-COPYING.txt.patch b/debian/patches/0007-do-not-install-scipy_spatial-COPYING.txt.patch new file mode 100644 index 0000000..7e0b287 --- /dev/null +++ b/debian/patches/0007-do-not-install-scipy_spatial-COPYING.txt.patch @@ -0,0 +1,22 @@ +From: =?utf-8?q?Picca_Fr=C3=A9d=C3=A9ric-Emmanuel?= <picca@debian.org> +Date: Thu, 3 Nov 2022 10:22:11 +0100 +Subject: do not install scipy_spatial COPYING.txt + +--- + setup.py | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/setup.py b/setup.py +index 18e10cc..523333f 100644 +--- a/setup.py ++++ b/setup.py +@@ -787,9 +787,6 @@ def get_project_configuration(): + }, + ext_modules=ext_modules, + package_data=package_data, +- data_files=[ +- ('silx/third_party/_local/scipy_spatial/qhull', ['src/silx/third_party/_local/scipy_spatial/qhull/COPYING.txt']) +- ], + ) + + diff --git a/debian/patches/0007-python3.10-fix.patch b/debian/patches/0007-python3.10-fix.patch new file mode 100644 index 0000000..c36eeb8 --- /dev/null +++ b/debian/patches/0007-python3.10-fix.patch @@ -0,0 +1,65 @@ +From: Nilesh Patra <nilesh@debian.org> +Date: Sun, 13 Mar 2022 03:37:32 +0100 +Subject: Fix int compare with python3.10, skip a couple of tests + +--- + src/silx/app/view/About.py | 2 +- + src/silx/gui/data/test/test_arraywidget.py | 2 ++ + src/silx/opencl/test/test_medfilt.py | 4 +++- + 3 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/silx/app/view/About.py b/src/silx/app/view/About.py +index 2af7ed4..eb5ec16 100644 +--- a/src/silx/app/view/About.py ++++ b/src/silx/app/view/About.py +@@ -242,7 +242,7 @@ class About(qt.QDialog): + width = hardLimit + + height = layoutMinimumSize.height() +- self.setFixedSize(width, height) ++ self.setFixedSize(int(width), int(height)) + + @staticmethod + def about(parent, applicationName): +diff --git a/src/silx/gui/data/test/test_arraywidget.py b/src/silx/gui/data/test/test_arraywidget.py +index 024383d..915238d 100644 +--- a/src/silx/gui/data/test/test_arraywidget.py ++++ b/src/silx/gui/data/test/test_arraywidget.py +@@ -28,6 +28,7 @@ __date__ = "05/12/2016" + import os + import tempfile + import unittest ++import pytest + + import numpy + +@@ -186,6 +187,7 @@ class TestArrayWidget(TestCaseQt): + b1 = self.aw.getData(copy=False) + self.assertIs(b0, b1) + ++ @pytest.mark.skip(reason="Skip for now since it chokes witth py3.10") + def testClipping(self): + """Test clipping of large arrays""" + self.aw.show() +diff --git a/src/silx/opencl/test/test_medfilt.py b/src/silx/opencl/test/test_medfilt.py +index e657d0d..dfc598d 100644 +--- a/src/silx/opencl/test/test_medfilt.py ++++ b/src/silx/opencl/test/test_medfilt.py +@@ -40,6 +40,8 @@ import time + import logging + import numpy + import unittest ++import pytest ++ + from collections import namedtuple + try: + import mako +@@ -69,7 +71,7 @@ except: + HAS_SCIPY = False + from silx.math import medfilt2d as median_filter + +-@unittest.skipUnless(ocl and mako, "PyOpenCl is missing") ++@pytest.mark.skip(reason="PyOpenCl is missing") + class TestMedianFilter(unittest.TestCase): + + def setUp(self): diff --git a/debian/patches/series b/debian/patches/series index efd273e..0d007fc 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,7 @@ 0002-use-the-system-mathjax-privacy-breach.patch 0003-do-not-modify-PYTHONPATH-from-setup.py.patch 0006-Tests-if-openCL-can-be-used.patch +0004-skip-two-tests.patch +0005-removed-hdf5plugin-from-full-dependencies.patch +0007-python3.10-fix.patch +0007-do-not-install-scipy_spatial-COPYING.txt.patch diff --git a/debian/rules b/debian/rules index 58893e8..0f9a149 100755 --- a/debian/rules +++ b/debian/rules @@ -52,11 +52,12 @@ execute_before_dh_install: # WITH_QT_TEST=False to disable graphical tests # SILX_OPENCL=False to disable OpenCL tests -# SILX_TEST_LOW_MEM=True to disable tests taking large amount of memory +# SILX_TEST_LOW_MEM=False to disable tests taking large amount of memory # GPU=False to disable the use of a GPU with OpenCL test # WITH_GL_TEST=False to disable tests using OpenGL override_dh_auto_test: - dh_auto_test -- -s custom --test-args="env PYTHONPATH={build_dir} GPU=False WITH_QT_TEST=False SILX_OPENCL=False SILX_TEST_LAW_MEM=True xvfb-run -a --server-args=\"-screen 0 1024x768x24\" {interpreter} run_tests.py -vv --installed" + GPU=False WITH_QT_TEST=False SILX_OPENCL=False SILX_TEST_LOW_MEM=False \ + dh_auto_test execute_after_dh_installdocs: dh_installdocs -p python-silx-doc "doc/build/html" --doc-main-package=python3-silx diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml new file mode 100644 index 0000000..1e7946b --- /dev/null +++ b/debian/salsa-ci.yml @@ -0,0 +1,7 @@ +--- +include: + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml + +variables: + SALSA_CI_DISABLE_REPROTEST: 1 diff --git a/debian/tests/control b/debian/tests/control index b6fa2c3..4dcec27 100644 --- a/debian/tests/control +++ b/debian/tests/control @@ -2,6 +2,13 @@ Test-Command: set -efu ; for py in $(py3versions -r 2>/dev/null) ; do cd "$AUTOPKGTEST_TMP" ; echo "Testing with $py:" - ; xvfb-run -a --server-args="-screen 0 1024x768x24" $py -c "import silx.test; silx.test.run_tests()" 2>&1 + ; SILX_TEST_LOW_MEM=False xvfb-run -a --server-args="-screen 0 1024x768x24" $py -c "import sys; import silx.test; sys.exit(silx.test.run_tests())" 2>&1 ; done -Depends: python3-all, python3-silx, xauth, xvfb +Depends: + @, + python3-all, + python3-pytest, + python3-pytest-xvfb, + xauth, + xvfb, +Architecture: !i386 diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc index 101f781..6fb0a40 100644 --- a/debian/upstream/signing-key.asc +++ b/debian/upstream/signing-key.asc @@ -1,201 +1,52 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -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 -YG7V46Fb3g29l4SV019ge/7aVyJPYyllvWg= -=D1XZ +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 +nb7YbK8= +=gXaR -----END PGP PUBLIC KEY BLOCK----- diff --git a/debian/watch b/debian/watch index 99444f9..d221e62 100644 --- a/debian/watch +++ b/debian/watch @@ -1,6 +1,7 @@ version=4 opts=repacksuffix=+dfsg,\ pgpsigurlmangle=s/$/.asc/,\ +pgpmode=none,\ dversionmangle=s/\+dfsg//,\ uversionmangle=s/(rc|a|b|c)/~$1/ \ https://pypi.python.org/packages/source/s/@PACKAGE@/ \ diff --git a/doc/source/Tutorials/array_widget.rst b/doc/source/Tutorials/array_widget.rst index c6a32e3..b0bc890 100644 --- a/doc/source/Tutorials/array_widget.rst +++ b/doc/source/Tutorials/array_widget.rst @@ -23,7 +23,7 @@ Let's look at a simple usage example: w = ArrayTableWidget() w.setArrayData(array, labels=True) w.show() - app.exec_() + app.exec() .. |imgArray0| image:: img/arraywidget3D_0.png @@ -242,6 +242,6 @@ of RGB colors. fgcolors=fcolors) atw.show() - app.exec_() + app.exec() diff --git a/doc/source/Tutorials/fit.rst b/doc/source/Tutorials/fit.rst index d9671f4..c0eafc5 100644 --- a/doc/source/Tutorials/fit.rst +++ b/doc/source/Tutorials/fit.rst @@ -450,7 +450,7 @@ The following example illustrates the strip background removal process: app = qt.QApplication([]) plot(x, y, x, actual_bg, x, strip_bg) plot(x, y, x, (y - strip_bg)) - app.exec_() + app.exec() .. |imgStrip1| image:: img/stripbg_plot1.png :height: 300px @@ -545,7 +545,7 @@ Simple usage w.setData(x=x, y=y) w.show() - a.exec_() + a.exec() .. |imgFitWidget1| image:: img/fitwidget1.png :width: 300px @@ -638,7 +638,7 @@ The :class:`FitWidget` can be initialised with a non-standard fw = FitWidget(fitmngr=myfitmngr) fw.show() - a.exec_() + a.exec() In our previous example, we didn't load a customised :class:`FitManager`, therefore, the fit widget automatically initialised the default fit manager and diff --git a/doc/source/Tutorials/fitconfig.rst b/doc/source/Tutorials/fitconfig.rst index 225ef8f..0d7538c 100644 --- a/doc/source/Tutorials/fitconfig.rst +++ b/doc/source/Tutorials/fitconfig.rst @@ -52,7 +52,7 @@ dialog by FitWidget: - :meth:`show`: should cause the widget to become visible to the user) - - :meth:`exec_`: should run while the user is interacting with the + - :meth:`exec`: should run while the user is interacting with the widget, interrupting the rest of the program. It should typically end (*return*) when the user clicks an *OK* or a *Cancel* button. @@ -175,7 +175,7 @@ used by our fit function to scale the *y* values. fw.associateConfigDialog("scaled linear", CustomConfigWidget()) fw.show() - app.exec_() + app.exec() .. |img0| image:: img/custom_config_scale1.0.png :height: 300px diff --git a/doc/source/Tutorials/io.rst b/doc/source/Tutorials/io.rst index 41a0dd3..4c54bba 100644 --- a/doc/source/Tutorials/io.rst +++ b/doc/source/Tutorials/io.rst @@ -324,6 +324,34 @@ For example to process all top-level groups of an HDF5 file: Note that the method with the `retry` decorator has to be idempotent as it can be executed several times for one call. +An equivalent decorator exists for context managers + +.. code-block:: python + + import silx.io.h5py_utils + + @silx.io.h5py_utils.retry_contextmanager() + def measurement_context(filename, name): + """The method will be entered again if + any HDF5 IO fails. + """ + with silx.io.h5py_utils.File(filename) as h5file: + yield h5file[name]["measurement"] + +Generator functions need to have a `start_index` parameter + +.. code-block:: python + + import silx.io.h5py_utils + + @silx.io.h5py_utils.retry() + def iter_measurement(filename, names, start_index=0): + """The method will be iterated again if any HDF5 + IO fails, possibly with a different start index. + """ + with silx.io.h5py_utils.File(filename) as h5file: + for name in names[start_index:]: + yield h5file[name]["measurement"] Additional resources -------------------- diff --git a/doc/source/Tutorials/writing_NXdata.rst b/doc/source/Tutorials/writing_NXdata.rst index 1c65199..4d87e3d 100644 --- a/doc/source/Tutorials/writing_NXdata.rst +++ b/doc/source/Tutorials/writing_NXdata.rst @@ -154,8 +154,7 @@ a *frame number*. .. note:: - This additional attribute is not mentionned in the official NXdata - specification. + This attribute is documented in the official NeXus `description <https://manual.nexusformat.org/nxdl_desc.html>`_ Writing NXdata with h5py diff --git a/doc/source/applications/view.rst b/doc/source/applications/view.rst index d4145c2..747a121 100644 --- a/doc/source/applications/view.rst +++ b/doc/source/applications/view.rst @@ -1,7 +1,11 @@ +.. _silx view: silx view ========= +.. figure:: http://www.silx.org/doc/silx/img/silx-view-v1-0.gif + :align: center + Purpose ------- diff --git a/doc/source/conf.py b/doc/source/conf.py index 86e7bfa..38b531d 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -1,6 +1,5 @@ -# -*- coding: utf-8 -*- # /*########################################################################## -# Copyright (C) 2015-2019 European Synchrotron Radiation Facility +# Copyright (C) 2015-2022 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -32,25 +31,16 @@ autogenerated file. All configuration values have a default; values that are commented out serve to show the default.""" -import sys +import importlib import os -import os.path -import glob -import subprocess +import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) project = u'silx' -try: - import silx - project_dir = os.path.abspath(os.path.join(__file__, "..", "..", "..")) - build_dir = os.path.abspath(silx.__file__) - if not build_dir.startswith(project_dir): - raise RuntimeError("%s looks to come from the system. Fix your PYTHONPATH and restart sphinx." % project) -except ImportError: - raise RuntimeError("%s is not on the path. Fix your PYTHONPATH and restart sphinx." % project) +import silx # Disable deprecation warnings: # It avoid to spam documentation logs with deprecation warnings. @@ -79,9 +69,13 @@ extensions = [ 'sphinxext-archive', 'snapshotqt_directive', 'nbsphinx' - ] +if importlib.util.find_spec('sphinx_autodoc_typehints'): + extensions.append('sphinx_autodoc_typehints') + + always_document_param_types = True + autodoc_member_order = 'bysource' # Add any paths that contain templates here, relative to this directory. diff --git a/doc/source/ext/snapshotqt_directive.py b/doc/source/ext/snapshotqt_directive.py index 582b934..2a40992 100644 --- a/doc/source/ext/snapshotqt_directive.py +++ b/doc/source/ext/snapshotqt_directive.py @@ -1,4 +1,3 @@ -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2004-2019 European Synchrotron Radiation Facility @@ -31,7 +30,6 @@ Configuration variable in conf.py: the documentation source directory (i.e., the directory of conf.py) (default: '..'). """ -from __future__ import absolute_import __authors__ = ["H. Payno", "T. Vincent"] __license__ = "MIT" @@ -152,7 +150,7 @@ else: _towrite = _line.lstrip(' ') if not _towrite.startswith(':'): _file.write(_towrite + '\n') - _file.write("app.exec_()") + _file.write("app.exec()") self.content = [] if script is not None: _logger.warning('Cannot specify a script if source code (content) is given.' diff --git a/doc/source/ext/sphinxext-archive.py b/doc/source/ext/sphinxext-archive.py index dc1c2c8..39004e0 100644 --- a/doc/source/ext/sphinxext-archive.py +++ b/doc/source/ext/sphinxext-archive.py @@ -1,4 +1,3 @@ -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2017 European Synchrotron Radiation Facility diff --git a/doc/source/index.rst b/doc/source/index.rst index 1c4ad72..027bd6f 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,6 +1,9 @@ silx |version| ============== +.. |silxView| image:: http://www.silx.org/doc/silx/img/silx-view-v1-0.gif + :height: 80px + The silx project aims to provide a collection of Python packages to support the development of data assessment, reduction and analysis at synchrotron radiation facilities. @@ -28,9 +31,13 @@ The current version (v\ |version|) caters for: * a set of applications: - * a unified viewer (*silx view filename*) for HDF5, SPEC and image file formats - * a unified converter to HDF5 format (*silx convert filename*) + * a unified viewer (:ref:`silx view` *filename*) for HDF5, SPEC and image file formats + + |silxView| + + * a unified converter to HDF5 format (*silx convert filename*) + .. toctree:: :hidden: diff --git a/doc/source/install.rst b/doc/source/install.rst index b0d6b4f..db86ac1 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -7,15 +7,15 @@ programming language. This table summarizes the support matrix of silx: -+------------+--------------+---------------------+ -| System | Python vers. | Qt and its bindings | -+------------+--------------+---------------------+ -| `Windows`_ | 3.6-3.9 | PyQt5.6+, PySide2 | -+------------+--------------+---------------------+ -| `MacOS`_ | 3.6-3.9 | PyQt5.6+, PySide2 | -+------------+--------------+---------------------+ -| `Linux`_ | 3.6-3.9 | PyQt5.3+, PySide2 | -+------------+--------------+---------------------+ ++------------+--------------+-----------------------------+ +| System | Python vers. | Qt and its bindings | ++------------+--------------+-----------------------------+ +| `Windows`_ | 3.6-3.9 | PyQt5.6+, PySide6, PyQt6.3+ | ++------------+--------------+-----------------------------+ +| `MacOS`_ | 3.6-3.9 | PyQt5.6+, PySide6, PyQt6.3+ | ++------------+--------------+-----------------------------+ +| `Linux`_ | 3.6-3.9 | PyQt5.3+, PySide6, PyQt6.3+ | ++------------+--------------+-----------------------------+ For the description of *silx* dependencies, see the Dependencies_ section. @@ -66,7 +66,8 @@ The mandatory dependencies are: The GUI widgets depend on the following extra packages: * A Qt binding: either `PyQt5 <https://riverbankcomputing.com/software/pyqt/intro>`_, - or `PySide2 <https://wiki.qt.io/Qt_for_Python>`_ + `PySide6 <https://pypi.org/project/PySide6/>`_ or + `PyQt6 <https://pypi.org/project/PyQt6/>`_ * `matplotlib <http://matplotlib.org/>`_ * `PyOpenGL <http://pyopengl.sourceforge.net/>`_ * `qt_console <https://pypi.org/project/qtconsole>`_ @@ -245,7 +246,7 @@ installed using: .. code-block:: bash - pip install -r https://github.com/silx-kit/silx/raw/0.8/requirements-dev.txt + pip install -r https://github.com/silx-kit/silx/raw/master/requirements-dev.txt Building from source @@ -288,32 +289,46 @@ To set the environment variables, type on the command line: Advanced build options ++++++++++++++++++++++ -In case you want more control over the build procedure, the build command is: +Advanced options can be set through the following environment variables: -.. code-block:: bash - - python setup.py build +.. list-table:: + :widths: 1 4 + :header-rows: 1 -There are few advanced options to ``setup.py build``: + * - Environment variable + - Description + * - ``SILX_WITH_OPENMP`` + - Whether or not to compile Cython code with OpenMP support (default: ``True`` except on macOS where it is ``False``) + * - ``SILX_FORCE_CYTHON`` + - Whether or not to force re-generating the C/C++ source code from Cython files (default: ``False``). + * - ``SPECFILE_USE_GNU_SOURCE`` + - Whether or not to use a cleaner locale independent implementation of :mod:`silx.io.specfile` by using `_GNU_SOURCE=1` + (default: ``False``; POSIX operating system only). + * - ``SILX_FULL_INSTALL_REQUIRES`` + - Set it to put all dependencies as ``install_requires`` (For packaging purpose). + * - ``SILX_INSTALL_REQUIRES_STRIP`` + - Comma-separated list of package names to remove from ``install_requires`` (For packaging purpose). +.. note:: Boolean options are passed as ``True`` or ``False``. -* ``--no-cython``: Prevent Cython (even if installed) from re-generating the C source code. - Use the one provided by the development team. -* ``--no-openmp``: Recompiles the Cython code without OpenMP support (default for MacOSX). -* ``--openmp``: Recompiles the Cython code with OpenMP support (default for Windows and Linux). -Package the build into a wheel and install it: +Package the build into a wheel and install it (this requires to install the `build <https://pypa-build.readthedocs.io>`_ package): .. code-block:: bash - python setup.py bdist_wheel + python -m build --wheel pip install dist/silx*.whl To build the documentation, using `Sphinx <http://www.sphinx-doc.org/>`_: .. code-block:: bash - python setup.py build build_doc + pip install . # Make sure to install the same version as the source + sphinx-build doc/source/ build/html + +.. note:: + To re-generate the example script screenshots, build the documentation with the + environment variable ``DIRECTIVE_SNAPSHOT_QT`` set to ``True``. Testing +++++++ diff --git a/doc/source/license.rst b/doc/source/license.rst index 760be91..2e79bc3 100644 --- a/doc/source/license.rst +++ b/doc/source/license.rst @@ -4,6 +4,18 @@ License The source code of *silx* is licensed under the `MIT <https://opensource.org/licenses/MIT>`_ license: .. include:: ../../LICENSE + :literal: + +Note: + The silx toolkit is a software library and one of its goals is not to impose any license to the end user. + + silx follows the permissive MIT license although it may include contributions following other licenses not interfering with the previous goal. + Detailed information can be found in the copyright file. + + silx uses the Qt library for its graphical user interfaces. + A word of caution is to be provided. + If users develop and distribute software using modules accessing Qt by means of Riverbank Computing Qt bindings PyQt4 or PyQt5, those users will be conditioned by the license of their PyQt4/5 software (GPL or commercial). + If the end user does not own a commercial license of PyQt4 or PyQt5 and wishes to be free of any distribution condition, (s)he should be able to use PySide2 because it uses the LGPL license. The following list provides the copyright and license of the different source files of the project: diff --git a/doc/source/modules/gui/data/img/ArrayTableWidget.png b/doc/source/modules/gui/data/img/ArrayTableWidget.png Binary files differindex e7bb2a9..138d189 100644 --- a/doc/source/modules/gui/data/img/ArrayTableWidget.png +++ b/doc/source/modules/gui/data/img/ArrayTableWidget.png diff --git a/doc/source/modules/gui/data/img/DataViewer.png b/doc/source/modules/gui/data/img/DataViewer.png Binary files differindex 7980de9..6d0da71 100644 --- a/doc/source/modules/gui/data/img/DataViewer.png +++ b/doc/source/modules/gui/data/img/DataViewer.png diff --git a/doc/source/modules/gui/icons.rst b/doc/source/modules/gui/icons.rst index 67235c2..238c724 100644 --- a/doc/source/modules/gui/icons.rst +++ b/doc/source/modules/gui/icons.rst @@ -49,12 +49,16 @@ Available icons - add-shape-polygon * - |add-shape-rectangle| - add-shape-rectangle + * - |add-shape-rotated-rectangle| + - add-shape-rotated-rectangle * - |add-shape-unknown| - add-shape-unknown * - |add-shape-vertical| - add-shape-vertical * - |add| - add + * - |aggregation-mode| + - aggregation-mode * - |arrow-keys| - arrow-keys * - |axis| @@ -313,6 +317,10 @@ Available icons - rotate-3d * - |rudder| - rudder + * - |scale-auto| + - scale-auto + * - |scale-fixed| + - scale-fixed * - |selected| - selected * - |shape-circle-solid| @@ -339,6 +347,8 @@ Available icons - shape-square * - |shape-vertical| - shape-vertical + * - |side-histograms| + - side-histograms * - |silx| - silx * - |slice-cross| @@ -402,194 +412,199 @@ Available icons * - |zoom| - zoom -.. |3d-plane-normal-x| image:: ../../../../silx/resources/gui/icons/3d-plane-normal-x.png -.. |3d-plane-normal-y| image:: ../../../../silx/resources/gui/icons/3d-plane-normal-y.png -.. |3d-plane-normal-z| image:: ../../../../silx/resources/gui/icons/3d-plane-normal-z.png -.. |3d-plane-pan| image:: ../../../../silx/resources/gui/icons/3d-plane-pan.png -.. |3d-plane| image:: ../../../../silx/resources/gui/icons/3d-plane.png -.. |add-range-horizontal| image:: ../../../../silx/resources/gui/icons/add-range-horizontal.png -.. |add-shape-arc| image:: ../../../../silx/resources/gui/icons/add-shape-arc.png -.. |add-shape-circle| image:: ../../../../silx/resources/gui/icons/add-shape-circle.png -.. |add-shape-cross| image:: ../../../../silx/resources/gui/icons/add-shape-cross.png -.. |add-shape-diagonal| image:: ../../../../silx/resources/gui/icons/add-shape-diagonal.png -.. |add-shape-ellipse| image:: ../../../../silx/resources/gui/icons/add-shape-ellipse.png -.. |add-shape-horizontal| image:: ../../../../silx/resources/gui/icons/add-shape-horizontal.png -.. |add-shape-point| image:: ../../../../silx/resources/gui/icons/add-shape-point.png -.. |add-shape-polygon| image:: ../../../../silx/resources/gui/icons/add-shape-polygon.png -.. |add-shape-rectangle| image:: ../../../../silx/resources/gui/icons/add-shape-rectangle.png -.. |add-shape-unknown| image:: ../../../../silx/resources/gui/icons/add-shape-unknown.png -.. |add-shape-vertical| image:: ../../../../silx/resources/gui/icons/add-shape-vertical.png -.. |add| image:: ../../../../silx/resources/gui/icons/add.png -.. |arrow-keys| image:: ../../../../silx/resources/gui/icons/arrow-keys.png -.. |axis| image:: ../../../../silx/resources/gui/icons/axis.png -.. |backend-opengl| image:: ../../../../silx/resources/gui/icons/backend-opengl.png -.. |camera| image:: ../../../../silx/resources/gui/icons/camera.png -.. |clipboard| image:: ../../../../silx/resources/gui/icons/clipboard.png -.. |close| image:: ../../../../silx/resources/gui/icons/close.png -.. |colorbar| image:: ../../../../silx/resources/gui/icons/colorbar.png -.. |colormap-histogram| image:: ../../../../silx/resources/gui/icons/colormap-histogram.png -.. |colormap-none| image:: ../../../../silx/resources/gui/icons/colormap-none.png -.. |colormap-norm-arcsinh| image:: ../../../../silx/resources/gui/icons/colormap-norm-arcsinh.png -.. |colormap-norm-gamma| image:: ../../../../silx/resources/gui/icons/colormap-norm-gamma.png -.. |colormap-norm-linear| image:: ../../../../silx/resources/gui/icons/colormap-norm-linear.png -.. |colormap-norm-log| image:: ../../../../silx/resources/gui/icons/colormap-norm-log.png -.. |colormap-norm-sqrt| image:: ../../../../silx/resources/gui/icons/colormap-norm-sqrt.png -.. |colormap-range| image:: ../../../../silx/resources/gui/icons/colormap-range.png -.. |colormap| image:: ../../../../silx/resources/gui/icons/colormap.png -.. |compare-align-auto| image:: ../../../../silx/resources/gui/icons/compare-align-auto.png -.. |compare-align-center| image:: ../../../../silx/resources/gui/icons/compare-align-center.png -.. |compare-align-origin| image:: ../../../../silx/resources/gui/icons/compare-align-origin.png -.. |compare-align-stretch| image:: ../../../../silx/resources/gui/icons/compare-align-stretch.png -.. |compare-keypoints| image:: ../../../../silx/resources/gui/icons/compare-keypoints.png -.. |compare-mode-a-minus-b| image:: ../../../../silx/resources/gui/icons/compare-mode-a-minus-b.png -.. |compare-mode-a| image:: ../../../../silx/resources/gui/icons/compare-mode-a.png -.. |compare-mode-b| image:: ../../../../silx/resources/gui/icons/compare-mode-b.png -.. |compare-mode-hline| image:: ../../../../silx/resources/gui/icons/compare-mode-hline.png -.. |compare-mode-rb-channel| image:: ../../../../silx/resources/gui/icons/compare-mode-rb-channel.png -.. |compare-mode-rbneg-channel| image:: ../../../../silx/resources/gui/icons/compare-mode-rbneg-channel.png -.. |compare-mode-vline| image:: ../../../../silx/resources/gui/icons/compare-mode-vline.png -.. |crop| image:: ../../../../silx/resources/gui/icons/crop.png -.. |crosshair| image:: ../../../../silx/resources/gui/icons/crosshair.png -.. |cube-back| image:: ../../../../silx/resources/gui/icons/cube-back.png -.. |cube-bottom| image:: ../../../../silx/resources/gui/icons/cube-bottom.png -.. |cube-front| image:: ../../../../silx/resources/gui/icons/cube-front.png -.. |cube-left| image:: ../../../../silx/resources/gui/icons/cube-left.png -.. |cube-right| image:: ../../../../silx/resources/gui/icons/cube-right.png -.. |cube-rotate| image:: ../../../../silx/resources/gui/icons/cube-rotate.png -.. |cube-top| image:: ../../../../silx/resources/gui/icons/cube-top.png -.. |cube| image:: ../../../../silx/resources/gui/icons/cube.png -.. |description-description| image:: ../../../../silx/resources/gui/icons/description-description.png -.. |description-error| image:: ../../../../silx/resources/gui/icons/description-error.png -.. |description-name| image:: ../../../../silx/resources/gui/icons/description-name.png -.. |description-program| image:: ../../../../silx/resources/gui/icons/description-program.png -.. |description-title| image:: ../../../../silx/resources/gui/icons/description-title.png -.. |description-value| image:: ../../../../silx/resources/gui/icons/description-value.png -.. |document-open| image:: ../../../../silx/resources/gui/icons/document-open.png -.. |document-print| image:: ../../../../silx/resources/gui/icons/document-print.png -.. |document-save| image:: ../../../../silx/resources/gui/icons/document-save.png -.. |draw-brush| image:: ../../../../silx/resources/gui/icons/draw-brush.png -.. |draw-pencil| image:: ../../../../silx/resources/gui/icons/draw-pencil.png -.. |draw-rubber| image:: ../../../../silx/resources/gui/icons/draw-rubber.png -.. |edit-copy| image:: ../../../../silx/resources/gui/icons/edit-copy.png -.. |eye| image:: ../../../../silx/resources/gui/icons/eye.png -.. |first| image:: ../../../../silx/resources/gui/icons/first.png -.. |folder| image:: ../../../../silx/resources/gui/icons/folder.png -.. |image-mask| image:: ../../../../silx/resources/gui/icons/image-mask.png -.. |image-select-add| image:: ../../../../silx/resources/gui/icons/image-select-add.png -.. |image-select-box| image:: ../../../../silx/resources/gui/icons/image-select-box.png -.. |image-select-brush| image:: ../../../../silx/resources/gui/icons/image-select-brush.png -.. |image-select-erase-rubber| image:: ../../../../silx/resources/gui/icons/image-select-erase-rubber.png -.. |image-select-erase| image:: ../../../../silx/resources/gui/icons/image-select-erase.png -.. |image| image:: ../../../../silx/resources/gui/icons/image.png -.. |item-0dim| image:: ../../../../silx/resources/gui/icons/item-0dim.png -.. |item-1dim| image:: ../../../../silx/resources/gui/icons/item-1dim.png -.. |item-2dim| image:: ../../../../silx/resources/gui/icons/item-2dim.png -.. |item-3dim| image:: ../../../../silx/resources/gui/icons/item-3dim.png -.. |item-ndim| image:: ../../../../silx/resources/gui/icons/item-ndim.png -.. |item-none| image:: ../../../../silx/resources/gui/icons/item-none.png -.. |item-object| image:: ../../../../silx/resources/gui/icons/item-object.png -.. |last| image:: ../../../../silx/resources/gui/icons/last.png -.. |layer-nx| image:: ../../../../silx/resources/gui/icons/layer-nx.png -.. |mask-clear-all| image:: ../../../../silx/resources/gui/icons/mask-clear-all.png -.. |mask-clear| image:: ../../../../silx/resources/gui/icons/mask-clear.png -.. |mask-invert| image:: ../../../../silx/resources/gui/icons/mask-invert.png -.. |math-amplitude| image:: ../../../../silx/resources/gui/icons/math-amplitude.png -.. |math-average| image:: ../../../../silx/resources/gui/icons/math-average.png -.. |math-derive| image:: ../../../../silx/resources/gui/icons/math-derive.png -.. |math-energy| image:: ../../../../silx/resources/gui/icons/math-energy.png -.. |math-fit| image:: ../../../../silx/resources/gui/icons/math-fit.png -.. |math-imaginary| image:: ../../../../silx/resources/gui/icons/math-imaginary.png -.. |math-mean| image:: ../../../../silx/resources/gui/icons/math-mean.png -.. |math-normalize| image:: ../../../../silx/resources/gui/icons/math-normalize.png -.. |math-peak-reset| image:: ../../../../silx/resources/gui/icons/math-peak-reset.png -.. |math-peak-search| image:: ../../../../silx/resources/gui/icons/math-peak-search.png -.. |math-peak| image:: ../../../../silx/resources/gui/icons/math-peak.png -.. |math-phase-color-log| image:: ../../../../silx/resources/gui/icons/math-phase-color-log.png -.. |math-phase-color| image:: ../../../../silx/resources/gui/icons/math-phase-color.png -.. |math-phase| image:: ../../../../silx/resources/gui/icons/math-phase.png -.. |math-real| image:: ../../../../silx/resources/gui/icons/math-real.png -.. |math-sigma| image:: ../../../../silx/resources/gui/icons/math-sigma.png -.. |math-smooth| image:: ../../../../silx/resources/gui/icons/math-smooth.png -.. |math-square-amplitude| image:: ../../../../silx/resources/gui/icons/math-square-amplitude.png -.. |math-substract| image:: ../../../../silx/resources/gui/icons/math-substract.png -.. |math-swap-sign| image:: ../../../../silx/resources/gui/icons/math-swap-sign.png -.. |math-ymin-to-zero| image:: ../../../../silx/resources/gui/icons/math-ymin-to-zero.png -.. |median-filter| image:: ../../../../silx/resources/gui/icons/median-filter.png -.. |next| image:: ../../../../silx/resources/gui/icons/next.png -.. |normal| image:: ../../../../silx/resources/gui/icons/normal.png -.. |nxdata-axis-add| image:: ../../../../silx/resources/gui/icons/nxdata-axis-add.png -.. |nxdata-axis-remove| image:: ../../../../silx/resources/gui/icons/nxdata-axis-remove.png -.. |nxdata-create| image:: ../../../../silx/resources/gui/icons/nxdata-create.png -.. |nxdata-remove| image:: ../../../../silx/resources/gui/icons/nxdata-remove.png -.. |pan| image:: ../../../../silx/resources/gui/icons/pan.png -.. |pixel-intensities| image:: ../../../../silx/resources/gui/icons/pixel-intensities.png -.. |plot-grid| image:: ../../../../silx/resources/gui/icons/plot-grid.png -.. |plot-roi-above| image:: ../../../../silx/resources/gui/icons/plot-roi-above.png -.. |plot-roi-below| image:: ../../../../silx/resources/gui/icons/plot-roi-below.png -.. |plot-roi-between| image:: ../../../../silx/resources/gui/icons/plot-roi-between.png -.. |plot-roi-reset| image:: ../../../../silx/resources/gui/icons/plot-roi-reset.png -.. |plot-roi| image:: ../../../../silx/resources/gui/icons/plot-roi.png -.. |plot-symbols| image:: ../../../../silx/resources/gui/icons/plot-symbols.png -.. |plot-toggle-points| image:: ../../../../silx/resources/gui/icons/plot-toggle-points.png -.. |plot-widget| image:: ../../../../silx/resources/gui/icons/plot-widget.png -.. |plot-window-image| image:: ../../../../silx/resources/gui/icons/plot-window-image.png -.. |plot-window| image:: ../../../../silx/resources/gui/icons/plot-window.png -.. |plot-xauto| image:: ../../../../silx/resources/gui/icons/plot-xauto.png -.. |plot-xlog| image:: ../../../../silx/resources/gui/icons/plot-xlog.png -.. |plot-yauto| image:: ../../../../silx/resources/gui/icons/plot-yauto.png -.. |plot-ydown| image:: ../../../../silx/resources/gui/icons/plot-ydown.png -.. |plot-ylog| image:: ../../../../silx/resources/gui/icons/plot-ylog.png -.. |plot-yup| image:: ../../../../silx/resources/gui/icons/plot-yup.png -.. |pointing-hand| image:: ../../../../silx/resources/gui/icons/pointing-hand.png -.. |previous| image:: ../../../../silx/resources/gui/icons/previous.png -.. |profile-clear| image:: ../../../../silx/resources/gui/icons/profile-clear.png -.. |profile1D| image:: ../../../../silx/resources/gui/icons/profile1D.png -.. |profile2D| image:: ../../../../silx/resources/gui/icons/profile2D.png -.. |remove| image:: ../../../../silx/resources/gui/icons/remove.png -.. |rm| image:: ../../../../silx/resources/gui/icons/rm.png -.. |rotate-3d| image:: ../../../../silx/resources/gui/icons/rotate-3d.png -.. |rudder| image:: ../../../../silx/resources/gui/icons/rudder.png -.. |selected| image:: ../../../../silx/resources/gui/icons/selected.png -.. |shape-circle-solid| image:: ../../../../silx/resources/gui/icons/shape-circle-solid.png -.. |shape-circle| image:: ../../../../silx/resources/gui/icons/shape-circle.png -.. |shape-cross| image:: ../../../../silx/resources/gui/icons/shape-cross.png -.. |shape-diagonal-directed| image:: ../../../../silx/resources/gui/icons/shape-diagonal-directed.png -.. |shape-diagonal| image:: ../../../../silx/resources/gui/icons/shape-diagonal.png -.. |shape-ellipse-solid| image:: ../../../../silx/resources/gui/icons/shape-ellipse-solid.png -.. |shape-ellipse| image:: ../../../../silx/resources/gui/icons/shape-ellipse.png -.. |shape-horizontal| image:: ../../../../silx/resources/gui/icons/shape-horizontal.png -.. |shape-polygon| image:: ../../../../silx/resources/gui/icons/shape-polygon.png -.. |shape-rectangle| image:: ../../../../silx/resources/gui/icons/shape-rectangle.png -.. |shape-square| image:: ../../../../silx/resources/gui/icons/shape-square.png -.. |shape-vertical| image:: ../../../../silx/resources/gui/icons/shape-vertical.png -.. |silx| image:: ../../../../silx/resources/gui/icons/silx.png -.. |slice-cross| image:: ../../../../silx/resources/gui/icons/slice-cross.png -.. |slice-horizontal| image:: ../../../../silx/resources/gui/icons/slice-horizontal.png -.. |slice-vertical| image:: ../../../../silx/resources/gui/icons/slice-vertical.png -.. |sliders-off| image:: ../../../../silx/resources/gui/icons/sliders-off.png -.. |sliders-on| image:: ../../../../silx/resources/gui/icons/sliders-on.png -.. |spec| image:: ../../../../silx/resources/gui/icons/spec.png -.. |stats-active-items| image:: ../../../../silx/resources/gui/icons/stats-active-items.png -.. |stats-visible-data| image:: ../../../../silx/resources/gui/icons/stats-visible-data.png -.. |stats-whole-data| image:: ../../../../silx/resources/gui/icons/stats-whole-data.png -.. |stats-whole-items| image:: ../../../../silx/resources/gui/icons/stats-whole-items.png -.. |tree-collapse-all| image:: ../../../../silx/resources/gui/icons/tree-collapse-all.png -.. |tree-expand-all| image:: ../../../../silx/resources/gui/icons/tree-expand-all.png -.. |tree-sort| image:: ../../../../silx/resources/gui/icons/tree-sort.png -.. |view-1d| image:: ../../../../silx/resources/gui/icons/view-1d.png -.. |view-2d-stack| image:: ../../../../silx/resources/gui/icons/view-2d-stack.png -.. |view-2d| image:: ../../../../silx/resources/gui/icons/view-2d.png -.. |view-3d| image:: ../../../../silx/resources/gui/icons/view-3d.png -.. |view-fullscreen| image:: ../../../../silx/resources/gui/icons/view-fullscreen.png -.. |view-hdf5| image:: ../../../../silx/resources/gui/icons/view-hdf5.png -.. |view-nexus| image:: ../../../../silx/resources/gui/icons/view-nexus.png -.. |view-nofullscreen| image:: ../../../../silx/resources/gui/icons/view-nofullscreen.png -.. |view-raw| image:: ../../../../silx/resources/gui/icons/view-raw.png -.. |view-refresh| image:: ../../../../silx/resources/gui/icons/view-refresh.png -.. |view-text| image:: ../../../../silx/resources/gui/icons/view-text.png -.. |window-new| image:: ../../../../silx/resources/gui/icons/window-new.png -.. |zoom-back| image:: ../../../../silx/resources/gui/icons/zoom-back.png -.. |zoom-in| image:: ../../../../silx/resources/gui/icons/zoom-in.png -.. |zoom-original| image:: ../../../../silx/resources/gui/icons/zoom-original.png -.. |zoom-out| image:: ../../../../silx/resources/gui/icons/zoom-out.png -.. |zoom| image:: ../../../../silx/resources/gui/icons/zoom.png +.. |3d-plane-normal-x| image:: ../../../../src/silx/resources/gui/icons/3d-plane-normal-x.png +.. |3d-plane-normal-y| image:: ../../../../src/silx/resources/gui/icons/3d-plane-normal-y.png +.. |3d-plane-normal-z| image:: ../../../../src/silx/resources/gui/icons/3d-plane-normal-z.png +.. |3d-plane-pan| image:: ../../../../src/silx/resources/gui/icons/3d-plane-pan.png +.. |3d-plane| image:: ../../../../src/silx/resources/gui/icons/3d-plane.png +.. |add-range-horizontal| image:: ../../../../src/silx/resources/gui/icons/add-range-horizontal.png +.. |add-shape-arc| image:: ../../../../src/silx/resources/gui/icons/add-shape-arc.png +.. |add-shape-circle| image:: ../../../../src/silx/resources/gui/icons/add-shape-circle.png +.. |add-shape-cross| image:: ../../../../src/silx/resources/gui/icons/add-shape-cross.png +.. |add-shape-diagonal| image:: ../../../../src/silx/resources/gui/icons/add-shape-diagonal.png +.. |add-shape-ellipse| image:: ../../../../src/silx/resources/gui/icons/add-shape-ellipse.png +.. |add-shape-horizontal| image:: ../../../../src/silx/resources/gui/icons/add-shape-horizontal.png +.. |add-shape-point| image:: ../../../../src/silx/resources/gui/icons/add-shape-point.png +.. |add-shape-polygon| image:: ../../../../src/silx/resources/gui/icons/add-shape-polygon.png +.. |add-shape-rectangle| image:: ../../../../src/silx/resources/gui/icons/add-shape-rectangle.png +.. |add-shape-rotated-rectangle| image:: ../../../../src/silx/resources/gui/icons/add-shape-rotated-rectangle.png +.. |add-shape-unknown| image:: ../../../../src/silx/resources/gui/icons/add-shape-unknown.png +.. |add-shape-vertical| image:: ../../../../src/silx/resources/gui/icons/add-shape-vertical.png +.. |add| image:: ../../../../src/silx/resources/gui/icons/add.png +.. |aggregation-mode| image:: ../../../../src/silx/resources/gui/icons/aggregation-mode.png +.. |arrow-keys| image:: ../../../../src/silx/resources/gui/icons/arrow-keys.png +.. |axis| image:: ../../../../src/silx/resources/gui/icons/axis.png +.. |backend-opengl| image:: ../../../../src/silx/resources/gui/icons/backend-opengl.png +.. |camera| image:: ../../../../src/silx/resources/gui/icons/camera.png +.. |clipboard| image:: ../../../../src/silx/resources/gui/icons/clipboard.png +.. |close| image:: ../../../../src/silx/resources/gui/icons/close.png +.. |colorbar| image:: ../../../../src/silx/resources/gui/icons/colorbar.png +.. |colormap-histogram| image:: ../../../../src/silx/resources/gui/icons/colormap-histogram.png +.. |colormap-none| image:: ../../../../src/silx/resources/gui/icons/colormap-none.png +.. |colormap-norm-arcsinh| image:: ../../../../src/silx/resources/gui/icons/colormap-norm-arcsinh.png +.. |colormap-norm-gamma| image:: ../../../../src/silx/resources/gui/icons/colormap-norm-gamma.png +.. |colormap-norm-linear| image:: ../../../../src/silx/resources/gui/icons/colormap-norm-linear.png +.. |colormap-norm-log| image:: ../../../../src/silx/resources/gui/icons/colormap-norm-log.png +.. |colormap-norm-sqrt| image:: ../../../../src/silx/resources/gui/icons/colormap-norm-sqrt.png +.. |colormap-range| image:: ../../../../src/silx/resources/gui/icons/colormap-range.png +.. |colormap| image:: ../../../../src/silx/resources/gui/icons/colormap.png +.. |compare-align-auto| image:: ../../../../src/silx/resources/gui/icons/compare-align-auto.png +.. |compare-align-center| image:: ../../../../src/silx/resources/gui/icons/compare-align-center.png +.. |compare-align-origin| image:: ../../../../src/silx/resources/gui/icons/compare-align-origin.png +.. |compare-align-stretch| image:: ../../../../src/silx/resources/gui/icons/compare-align-stretch.png +.. |compare-keypoints| image:: ../../../../src/silx/resources/gui/icons/compare-keypoints.png +.. |compare-mode-a-minus-b| image:: ../../../../src/silx/resources/gui/icons/compare-mode-a-minus-b.png +.. |compare-mode-a| image:: ../../../../src/silx/resources/gui/icons/compare-mode-a.png +.. |compare-mode-b| image:: ../../../../src/silx/resources/gui/icons/compare-mode-b.png +.. |compare-mode-hline| image:: ../../../../src/silx/resources/gui/icons/compare-mode-hline.png +.. |compare-mode-rb-channel| image:: ../../../../src/silx/resources/gui/icons/compare-mode-rb-channel.png +.. |compare-mode-rbneg-channel| image:: ../../../../src/silx/resources/gui/icons/compare-mode-rbneg-channel.png +.. |compare-mode-vline| image:: ../../../../src/silx/resources/gui/icons/compare-mode-vline.png +.. |crop| image:: ../../../../src/silx/resources/gui/icons/crop.png +.. |crosshair| image:: ../../../../src/silx/resources/gui/icons/crosshair.png +.. |cube-back| image:: ../../../../src/silx/resources/gui/icons/cube-back.png +.. |cube-bottom| image:: ../../../../src/silx/resources/gui/icons/cube-bottom.png +.. |cube-front| image:: ../../../../src/silx/resources/gui/icons/cube-front.png +.. |cube-left| image:: ../../../../src/silx/resources/gui/icons/cube-left.png +.. |cube-right| image:: ../../../../src/silx/resources/gui/icons/cube-right.png +.. |cube-rotate| image:: ../../../../src/silx/resources/gui/icons/cube-rotate.png +.. |cube-top| image:: ../../../../src/silx/resources/gui/icons/cube-top.png +.. |cube| image:: ../../../../src/silx/resources/gui/icons/cube.png +.. |description-description| image:: ../../../../src/silx/resources/gui/icons/description-description.png +.. |description-error| image:: ../../../../src/silx/resources/gui/icons/description-error.png +.. |description-name| image:: ../../../../src/silx/resources/gui/icons/description-name.png +.. |description-program| image:: ../../../../src/silx/resources/gui/icons/description-program.png +.. |description-title| image:: ../../../../src/silx/resources/gui/icons/description-title.png +.. |description-value| image:: ../../../../src/silx/resources/gui/icons/description-value.png +.. |document-open| image:: ../../../../src/silx/resources/gui/icons/document-open.png +.. |document-print| image:: ../../../../src/silx/resources/gui/icons/document-print.png +.. |document-save| image:: ../../../../src/silx/resources/gui/icons/document-save.png +.. |draw-brush| image:: ../../../../src/silx/resources/gui/icons/draw-brush.png +.. |draw-pencil| image:: ../../../../src/silx/resources/gui/icons/draw-pencil.png +.. |draw-rubber| image:: ../../../../src/silx/resources/gui/icons/draw-rubber.png +.. |edit-copy| image:: ../../../../src/silx/resources/gui/icons/edit-copy.png +.. |eye| image:: ../../../../src/silx/resources/gui/icons/eye.png +.. |first| image:: ../../../../src/silx/resources/gui/icons/first.png +.. |folder| image:: ../../../../src/silx/resources/gui/icons/folder.png +.. |image-mask| image:: ../../../../src/silx/resources/gui/icons/image-mask.png +.. |image-select-add| image:: ../../../../src/silx/resources/gui/icons/image-select-add.png +.. |image-select-box| image:: ../../../../src/silx/resources/gui/icons/image-select-box.png +.. |image-select-brush| image:: ../../../../src/silx/resources/gui/icons/image-select-brush.png +.. |image-select-erase-rubber| image:: ../../../../src/silx/resources/gui/icons/image-select-erase-rubber.png +.. |image-select-erase| image:: ../../../../src/silx/resources/gui/icons/image-select-erase.png +.. |image| image:: ../../../../src/silx/resources/gui/icons/image.png +.. |item-0dim| image:: ../../../../src/silx/resources/gui/icons/item-0dim.png +.. |item-1dim| image:: ../../../../src/silx/resources/gui/icons/item-1dim.png +.. |item-2dim| image:: ../../../../src/silx/resources/gui/icons/item-2dim.png +.. |item-3dim| image:: ../../../../src/silx/resources/gui/icons/item-3dim.png +.. |item-ndim| image:: ../../../../src/silx/resources/gui/icons/item-ndim.png +.. |item-none| image:: ../../../../src/silx/resources/gui/icons/item-none.png +.. |item-object| image:: ../../../../src/silx/resources/gui/icons/item-object.png +.. |last| image:: ../../../../src/silx/resources/gui/icons/last.png +.. |layer-nx| image:: ../../../../src/silx/resources/gui/icons/layer-nx.png +.. |mask-clear-all| image:: ../../../../src/silx/resources/gui/icons/mask-clear-all.png +.. |mask-clear| image:: ../../../../src/silx/resources/gui/icons/mask-clear.png +.. |mask-invert| image:: ../../../../src/silx/resources/gui/icons/mask-invert.png +.. |math-amplitude| image:: ../../../../src/silx/resources/gui/icons/math-amplitude.png +.. |math-average| image:: ../../../../src/silx/resources/gui/icons/math-average.png +.. |math-derive| image:: ../../../../src/silx/resources/gui/icons/math-derive.png +.. |math-energy| image:: ../../../../src/silx/resources/gui/icons/math-energy.png +.. |math-fit| image:: ../../../../src/silx/resources/gui/icons/math-fit.png +.. |math-imaginary| image:: ../../../../src/silx/resources/gui/icons/math-imaginary.png +.. |math-mean| image:: ../../../../src/silx/resources/gui/icons/math-mean.png +.. |math-normalize| image:: ../../../../src/silx/resources/gui/icons/math-normalize.png +.. |math-peak-reset| image:: ../../../../src/silx/resources/gui/icons/math-peak-reset.png +.. |math-peak-search| image:: ../../../../src/silx/resources/gui/icons/math-peak-search.png +.. |math-peak| image:: ../../../../src/silx/resources/gui/icons/math-peak.png +.. |math-phase-color-log| image:: ../../../../src/silx/resources/gui/icons/math-phase-color-log.png +.. |math-phase-color| image:: ../../../../src/silx/resources/gui/icons/math-phase-color.png +.. |math-phase| image:: ../../../../src/silx/resources/gui/icons/math-phase.png +.. |math-real| image:: ../../../../src/silx/resources/gui/icons/math-real.png +.. |math-sigma| image:: ../../../../src/silx/resources/gui/icons/math-sigma.png +.. |math-smooth| image:: ../../../../src/silx/resources/gui/icons/math-smooth.png +.. |math-square-amplitude| image:: ../../../../src/silx/resources/gui/icons/math-square-amplitude.png +.. |math-substract| image:: ../../../../src/silx/resources/gui/icons/math-substract.png +.. |math-swap-sign| image:: ../../../../src/silx/resources/gui/icons/math-swap-sign.png +.. |math-ymin-to-zero| image:: ../../../../src/silx/resources/gui/icons/math-ymin-to-zero.png +.. |median-filter| image:: ../../../../src/silx/resources/gui/icons/median-filter.png +.. |next| image:: ../../../../src/silx/resources/gui/icons/next.png +.. |normal| image:: ../../../../src/silx/resources/gui/icons/normal.png +.. |nxdata-axis-add| image:: ../../../../src/silx/resources/gui/icons/nxdata-axis-add.png +.. |nxdata-axis-remove| image:: ../../../../src/silx/resources/gui/icons/nxdata-axis-remove.png +.. |nxdata-create| image:: ../../../../src/silx/resources/gui/icons/nxdata-create.png +.. |nxdata-remove| image:: ../../../../src/silx/resources/gui/icons/nxdata-remove.png +.. |pan| image:: ../../../../src/silx/resources/gui/icons/pan.png +.. |pixel-intensities| image:: ../../../../src/silx/resources/gui/icons/pixel-intensities.png +.. |plot-grid| image:: ../../../../src/silx/resources/gui/icons/plot-grid.png +.. |plot-roi-above| image:: ../../../../src/silx/resources/gui/icons/plot-roi-above.png +.. |plot-roi-below| image:: ../../../../src/silx/resources/gui/icons/plot-roi-below.png +.. |plot-roi-between| image:: ../../../../src/silx/resources/gui/icons/plot-roi-between.png +.. |plot-roi-reset| image:: ../../../../src/silx/resources/gui/icons/plot-roi-reset.png +.. |plot-roi| image:: ../../../../src/silx/resources/gui/icons/plot-roi.png +.. |plot-symbols| image:: ../../../../src/silx/resources/gui/icons/plot-symbols.png +.. |plot-toggle-points| image:: ../../../../src/silx/resources/gui/icons/plot-toggle-points.png +.. |plot-widget| image:: ../../../../src/silx/resources/gui/icons/plot-widget.png +.. |plot-window-image| image:: ../../../../src/silx/resources/gui/icons/plot-window-image.png +.. |plot-window| image:: ../../../../src/silx/resources/gui/icons/plot-window.png +.. |plot-xauto| image:: ../../../../src/silx/resources/gui/icons/plot-xauto.png +.. |plot-xlog| image:: ../../../../src/silx/resources/gui/icons/plot-xlog.png +.. |plot-yauto| image:: ../../../../src/silx/resources/gui/icons/plot-yauto.png +.. |plot-ydown| image:: ../../../../src/silx/resources/gui/icons/plot-ydown.png +.. |plot-ylog| image:: ../../../../src/silx/resources/gui/icons/plot-ylog.png +.. |plot-yup| image:: ../../../../src/silx/resources/gui/icons/plot-yup.png +.. |pointing-hand| image:: ../../../../src/silx/resources/gui/icons/pointing-hand.png +.. |previous| image:: ../../../../src/silx/resources/gui/icons/previous.png +.. |profile-clear| image:: ../../../../src/silx/resources/gui/icons/profile-clear.png +.. |profile1D| image:: ../../../../src/silx/resources/gui/icons/profile1D.png +.. |profile2D| image:: ../../../../src/silx/resources/gui/icons/profile2D.png +.. |remove| image:: ../../../../src/silx/resources/gui/icons/remove.png +.. |rm| image:: ../../../../src/silx/resources/gui/icons/rm.png +.. |rotate-3d| image:: ../../../../src/silx/resources/gui/icons/rotate-3d.png +.. |rudder| image:: ../../../../src/silx/resources/gui/icons/rudder.png +.. |scale-auto| image:: ../../../../src/silx/resources/gui/icons/scale-auto.png +.. |scale-fixed| image:: ../../../../src/silx/resources/gui/icons/scale-fixed.png +.. |selected| image:: ../../../../src/silx/resources/gui/icons/selected.png +.. |shape-circle-solid| image:: ../../../../src/silx/resources/gui/icons/shape-circle-solid.png +.. |shape-circle| image:: ../../../../src/silx/resources/gui/icons/shape-circle.png +.. |shape-cross| image:: ../../../../src/silx/resources/gui/icons/shape-cross.png +.. |shape-diagonal-directed| image:: ../../../../src/silx/resources/gui/icons/shape-diagonal-directed.png +.. |shape-diagonal| image:: ../../../../src/silx/resources/gui/icons/shape-diagonal.png +.. |shape-ellipse-solid| image:: ../../../../src/silx/resources/gui/icons/shape-ellipse-solid.png +.. |shape-ellipse| image:: ../../../../src/silx/resources/gui/icons/shape-ellipse.png +.. |shape-horizontal| image:: ../../../../src/silx/resources/gui/icons/shape-horizontal.png +.. |shape-polygon| image:: ../../../../src/silx/resources/gui/icons/shape-polygon.png +.. |shape-rectangle| image:: ../../../../src/silx/resources/gui/icons/shape-rectangle.png +.. |shape-square| image:: ../../../../src/silx/resources/gui/icons/shape-square.png +.. |shape-vertical| image:: ../../../../src/silx/resources/gui/icons/shape-vertical.png +.. |side-histograms| image:: ../../../../src/silx/resources/gui/icons/side-histograms.png +.. |silx| image:: ../../../../src/silx/resources/gui/icons/silx.png +.. |slice-cross| image:: ../../../../src/silx/resources/gui/icons/slice-cross.png +.. |slice-horizontal| image:: ../../../../src/silx/resources/gui/icons/slice-horizontal.png +.. |slice-vertical| image:: ../../../../src/silx/resources/gui/icons/slice-vertical.png +.. |sliders-off| image:: ../../../../src/silx/resources/gui/icons/sliders-off.png +.. |sliders-on| image:: ../../../../src/silx/resources/gui/icons/sliders-on.png +.. |spec| image:: ../../../../src/silx/resources/gui/icons/spec.png +.. |stats-active-items| image:: ../../../../src/silx/resources/gui/icons/stats-active-items.png +.. |stats-visible-data| image:: ../../../../src/silx/resources/gui/icons/stats-visible-data.png +.. |stats-whole-data| image:: ../../../../src/silx/resources/gui/icons/stats-whole-data.png +.. |stats-whole-items| image:: ../../../../src/silx/resources/gui/icons/stats-whole-items.png +.. |tree-collapse-all| image:: ../../../../src/silx/resources/gui/icons/tree-collapse-all.png +.. |tree-expand-all| image:: ../../../../src/silx/resources/gui/icons/tree-expand-all.png +.. |tree-sort| image:: ../../../../src/silx/resources/gui/icons/tree-sort.png +.. |view-1d| image:: ../../../../src/silx/resources/gui/icons/view-1d.png +.. |view-2d-stack| image:: ../../../../src/silx/resources/gui/icons/view-2d-stack.png +.. |view-2d| image:: ../../../../src/silx/resources/gui/icons/view-2d.png +.. |view-3d| image:: ../../../../src/silx/resources/gui/icons/view-3d.png +.. |view-fullscreen| image:: ../../../../src/silx/resources/gui/icons/view-fullscreen.png +.. |view-hdf5| image:: ../../../../src/silx/resources/gui/icons/view-hdf5.png +.. |view-nexus| image:: ../../../../src/silx/resources/gui/icons/view-nexus.png +.. |view-nofullscreen| image:: ../../../../src/silx/resources/gui/icons/view-nofullscreen.png +.. |view-raw| image:: ../../../../src/silx/resources/gui/icons/view-raw.png +.. |view-refresh| image:: ../../../../src/silx/resources/gui/icons/view-refresh.png +.. |view-text| image:: ../../../../src/silx/resources/gui/icons/view-text.png +.. |window-new| image:: ../../../../src/silx/resources/gui/icons/window-new.png +.. |zoom-back| image:: ../../../../src/silx/resources/gui/icons/zoom-back.png +.. |zoom-in| image:: ../../../../src/silx/resources/gui/icons/zoom-in.png +.. |zoom-original| image:: ../../../../src/silx/resources/gui/icons/zoom-original.png +.. |zoom-out| image:: ../../../../src/silx/resources/gui/icons/zoom-out.png +.. |zoom| image:: ../../../../src/silx/resources/gui/icons/zoom.png diff --git a/doc/source/modules/gui/plot/getting_started.rst b/doc/source/modules/gui/plot/getting_started.rst index c105395..f8d80ec 100644 --- a/doc/source/modules/gui/plot/getting_started.rst +++ b/doc/source/modules/gui/plot/getting_started.rst @@ -20,7 +20,7 @@ For a complete description of the API, see :mod:`silx.gui.plot`. Use :mod:`silx.gui.plot` from (I)Python console ----------------------------------------------- -We recommend to use (I)Python >=3.5 and PyQt5. +We recommend to use (I)Python >=3.6 and PyQt5. From a Python or IPython interpreter, the simplest way is to import the :mod:`silx.sx` module: @@ -87,9 +87,9 @@ A Qt GUI script must have a QApplication initialised before creating widgets: if __name__ == '__main__': [...] - qapp.exec_() + qapp.exec() -Unless a Qt binding has already been loaded, :mod:`silx.gui.qt` uses one of the supported Qt bindings (PyQt5, PyQt4, PySide2). +Unless a Qt binding has already been loaded, :mod:`silx.gui.qt` uses one of the supported Qt bindings (PyQt5, PySide6, PyQt6). If you prefer to choose the Qt binding yourself, import it before importing a module from :mod:`silx.gui`: diff --git a/doc/source/modules/gui/plot/img/BasicGridStatsWidget.png b/doc/source/modules/gui/plot/img/BasicGridStatsWidget.png Binary files differindex 261909a..a468cc1 100644 --- a/doc/source/modules/gui/plot/img/BasicGridStatsWidget.png +++ b/doc/source/modules/gui/plot/img/BasicGridStatsWidget.png diff --git a/doc/source/modules/gui/plot/img/BasicStatsWidget.png b/doc/source/modules/gui/plot/img/BasicStatsWidget.png Binary files differindex b0d815d..6dbdd30 100644 --- a/doc/source/modules/gui/plot/img/BasicStatsWidget.png +++ b/doc/source/modules/gui/plot/img/BasicStatsWidget.png diff --git a/doc/source/modules/gui/plot/img/LimitsToolBar.png b/doc/source/modules/gui/plot/img/LimitsToolBar.png Binary files differindex b360fe0..2d96458 100644 --- a/doc/source/modules/gui/plot/img/LimitsToolBar.png +++ b/doc/source/modules/gui/plot/img/LimitsToolBar.png diff --git a/doc/source/modules/gui/plot/img/ROIStatsWidget.png b/doc/source/modules/gui/plot/img/ROIStatsWidget.png Binary files differindex 7a634fe..fae9d62 100644 --- a/doc/source/modules/gui/plot/img/ROIStatsWidget.png +++ b/doc/source/modules/gui/plot/img/ROIStatsWidget.png diff --git a/doc/source/modules/gui/plot/img/logColorbar.png b/doc/source/modules/gui/plot/img/logColorbar.png Binary files differindex 49282e7..31594e0 100644 --- a/doc/source/modules/gui/plot/img/logColorbar.png +++ b/doc/source/modules/gui/plot/img/logColorbar.png diff --git a/doc/source/modules/gui/plot3d/img/SceneWidget.png b/doc/source/modules/gui/plot3d/img/SceneWidget.png Binary files differindex 4ddc0a8..7ad6de4 100644 --- a/doc/source/modules/gui/plot3d/img/SceneWidget.png +++ b/doc/source/modules/gui/plot3d/img/SceneWidget.png diff --git a/doc/source/modules/gui/widgets/img/FrameBrowser.png b/doc/source/modules/gui/widgets/img/FrameBrowser.png Binary files differindex 1d4ebcf..6f46631 100644 --- a/doc/source/modules/gui/widgets/img/FrameBrowser.png +++ b/doc/source/modules/gui/widgets/img/FrameBrowser.png diff --git a/doc/source/modules/gui/widgets/img/HorizontalSliderWithBrowser.png b/doc/source/modules/gui/widgets/img/HorizontalSliderWithBrowser.png Binary files differindex 96edd3c..13a4ddf 100644 --- a/doc/source/modules/gui/widgets/img/HorizontalSliderWithBrowser.png +++ b/doc/source/modules/gui/widgets/img/HorizontalSliderWithBrowser.png diff --git a/doc/source/modules/gui/widgets/img/PeriodicCombo.png b/doc/source/modules/gui/widgets/img/PeriodicCombo.png Binary files differindex 7534805..bec3a78 100644 --- a/doc/source/modules/gui/widgets/img/PeriodicCombo.png +++ b/doc/source/modules/gui/widgets/img/PeriodicCombo.png diff --git a/doc/source/modules/gui/widgets/img/PeriodicList.png b/doc/source/modules/gui/widgets/img/PeriodicList.png Binary files differindex 74ce7d6..a695525 100644 --- a/doc/source/modules/gui/widgets/img/PeriodicList.png +++ b/doc/source/modules/gui/widgets/img/PeriodicList.png diff --git a/doc/source/modules/gui/widgets/img/PeriodicTable.png b/doc/source/modules/gui/widgets/img/PeriodicTable.png Binary files differindex bada39a..70039ab 100644 --- a/doc/source/modules/gui/widgets/img/PeriodicTable.png +++ b/doc/source/modules/gui/widgets/img/PeriodicTable.png diff --git a/doc/source/modules/gui/widgets/img/RangeSlider.png b/doc/source/modules/gui/widgets/img/RangeSlider.png Binary files differindex e7a1011..f552fb3 100644 --- a/doc/source/modules/gui/widgets/img/RangeSlider.png +++ b/doc/source/modules/gui/widgets/img/RangeSlider.png diff --git a/doc/source/modules/gui/widgets/img/TableWidget.png b/doc/source/modules/gui/widgets/img/TableWidget.png Binary files differindex a614ae7..959af57 100644 --- a/doc/source/modules/gui/widgets/img/TableWidget.png +++ b/doc/source/modules/gui/widgets/img/TableWidget.png diff --git a/doc/source/modules/gui/widgets/img/ThreadPoolPushButton.png b/doc/source/modules/gui/widgets/img/ThreadPoolPushButton.png Binary files differindex eb55b14..5d1af4c 100644 --- a/doc/source/modules/gui/widgets/img/ThreadPoolPushButton.png +++ b/doc/source/modules/gui/widgets/img/ThreadPoolPushButton.png diff --git a/doc/source/modules/gui/widgets/img/WaitingPushButton.png b/doc/source/modules/gui/widgets/img/WaitingPushButton.png Binary files differindex 97bd14a..5bfcdb8 100644 --- a/doc/source/modules/gui/widgets/img/WaitingPushButton.png +++ b/doc/source/modules/gui/widgets/img/WaitingPushButton.png diff --git a/doc/source/modules/gui/widgets/printpreview.rst b/doc/source/modules/gui/widgets/printpreview.rst index d0b7999..bff2381 100644 --- a/doc/source/modules/gui/widgets/printpreview.rst +++ b/doc/source/modules/gui/widgets/printpreview.rst @@ -56,5 +56,5 @@ Example commentPosition="CENTER") w.addImage(qt.QImage(filename), comment=comment, commentPosition="LEFT") - w.exec_() - a.exec_() + w.exec() + a.exec() diff --git a/doc/source/modules/io/commonh5.rst b/doc/source/modules/io/commonh5.rst new file mode 100644 index 0000000..9e62ccd --- /dev/null +++ b/doc/source/modules/io/commonh5.rst @@ -0,0 +1,28 @@ +. currentmodule:: silx.io + +:mod:`commonh5`: Helpers for writing h5py-like API +-------------------------------------------------- + +.. automodule:: silx.io.commonh5 + +Classes ++++++++ + +.. autoclass:: Node + :members: + +.. autoclass:: File + :show-inheritance: + :members: + +.. autoclass:: Group + :show-inheritance: + :undoc-members: + :members: name, basename, file, attrs, h5py_class, parent, + get, keys, values, items, visit, visititems + :special-members: __getitem__, __len__, __contains__, __iter__ + :exclude-members: add_node + +.. autoclass:: Dataset + :show-inheritance: + :members: diff --git a/doc/source/modules/io/fioh5.rst b/doc/source/modules/io/fioh5.rst new file mode 100644 index 0000000..99498de --- /dev/null +++ b/doc/source/modules/io/fioh5.rst @@ -0,0 +1,27 @@ + +.. currentmodule:: silx.io + +:mod:`fioh5`: h5py-like API to FIO file +---------------------------------------- + +.. automodule:: silx.io.fioh5 + + +Classes ++++++++ + +- :class:`FioH5` +- :class:`FioFile` + +.. autoclass:: FioH5 + :members: + :show-inheritance: + :undoc-members: + :inherited-members: name, basename, attrs, h5py_class, parent, + get, keys, values, items, + :special-members: __getitem__, __len__, __contains__, __enter__, __exit__, __iter__ + :exclude-members: add_node + +.. autoclass:: FioFile + +.. autofunction:: is_fiofile
\ No newline at end of file diff --git a/doc/source/modules/io/index.rst b/doc/source/modules/io/index.rst index 581f763..b69a760 100644 --- a/doc/source/modules/io/index.rst +++ b/doc/source/modules/io/index.rst @@ -7,7 +7,8 @@ .. toctree:: :maxdepth: 1 - + + commonh5.rst configdict.rst convert.rst dictdump.rst @@ -16,6 +17,7 @@ specfile.rst specfilewrapper.rst spech5.rst + fioh5.rst url.rst utils.rst h5py_utils.rst diff --git a/doc/source/modules/io/spech5.rst b/doc/source/modules/io/spech5.rst index 61e0083..a9b8456 100644 --- a/doc/source/modules/io/spech5.rst +++ b/doc/source/modules/io/spech5.rst @@ -26,14 +26,6 @@ Classes .. autoclass:: SpecH5Group :show-inheritance: -.. autoclass:: silx.io.commonh5.Group - :show-inheritance: - :undoc-members: - :members: name, basename, file, attrs, h5py_class, parent, - get, keys, values, items, visit, visititems - :special-members: __getitem__, __len__, __contains__, __iter__ - :exclude-members: add_node - .. autoclass:: SpecH5Dataset :show-inheritance: diff --git a/doc/source/overview.rst b/doc/source/overview.rst index e65c163..729bdec 100644 --- a/doc/source/overview.rst +++ b/doc/source/overview.rst @@ -8,16 +8,21 @@ Source code, pre-built binaries (aka Python wheels) for Windows, MacOS and ManyLinux, Debian/Ubuntu packages of released versions are made available in the following places: - `Wheels and source code on PyPi <https://pypi.org/project/silx/>`_ +- `Conda package on conda-forge channel <https://anaconda.org/conda-forge/silx>`_ +- Windows application installer `on github release page <https://github.com/silx-kit/silx/releases/latest/>`_ (available in the `Assets` at the bottom). - `Documentation on silx.org <http://www.silx.org/doc/silx/latest/>`_ -- `Unofficial Debian/Ubuntu packages <https://github.com/silx-kit/silx/releases>`_ +- `Unofficial Debian/Ubuntu packages <https://github.com/silx-kit/silx/releases/latest>`_ - :doc:`changelog` +|release| |version| + Nightly builds -------------- Linux packages and documentation are automatically generated from the tip of the project's repository on a regular basis: - `Debian 10 and Ubuntu20.04 packages <http://www.silx.org/pub/linux-repo/>`_ +- `Wheels and Windows application <https://silx.gitlab-pages.esrf.fr/bob/silx/>`_ - `Documentation <http://www.silx.org/doc/silx/dev/>`_ Project diff --git a/doc/source/sample_code/img/plotUpdateImageFromGevent.png b/doc/source/sample_code/img/plotUpdateImageFromGevent.png Binary files differnew file mode 100644 index 0000000..c0caec3 --- /dev/null +++ b/doc/source/sample_code/img/plotUpdateImageFromGevent.png diff --git a/doc/source/sample_code/index.rst b/doc/source/sample_code/index.rst index 0aade4c..c33d560 100644 --- a/doc/source/sample_code/index.rst +++ b/doc/source/sample_code/index.rst @@ -343,6 +343,10 @@ Sample code that illustrates some functionalities of :class:`~silx.gui.plot.Plot In this example a thread calls submitToQtMainThread to update the curve of a plot. + * - :download:`plotUpdateImageFromGevent.py <../../../examples/plotUpdateImageFromGevent.py>` + - .. image:: img/plotUpdateImageFromGevent.png + :width: 150px + - This script illustrates the update of a :class:`~silx.gui.plot.Plot2D` widget from a gevent coroutine. * - :download:`plotUpdateImageFromThread.py <../../../examples/plotUpdateImageFromThread.py>` - .. image:: img/plotUpdateImageFromThread.png :width: 150px diff --git a/doc/source/virtualenv.rst b/doc/source/virtualenv.rst index ccdd9b6..537336d 100644 --- a/doc/source/virtualenv.rst +++ b/doc/source/virtualenv.rst @@ -132,7 +132,7 @@ To test *silx*, open an interactive python console: python -If you don't have PyQt5 or PySide2, run: +If you don't have PyQt5, PySide6 or PyQt6, run: .. code-block:: bash diff --git a/examples/__init__.py b/examples/__init__.py index 625d5fa..2387e3c 100644 --- a/examples/__init__.py +++ b/examples/__init__.py @@ -1,4 +1,3 @@ -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2018 European Synchrotron Radiation Facility diff --git a/examples/colormapDialog.py b/examples/colormapDialog.py index c9e7c35..c3065f9 100644 --- a/examples/colormapDialog.py +++ b/examples/colormapDialog.py @@ -1,7 +1,6 @@ -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2017-2018 European Synchrotron Radiation Facility +# Copyright (c) 2017-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -140,7 +139,7 @@ class ColormapDialogExample(qt.QMainWindow): button = qt.QPushButton("Negative to positive") button.clicked.connect(self.setDataFromNegToPos) layout.addWidget(button) - button = qt.QPushButton("Only non finite values") + button = qt.QPushButton("With non finite values") button.clicked.connect(self.setDataWithNonFinite) layout.addWidget(button) @@ -259,7 +258,7 @@ class ColormapDialogExample(qt.QMainWindow): if scipy is not None: from scipy import ndimage data = ndimage.gaussian_filter(data, sigma=20) - data = numpy.random.poisson(data) + data = numpy.random.poisson(data).astype(numpy.float32) data[10] = float("nan") data[50] = float("+inf") data[100] = float("-inf") @@ -275,7 +274,7 @@ def main(): example = ColormapDialogExample() example.show() - app.exec_() + app.exec() if __name__ == '__main__': diff --git a/examples/compareImages.py b/examples/compareImages.py index 623216a..df2f40c 100644 --- a/examples/compareImages.py +++ b/examples/compareImages.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2017 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -208,4 +207,4 @@ if __name__ == "__main__": window.setFiles(options.files) window.setVisible(True) - app.exec_() + app.exec() diff --git a/examples/compositeline.py b/examples/compositeline.py index 892ecf3..2416495 100644 --- a/examples/compositeline.py +++ b/examples/compositeline.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2019 European Synchrotron Radiation Facility @@ -26,7 +25,6 @@ """ Example to show the use of markers to draw head and tail of lines. """ -from __future__ import division __license__ = "MIT" @@ -72,7 +70,7 @@ def main(argv=None): addLine([70, 0], [70, 100], "_", "_", "l6", "black") mainWindow.setVisible(True) - return app.exec_() + return app.exec() if __name__ == "__main__": diff --git a/examples/customDataView.py b/examples/customDataView.py index 33662e8..8c2855d 100644 --- a/examples/customDataView.py +++ b/examples/customDataView.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2018 European Synchrotron Radiation Facility @@ -96,7 +95,7 @@ def main(): widget.addView(MyColorView(widget)) widget.setData(Color.GREEN) widget.show() - result = app.exec_() + result = app.exec() # remove ending warnings relative to QTimer app.deleteLater() sys.exit(result) diff --git a/examples/customHdf5TreeModel.py b/examples/customHdf5TreeModel.py index fde76c5..c3bd45a 100644 --- a/examples/customHdf5TreeModel.py +++ b/examples/customHdf5TreeModel.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2018 European Synchrotron Radiation Facility @@ -279,7 +278,7 @@ def main(filenames): sys.excepthook = qt.exceptionHandler window = Hdf5TreeViewExample(filenames) window.show() - result = app.exec_() + result = app.exec() # remove ending warnings relative to QTimer app.deleteLater() sys.exit(result) diff --git a/examples/customSilxView.py b/examples/customSilxView.py index c240280..11fa8e4 100644 --- a/examples/customSilxView.py +++ b/examples/customSilxView.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2020 European Synchrotron Radiation Facility diff --git a/examples/dropZones.py b/examples/dropZones.py index 68d0a57..48e1fc4 100644 --- a/examples/dropZones.py +++ b/examples/dropZones.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2020 European Synchrotron Radiation Facility @@ -31,8 +30,6 @@ It provides 2 URLs (corresponding to 2 datasets) that can be dragged to either a :class:`PlotWidget` or a QLable displaying the URL information. """ -from __future__ import absolute_import - __authors__ = ["V. Valls"] __license__ = "MIT" __date__ = "25/01/2019" @@ -140,7 +137,7 @@ class DragLabel(qt.QLabel): self._url.path().encode(encoding='utf-8')) drag = qt.QDrag(self) drag.setMimeData(mimeData) - dropAction = drag.exec_() + dropAction = drag.exec() class DragAndDropExample(qt.QMainWindow): @@ -178,7 +175,7 @@ def main(): silx.io.url.DataUrl(file_path=filename, data_path='/curve', scheme="silx"))) example.setWindowTitle("Drag&Drop URLs sample code") example.show() - app.exec_() + app.exec() if __name__ == "__main__": diff --git a/examples/exampleBaseline.py b/examples/exampleBaseline.py index edd0fc3..7c22f1d 100644 --- a/examples/exampleBaseline.py +++ b/examples/exampleBaseline.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2017-2018 European Synchrotron Radiation Facility +# Copyright (c) 2017-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -157,7 +156,7 @@ def main(argv): plot_log = get_plot_log(backend=options.backend) plot_log.show() - qapp.exec_() + qapp.exec() if __name__ == '__main__': diff --git a/examples/fftPlotAction.py b/examples/fftPlotAction.py index bdea08d..d51a121 100755 --- a/examples/fftPlotAction.py +++ b/examples/fftPlotAction.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2020 European Synchrotron Radiation Facility @@ -190,5 +189,5 @@ plotwin.getYAxis().setLabel("amplitude") plotwin.getXAxis().setLabel("time") plotwin.show() -app.exec_() +app.exec() sys.excepthook = sys.__excepthook__ diff --git a/examples/fileDialog.py b/examples/fileDialog.py index 40191bb..69d6a94 100644 --- a/examples/fileDialog.py +++ b/examples/fileDialog.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2019 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -27,8 +26,6 @@ Example for the use of the ImageFileDialog. """ -from __future__ import absolute_import - __authors__ = ["V. Valls"] __license__ = "MIT" __date__ = "14/02/2018" @@ -216,7 +213,7 @@ class DialogExample(qt.QMainWindow): dialog = self.createDialog() # Execute the dialog as modal - result = dialog.exec_() + result = dialog.exec() self.printResult(dialog, result) def openDialogStoredState(self): @@ -226,7 +223,7 @@ class DialogExample(qt.QMainWindow): dialog.restoreState(self.__state[dialog.__class__]) # Execute the dialog as modal - result = dialog.exec_() + result = dialog.exec() self.__state[dialog.__class__] = dialog.saveState() self.printResult(dialog, result) @@ -237,7 +234,7 @@ class DialogExample(qt.QMainWindow): dialog.setDirectory(path) # Execute the dialog as modal - result = dialog.exec_() + result = dialog.exec() self.printResult(dialog, result) def openDialogAtComputer(self): @@ -247,7 +244,7 @@ class DialogExample(qt.QMainWindow): dialog.setDirectory(path) # Execute the dialog as modal - result = dialog.exec_() + result = dialog.exec() self.printResult(dialog, result) @@ -255,7 +252,7 @@ def main(): app = qt.QApplication([]) example = DialogExample() example.show() - app.exec_() + app.exec() if __name__ == "__main__": diff --git a/examples/findContours.py b/examples/findContours.py index 6199ba6..5b4eaf4 100644 --- a/examples/findContours.py +++ b/examples/findContours.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2019 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -694,7 +693,7 @@ def main(): window = FindContours() window.generateIsland() window.show() - result = app.exec_() + result = app.exec() # remove ending warnings relative to QTimer app.deleteLater() return result diff --git a/examples/hdf5widget.py b/examples/hdf5widget.py index 0d45b8f..f578660 100755 --- a/examples/hdf5widget.py +++ b/examples/hdf5widget.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2019 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -25,12 +24,12 @@ # ###########################################################################*/ """Qt Hdf5 widget examples""" +import html import logging import sys import tempfile import numpy -import six logging.basicConfig() _logger = logging.getLogger("hdf5widget") @@ -46,7 +45,6 @@ except ImportError: import h5py import silx.gui.hdf5 -import silx.utils.html from silx.gui import qt from silx.gui.data.DataViewerFrame import DataViewerFrame from silx.gui.widgets.ThreadPoolPushButton import ThreadPoolPushButton @@ -59,7 +57,7 @@ _file_cache = {} def str_attrs(str_list): """Return a numpy array of unicode strings""" - text_dtype = h5py.special_dtype(vlen=six.text_type) + text_dtype = h5py.special_dtype(vlen=str) return numpy.array(str_list, dtype=text_dtype) @@ -573,7 +571,7 @@ class Hdf5TreeViewExample(qt.QMainWindow): """Called to log event in widget """ def formatKey(name, value): - name, value = silx.utils.html.escape(str(name)), silx.utils.html.escape(str(value)) + name, value = html.escape(str(name)), html.escape(str(value)) return "<li><b>%s</b>: %s</li>" % (name, value) text = "<html>" @@ -791,7 +789,7 @@ def main(filenames): sys.excepthook = qt.exceptionHandler window = Hdf5TreeViewExample(filenames) window.show() - result = app.exec_() + result = app.exec() # remove ending warnings relative to QTimer app.deleteLater() sys.exit(result) diff --git a/examples/icons.py b/examples/icons.py index ae77630..d30c57c 100644 --- a/examples/icons.py +++ b/examples/icons.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2018 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -177,4 +176,4 @@ if __name__ == "__main__": app = qt.QApplication([]) window = IconPreview() window.setVisible(True) - app.exec_() + app.exec() diff --git a/examples/imageStack.py b/examples/imageStack.py index 0437a6e..244ac40 100644 --- a/examples/imageStack.py +++ b/examples/imageStack.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2018 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -132,7 +131,7 @@ def main(): urls = create_datasets(folder=dataset_folder) widget.setUrls(urls=urls) widget.show() - qapp.exec_() + qapp.exec() widget.close() shutil.rmtree(dataset_folder) diff --git a/examples/imageview.py b/examples/imageview.py index 81741b1..2b3273e 100755 --- a/examples/imageview.py +++ b/examples/imageview.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2019 European Synchrotron Radiation Facility @@ -33,21 +32,82 @@ To view an image file with the current installed silx library: To get help: ``python examples/imageview.py -h`` """ -from __future__ import division __authors__ = ["T. Vincent"] __license__ = "MIT" __date__ = "08/11/2018" import logging +import numpy +import time +import threading + +from silx.gui.utils import concurrent from silx.gui.plot.ImageView import ImageViewMainWindow from silx.gui import qt -import numpy logging.basicConfig() logger = logging.getLogger(__name__) +Nx = 150 +Ny = 50 + + +class UpdateThread(threading.Thread): + """Thread updating the image of a :class:`~sil.gui.plot.Plot2D` + + :param plot2d: The Plot2D to update.""" + + def __init__(self, imageview): + self.imageview = imageview + self.running = False + self.future_result = None + super(UpdateThread, self).__init__() + + def start(self): + """Start the update thread""" + self.running = True + super(UpdateThread, self).start() + + def run(self, pos={'x0': 0, 'y0': 0}): + """Method implementing thread loop that updates the plot + + It produces an image every 10 ms or so, and + either updates the plot or skip the image + """ + while self.running: + time.sleep(0.01) + + # Create image + # width of peak + sigma_x = 0.15 + sigma_y = 0.25 + # x and y positions + x = numpy.linspace(-1.5, 1.5, Nx) + y = numpy.linspace(-1.0, 1.0, Ny) + xv, yv = numpy.meshgrid(x, y) + signal = numpy.exp(- ((xv - pos['x0']) ** 2 / sigma_x ** 2 + + (yv - pos['y0']) ** 2 / sigma_y ** 2)) + # add noise + signal += 0.3 * numpy.random.random(size=signal.shape) + # random walk of center of peak ('drift') + pos['x0'] += 0.05 * (numpy.random.random() - 0.5) + pos['y0'] += 0.05 * (numpy.random.random() - 0.5) + + # If previous frame was not added to the plot yet, skip this one + if self.future_result is None or self.future_result.done(): + # plot the data asynchronously, and + # keep a reference to the `future` object + self.future_result = concurrent.submitToQtMainThread( + self.imageview.setImage, signal, resetzoom=False) + + def stop(self): + """Stop the update thread""" + self.running = False + self.join(2) + + def main(argv=None): """Display an image from a file in an :class:`ImageView` widget. @@ -82,12 +142,17 @@ def main(argv=None): parser.add_argument( 'filename', nargs='?', help='EDF filename of the image to open') + parser.add_argument( + '--live', action='store_true', + help='Live update of a generated image') args = parser.parse_args(args=argv) # Open the input file - if not args.filename: + edfFile = None + if args.live: + data = None + elif not args.filename: logger.warning('No image file provided, displaying dummy data') - edfFile = None size = 512 xx, yy = numpy.ogrid[-size:size, -size:size] data = numpy.cos(xx / (size//5)) + numpy.cos(yy / (size//5)) @@ -118,9 +183,10 @@ def main(argv=None): colormap = mainWindow.getDefaultColormap() colormap.setNormalization(colormap.LOGARITHM) - mainWindow.setImage(data, - origin=args.origin, - scale=args.scale) + if data is not None: + mainWindow.setImage(data, + origin=args.origin, + scale=args.scale) if edfFile is not None and nbFrames > 1: # Add a toolbar for multi-frame EDF support @@ -144,7 +210,12 @@ def main(argv=None): mainWindow.show() mainWindow.setFocus(qt.Qt.OtherFocusReason) - return app.exec_() + if args.live: + # Start updating the plot + updateThread = UpdateThread(mainWindow) + updateThread.start() + + return app.exec() if __name__ == "__main__": diff --git a/examples/periodicTable.py b/examples/periodicTable.py index e329ef7..31c2d46 100644 --- a/examples/periodicTable.py +++ b/examples/periodicTable.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2004-2017 European Synchrotron Radiation Facility +# Copyright (c) 2004-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -77,5 +76,4 @@ w.addTab(pl, "PeriodicList") w.addTab(comboContainer, "PeriodicCombo") w.show() -a.exec_() - +a.exec() diff --git a/examples/plot3dContextMenu.py b/examples/plot3dContextMenu.py index d33bb8f..2436b50 100644 --- a/examples/plot3dContextMenu.py +++ b/examples/plot3dContextMenu.py @@ -1,7 +1,6 @@ -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2017 European Synchrotron Radiation Facility +# Copyright (c) 2017-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -33,8 +32,6 @@ This is done by adding a custom context menu to the :class:`Plot3DWidget`: For more information on context menus, see Qt documentation. """ -from __future__ import absolute_import, division, unicode_literals - __authors__ = ["T. Vincent"] __license__ = "MIT" __date__ = "03/10/2017" @@ -86,7 +83,7 @@ class ScalarFieldViewWithContextMenu(ScalarFieldView): # The position received as argument is relative to Plot3DWidget # and needs to be converted. globalPosition = self.getPlot3DWidget().mapToGlobal(pos) - menu.exec_(globalPosition) + menu.exec(globalPosition) # Start Qt QApplication @@ -109,4 +106,4 @@ window.setData(data) window.addIsosurface(0.2, '#FF0000FF') window.show() -app.exec_() +app.exec() diff --git a/examples/plot3dSceneWindow.py b/examples/plot3dSceneWindow.py index 1b2f808..9e20dd3 100644 --- a/examples/plot3dSceneWindow.py +++ b/examples/plot3dSceneWindow.py @@ -1,7 +1,6 @@ -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2017-2019 European Synchrotron Radiation Facility +# Copyright (c) 2017-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -39,8 +38,6 @@ It features: """ -from __future__ import absolute_import - __authors__ = ["T. Vincent"] __license__ = "MIT" __date__ = "17/11/2017" @@ -200,4 +197,4 @@ window.show() sys.excepthook = qt.exceptionHandler # Run Qt event loop -qapp.exec_() +qapp.exec() diff --git a/examples/plot3dUpdateScatterFromThread.py b/examples/plot3dUpdateScatterFromThread.py index 9c2213f..a5b3df1 100644 --- a/examples/plot3dUpdateScatterFromThread.py +++ b/examples/plot3dUpdateScatterFromThread.py @@ -1,4 +1,3 @@ -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2019 European Synchrotron Radiation Facility @@ -167,7 +166,7 @@ def main(): updateThread = UpdateScatterThread(scatter) updateThread.start() # Start updating the plot - app.exec_() + app.exec() updateThread.stop() # Stop updating the plot diff --git a/examples/plotClearAction.py b/examples/plotClearAction.py index e1130cb..4237bf9 100644 --- a/examples/plotClearAction.py +++ b/examples/plotClearAction.py @@ -1,7 +1,6 @@ -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2018 European Synchrotron Radiation Facility +# Copyright (c) 2018-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -72,4 +71,4 @@ if __name__ == '__main__': plot.addCurve((0, 1, 2, 3, 4), (0, 1, 1.5, 1, 0)) # Add a curve to the plot plot.show() # Show the plot widget - app.exec_() # Start Qt application + app.exec() # Start Qt application diff --git a/examples/plotContextMenu.py b/examples/plotContextMenu.py index 5f02f5f..8eb9758 100644 --- a/examples/plotContextMenu.py +++ b/examples/plotContextMenu.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2017-2018 European Synchrotron Radiation Facility @@ -87,7 +86,7 @@ class PlotWidgetWithContextMenu(PlotWidget): # plot area, and thus needs to be converted. plotArea = self.getWidgetHandle() globalPosition = plotArea.mapToGlobal(pos) - menu.exec_(globalPosition) + menu.exec(globalPosition) # Start the QApplication @@ -100,4 +99,4 @@ plot.addCurve(x, numpy.sin(x), legend='sin') # Show the widget and start the application plot.show() -app.exec_() +app.exec() diff --git a/examples/plotCurveLegendWidget.py b/examples/plotCurveLegendWidget.py index 97c516a..d0bbca3 100644 --- a/examples/plotCurveLegendWidget.py +++ b/examples/plotCurveLegendWidget.py @@ -1,7 +1,6 @@ -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2018-2020 European Synchrotron Radiation Facility +# Copyright (c) 2018-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -112,7 +111,7 @@ class MyCurveLegendsWidget(CurveLegendsWidget): functools.partial(self._switchCurveVisibility, curve)) globalPosition = self.mapToGlobal(pos) - menu.exec_(globalPosition) + menu.exec(globalPosition) # First create the QApplication @@ -151,4 +150,4 @@ window.addDockWidget(qt.Qt.RightDockWidgetArea, dock) window.setAttribute(qt.Qt.WA_DeleteOnClose) window.show() -app.exec_() +app.exec() diff --git a/examples/plotInteractiveImageROI.py b/examples/plotInteractiveImageROI.py index 7254b7e..e2cbe7e 100644 --- a/examples/plotInteractiveImageROI.py +++ b/examples/plotInteractiveImageROI.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2018-2020 European Synchrotron Radiation Facility +# Copyright (c) 2018-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -153,6 +152,6 @@ plot.addTabbedDockWidget(dock) # Show the widget and start the application plot.show() -result = app.exec_() +result = app.exec() app.deleteLater() sys.exit(result) diff --git a/examples/plotItemsSelector.py b/examples/plotItemsSelector.py index 177489f..bdfc3bd 100755 --- a/examples/plotItemsSelector.py +++ b/examples/plotItemsSelector.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2017-2020 European Synchrotron Radiation Facility @@ -46,11 +45,11 @@ pw.show() isd = ItemsSelectionDialog(plot=pw) isd.setItemsSelectionMode(qt.QTableWidget.ExtendedSelection) -result = isd.exec_() +result = isd.exec() if result: for item in isd.getSelectedItems(): print(item.getName(), type(item)) else: print("Selection cancelled") -app.exec_() +app.exec() diff --git a/examples/plotLimits.py b/examples/plotLimits.py index c7cc7f5..052e802 100644 --- a/examples/plotLimits.py +++ b/examples/plotLimits.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2017 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -90,4 +89,4 @@ if __name__ == "__main__": app = qt.QApplication([]) window = ConstrainedViewPlot() window.setVisible(True) - app.exec_() + app.exec() diff --git a/examples/plotProfile.py b/examples/plotProfile.py index 931f9b4..61fe53a 100644 --- a/examples/plotProfile.py +++ b/examples/plotProfile.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2020 European Synchrotron Radiation Facility @@ -201,7 +200,7 @@ def main(): app = qt.QApplication([]) widget = Example() widget.show() - app.exec_() + app.exec() if __name__ == "__main__": main() diff --git a/examples/plotROIStats.py b/examples/plotROIStats.py index 3caff7e..53a45dc 100644 --- a/examples/plotROIStats.py +++ b/examples/plotROIStats.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2019 European Synchrotron Radiation Facility @@ -248,7 +247,7 @@ def example_curve(mode): window.setUpdateMode(mode) window.show() - app.exec_() + app.exec() def example_image(mode): @@ -278,7 +277,7 @@ def example_image(mode): window.setUpdateMode(mode) window.show() - app.exec_() + app.exec() updateThread.stop() # Stop updating the plot @@ -314,7 +313,7 @@ def example_curve_image(mode): updateThread.start() # Start updating the plot window.show() - app.exec_() + app.exec() updateThread.stop() # Stop updating the plot diff --git a/examples/plotStats.py b/examples/plotStats.py index 030caf8..dc2dc5b 100644 --- a/examples/plotStats.py +++ b/examples/plotStats.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2019 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -161,7 +160,7 @@ def main(argv): plot.getStatsWidget().parent().setVisible(True) plot.show() - app.exec_() + app.exec() updateThread.stop() # Stop updating the plot diff --git a/examples/plotUpdateCurveFromThread.py b/examples/plotUpdateCurveFromThread.py index a36e5ee..8f8717b 100644 --- a/examples/plotUpdateCurveFromThread.py +++ b/examples/plotUpdateCurveFromThread.py @@ -1,7 +1,6 @@ -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2017-2018 European Synchrotron Radiation Facility +# Copyright (c) 2017-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -95,7 +94,7 @@ def main(): updateThread = UpdateThread(plot1d) updateThread.start() # Start updating the plot - app.exec_() + app.exec() updateThread.stop() # Stop updating the plot diff --git a/examples/plotUpdateImageFromGevent.py b/examples/plotUpdateImageFromGevent.py new file mode 100644 index 0000000..453cbbd --- /dev/null +++ b/examples/plotUpdateImageFromGevent.py @@ -0,0 +1,112 @@ +# coding: utf-8 +# /*########################################################################## +# +# Copyright (c) 2017-2022 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ###########################################################################*/ +"""This script illustrates the update of a :class:`~silx.gui.plot.Plot2D` +widget from a gevent coroutine. +""" + +__authors__ = ["T. Vincent"] +__license__ = "MIT" +__date__ = "05/09/2017" + + +import threading +import time +import gevent +import logging + +import numpy + +from silx.gui import qt +from silx.gui.utils import concurrent +from silx.gui.plot import Plot2D + +_logger = logging.getLogger(__name__) + +Nx = 150 +Ny = 50 + + +def process_gevent(): + """Process gevent in case of QTimer triggering it.""" + try: + gevent.sleep(0.01) + except Exception: + _logger.critical("Uncaught exception from gevent", exc_info=True) + + +def update_image(plot2d): + """Update the image of a :class:`~sil.gui.plot.Plot2D` + + :param plot2d: The Plot2D to update.""" + + pos = {'x0': 0, 'y0': 0} + while True: + gevent.sleep(0.01) + + # Create image + # width of peak + sigma_x = 0.15 + sigma_y = 0.25 + # x and y positions + x = numpy.linspace(-1.5, 1.5, Nx) + y = numpy.linspace(-1.0, 1.0, Ny) + xv, yv = numpy.meshgrid(x, y) + signal = numpy.exp(- ((xv - pos['x0']) ** 2 / sigma_x ** 2 + + (yv - pos['y0']) ** 2 / sigma_y ** 2)) + # add noise + signal += 0.3 * numpy.random.random(size=signal.shape) + # random walk of center of peak ('drift') + pos['x0'] += 0.05 * (numpy.random.random() - 0.5) + pos['y0'] += 0.05 * (numpy.random.random() - 0.5) + + plot2d.addImage(signal, resetzoom=False) + + +def main(): + global app + app = qt.QApplication([]) + + gevent_timer = qt.QTimer() + gevent_timer.start(10) + gevent_timer.timeout.connect(process_gevent) + + # Create a Plot2D, set its limits and display it + plot2d = Plot2D() + plot2d.getIntensityHistogramAction().setVisible(True) + plot2d.setLimits(0, Nx, 0, Ny) + plot2d.getDefaultColormap().setVRange(0., 1.5) + plot2d.show() + + # Create the thread that calls submitToQtMainThread + updater = gevent.spawn(update_image, plot2d) + + app.exec() + + updater.kill() # Stop updating the plot + updater.join() + + +if __name__ == '__main__': + main() diff --git a/examples/plotUpdateImageFromThread.py b/examples/plotUpdateImageFromThread.py index 5850263..63f04ab 100644 --- a/examples/plotUpdateImageFromThread.py +++ b/examples/plotUpdateImageFromThread.py @@ -1,7 +1,6 @@ -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2017-2018 European Synchrotron Radiation Facility +# Copyright (c) 2017-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -116,6 +115,7 @@ def main(): # Create a Plot2D, set its limits and display it plot2d = Plot2D() + plot2d.getIntensityHistogramAction().setVisible(True) plot2d.setLimits(0, Nx, 0, Ny) plot2d.getDefaultColormap().setVRange(0., 1.5) plot2d.show() @@ -124,7 +124,7 @@ def main(): updateThread = UpdateThread(plot2d) updateThread.start() # Start updating the plot - app.exec_() + app.exec() updateThread.stop() # Stop updating the plot diff --git a/examples/plotWidget.py b/examples/plotWidget.py index af64afb..5cfe6cc 100644 --- a/examples/plotWidget.py +++ b/examples/plotWidget.py @@ -1,7 +1,6 @@ -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2017-2018 European Synchrotron Radiation Facility +# Copyright (c) 2017-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -64,7 +63,7 @@ class MyPlotWindow(qt.QMainWindow): # Make ColorBarWidget background white by changing its palette colorBar.setAutoFillBackground(True) palette = colorBar.palette() - palette.setColor(qt.QPalette.Background, qt.Qt.white) + palette.setColor(qt.QPalette.Window, qt.Qt.white) palette.setColor(qt.QPalette.Window, qt.Qt.white) colorBar.setPalette(palette) @@ -178,7 +177,7 @@ def main(): window.setAttribute(qt.Qt.WA_DeleteOnClose) window.show() window.showImage() - app.exec_() + app.exec() if __name__ == '__main__': diff --git a/examples/printPreview.py b/examples/printPreview.py index 6de8209..1a96e29 100755 --- a/examples/printPreview.py +++ b/examples/printPreview.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2018 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -96,4 +95,4 @@ pw3.show() pw3.addCurve(x, numpy.cos(x * 2 * numpy.pi / 1000)) -app.exec_() +app.exec() diff --git a/examples/scatterMask.py b/examples/scatterMask.py index 7a407ad..4244baa 100644 --- a/examples/scatterMask.py +++ b/examples/scatterMask.py @@ -1,4 +1,3 @@ -# coding: utf-8 # /*########################################################################## # Copyright (c) 2016-2018 European Synchrotron Radiation Facility # @@ -150,4 +149,4 @@ if __name__ == "__main__": msw.setScatter(x, y, v=v) msw.setBackgroundImage(bg_img) msw.show() - app.exec_() + app.exec() diff --git a/examples/scatterview.py b/examples/scatterview.py index cab32c0..2afae80 100755 --- a/examples/scatterview.py +++ b/examples/scatterview.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2019 European Synchrotron Radiation Facility @@ -26,7 +25,6 @@ """ Example to show the use of :class:`~silx.gui.plot.ScatterView.ScatterView` widget. """ -from __future__ import division __license__ = "MIT" @@ -91,7 +89,7 @@ def main(argv=None): mainWindow.show() mainWindow.setFocus(qt.Qt.OtherFocusReason) - return app.exec_() + return app.exec() if __name__ == "__main__": diff --git a/examples/shiftPlotAction.py b/examples/shiftPlotAction.py index f272cda..5faa9ba 100755 --- a/examples/shiftPlotAction.py +++ b/examples/shiftPlotAction.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2018 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -110,4 +109,4 @@ plotwin.addCurve(x, y1, legend="triangle shaped curve") plotwin.addCurve(x, y2, legend="oblique line") plotwin.show() -app.exec_() +app.exec() diff --git a/examples/simplewidget.py b/examples/simplewidget.py index 0e9038e..30b11d2 100755 --- a/examples/simplewidget.py +++ b/examples/simplewidget.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2018 European Synchrotron Radiation Facility @@ -219,7 +218,7 @@ def main(): sys.excepthook = qt.exceptionHandler window = SimpleWidgetExample() window.show() - result = app.exec_() + result = app.exec() # remove ending warnings relative to QTimer app.deleteLater() sys.excepthook = sys.__excepthook__ diff --git a/examples/stackView.py b/examples/stackView.py index a4b6e8c..5cb9a1c 100644 --- a/examples/stackView.py +++ b/examples/stackView.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2021 European Synchrotron Radiation Facility @@ -61,4 +60,4 @@ maskToolsWidget.setItemMaskUpdated(True) sv.show() -app.exec_() +app.exec() diff --git a/examples/syncPlotLocation.py b/examples/syncPlotLocation.py index 55332bc..66b787b 100644 --- a/examples/syncPlotLocation.py +++ b/examples/syncPlotLocation.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2017 European Synchrotron Radiation Facility @@ -102,4 +101,4 @@ if __name__ == "__main__": window = SyncPlot() window.setAttribute(qt.Qt.WA_DeleteOnClose, True) window.setVisible(True) - app.exec_() + app.exec() diff --git a/examples/syncaxis.py b/examples/syncaxis.py index 02505c9..166d931 100644 --- a/examples/syncaxis.py +++ b/examples/syncaxis.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2017 European Synchrotron Radiation Facility @@ -99,4 +98,4 @@ if __name__ == "__main__": window = SyncPlot() window.setAttribute(qt.Qt.WA_DeleteOnClose, True) window.setVisible(True) - app.exec_() + app.exec() diff --git a/examples/viewer3DVolume.py b/examples/viewer3DVolume.py index 2193402..001fe19 100644 --- a/examples/viewer3DVolume.py +++ b/examples/viewer3DVolume.py @@ -1,4 +1,3 @@ -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2016-2020 European Synchrotron Radiation Facility @@ -29,8 +28,6 @@ an interactive cutting plane. It can also be started without providing a file. """ -from __future__ import absolute_import, division, unicode_literals - __authors__ = ["T. Vincent"] __license__ = "MIT" __date__ = "05/01/2017" @@ -203,4 +200,4 @@ else: window.addIsosurface(default_isolevel, '#FF0000FF') window.show() -app.exec_() +app.exec() diff --git a/examples/writetoh5.py b/examples/writetoh5.py index 5e89e48..86bf1ec 100644 --- a/examples/writetoh5.py +++ b/examples/writetoh5.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # # Copyright (c) 2004-2017 European Synchrotron Radiation Facility diff --git a/package/debian10/control b/package/debian10/control index d724e69..25cf293 100644 --- a/package/debian10/control +++ b/package/debian10/control @@ -16,7 +16,6 @@ Build-Depends: cython3 (>= 0.23.2), python3-all-dev, python3-dateutil, python3-qtconsole, - python3-six, python3-fabio, python3-h5py, python3-mako, @@ -29,6 +28,8 @@ Build-Depends: cython3 (>= 0.23.2), python3-pyqt5, python3-pyqt5.qtopengl, python3-pyqt5.qtsvg, + python3-pytest, + python3-pytest-xvfb, python3-scipy, python3-setuptools, python3-sphinx, diff --git a/package/debian10/rules b/package/debian10/rules index e56f801..3a4310d 100755 --- a/package/debian10/rules +++ b/package/debian10/rules @@ -10,6 +10,7 @@ export PYBUILD_AFTER_INSTALL=rm -rf {destdir}/usr/bin/ export PYBUILD_NAME=silx export SPECFILE_USE_GNU_SOURCE=1 export SILX_FULL_INSTALL_REQUIRES=1 +export SILX_INSTALL_REQUIRES_STRIP=hdf5plugin DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) diff --git a/package/debian11/control b/package/debian11/control index 5e387fc..775753d 100644 --- a/package/debian11/control +++ b/package/debian11/control @@ -34,11 +34,12 @@ Build-Depends: cython3 (>= 0.23.2), python3-pyqt5.qtopengl-dbg, python3-pyqt5.qtsvg, python3-pyqt5.qtsvg-dbg, + python3-pytest, + python3-pytest-xvfb, python3-qtconsole, python3-scipy, python3-scipy-dbg, python3-setuptools, - python3-six, python3-sphinx, python3-sphinxcontrib.programoutput, xauth, diff --git a/package/debian11/rules b/package/debian11/rules index d086f63..57ff649 100755 --- a/package/debian11/rules +++ b/package/debian11/rules @@ -10,6 +10,7 @@ export PYBUILD_AFTER_INSTALL=rm -rf {destdir}/usr/bin/ export PYBUILD_NAME=silx export SPECFILE_USE_GNU_SOURCE=1 export SILX_FULL_INSTALL_REQUIRES=1 +export SILX_INSTALL_REQUIRES_STRIP=hdf5plugin DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) diff --git a/package/windows/README.rst b/package/windows/README.rst index 97c1d54..cbf6fa3 100644 --- a/package/windows/README.rst +++ b/package/windows/README.rst @@ -4,20 +4,13 @@ Generate silx fat binary for Windows Pre-requisites
--------------
-- PyInstaller must be installed.
- It is best to use the development version to use package specific hooks up-to-date.
- Run either::
-
- pip install -r requirements-dev.txt
-
- or::
-
- pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip
-
+- `PyInstaller <https://pyinstaller.readthedocs.io/>`_ must be installed.
+ Run: ``pip install -r requirements-dev.txt``
+- `InnoSetup <https://jrsoftware.org/isinfo.php>`_ must be installed and in the ``PATH``.
- silx and all its dependencies must be INSTALLED::
pip install silx[full]
-
+
or from the source directory::
pip install .[full]
@@ -28,10 +21,5 @@ Procedure - Go to the ``package/windows`` folder in the source directory
- Run ``pyinstaller pyinstaller.spec``.
- This generates a fat binary in ``package/windows/dist/silx/`` for the generic launcher ``silx.exe``.
-- Run ``pyinstaller pyinstaller-silx-view.spec``.
- This generates a fat binary in ``package/windows/dist/silx-view/`` for the silx view command ``silx-view.exe``.
-- Copy ``silx-view.exe`` and ``silx-view.exe.manifest`` to ``package/windows/dist/silx/``.
- This is a hack until PyInstaller supports multiple executables (see https://github.com/pyinstaller/pyinstaller/issues/1527).
-- Zip ``package\windows\dist\silx`` to make the application available as a single zip file.
-
+ This will generates the fat binary in ``package/windows/dist/``.
+ It will then run InnoSetup to create the installer in ``package/windows/artifacts/``.
diff --git a/package/windows/bootstrap-silx-view.py b/package/windows/bootstrap-silx-view.py index f8da02d..9d17483 100644 --- a/package/windows/bootstrap-silx-view.py +++ b/package/windows/bootstrap-silx-view.py @@ -1,4 +1,3 @@ -# coding: utf-8
import logging
diff --git a/package/windows/bootstrap.py b/package/windows/bootstrap.py index 3c6e887..06800ad 100644 --- a/package/windows/bootstrap.py +++ b/package/windows/bootstrap.py @@ -1,4 +1,3 @@ -# coding: utf-8
import logging
diff --git a/package/windows/create-installer.iss.template b/package/windows/create-installer.iss.template new file mode 100644 index 0000000..3e913b9 --- /dev/null +++ b/package/windows/create-installer.iss.template @@ -0,0 +1,92 @@ +[Setup]
+AppId={{A694A78C-B4D1-4983-8BC6-A84D30341EB4}
+AppName=silx view
+AppVersion=#Version
+AppVerName=silx-view-#Version
+AppPublisher=ESRF
+AppPublisherURL=https://www.silx.org
+AppSupportURL=https://github.com/silx-kit/silx
+AppUpdatesURL=https://github.com/silx-kit/silx/releases
+DefaultDirName={autopf}\silx
+DefaultGroupName=silx
+LicenseFile=LICENSE
+OutputDir=artifacts
+OutputBaseFilename=silx-#Version-x64
+Compression=lzma
+SolidCompression=yes
+ArchitecturesAllowed=x64
+ArchitecturesInstallIn64BitMode=x64
+WizardStyle=modern
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+[Files]
+Source: "dist\silx\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
+Source: "silx.ico"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\silx"; Filename: "{app}\silx-view.exe"; IconFilename: "{app}\silx.ico"
+Name: "{group}\Uninstall"; Filename: "{uninstallexe}"
+
+// Code from https://stackoverflow.com/questions/2000296/inno-setup-how-to-automatically-uninstall-previous-installed-version/2099805#209980
+[Code]
+
+/////////////////////////////////////////////////////////////////////
+function GetUninstallString(): String;
+var
+ sUnInstPath: String;
+ sUnInstallString: String;
+begin
+ sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
+ sUnInstallString := '';
+ if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
+ RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
+ Result := sUnInstallString;
+end;
+
+
+/////////////////////////////////////////////////////////////////////
+function IsUpgrade(): Boolean;
+begin
+ Result := (GetUninstallString() <> '');
+end;
+
+
+/////////////////////////////////////////////////////////////////////
+function UnInstallOldVersion(): Integer;
+var
+ sUnInstallString: String;
+ iResultCode: Integer;
+begin
+ // Return Values:
+ // 1 - uninstall string is empty
+ // 2 - error executing the UnInstallString
+ // 3 - successfully executed the UnInstallString
+
+ // default return value
+ Result := 0;
+
+ // get the uninstall string of the old app
+ sUnInstallString := GetUninstallString();
+ if sUnInstallString <> '' then begin
+ sUnInstallString := RemoveQuotes(sUnInstallString);
+ if Exec(sUnInstallString, '/VERYSILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
+ Result := 3
+ else
+ Result := 2;
+ end else
+ Result := 1;
+end;
+
+/////////////////////////////////////////////////////////////////////
+procedure CurStepChanged(CurStep: TSetupStep);
+begin
+ if (CurStep=ssInstall) then
+ begin
+ if (IsUpgrade()) then
+ begin
+ UnInstallOldVersion();
+ end;
+ end;
+end;
diff --git a/package/windows/pyinstaller-silx-view.spec b/package/windows/pyinstaller-silx-view.spec deleted file mode 100644 index cf01fd1..0000000 --- a/package/windows/pyinstaller-silx-view.spec +++ /dev/null @@ -1,55 +0,0 @@ -# -*- mode: python -*-
-import os.path
-from PyInstaller.utils.hooks import collect_data_files, collect_submodules
-
-datas = []
-
-PROJECT_PATH = os.path.abspath(os.path.join(SPECPATH, "..", ".."))
-datas.append((os.path.join(PROJECT_PATH, "README.rst"), "."))
-datas.append((os.path.join(PROJECT_PATH, "LICENSE"), "."))
-datas.append((os.path.join(PROJECT_PATH, "copyright"), "."))
-datas += collect_data_files("silx.resources")
-
-
-hiddenimports = collect_submodules('fabio')
-
-
-block_cipher = None
-
-
-a = Analysis(['bootstrap-silx-view.py'],
- pathex=[],
- binaries=[],
- datas=datas,
- hiddenimports=hiddenimports,
- hookspath=[],
- runtime_hooks=[],
- excludes=[],
- win_no_prefer_redirects=False,
- win_private_assemblies=False,
- cipher=block_cipher,
- noarchive=False)
-
-pyz = PYZ(a.pure,
- a.zipped_data,
- cipher=block_cipher)
-
-exe = EXE(pyz,
- a.scripts,
- [],
- exclude_binaries=True,
- name='silx-view',
- debug=False,
- bootloader_ignore_signals=False,
- strip=False,
- upx=False,
- console=False,
- icon='silx.ico')
-
-coll = COLLECT(exe,
- a.binaries,
- a.zipfiles,
- a.datas,
- strip=False,
- upx=False,
- name='silx-view')
diff --git a/package/windows/pyinstaller.spec b/package/windows/pyinstaller.spec index 548e41a..a0066cf 100644 --- a/package/windows/pyinstaller.spec +++ b/package/windows/pyinstaller.spec @@ -1,5 +1,13 @@ # -*- mode: python -*-
+import importlib.metadata
import os.path
+from pathlib import Path
+import shutil
+import subprocess
+import sys
+
+import pkg_resources
+
from PyInstaller.utils.hooks import collect_data_files, collect_submodules
datas = []
@@ -9,47 +17,156 @@ datas.append((os.path.join(PROJECT_PATH, "README.rst"), ".")) datas.append((os.path.join(PROJECT_PATH, "LICENSE"), "."))
datas.append((os.path.join(PROJECT_PATH, "copyright"), "."))
datas += collect_data_files("silx.resources")
+datas += collect_data_files("hdf5plugin")
-hiddenimports = collect_submodules('fabio')
+hiddenimports = []
+hiddenimports += collect_submodules('fabio')
+hiddenimports += collect_submodules('hdf5plugin')
block_cipher = None
-a = Analysis(['bootstrap.py'],
- pathex=[],
- binaries=[],
- datas=datas,
- hiddenimports=hiddenimports,
- hookspath=[],
- runtime_hooks=[],
- excludes=[],
- win_no_prefer_redirects=False,
- win_private_assemblies=False,
- cipher=block_cipher,
- noarchive=False)
-
-pyz = PYZ(a.pure,
- a.zipped_data,
- cipher=block_cipher)
-
-exe = EXE(pyz,
- a.scripts,
- [],
- exclude_binaries=True,
- name='silx',
- debug=False,
- bootloader_ignore_signals=False,
- strip=False,
- upx=False,
- console=True,
- icon='silx.ico')
-
-coll = COLLECT(exe,
- a.binaries,
- a.zipfiles,
- a.datas,
- strip=False,
- upx=False,
- name='silx')
+silx_a = Analysis(
+ ['bootstrap.py'],
+ pathex=[],
+ binaries=[],
+ datas=datas,
+ hiddenimports=hiddenimports,
+ hookspath=[],
+ runtime_hooks=[],
+ excludes=[],
+ win_no_prefer_redirects=False,
+ win_private_assemblies=False,
+ cipher=block_cipher,
+ noarchive=False)
+
+silx_view_a = Analysis(
+ ['bootstrap-silx-view.py'],
+ pathex=[],
+ binaries=[],
+ datas=datas,
+ hiddenimports=hiddenimports,
+ hookspath=[],
+ runtime_hooks=[],
+ excludes=[],
+ win_no_prefer_redirects=False,
+ win_private_assemblies=False,
+ cipher=block_cipher,
+ noarchive=False)
+
+MERGE(
+ (silx_a, 'silx', os.path.join('silx', 'silx')),
+ (silx_view_a, 'silx-view', os.path.join('silx-view', 'silx-view')),
+)
+
+
+silx_pyz = PYZ(
+ silx_a.pure,
+ silx_a.zipped_data,
+ cipher=block_cipher)
+
+silx_exe = EXE(
+ silx_pyz,
+ silx_a.scripts,
+ silx_a.dependencies,
+ [],
+ exclude_binaries=True,
+ name='silx',
+ debug=False,
+ bootloader_ignore_signals=False,
+ strip=False,
+ upx=False,
+ console=True,
+ icon='silx.ico')
+
+silx_coll = COLLECT(
+ silx_exe,
+ silx_a.binaries,
+ silx_a.zipfiles,
+ silx_a.datas,
+ strip=False,
+ upx=False,
+ name='silx')
+
+
+silx_view_pyz = PYZ(
+ silx_view_a.pure,
+ silx_view_a.zipped_data,
+ cipher=block_cipher)
+
+silx_view_exe = EXE(
+ silx_view_pyz,
+ silx_view_a.scripts,
+ silx_view_a.dependencies,
+ [],
+ exclude_binaries=True,
+ name='silx-view',
+ debug=False,
+ bootloader_ignore_signals=False,
+ strip=False,
+ upx=False,
+ console=False,
+ icon='silx.ico')
+
+silx_view_coll = COLLECT(
+ silx_view_exe,
+ silx_view_a.binaries,
+ silx_view_a.zipfiles,
+ silx_view_a.datas,
+ strip=False,
+ upx=False,
+ name='silx-view')
+
+
+# Fix MERGE by copying produced silx-view.exe file
+def move_silx_view_exe():
+ dist = Path(SPECPATH) / 'dist'
+ shutil.copy2(
+ src=dist / 'silx-view' / 'silx-view.exe',
+ dst=dist / 'silx',
+ )
+ shutil.rmtree(dist / 'silx-view')
+
+move_silx_view_exe()
+
+# Generate license file from current Python env
+def create_license_file(filename: str):
+ import PyQt5.QtCore
+
+ with open(filename, 'w') as f:
+ f.write(f"""
+This is free software.
+
+This distribution of silx is provided under the
+GNU General Public License v3 (https://www.gnu.org/licenses/gpl-3.0.en.html) since it includes PyQt5.
+
+It includes mainy software packages with different licenses:
+
+- Python ({sys.version}): PSF license, https://www.python.org/
+- Qt ({PyQt5.QtCore.qVersion()}): GNU Lesser General Public License v3, https://www.qt.io/
+""")
+
+ for dist in sorted(pkg_resources.working_set, key=lambda d: d.key):
+ license = importlib.metadata.metadata(dist.key).get('License')
+ homepage = importlib.metadata.metadata(dist.key).get('Home-page')
+ info = ", ".join(info for info in (license, homepage) if info)
+ f.write(f"- {dist.project_name} ({importlib.metadata.version(dist.key)}): {info}\n")
+
+create_license_file('LICENSE')
+
+# Run innosetup
+def innosetup():
+ from silx import version
+
+ config_name = "create-installer.iss"
+ with open(config_name + '.template') as f:
+ content = f.read().replace("#Version", version)
+ with open(config_name, "w") as f:
+ f.write(content)
+
+ subprocess.call(["iscc", os.path.join(SPECPATH, config_name)])
+ os.remove(config_name)
+
+innosetup()
diff --git a/pyproject.toml b/pyproject.toml index c80dee7..cc3b000 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,8 @@ [build-system] requires = [ "wheel", - "setuptools", + "setuptools<60.0.0", "numpy>=1.12", "Cython>=0.21.1" ] +build-backend = "setuptools.build_meta"
\ No newline at end of file diff --git a/qtdesigner_plugins/plot1dplugin.py b/qtdesigner_plugins/plot1dplugin.py index 86982af..d41a328 100644 --- a/qtdesigner_plugins/plot1dplugin.py +++ b/qtdesigner_plugins/plot1dplugin.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -32,9 +31,7 @@ __date__ = "30/05/2016" from silx.gui import icons, qt -if qt.BINDING == 'PyQt4': - from PyQt4 import QtDesigner -elif qt.BINDING == 'PyQt5': +if qt.BINDING == 'PyQt5': from PyQt5 import QtDesigner else: raise RuntimeError("Unsupport Qt BINDING: %s" % qt.BINDING) diff --git a/qtdesigner_plugins/plot2dplugin.py b/qtdesigner_plugins/plot2dplugin.py index 1a07510..4d211c4 100644 --- a/qtdesigner_plugins/plot2dplugin.py +++ b/qtdesigner_plugins/plot2dplugin.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016 European Synchrotron Radiation Facility +# Copyright (c) 2016-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -32,9 +31,7 @@ __date__ = "30/05/2016" from silx.gui import icons, qt -if qt.BINDING == 'PyQt4': - from PyQt4 import QtDesigner -elif qt.BINDING == 'PyQt5': +if qt.BINDING == 'PyQt5': from PyQt5 import QtDesigner else: raise RuntimeError("Unsupport Qt BINDING: %s" % qt.BINDING) diff --git a/qtdesigner_plugins/plotwidgetplugin.py b/qtdesigner_plugins/plotwidgetplugin.py index 6cc97a5..f1d0d0b 100644 --- a/qtdesigner_plugins/plotwidgetplugin.py +++ b/qtdesigner_plugins/plotwidgetplugin.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2015-2016 European Synchrotron Radiation Facility +# Copyright (c) 2015-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -32,9 +31,7 @@ __date__ = "30/05/2016" from silx.gui import qt, icons -if qt.BINDING == 'PyQt4': - from PyQt4 import QtDesigner -elif qt.BINDING == 'PyQt5': +if qt.BINDING == 'PyQt5': from PyQt5 import QtDesigner else: raise RuntimeError("Unsupport Qt BINDING: %s" % qt.BINDING) diff --git a/qtdesigner_plugins/plotwindowplugin.py b/qtdesigner_plugins/plotwindowplugin.py index b666399..649bbf5 100644 --- a/qtdesigner_plugins/plotwindowplugin.py +++ b/qtdesigner_plugins/plotwindowplugin.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# coding: utf-8 # /*########################################################################## # -# Copyright (c) 2015-2016 European Synchrotron Radiation Facility +# Copyright (c) 2015-2021 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -32,9 +31,7 @@ __date__ = "30/05/2016" from silx.gui import icons, qt -if qt.BINDING == 'PyQt4': - from PyQt4 import QtDesigner -elif qt.BINDING == 'PyQt5': +if qt.BINDING == 'PyQt5': from PyQt5 import QtDesigner else: raise RuntimeError("Unsupport Qt BINDING: %s" % qt.BINDING) diff --git a/requirements-dev.txt b/requirements-dev.txt index dac7fad..9b5807a 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,14 +1,20 @@ # List of silx development dependencies -# Those ARE NOT required for installation, at runtime or to build from source (except for the doc) +# Those ARE NOT required for installation or at runtime -r requirements.txt +build # To build the project wheel # To build wheels Sphinx # To build the documentation in doc/ -lxml # For test coverage in run_test.py -coverage # For test coverage in run_test.py +sphinx-autodoc-typehints # For leveraging Python type hints from Sphinx pillow # For loading images in documentation generation nbsphinx # For converting ipynb in documentation pandoc # For documentation Qt snapshot updates +pytest # For testing +pytest-xvfb # For GUI testing +pytest-cov # For coverage + +hdf5plugin # For HDF5 compression filters handling + # Use dev version of PyInstaller to keep hooks up-to-date https://github.com/pyinstaller/pyinstaller/archive/develop.zip; sys_platform == "win32" diff --git a/requirements.txt b/requirements.txt index fb5690d..7e2e8be 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,15 +3,14 @@ --trusted-host www.silx.org --find-links http://www.silx.org/pub/wheelhouse/ ---only-binary numpy,h5py,scipy,PySide2,PyQt5 +--only-binary numpy,h5py,scipy,PySide2,PyQt5,PySide6,PyQt6 # Required dependencies (from setup.py setup_requires and install_requires) numpy >= 1.12 -setuptools +setuptools < 60.0.0 Cython >= 0.21.1 h5py fabio >= 0.9 -six # Extra dependencies (from setup.py extra_requires 'full' target) pyopencl; platform_machine in "i386, x86_64, AMD64" # For silx.opencl @@ -22,4 +21,4 @@ PyOpenGL # For silx.gui.plot3d python-dateutil # For silx.gui.plot scipy # For silx.math.fit demo, silx.image.sift demo, silx.image.sift.test Pillow # For silx.opencl.image.test -PyQt5 # or PySide2 # For silx.gui +PyQt5 # PySide6, PyQt6>=6.3 # For silx.gui diff --git a/run_tests.py b/run_tests.py index 5d3155a..19368b3 100755 --- a/run_tests.py +++ b/run_tests.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -# coding: utf8 # /*########################################################################## # -# Copyright (c) 2015-2020 European Synchrotron Radiation Facility +# Copyright (c) 2015-2022 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -35,48 +34,14 @@ __authors__ = ["Jérôme Kieffer", "Thomas Vincent"] __date__ = "30/09/2020" __license__ = "MIT" -import distutils.util +import importlib import logging import os import subprocess import sys -import time -import unittest -import collections -from argparse import ArgumentParser +import sysconfig -class StreamHandlerUnittestReady(logging.StreamHandler): - """The unittest class TestResult redefine sys.stdout/err to capture - stdout/err from tests and to display them only when a test fail. - This class allow to use unittest stdout-capture by using the last sys.stdout - and not a cached one. - """ - - def emit(self, record): - """ - :type record: logging.LogRecord - """ - self.stream = sys.stderr - super(StreamHandlerUnittestReady, self).emit(record) - - def flush(self): - pass - - -def createBasicHandler(): - """Create the handler using the basic configuration""" - hdlr = StreamHandlerUnittestReady() - fs = logging.BASIC_FORMAT - dfs = None - fmt = logging.Formatter(fs, dfs) - hdlr.setFormatter(fmt) - return hdlr - - -# Use an handler compatible with unittests, else use_buffer is not working -logging.root.addHandler(createBasicHandler()) - # Capture all default warnings logging.captureWarnings(True) import warnings @@ -87,25 +52,6 @@ logger.setLevel(logging.WARNING) logger.info("Python %s %s", sys.version, tuple.__itemsize__ * 8) -try: - import resource -except ImportError: - resource = None - logger.warning("resource module missing") - -try: - import importlib - importer = importlib.import_module -except ImportError: - - def importer(name): - module = __import__(name) - # returns the leaf module, instead of the root module - subnames = name.split(".") - subnames.pop(0) - for subname in subnames: - module = getattr(module, subname) - return module try: import numpy @@ -136,131 +82,8 @@ def get_project_name(root_dir): return name.split()[-1].decode('ascii') -class TextTestResultWithSkipList(unittest.TextTestResult): - """Override default TextTestResult to display list of skipped tests at the - end - """ - - def printErrors(self): - unittest.TextTestResult.printErrors(self) - # Print skipped tests at the end - self.printGroupedList("SKIPPED", self.skipped) - - def printGroupedList(self, flavour, errors): - grouped = collections.OrderedDict() - - for test, err in errors: - if err in grouped: - grouped[err] = grouped[err] + [test] - else: - grouped[err] = [test] - - for err, tests in grouped.items(): - self.stream.writeln(self.separator1) - for test in tests: - self.stream.writeln("%s: %s" % (flavour, self.getDescription(test))) - self.stream.writeln(self.separator2) - self.stream.writeln("%s" % err) - - -class ProfileTextTestResult(unittest.TextTestRunner.resultclass): - - def __init__(self, *arg, **kwarg): - unittest.TextTestRunner.resultclass.__init__(self, *arg, **kwarg) - self.logger = logging.getLogger("memProf") - self.logger.setLevel(min(logging.INFO, logging.root.level)) - self.logger.handlers.append(logging.FileHandler("profile.log")) - - def startTest(self, test): - unittest.TextTestRunner.resultclass.startTest(self, test) - if resource: - self.__mem_start = \ - resource.getrusage(resource.RUSAGE_SELF).ru_maxrss - self.__time_start = time.time() - - def stopTest(self, test): - unittest.TextTestRunner.resultclass.stopTest(self, test) - # see issue 311. For other platform, get size of ru_maxrss in "man getrusage" - if sys.platform == "darwin": - ratio = 1e-6 - else: - ratio = 1e-3 - if resource: - memusage = (resource.getrusage(resource.RUSAGE_SELF).ru_maxrss - - self.__mem_start) * ratio - else: - memusage = 0 - self.logger.info("Time: %.3fs \t RAM: %.3f Mb\t%s", - time.time() - self.__time_start, - memusage, test.id()) - - -def report_rst(cov, package, version="0.0.0", base=""): - """ - Generate a report of test coverage in RST (for Sphinx inclusion) - - :param cov: test coverage instance - :param str package: Name of the package - :param str base: base directory of modules to include in the report - :return: RST string - """ - import tempfile - fd, fn = tempfile.mkstemp(suffix=".xml") - os.close(fd) - cov.xml_report(outfile=fn) - - from lxml import etree - xml = etree.parse(fn) - classes = xml.xpath("//class") - - line0 = "Test coverage report for %s" % package - res = [line0, "=" * len(line0), ""] - res.append("Measured on *%s* version %s, %s" % - (package, version, time.strftime("%d/%m/%Y"))) - res += ["", - ".. csv-table:: Test suite coverage", - ' :header: "Name", "Stmts", "Exec", "Cover"', - ' :widths: 35, 8, 8, 8', - ''] - tot_sum_lines = 0 - tot_sum_hits = 0 - - for cl in classes: - name = cl.get("name") - fname = cl.get("filename") - if not os.path.abspath(fname).startswith(base): - continue - lines = cl.find("lines").getchildren() - hits = [int(i.get("hits")) for i in lines] - - sum_hits = sum(hits) - sum_lines = len(lines) - - cover = 100.0 * sum_hits / sum_lines if sum_lines else 0 - - if base: - name = os.path.relpath(fname, base) - - res.append(' "%s", "%s", "%s", "%.1f %%"' % - (name, sum_lines, sum_hits, cover)) - tot_sum_lines += sum_lines - tot_sum_hits += sum_hits - res.append("") - res.append(' "%s total", "%s", "%s", "%.1f %%"' % - (package, tot_sum_lines, tot_sum_hits, - 100.0 * tot_sum_hits / tot_sum_lines if tot_sum_lines else 0)) - res.append("") - return os.linesep.join(res) - - def is_debug_python(): """Returns true if the Python interpreter is in debug mode.""" - try: - import sysconfig - except ImportError: # pragma nocover - # Python < 2.7 - import distutils.sysconfig as sysconfig - if sysconfig.get_config_var("Py_DEBUG"): return True @@ -276,7 +99,7 @@ def build_project(name, root_dir): :param str root_dir: Root directory of the project :return: The path to the directory were build was performed """ - platform = distutils.util.get_platform() + platform = sysconfig.get_platform() architecture = "lib.%s-%i.%i" % (platform, sys.version_info[0], sys.version_info[1]) if is_debug_python(): @@ -291,8 +114,10 @@ def build_project(name, root_dir): home = os.path.join(root_dir, "build", architecture) logger.warning("Building %s to %s", name, home) - p = subprocess.Popen([sys.executable, "setup.py", "build"], - shell=False, cwd=root_dir) + cmd = [sys.executable, "setup.py", "build"] + if home: + cmd += ["--build-lib", home] + p = subprocess.Popen(cmd, shell=False, cwd=root_dir) logger.debug("subprocess ended with rc= %s", p.wait()) if os.path.isdir(home): @@ -304,14 +129,9 @@ def build_project(name, root_dir): def import_project_module(project_name, project_dir): """Import project module, from the system of from the project directory""" - # Prevent importing from source directory - if (os.path.dirname(os.path.abspath(__file__)) == os.path.abspath(sys.path[0])): - removed_from_sys_path = sys.path.pop(0) - logger.info("Patched sys.path, removed: '%s'", removed_from_sys_path) - if "--installed" in sys.argv: try: - module = importer(project_name) + module = importlib.import_module(project_name) except Exception: logger.error("Cannot run tests on installed version: %s not installed or raising error.", project_name) @@ -322,25 +142,13 @@ def import_project_module(project_name, project_dir): logging.error("Built project is not available !!! investigate") sys.path.insert(0, build_dir) logger.warning("Patched sys.path, added: '%s'", build_dir) - module = importer(project_name) + module = importlib.import_module(project_name) return module -def get_test_options(project_module): - """Returns the test options if available, else None""" - module_name = project_module.__name__ + '.test.utils' - logger.info('Import %s', module_name) - try: - test_utils = importer(module_name) - except ImportError: - logger.warning("No module named '%s'. No test options available.", module_name) - return None - - test_options = getattr(test_utils, "test_options", None) - return test_options - - if __name__ == "__main__": # Needed for multiprocessing support on Windows + import pytest + PROJECT_DIR = os.path.dirname(os.path.abspath(__file__)) PROJECT_NAME = get_project_name(PROJECT_DIR) logger.info("Project name: %s", PROJECT_NAME) @@ -349,143 +157,20 @@ if __name__ == "__main__": # Needed for multiprocessing support on Windows PROJECT_VERSION = getattr(project_module, 'version', '') PROJECT_PATH = project_module.__path__[0] - test_options = get_test_options(project_module) - """Contains extra configuration for the tests.""" - - epilog = """Environment variables: - WITH_QT_TEST=False to disable graphical tests - SILX_OPENCL=False to disable OpenCL tests - SILX_TEST_LOW_MEM=True to disable tests taking large amount of memory - GPU=False to disable the use of a GPU with OpenCL test - WITH_GL_TEST=False to disable tests using OpenGL - """ - parser = ArgumentParser(description='Run the tests.', - epilog=epilog) - - parser.add_argument("--installed", - action="store_true", dest="installed", default=False, - help=("Test the installed version instead of" + - "building from the source")) - parser.add_argument("-c", "--coverage", dest="coverage", - action="store_true", default=False, - help=("Report code coverage" + - "(requires 'coverage' and 'lxml' module)")) - parser.add_argument("-m", "--memprofile", dest="memprofile", - action="store_true", default=False, - help="Report memory profiling") - parser.add_argument("-v", "--verbose", default=0, - action="count", dest="verbose", - help="Increase verbosity. Option -v prints additional " + - "INFO messages. Use -vv for full verbosity, " + - "including debug messages and test help strings.") - parser.add_argument("--qt-binding", dest="qt_binding", default=None, - help="Force using a Qt binding, from 'PyQt4', 'PyQt5', or 'PySide'") - if test_options is not None: - test_options.add_parser_argument(parser) - - default_test_name = "%s.test.suite" % PROJECT_NAME |