From b2965cdbdf9cb93efe94c8841a8a61775045a7e4 Mon Sep 17 00:00:00 2001 From: Valerio Viperino <10340139+vvzen@users.noreply.github.com> Date: Mon, 11 May 2026 17:11:32 +0100 Subject: [PATCH 1/5] refactor: Modernize for pyproject.toml There were a lot of hacks in here to make life easier to folks in VFX. Hopefully, since it's now 2026, people there have started using the pyproject.toml. If not, I'm genuinely sorry. --- dev-requirements.txt | 4 --- pyproject.toml | 21 ++++++++++++++ src/{ => parse_exr_header}/__init__.py | 0 .../cli.py} | 10 ++----- .../lib.py} | 0 tests/openexr-images | 2 +- tests/test_exr.py | 29 +++++-------------- 7 files changed, 33 insertions(+), 33 deletions(-) delete mode 100644 dev-requirements.txt create mode 100644 pyproject.toml rename src/{ => parse_exr_header}/__init__.py (100%) rename src/{bin/vv-exr-metadata.py => parse_exr_header/cli.py} (78%) rename src/{parse_metadata.py => parse_exr_header/lib.py} (100%) diff --git a/dev-requirements.txt b/dev-requirements.txt deleted file mode 100644 index 5e0b0c4..0000000 --- a/dev-requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -pytest==9.0.3 -# attrs is required by pytest, see https://stackoverflow.com/a/58189684 -attrs==19.1.0 -yapf==0.30.0 \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a36d4f8 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,21 @@ +[project] +name = "parse-exr-header" +version = "0.1.0" +description = "Pure python module to read metadata files from the header of OpenEXR files." +readme = "README.md" +requires-python = ">=3.10" +dependencies = [] + +[project.scripts] +vv-exr-metadata = "parse_exr_header.cli:main" + +[build-system] +requires = ["setuptools >= 77.0.3"] +build-backend = "setuptools.build_meta" + +[project.optional-dependencies] +test = [ + "attrs>=26.1.0", + "pytest==9.0.3", + "yapf>=0.43.0", +] diff --git a/src/__init__.py b/src/parse_exr_header/__init__.py similarity index 100% rename from src/__init__.py rename to src/parse_exr_header/__init__.py diff --git a/src/bin/vv-exr-metadata.py b/src/parse_exr_header/cli.py similarity index 78% rename from src/bin/vv-exr-metadata.py rename to src/parse_exr_header/cli.py index 5bff744..8d12e25 100755 --- a/src/bin/vv-exr-metadata.py +++ b/src/parse_exr_header/cli.py @@ -1,21 +1,17 @@ -#!/usr/bin/env python from __future__ import print_function import os -import sys import pprint import logging import argparse +import parse_exr_header.lib + log = logging.getLogger('vvzen.parse_metadata') log.setLevel(logging.INFO) console_handler = logging.StreamHandler() log.addHandler(console_handler) -CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) - -sys.path.append(os.path.join(CURRENT_DIR, "..")) -import parse_metadata def main(): parser = argparse.ArgumentParser() @@ -33,7 +29,7 @@ def main(): log.error("Source Path was not found on disk: %s", path) continue - metadata = parse_metadata.read_exr_header(path) + metadata = parse_exr_header.lib.read_exr_header(path) print(pprint.pformat(metadata)) if len(paths) > 1: print("-"*80) diff --git a/src/parse_metadata.py b/src/parse_exr_header/lib.py similarity index 100% rename from src/parse_metadata.py rename to src/parse_exr_header/lib.py diff --git a/tests/openexr-images b/tests/openexr-images index 6e32d0f..e38ffb0 160000 --- a/tests/openexr-images +++ b/tests/openexr-images @@ -1 +1 @@ -Subproject commit 6e32d0f2f56189bc20a6b3958c322c4ff6340633 +Subproject commit e38ffb0790f62f05a6f083a6fa4cac150b3b7452 diff --git a/tests/test_exr.py b/tests/test_exr.py index 681c326..016cd67 100644 --- a/tests/test_exr.py +++ b/tests/test_exr.py @@ -1,26 +1,13 @@ #-*- coding: utf-8 -*- import os -import sys import pytest """ -The tests are ment to work with Python 2 and Python 3. -Please remember that Python 2 works with byte strings as default -and with the change of Python 3 unicode strings are used. - -Python 2 default string -foo = b'bar' - -Python 3 default string: -foo = u'bar' +The tests are ment to work with Python 3.10+. """ -# Append the required module -sys.path.append( - os.path.join(os.path.abspath(os.path.dirname(__file__)), '..', 'src')) - -import parse_metadata +import parse_exr_header.lib EXR_IMAGES_DIR_PATH = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'openexr-images') @@ -31,13 +18,13 @@ def test_oserror_thrown_if_file_does_not_exist(): with pytest.raises(OSError): - parse_metadata.read_exr_header('pippo.exr') + parse_exr_header.lib.read_exr_header('pippo.exr') @pytest.mark.parametrize("input_path,expected_lineorder", [ pytest.param(REC709_TEST_IMAGE_PATH, 'INCREASING_Y') ]) def test_exr_meta_lineOrder(input_path, expected_lineorder): - metadata = parse_metadata.read_exr_header(input_path) + metadata = parse_exr_header.lib.read_exr_header(input_path) assert metadata['lineOrder'] == expected_lineorder @pytest.mark.parametrize("input_path,expected_compression", [ @@ -49,15 +36,15 @@ def test_exr_meta_lineOrder(input_path, expected_lineorder): pytest.param(os.path.join(EXR_IMAGES_DIR_PATH, 'TestImages', 'SquaresSwirls.exr'), 'PXR24_COMPRESSION'), ]) def test_exr_meta_compression(input_path,expected_compression): - metadata = parse_metadata.read_exr_header(input_path) + metadata = parse_exr_header.lib.read_exr_header(input_path) assert metadata['compression'] == expected_compression def test_exr_meta_pixelAspectRatio(): - metadata = parse_metadata.read_exr_header(REC709_TEST_IMAGE_PATH) + metadata = parse_exr_header.lib.read_exr_header(REC709_TEST_IMAGE_PATH) assert metadata['pixelAspectRatio'] == 1 def test_exr_meta_owner(): - metadata = parse_metadata.read_exr_header(REC709_TEST_IMAGE_PATH) + metadata = parse_exr_header.lib.read_exr_header(REC709_TEST_IMAGE_PATH) assert metadata['owner'] == 'Copyright 2006 Industrial Light & Magic' @pytest.mark.parametrize("input_path,expected_metadata", [ @@ -107,5 +94,5 @@ def test_exr_meta_owner(): }) ]) def test_exr_meta_all(input_path, expected_metadata): - result = parse_metadata.read_exr_header(input_path) + result = parse_exr_header.lib.read_exr_header(input_path) assert result == expected_metadata From 518b226df8c98b6b8b32298df1f29612401f17f1 Mon Sep 17 00:00:00 2001 From: Valerio Viperino <10340139+vvzen@users.noreply.github.com> Date: Mon, 11 May 2026 17:12:54 +0100 Subject: [PATCH 2/5] ci: React to pyproject.toml port Plus try to use a matrix strategy to avoid duplicating too much code. --- .github/workflows/run-tests-on-mr.yml | 43 ++++++++++++--------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/.github/workflows/run-tests-on-mr.yml b/.github/workflows/run-tests-on-mr.yml index ecbe09b..0a2e6a2 100644 --- a/.github/workflows/run-tests-on-mr.yml +++ b/.github/workflows/run-tests-on-mr.yml @@ -2,35 +2,30 @@ name: Run tests on Pull Request on: [pull_request] jobs: - run-tests-on-py310: + check: runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Check out repo code - uses: actions/checkout@v2 - with: - submodules: true - - name: Install Python - uses: actions/setup-python@v2 - with: - python-version: "3.10" - - name: Install dependencies - run: python -m pip install -r dev-requirements.txt - - name: Run Tests - run: pytest tests - run-tests-on-py314: - runs-on: ubuntu-latest - timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.14"] + steps: - name: Check out repo code - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: true - - name: Install Python - uses: actions/setup-python@v2 + + - name: Install Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 with: - python-version: "3.14" - - name: Install dependencies - run: python -m pip install -r dev-requirements.txt + python-version: ${{matrix.python-version}} + + - name: Install project + run: python3 -m pip install . + + - name: Install dev dependencies + run: python3 -m pip install -e '.[test]' + - name: Run Tests run: pytest tests From 657bab4cd5b03fcbb95587fdc3ba13e309fc7cd3 Mon Sep 17 00:00:00 2001 From: Valerio Viperino <10340139+vvzen@users.noreply.github.com> Date: Mon, 11 May 2026 17:20:38 +0100 Subject: [PATCH 3/5] docs: Update dev dependencies --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c011dfc..e7f1b2f 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,10 @@ That's why I've written this very small python module (currently ~360 LOCs) that # Dependencies Optional, for tests: -`pytest==4.2.0` +`pytest==9.0.3` Optional, for formatting: -`yapf==0.30.0` +`yapf==0.43.0` # Support From 5fbb83e30b8efe9cf045a79468708d4bcbc8e253 Mon Sep 17 00:00:00 2001 From: Valerio Viperino <10340139+vvzen@users.noreply.github.com> Date: Mon, 11 May 2026 17:25:56 +0100 Subject: [PATCH 4/5] docs: Update to match current state --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e7f1b2f..9bef0dd 100644 --- a/README.md +++ b/README.md @@ -23,16 +23,19 @@ Optional, for formatting: # Support ## Python version -This repo now supports both Python2.7 and also Python3.8. -Thanks to [jonaskluger](https://github.com/jonaskluger) for providing python3 support. +This project is compatible with Python3.7+, although officially it requires 3.10 (because it's 2026 and 3.7 should really be a thing of the past given its EOL date). The CI runs tests against Python 3.10 and 3.14. +Thanks to [jonaskluger](https://github.com/jonaskluger) for providing original support for Python 3. ## Multipart files Support for multipart files is on its way but it will need a bit of work since the original design of this hobby project was a bit naive. A PR is currently pending. # Install -This script is not packaged in any fancy way. Just grab the `parse_metadata.py` and put it wherever you want. +This project uses the `pyproject.toml` (with setuptools as its build backend). +Once you cloned the repo, you can install it via pip into the venv of your choice: `python3 -m pip install /path/where/you/cloned/this`. -_Update (2021/12/27)_: Now there is also a tiny cli (`bin/vv-exr-metadata`) that you can use, if you want, to list the metadata of a file from a shell session. It supports the wildcard notation (*) if you want to look at multiple files at once. +But you can also just grab the `parse_metadata.py` and put it wherever you want, since it's a single file library. + +_Update (2021/12/27)_: Now there is also a small cli (`vv-exr-metadata`) that you can use, if you want, to list the metadata of a file from a shell session. It supports the wildcard notation (*) if you want to look at multiple files at once. # Tests I'm not a TDD guy (yet) - so there are very few tests. I'm planning to write more of them as soon as I can breathe a little. From 3dc56b7f1c92cd7940ba121d8d2ccea738aae8b9 Mon Sep 17 00:00:00 2001 From: Valerio Viperino <10340139+vvzen@users.noreply.github.com> Date: Mon, 11 May 2026 17:27:08 +0100 Subject: [PATCH 5/5] fix(docs): Typo --- tests/test_exr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_exr.py b/tests/test_exr.py index 016cd67..658b54b 100644 --- a/tests/test_exr.py +++ b/tests/test_exr.py @@ -4,7 +4,7 @@ import pytest """ -The tests are ment to work with Python 3.10+. +The tests are meant to work with Python 3.10+. """ import parse_exr_header.lib