From 1f466fb9966ba3fe07a60355150aad0dfe02bfa8 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Thu, 25 Jun 2026 11:31:09 +0200 Subject: [PATCH 1/6] Switch config from bandit, black, isort, flake8 to ruff --- .flake8 | 6 ------ pyproject.toml | 35 +++++++++++++++++++---------------- 2 files changed, 19 insertions(+), 22 deletions(-) delete mode 100644 .flake8 diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 68e6a65b..00000000 --- a/.flake8 +++ /dev/null @@ -1,6 +0,0 @@ -[flake8] -max-line-length = 88 -extend-ignore = E203,E501,E701 -extend-exclude = - build, - lib diff --git a/pyproject.toml b/pyproject.toml index 7e45f7e0..5f8e12ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,27 +62,30 @@ package-dir = {"" = "src"} [tool.setuptools.dynamic] version = {attr = "hdf5plugin._version.version"} -[tool.bandit] -exclude_dirs = [ +[tool.ruff] +exclude = [ "build", - "doc/hdf5plugin_EuropeanHUG2023", "lib", ] +line-length = 88 -[tool.bandit.assert_used] -skips = ["*test.py"] - -[tool.black] -extend-exclude = ''' -( - lib - | .*\.ipynb -) -''' +[tool.ruff.lint] +select = [ + "E", # pycodestyle + "F", # pyflakes + "I", # isort + "S", # flake8-bandit + "W", # pycodestyle +] -[tool.isort] -profile = "black" -skip_glob = ["lib"] +[tool.ruff.lint.per-file-ignores] +"*" = ["E501"] # line too long +"test*.py" = ["S101"] # assert +"doc/hdf5plugin_EuropeanHUG2023/*" = ["S108"] # access to /dev/shm +# urlretrieve without url schema check +"doc/hdf5plugin_EuropeanHUG2021.ipynb" = ["S310"] +"doc/hdf5plugin_EuropeanHUG2022.ipynb" = ["S310"] +"doc/hdf5plugin_EuropeanHUG2023/presentation.ipynb" = ["S310"] [tool.mypy] mypy_path = ["src"] From 2ecc6ae1dde649bdd6e0df6f4b2cce90ad062af6 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Thu, 25 Jun 2026 11:32:11 +0200 Subject: [PATCH 2/6] Apply ruff to src/ and test/ --- src/h5py.pyi | 4 ++-- src/hdf5plugin/__init__.py | 2 +- src/hdf5plugin/test.py | 2 +- test/test.py | 6 ++---- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/h5py.pyi b/src/h5py.pyi index 33d5a4f3..664cdbfa 100644 --- a/src/h5py.pyi +++ b/src/h5py.pyi @@ -1,7 +1,7 @@ -from __future__ import annotations - """mypy stubs for h5py usage in hdf5plugin""" +from __future__ import annotations + import ctypes from collections.abc import Buffer from types import TracebackType diff --git a/src/hdf5plugin/__init__.py b/src/hdf5plugin/__init__.py index fab4dac6..fd7b8faf 100644 --- a/src/hdf5plugin/__init__.py +++ b/src/hdf5plugin/__init__.py @@ -27,13 +27,13 @@ """ from . import _version -from ._filters import FILTERS # noqa from ._filters import ( # noqa BLOSC2_ID, BLOSC_ID, BSHUF_ID, BZIP2_ID, FCIDECOMP_ID, + FILTERS, LZ4, LZ4_ID, SPERR_ID, diff --git a/src/hdf5plugin/test.py b/src/hdf5plugin/test.py index bbfc0f61..fe0c6187 100644 --- a/src/hdf5plugin/test.py +++ b/src/hdf5plugin/test.py @@ -33,10 +33,10 @@ import unittest from typing import Any, cast -import h5py import numpy from packaging.version import parse as parse_version +import h5py import hdf5plugin try: diff --git a/test/test.py b/test/test.py index 888a6b2a..255c3159 100644 --- a/test/test.py +++ b/test/test.py @@ -31,9 +31,9 @@ import tempfile import unittest -import h5py import numpy +import h5py import hdf5plugin from hdf5plugin import _filters from hdf5plugin.test import suite as hdf5plugin_suite @@ -370,9 +370,7 @@ def testReprRoundtrip(self): with self.subTest(filter=filter_class.filter_name): filter_instance = filter_class() repr_string = repr(filter_instance) - repr_instance = eval( - repr_string, {filter_class.__name__: filter_class} - ) # nosec + repr_instance = eval(repr_string, {filter_class.__name__: filter_class}) # noqa: S307 self.assertEqual(filter_instance, repr_instance) From 8e58918804c4dba2b508ecb0cde6e4b75496675b Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Thu, 25 Jun 2026 11:35:35 +0200 Subject: [PATCH 3/6] apply ruff to notebooks --- doc/hdf5plugin_EuropeanHUG2021.ipynb | 37 +++++--- doc/hdf5plugin_EuropeanHUG2022.ipynb | 35 ++++---- .../benchmark.ipynb | 90 ++++++++++--------- doc/hdf5plugin_EuropeanHUG2023/benchmark.py | 3 +- .../hdf5_compressed_chunk_direct_read.ipynb | 69 ++++++++------ .../presentation.ipynb | 32 +++---- 6 files changed, 152 insertions(+), 114 deletions(-) diff --git a/doc/hdf5plugin_EuropeanHUG2021.ipynb b/doc/hdf5plugin_EuropeanHUG2021.ipynb index c5ea342c..ea76c65f 100755 --- a/doc/hdf5plugin_EuropeanHUG2021.ipynb +++ b/doc/hdf5plugin_EuropeanHUG2021.ipynb @@ -51,12 +51,14 @@ "%matplotlib inline\n", "\n", "# Creates data.h5 used for demos\n", + "import urllib.request\n", + "\n", + "import numpy\n", "from matplotlib import pyplot as plt\n", + "from PIL import Image\n", + "\n", "import h5py\n", "import hdf5plugin\n", - "import numpy\n", - "from PIL import Image\n", - "import urllib.request\n", "\n", "url = \"https://www.eiroforum.org/wp-content/uploads/pg-esrf-01.jpg\"\n", "filename = urllib.request.urlretrieve(url)[0]\n", @@ -67,7 +69,9 @@ "h5file[\"copyright\"] = \"P.Ginter/ESRF\"\n", "h5file.attrs[\"url\"] = url\n", "h5file.create_dataset(\"/data\", data=image)\n", - "h5file.create_dataset(\"/compressed_data_bitshuffle_lz4\", data=image, **hdf5plugin.Bitshuffle())\n", + "h5file.create_dataset(\n", + " \"/compressed_data_bitshuffle_lz4\", data=image, **hdf5plugin.Bitshuffle()\n", + ")\n", "h5file.close()\n", "\n", "# Restart kernel once the file is created!" @@ -334,6 +338,7 @@ ], "source": [ "from h5glance import H5Glance # Browsing HDF5 files\n", + "\n", "H5Glance(\"data.h5\")" ] }, @@ -373,8 +378,9 @@ "import h5py # Pythonic HDF5 wrapper: https://docs.h5py.org/\n", "\n", "h5file = h5py.File(\"data.h5\", mode=\"r\") # Open HDF5 file in read mode\n", - "data = h5file[\"/data\"][()] # Access HDF5 dataset \"/data\"\n", - "plt.imshow(data); plt.colorbar() # Display data" + "data = h5file[\"/data\"][()] # Access HDF5 dataset \"/data\"\n", + "plt.imshow(data) # Display data\n", + "plt.colorbar()" ] }, { @@ -506,7 +512,8 @@ ], "source": [ "data = h5file[\"/compressed_data_bitshuffle_lz4\"][()] # Access datset\n", - "plt.imshow(data); plt.colorbar() # Display data" + "plt.imshow(data) # Display data\n", + "plt.colorbar()" ] }, { @@ -567,7 +574,7 @@ " \"/compressed_data_bitshuffle_lz4\",\n", " data=data,\n", " compression=32008, # bitshuffle/lz4 HDF5 filter identifier\n", - " compression_opts=(0, 2) # options: default number of elements/block, enable LZ4\n", + " compression_opts=(0, 2), # options: default number of elements/block, enable LZ4\n", ")\n", "h5file.close()" ] @@ -597,7 +604,7 @@ "h5file.create_dataset(\n", " \"/compressed_data_bitshuffle_lz4\",\n", " data=data,\n", - " **hdf5plugin.Bitshuffle() # Or: **hdf5plugin.BitShuffle(lz4=True)\n", + " **hdf5plugin.Bitshuffle(), # Or: **hdf5plugin.BitShuffle(lz4=True)\n", ")\n", "h5file.close()" ] @@ -847,7 +854,8 @@ ], "source": [ "h5file = h5py.File(\"new_file_bitshuffle_lz4.h5\", mode=\"r\")\n", - "plt.imshow(h5file[\"/compressed_data_bitshuffle_lz4\"][()]); plt.colorbar()\n", + "plt.imshow(h5file[\"/compressed_data_bitshuffle_lz4\"][()])\n", + "plt.colorbar()\n", "h5file.close()" ] }, @@ -914,7 +922,8 @@ "source": [ "h5file = h5py.File(\"new_file_shuffle_gzip.h5\", mode=\"w\")\n", "h5file.create_dataset(\n", - " \"/compressed_data_shuffle_gzip\", data=data, shuffle=True, compression=\"gzip\")\n", + " \"/compressed_data_shuffle_gzip\", data=data, shuffle=True, compression=\"gzip\"\n", + ")\n", "h5file.close()" ] }, @@ -947,7 +956,7 @@ "h5file.create_dataset(\n", " \"/compressed_data_blosc\",\n", " data=data,\n", - " **hdf5plugin.Blosc(cname='zlib', clevel=5, shuffle=hdf5plugin.Blosc.SHUFFLE)\n", + " **hdf5plugin.Blosc(cname=\"zlib\", clevel=5, shuffle=hdf5plugin.Blosc.SHUFFLE),\n", ")\n", "h5file.close()" ] @@ -1098,7 +1107,7 @@ } ], "source": [ - "!h5dump -d /compressed_data_bitshuffle_lz4 -s \"0,0\" -c \"5,10\" data.h5 " + "!h5dump -d /compressed_data_bitshuffle_lz4 -s \"0,0\" -c \"5,10\" data.h5" ] }, { @@ -1137,7 +1146,7 @@ "outputs": [], "source": [ "# Retrieve hdf5plugin.PLUGINS_PATH from the command line\n", - "!python3 -c \"import hdf5plugin; print(hdf5plugin.PLUGINS_PATH)\" " + "!python3 -c \"import hdf5plugin; print(hdf5plugin.PLUGINS_PATH)\"" ] }, { diff --git a/doc/hdf5plugin_EuropeanHUG2022.ipynb b/doc/hdf5plugin_EuropeanHUG2022.ipynb index 4c0475bb..3f45185e 100644 --- a/doc/hdf5plugin_EuropeanHUG2022.ipynb +++ b/doc/hdf5plugin_EuropeanHUG2022.ipynb @@ -30,7 +30,7 @@ "source": [ "# Notebook requirements\n", "# A recent version of Pillow is required!\n", - "#%pip install numpy h5py hdf5plugin h5glance rise jupyterlab matplotlib ipympl Pillow" + "# %pip install numpy h5py hdf5plugin h5glance rise jupyterlab matplotlib ipympl Pillow" ] }, { @@ -47,12 +47,14 @@ "%matplotlib inline\n", "\n", "# Creates data.h5 used for demos\n", + "import urllib.request\n", + "\n", + "import numpy\n", "from matplotlib import pyplot as plt\n", + "from PIL import Image\n", + "\n", "import h5py\n", "import hdf5plugin\n", - "import numpy\n", - "from PIL import Image\n", - "import urllib.request\n", "\n", "url = \"https://www.iter.org/doc/www/content/com/Lists/WebText_2014/Attachments/236/platform_view_north_1.jpg\"\n", "filename = urllib.request.urlretrieve(url)[0]\n", @@ -66,7 +68,7 @@ "h5file.create_dataset(\n", " \"/compressed_data\",\n", " data=image,\n", - " **hdf5plugin.Blosc('lz4', shuffle=hdf5plugin.Blosc.BITSHUFFLE)\n", + " **hdf5plugin.Blosc(\"lz4\", shuffle=hdf5plugin.Blosc.BITSHUFFLE),\n", ")\n", "h5file.close()" ] @@ -93,6 +95,7 @@ "outputs": [], "source": [ "import os\n", + "\n", "os._exit(0) # Makes the kernel restart" ] }, @@ -110,6 +113,7 @@ "%matplotlib inline\n", "from matplotlib import pyplot as plt\n", "\n", + "\n", "def imshow(image):\n", " plt.imshow(image)\n", " plt.colorbar()" @@ -360,6 +364,7 @@ ], "source": [ "from h5glance import H5Glance # Browsing HDF5 files\n", + "\n", "H5Glance(\"data.h5\")" ] }, @@ -389,8 +394,8 @@ "import h5py # Pythonic HDF5 wrapper: https://docs.h5py.org/\n", "\n", "h5file = h5py.File(\"data.h5\", mode=\"r\") # Open HDF5 file in read mode\n", - "data = h5file[\"/data\"][()] # Access HDF5 dataset \"/data\"\n", - "imshow(data) # Display data" + "data = h5file[\"/data\"][()] # Access HDF5 dataset \"/data\"\n", + "imshow(data) # Display data" ] }, { @@ -536,7 +541,7 @@ ], "source": [ "data = h5file[\"/compressed_data\"][()] # Access datset\n", - "imshow(data) # Display data" + "imshow(data) # Display data" ] }, { @@ -598,7 +603,7 @@ " data=data,\n", " compression=32001, # blosc HDF5 filter identifier\n", " # options: 0, 0, 0, 0, level, shuffle, compression\n", - " compression_opts=(0, 0, 0, 0, 5, 2, 1) \n", + " compression_opts=(0, 0, 0, 0, 5, 2, 1),\n", ")\n", "h5file.close()" ] @@ -628,10 +633,7 @@ "h5file.create_dataset(\n", " \"/compressed_data\",\n", " data=data,\n", - " **hdf5plugin.Blosc(\n", - " cname='lz4',\n", - " clevel=5,\n", - " shuffle=hdf5plugin.Blosc.BITSHUFFLE),\n", + " **hdf5plugin.Blosc(cname=\"lz4\", clevel=5, shuffle=hdf5plugin.Blosc.BITSHUFFLE),\n", ")\n", "h5file.close()" ] @@ -1071,7 +1073,8 @@ "source": [ "h5file = h5py.File(\"new_file_shuffle_gzip.h5\", mode=\"w\")\n", "h5file.create_dataset(\n", - " \"/compressed_data_shuffle_gzip\", data=data, shuffle=True, compression=\"gzip\")\n", + " \"/compressed_data_shuffle_gzip\", data=data, shuffle=True, compression=\"gzip\"\n", + ")\n", "h5file.close()" ] }, @@ -1102,9 +1105,7 @@ "source": [ "h5file = h5py.File(\"new_file_bitshuffle_lz4.h5\", mode=\"w\")\n", "h5file.create_dataset(\n", - " \"/compressed_data_bitshuffle_lz4\",\n", - " data=data,\n", - " **hdf5plugin.Bitshuffle()\n", + " \"/compressed_data_bitshuffle_lz4\", data=data, **hdf5plugin.Bitshuffle()\n", ")\n", "h5file.close()" ] diff --git a/doc/hdf5plugin_EuropeanHUG2023/benchmark.ipynb b/doc/hdf5plugin_EuropeanHUG2023/benchmark.ipynb index a5c89922..351b7a27 100644 --- a/doc/hdf5plugin_EuropeanHUG2023/benchmark.ipynb +++ b/doc/hdf5plugin_EuropeanHUG2023/benchmark.ipynb @@ -116,16 +116,13 @@ "outputs": [], "source": [ "# Initialization\n", - "#%matplotlib inline\n", + "# %matplotlib inline\n", "%matplotlib widget\n", "\n", + "import numpy\n", "from matplotlib import pyplot as plt\n", - "from matplotlib.colors import LogNorm\n", "\n", - "import numpy\n", - "import h5py\n", - "import hdf5plugin\n", - "from h5glance import H5Glance" + "import hdf5plugin" ] }, { @@ -141,6 +138,7 @@ "\n", "from typing import NamedTuple\n", "\n", + "\n", "class Result(NamedTuple):\n", " \"\"\"Store benchmark result\"\"\"\n", "\n", @@ -150,35 +148,38 @@ " read_duration: float\n", " chunks: tuple[int]\n", "\n", - " compression_rate = property(\n", - " lambda self: self.raw_nbytes / self.compressed_nbytes)\n", + " compression_rate = property(lambda self: self.raw_nbytes / self.compressed_nbytes)\n", " write_speed = property(\n", " lambda self: (self.raw_nbytes / 1024**2) / self.write_duration,\n", - " doc=\"Unit: MB/sec\")\n", + " doc=\"Unit: MB/sec\",\n", + " )\n", " read_speed = property(\n", " lambda self: (self.raw_nbytes / 1024**2) / self.read_duration,\n", - " doc=\"Unit: MB/sec\")\n", + " doc=\"Unit: MB/sec\",\n", + " )\n", "\n", - " \n", - "def display_results(title: str='', key=None, **results):\n", + "\n", + "def display_results(title: str = \"\", key=None, **results):\n", " \"\"\"Plot comparison of compression results.\n", - " \n", + "\n", " :param title: Additional dataset name\n", " :param key: Key function to customize the sort\n", - " :param **results: {compression-name: Result} mapping \n", + " :param **results: {compression-name: Result} mapping\n", " \"\"\"\n", " # Sort results by compression rate\n", - " results = dict(sorted(\n", - " results.items(),\n", - " key=(lambda item: item[1].compression_rate) if key is None else key,\n", - " ))\n", - " \n", + " results = dict(\n", + " sorted(\n", + " results.items(),\n", + " key=(lambda item: item[1].compression_rate) if key is None else key,\n", + " )\n", + " )\n", + "\n", " names = list(results.keys())\n", " write_speed = numpy.array([r.write_speed for r in results.values()])\n", " read_speed = numpy.array([r.read_speed for r in results.values()])\n", " c_rate = numpy.array([r.compression_rate for r in results.values()])\n", - " \n", - " #print(f\"hdf5plugin_config: {results[names[0]].config}\")\n", + "\n", + " # print(f\"hdf5plugin_config: {results[names[0]].config}\")\n", "\n", " fig, axes = plt.subplots(1, 2)\n", " speed_plt, c_rate_plt = axes\n", @@ -188,23 +189,25 @@ " ticks = numpy.arange(len(names))\n", "\n", " # Speed\n", - " speed_plt.barh(y=ticks, width=write_speed, height=0.4, align='edge', label=\"Write\")\n", - " speed_plt.barh(y=ticks-.4, width=read_speed, height=0.4, align='edge', label=\"Read\")\n", + " speed_plt.barh(y=ticks, width=write_speed, height=0.4, align=\"edge\", label=\"Write\")\n", + " speed_plt.barh(\n", + " y=ticks - 0.4, width=read_speed, height=0.4, align=\"edge\", label=\"Read\"\n", + " )\n", " speed_plt.set_xlabel(\"Speed [MB/s]\")\n", - " speed_plt.autoscale(axis='y')\n", + " speed_plt.autoscale(axis=\"y\")\n", " speed_plt.yaxis.set_ticks(ticks)\n", " speed_plt.yaxis.set_ticklabels(names, fontsize=8)\n", - " speed_plt.set_ylim(-0.5, len(ticks)-0.5)\n", + " speed_plt.set_ylim(-0.5, len(ticks) - 0.5)\n", " speed_plt.grid(axis=\"x\")\n", " speed_plt.legend()\n", - " \n", + "\n", " # Compression ratio\n", " c_rate_plt.barh(y=ticks, width=c_rate)\n", " c_rate_plt.set_xlabel(\"Compression rate\")\n", - " c_rate_plt.autoscale(axis='y')\n", + " c_rate_plt.autoscale(axis=\"y\")\n", " c_rate_plt.yaxis.set_ticks(ticks)\n", - " c_rate_plt.yaxis.set_ticklabels([''] * len(ticks))\n", - " c_rate_plt.set_ylim(-0.5,len(ticks)-0.5)\n", + " c_rate_plt.yaxis.set_ticklabels([\"\"] * len(ticks))\n", + " c_rate_plt.set_ylim(-0.5, len(ticks) - 0.5)\n", " c_rate_plt.axvline(1, color=\"red\")\n", " c_rate_plt.grid(axis=\"x\")\n", "\n", @@ -212,25 +215,30 @@ "\n", " # Tooltip\n", " tooltip = c_rate_plt.annotate(\n", - " \"\", (0, 0), backgroundcolor=\"lightyellow\",\n", - " verticalalignment=\"top\", xycoords='figure pixels')\n", + " \"\",\n", + " (0, 0),\n", + " backgroundcolor=\"lightyellow\",\n", + " verticalalignment=\"top\",\n", + " xycoords=\"figure pixels\",\n", + " )\n", " tooltip.set_visible(False)\n", "\n", " def hover(event):\n", " if event.inaxes in (speed_plt, c_rate_plt):\n", - " index = numpy.clip(round(event.ydata), 0, len(names)-1)\n", + " index = numpy.clip(round(event.ydata), 0, len(names) - 1)\n", " tooltip.set_text(\n", " f\"{names[index]}\\n\"\n", " f\"Comp. Rate: {c_rate[index]:.2f}x\\n\"\n", " f\"Write: {write_speed[index]:.1f}MB/s\\n\"\n", - " f\"Read: {read_speed[index]:.1f}MB/s\")\n", + " f\"Read: {read_speed[index]:.1f}MB/s\"\n", + " )\n", " tooltip.set_x(event.x + 15)\n", " tooltip.set_y(event.y)\n", " tooltip.set_visible(True)\n", " else:\n", " tooltip.set_visible(False)\n", " fig.canvas.draw_idle()\n", - " \n", + "\n", " def resize(event):\n", " fig.tight_layout()\n", "\n", @@ -279,17 +287,18 @@ } ], "source": [ - "import os\n", "import sys\n", "\n", - "print('Python:', sys.version)\n", + "print(\"Python:\", sys.version)\n", "\n", "config = hdf5plugin.get_config()\n", "print(f\"\"\"hdf5plugin:\n", "* Version: {hdf5plugin.version}\n", "* Build config:\n", - "{'''\n", - "'''.join(f' - {k}: {v}' for k, v in config.build_config._asdict().items())}\n", + "{\n", + " '''\n", + "'''.join(f\" - {k}: {v}\" for k, v in config.build_config._asdict().items())\n", + "}\n", "\"\"\")" ] }, @@ -352,10 +361,7 @@ } ], "source": [ - "display_results(\n", - " title=\"Filters comparison\",\n", - " **results\n", - ")" + "display_results(title=\"Filters comparison\", **results)" ] }, { diff --git a/doc/hdf5plugin_EuropeanHUG2023/benchmark.py b/doc/hdf5plugin_EuropeanHUG2023/benchmark.py index 6f53a9b7..8ae60424 100644 --- a/doc/hdf5plugin_EuropeanHUG2023/benchmark.py +++ b/doc/hdf5plugin_EuropeanHUG2023/benchmark.py @@ -9,9 +9,10 @@ import time from typing import NamedTuple, Optional -import h5py import numpy +import h5py + # Set affinity and env. var. before importing hdf5plugin if len(sys.argv) >= 2: diff --git a/doc/hdf5plugin_EuropeanHUG2023/hdf5_compressed_chunk_direct_read.ipynb b/doc/hdf5plugin_EuropeanHUG2023/hdf5_compressed_chunk_direct_read.ipynb index 07e30cb6..2520996b 100644 --- a/doc/hdf5plugin_EuropeanHUG2023/hdf5_compressed_chunk_direct_read.ipynb +++ b/doc/hdf5plugin_EuropeanHUG2023/hdf5_compressed_chunk_direct_read.ipynb @@ -40,27 +40,12 @@ "env:\n", " OPENMP_NUM_THREADS: 1\n", " BLOSC_NTHREADS: 1\n", - "\n", - "hdf5plugin:\n", - " Version: 4.2.0\n", - " Build config:\n", - " openmp: True\n", - " native: True\n", - " bmi2: True\n", - " sse2: True\n", - " avx2: True\n", - " avx512: False\n", - " cpp11: True\n", - " cpp14: True\n", - " ipp: False\n", - " filter_file_extension: .so\n", - " embedded_filters: ('blosc', 'blosc2', 'bshuf', 'bzip2', 'fcidecomp', 'lz4', 'sz', 'sz3', 'zfp', 'zstd')\n", "\n" ] } ], "source": [ - "#Set affinity and multithreading env. var. before any import\n", + "# Set affinity and multithreading env. var. before any import\n", "import os\n", "\n", "os.sched_setaffinity(0, [0])\n", @@ -75,8 +60,38 @@ "print(f\"\"\"env:\n", " OPENMP_NUM_THREADS: {os.environ.get(\"OPENMP_NUM_THREADS\", \"unset\")}\n", " BLOSC_NTHREADS: {os.environ.get(\"BLOSC_NTHREADS\", \"unset\")}\n", - "\"\"\")\n", - "\n", + "\"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "d56ca93e-9dea-4e14-bb99-c39907ab8274", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "hdf5plugin:\n", + " Version: 4.2.0\n", + " Build config:\n", + " openmp: True\n", + " native: True\n", + " bmi2: True\n", + " sse2: True\n", + " avx2: True\n", + " avx512: False\n", + " cpp11: True\n", + " cpp14: True\n", + " ipp: False\n", + " filter_file_extension: .so\n", + " embedded_filters: ('blosc', 'blosc2', 'bshuf', 'bzip2', 'fcidecomp', 'lz4', 'sz', 'sz3', 'zfp', 'zstd')\n", + "\n" + ] + } + ], + "source": [ "import h5py\n", "import hdf5plugin\n", "\n", @@ -85,8 +100,10 @@ "print(f\"\"\"hdf5plugin:\n", " Version: {hdf5plugin.version}\n", " Build config:\n", - "{'''\n", - "'''.join(f' {k}: {v}' for k, v in config.build_config._asdict().items())}\n", + "{\n", + " '''\n", + "'''.join(f\" {k}: {v}\" for k, v in config.build_config._asdict().items())\n", + "}\n", "\"\"\")" ] }, @@ -126,7 +143,6 @@ }, "outputs": [], "source": [ - "import h5py\n", "import hdf5plugin\n", "\n", "with h5py.File(\"/dev/shm/kevlar.h5\", \"r\") as h:\n", @@ -138,7 +154,7 @@ " data=data_ref,\n", " chunks=data_ref.shape,\n", " compression=hdf5plugin.Blosc2(\n", - " cname='lz4',\n", + " cname=\"lz4\",\n", " clevel=5,\n", " filters=hdf5plugin.Blosc2.BITSHUFFLE,\n", " ),\n", @@ -174,6 +190,7 @@ "import blosc2\n", "import numpy\n", "\n", + "\n", "def decompress_blosc2_chunk(chunk: bytes, array: numpy.ndarray):\n", " \"\"\"Decompress chunk data to provided array\"\"\"\n", " blosc2.schunk_from_cframe(chunk).get_slice(out=array)" @@ -299,13 +316,15 @@ "outputs": [], "source": [ "import struct\n", + "\n", "import bitshuffle\n", "import numpy\n", "\n", + "\n", "def decompress_bslz4_chunk(payload, dtype, chunk_shape):\n", - " \"\"\"This function decompresses ONE chunk with bitshuffle-LZ4. \n", + " \"\"\"This function decompresses ONE chunk with bitshuffle-LZ4.\n", " The library needs to be compiled without OpenMP when using threads !\n", - " \n", + "\n", " :param payload: string with the compressed data as read by h5py.\n", " :param dtype: data type of the stored content\n", " :param chunk_shape: shape of one chunk\n", @@ -426,7 +445,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.0" + "version": "3.14.4" } }, "nbformat": 4, diff --git a/doc/hdf5plugin_EuropeanHUG2023/presentation.ipynb b/doc/hdf5plugin_EuropeanHUG2023/presentation.ipynb index 2ea67c7e..4dec11d3 100644 --- a/doc/hdf5plugin_EuropeanHUG2023/presentation.ipynb +++ b/doc/hdf5plugin_EuropeanHUG2023/presentation.ipynb @@ -30,7 +30,7 @@ "source": [ "# Notebook requirements\n", "# A recent version of Pillow is required!\n", - "#%pip install numpy h5py hdf5plugin h5glance rise jupyterlab matplotlib ipympl Pillow" + "# %pip install numpy h5py hdf5plugin h5glance rise jupyterlab matplotlib ipympl Pillow" ] }, { @@ -47,12 +47,14 @@ "%matplotlib inline\n", "\n", "# Creates data.h5 used for demos\n", + "import urllib.request\n", + "\n", + "import numpy\n", "from matplotlib import pyplot as plt\n", + "from PIL import Image\n", + "\n", "import h5py\n", "import hdf5plugin\n", - "import numpy\n", - "from PIL import Image\n", - "import urllib.request\n", "\n", "url = \"https://www.desy.de/e409/e116959/e119238/media/7795/1963_Luftbild_DESY-Gelaende_1284_gf_01sw_a3.jpg\"\n", "filename = urllib.request.urlretrieve(url)[0]\n", @@ -67,7 +69,7 @@ " \"/compressed_data\",\n", " data=image,\n", " chunks=image.shape,\n", - " **hdf5plugin.Blosc2('lz4', filters=hdf5plugin.Blosc.BITSHUFFLE)\n", + " **hdf5plugin.Blosc2(\"lz4\", filters=hdf5plugin.Blosc.BITSHUFFLE),\n", ")\n", "h5file.close()" ] @@ -94,6 +96,7 @@ "outputs": [], "source": [ "import os\n", + "\n", "os._exit(0) # Makes the kernel restart" ] }, @@ -354,6 +357,7 @@ ], "source": [ "from h5glance import H5Glance # Browsing HDF5 files\n", + "\n", "H5Glance(\"data.h5\")" ] }, @@ -370,7 +374,7 @@ "import h5py # Pythonic HDF5 wrapper: https://docs.h5py.org/\n", "\n", "h5file = h5py.File(\"data.h5\", mode=\"r\") # Open HDF5 file in read mode\n", - "data = h5file[\"/data\"][()] # Access HDF5 dataset \"/data\"" + "data = h5file[\"/data\"][()] # Access HDF5 dataset \"/data\"" ] }, { @@ -570,7 +574,7 @@ ], "source": [ "data = h5file[\"/compressed_data\"][()] # Access datset\n", - "plt.imshow(data, cmap=\"gray\") # Display data" + "plt.imshow(data, cmap=\"gray\") # Display data" ] }, { @@ -632,7 +636,7 @@ " data=data,\n", " compression=32026, # Blosc2 HDF5 filter identifier\n", " # options: 0, 0, 0, 0, level, filter, compression\n", - " compression_opts=(0, 0, 0, 0, 5, 2, 1) \n", + " compression_opts=(0, 0, 0, 0, 5, 2, 1),\n", ")\n", "h5file.close()" ] @@ -663,9 +667,8 @@ " \"/compressed_data\",\n", " data=data,\n", " compression=hdf5plugin.Blosc2(\n", - " cname='lz4',\n", - " clevel=5,\n", - " filters=hdf5plugin.Blosc2.BITSHUFFLE),\n", + " cname=\"lz4\", clevel=5, filters=hdf5plugin.Blosc2.BITSHUFFLE\n", + " ),\n", ")\n", "h5file.close()" ] @@ -982,7 +985,8 @@ "source": [ "h5file = h5py.File(\"new_file_shuffle_gzip.h5\", mode=\"w\")\n", "h5file.create_dataset(\n", - " \"/compressed_data_shuffle_gzip\", data=data, shuffle=True, compression=\"gzip\")\n", + " \"/compressed_data_shuffle_gzip\", data=data, shuffle=True, compression=\"gzip\"\n", + ")\n", "h5file.close()" ] }, @@ -1015,9 +1019,7 @@ "source": [ "h5file = h5py.File(\"new_file_bitshuffle_lz4.h5\", mode=\"w\")\n", "h5file.create_dataset(\n", - " \"/compressed_data_bitshuffle_lz4\",\n", - " data=data,\n", - " compression=hdf5plugin.Bitshuffle()\n", + " \"/compressed_data_bitshuffle_lz4\", data=data, compression=hdf5plugin.Bitshuffle()\n", ")\n", "h5file.close()" ] From 910cbfd6848561d2716fce2ea86a77e62f6134dc Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Thu, 25 Jun 2026 11:40:58 +0200 Subject: [PATCH 4/6] use ruff in CI --- .github/workflows/ci.yml | 8 +++----- .github/workflows/release.yml | 6 ++++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8cdb3dbe..4db16665 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,11 +17,9 @@ jobs: with: python-version: '3.12' cache: 'pip' - - run: python -m pip install --upgrade pip bandit black build flake8 isort mypy numpy twine - - run: bandit -c pyproject.toml -r . - - run: black --check . - - run: flake8 - - run: isort --check . + - run: python -m pip install --upgrade build mypy numpy pip ruff twine + - run: ruff format --check + - run: ruff check - run: mypy - run: python -m build --sdist - run: python -m twine check dist/* diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 10753086..5ca23dc3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,8 +16,10 @@ jobs: with: python-version: '3.12' cache: 'pip' - - run: python -m pip install --upgrade pip bandit build twine - - run: bandit -c pyproject.toml -r . + - run: python -m pip install --upgrade build mypy numpy pip ruff twine + - run: ruff format --check + - run: ruff check + - run: mypy - run: python -m build --sdist - run: python -m twine check dist/* - run: pip install --pre "$(ls dist/hdf5plugin*.tar.gz)[test]" From 722de4613dd098eab296fe5afdef5d6b39aa04d6 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Thu, 25 Jun 2026 11:41:12 +0200 Subject: [PATCH 5/6] update documentation to use ruff --- doc/contribute.rst | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/doc/contribute.rst b/doc/contribute.rst index fbc5ebb0..6fdc822d 100644 --- a/doc/contribute.rst +++ b/doc/contribute.rst @@ -29,23 +29,15 @@ Formatting/Linting From the source directory: -* Format code with `black `_:: +* To format the code, use `ruff format `_:: - black . + ruff format -* Sort imports with `isort `_:: +* To check (lint) the code, use `ruff check `_:: - isort . + ruff check -* Check code with `flake8 `_:: - - flake8 - -* Check code with `bandit `_ security linter:: - - bandit -c pyproject.toml -r . - -* Check typing with `mypy `_:: +* To check typing, use `mypy `_:: mypy From 48744c82bd95ef427174f7937208d54c7a99d5ed Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Thu, 25 Jun 2026 11:51:03 +0200 Subject: [PATCH 6/6] update dev dependencies --- pyproject.toml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5f8e12ff..79084fd9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,10 +49,8 @@ test = [ ] dev = [ "hdf5plugin[doc,test]", - "bandit", - "black", - "flake8", - "isort", + "mypy", + "ruff", ] [tool.setuptools]