From 2f4ec21132ffb7142bfb8706e19abb4995b988de Mon Sep 17 00:00:00 2001 From: franziska-denk Date: Wed, 21 Jan 2026 14:31:26 +0100 Subject: [PATCH 1/6] add pre-commit checks with gitleaks --- .github/workflows/pre-commit.yaml | 23 ++++++++++++++++++ .../{python-app.yml => python-app.yaml} | 0 .gitignore | 4 ++-- .pre-commit-config.yaml | 24 +++++++++++++++++++ ruff.toml | 2 +- src/seaclips/collate.py | 6 ++--- src/seaclips/visualization.py | 2 +- tests/conftest.py | 1 - tests/test_collate.py | 2 -- tests/test_config.py | 1 - tests/test_dataset.py | 1 - 11 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/pre-commit.yaml rename .github/workflows/{python-app.yml => python-app.yaml} (100%) create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml new file mode 100644 index 0000000..1ef9035 --- /dev/null +++ b/.github/workflows/pre-commit.yaml @@ -0,0 +1,23 @@ +# .github/workflows/pre-commit.yml +name: Pre-commit + +on: + pull_request: + branches: [develop] + push: + branches: [develop] + +jobs: + pre-commit: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - uses: pre-commit/action@v3.0.0 \ No newline at end of file diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yaml similarity index 100% rename from .github/workflows/python-app.yml rename to .github/workflows/python-app.yaml diff --git a/.gitignore b/.gitignore index b7faf40..09be0ef 100644 --- a/.gitignore +++ b/.gitignore @@ -182,9 +182,9 @@ cython_debug/ .abstra/ # Visual Studio Code -# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore +# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore -# and can be added to the global gitignore or merged into this file. However, if you prefer, +# and can be added to the global gitignore or merged into this file. However, if you prefer, # you could uncomment the following to ignore the entire vscode folder # .vscode/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..7a5e553 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,24 @@ +repos: + # housekeeping ๐Ÿงน + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + args: ['--maxkb=500'] + + # make code pretty ๐Ÿ’„ + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.0 + hooks: + - id: ruff + args: [ --fix ] + - id: ruff-format + + # scanning for leaked secrets ใŠ™๏ธ + - repo: https://github.com/gitleaks/gitleaks + rev: v8.18.2 + hooks: + - id: gitleaks \ No newline at end of file diff --git a/ruff.toml b/ruff.toml index 20ceda6..cfdc5ef 100644 --- a/ruff.toml +++ b/ruff.toml @@ -45,7 +45,7 @@ select = [ # https://docs.astral.sh/ruff/rules/ "W", # PyCodeStyle Warnings "ANN", # flake8-annotations "B", # flake8-bugbear - "TC", # flake8-type-checking + "TCH", # flake8-type-checking "PTH", # flake8-use-pathlib "NPY", # NumPy specific rules "TID", # flake8-tidy-imports diff --git a/src/seaclips/collate.py b/src/seaclips/collate.py index 1cddb86..ebfa4fc 100644 --- a/src/seaclips/collate.py +++ b/src/seaclips/collate.py @@ -4,7 +4,7 @@ # Licensed under the Apache License 2.0. See LICENSE file. from dataclasses import dataclass -from typing import Any +from typing import Any, Union import numpy as np import torch @@ -161,7 +161,7 @@ def _collate_reference_frames( def _get_image_tensor( - image: Any, target_size: tuple[int, int] | None = None + image: Union[Image.Image, torch.Tensor], target_size: tuple[int, int] | None = None ) -> torch.Tensor: if isinstance(image, Image.Image): image_array = np.array(image) @@ -175,7 +175,7 @@ def _get_image_tensor( return image_tensor # --- 2. Pad to fixed size --- - C, H, W = image_tensor.shape + _, H, W = image_tensor.shape target_h, target_w = target_size if target_h < H or target_w < W: diff --git a/src/seaclips/visualization.py b/src/seaclips/visualization.py index cadb514..dcaa7f3 100644 --- a/src/seaclips/visualization.py +++ b/src/seaclips/visualization.py @@ -5,9 +5,9 @@ import random -import matplotlib.patches as patches import matplotlib.pyplot as plt import numpy as np +from matplotlib import patches from matplotlib.figure import Figure from PIL import Image diff --git a/tests/conftest.py b/tests/conftest.py index fac9d17..67e27fe 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,7 +5,6 @@ import pytest from PIL import Image - from seaclips.dataset import ReferenceFrame, SeaClipsSample diff --git a/tests/test_collate.py b/tests/test_collate.py index 4084564..a480579 100644 --- a/tests/test_collate.py +++ b/tests/test_collate.py @@ -1,8 +1,6 @@ """Tests for collate functions.""" -import pytest import torch - from seaclips.collate import seaclips_collate_fn diff --git a/tests/test_config.py b/tests/test_config.py index eef11c2..81226c5 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -4,7 +4,6 @@ from pathlib import Path import pytest - from seaclips.config import SeaClipsConfig diff --git a/tests/test_dataset.py b/tests/test_dataset.py index 74bd228..afcd29b 100644 --- a/tests/test_dataset.py +++ b/tests/test_dataset.py @@ -3,7 +3,6 @@ import pytest from PIL import Image - from seaclips.config import SeaClipsConfig from seaclips.dataset import SeaClipsDataset From 29525b37c71272ce3940961ad1dcdc9e7de920cb Mon Sep 17 00:00:00 2001 From: franziska-denk Date: Wed, 21 Jan 2026 15:21:44 +0100 Subject: [PATCH 2/6] change in branch name pattern for pre-commit action --- .github/workflows/pre-commit.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 1ef9035..c5aed88 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -3,9 +3,9 @@ name: Pre-commit on: pull_request: - branches: [develop] + branches: ['**'] push: - branches: [develop] + branches: ['**'] jobs: pre-commit: From 06950af62e1342b0819917815edd8f23cec030e6 Mon Sep 17 00:00:00 2001 From: franziska-denk Date: Wed, 21 Jan 2026 15:36:13 +0100 Subject: [PATCH 3/6] fixes --- .github/workflows/pre-commit.yaml | 4 ++-- .github/workflows/python-app.yaml | 6 +++--- .pre-commit-config.yaml | 2 +- src/seaclips/collate.py | 4 ++-- src/seaclips/dataset.py | 14 ++++++++------ src/seaclips/visualization.py | 8 ++++---- tests/conftest.py | 3 ++- 7 files changed, 22 insertions(+), 19 deletions(-) diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index c5aed88..cf561af 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -18,6 +18,6 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.12' - - uses: pre-commit/action@v3.0.0 \ No newline at end of file + - uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/python-app.yaml b/.github/workflows/python-app.yaml index b981924..3ed2129 100644 --- a/.github/workflows/python-app.yaml +++ b/.github/workflows/python-app.yaml @@ -21,12 +21,12 @@ jobs: steps: - name: Checkout Repository uses: actions/checkout@v4 - + - name: Install uv uses: astral-sh/setup-uv@v6 - + - name: Sync dependencies run: uv sync --all-extras - + - name: Run tests run: uv run pytest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7a5e553..a9924e0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,4 +21,4 @@ repos: - repo: https://github.com/gitleaks/gitleaks rev: v8.18.2 hooks: - - id: gitleaks \ No newline at end of file + - id: gitleaks diff --git a/src/seaclips/collate.py b/src/seaclips/collate.py index ebfa4fc..558f56a 100644 --- a/src/seaclips/collate.py +++ b/src/seaclips/collate.py @@ -39,7 +39,7 @@ class SeaClipsBatch: image_infos: List of image metadata dictionaries annotations: List of lists of annotation dictionaries video_infos: List of video metadata dictionaries - reference_frames: (optional) BatchedReferenceFrames instance for reference frames + reference_frames: (optional) BatchedReferenceFrames instance for ref frames """ images: torch.Tensor @@ -60,7 +60,7 @@ def seaclips_collate_fn(batch: list[SeaClipsSample]) -> SeaClipsBatch: batch: List of samples from SeaClipsDataset.__getitem__ Returns: - SeaClipsBatch: Batched data structure containing images, annotations, and metadata. + SeaClipsBatch: Batched data structure containing images, annotations & metadata. Example: >>> from torch.utils.data import DataLoader diff --git a/src/seaclips/dataset.py b/src/seaclips/dataset.py index b700e56..a8ce9da 100644 --- a/src/seaclips/dataset.py +++ b/src/seaclips/dataset.py @@ -91,14 +91,14 @@ def _load_metadata(self) -> None: self.videos_idx = {} return - with open(self.config.annotation_path, encoding="utf-8") as f: + with open(self.config.annotation_path, encoding="utf-8") as f: # noqa: PTH123 data = json.load(f) self.videos_data = data["videos"] self.videos_idx = {vid["id"]: vid for vid in self.videos_data} def _build_video_frame_index(self) -> None: - """Build index mapping video_id to sorted list of (frame_id, image_id, idx) tuples.""" + """Build index mapping video_id -> sorted list w (frame_id,image_id,idx).""" self.video_frames_idx = {} for idx, img_id in enumerate(self.image_ids): @@ -138,7 +138,8 @@ def __getitem__(self, idx: int) -> SeaClipsSample: - image_info: Image metadata (id, video_id, frame_id, etc.) - annotations: List of annotation dictionaries with parsed fields - video_info: Video metadata for this frame - - reference_frames: List of ReferenceFrame if load_reference_frames=True else None. + - reference_frames: List of ReferenceFrame if load_reference_frames=True + else None. """ if idx >= len(self): raise IndexError( @@ -198,7 +199,8 @@ def _get_reference_frames( if current_pos is None: raise ValueError( - f"Current index {current_idx} not found in video frames for video_id {video_id}" + f"Current index {current_idx} not found in video \ + frames for video_id {video_id}" ) for offset in self.config.ref_frame_range: @@ -207,7 +209,7 @@ def _get_reference_frames( # Check if reference frame exists if not (0 <= ref_pos < len(video_frames)): ref_pos = current_pos # Use current frame if out of bounds - offset = 0 + offset = 0 # noqa: PLW2901 _, ref_img_id, _ = video_frames[ref_pos] @@ -300,7 +302,7 @@ def filter_by_metadata( """Filter images by metadata attributes. Args: - weather: Filter by weather condition ("sunny", "overcast", "cloudy", "rainy") + weather: Filter by weather ("sunny", "overcast", "cloudy", "rainy") sea_state: Filter by sea state ("smooth", "wavy") camera_sensor: Filter by camera sensor type ("e-CAM", "Axis", "FLIR") water_reflections: Filter by water reflections presence ("yes", "no") diff --git a/src/seaclips/visualization.py b/src/seaclips/visualization.py index dcaa7f3..8cb023a 100644 --- a/src/seaclips/visualization.py +++ b/src/seaclips/visualization.py @@ -145,7 +145,7 @@ def show_sample( return fig - def show_sample_with_references( + def show_sample_with_references( # noqa: PLR0914 self, idx: int, show_labels: bool = True, @@ -218,7 +218,7 @@ def show_sample_with_references( spine.set_linewidth(3) spine.set_visible(True) - for idx in range(n_frames, len(axes)): + for idx in range(n_frames, len(axes)): # noqa: PLR1704 axes[idx].axis("off") video_info = self.dataset.videos_idx[sample.video_info["id"]] @@ -266,7 +266,7 @@ def show_video_sequence( axes = np.array([axes]) axes = axes.flatten() - for idx, (frame, ax) in enumerate(zip(frames_to_show, axes)): + for _, (frame, ax) in enumerate(zip(frames_to_show, axes)): image = frame.image annotations = frame.annotations img_info = frame.image_info @@ -330,7 +330,7 @@ def show_grid( return fig -def show_sample(dataset: SeaClipsDataset, idx: int, **kwargs) -> Figure: +def show_sample(dataset: SeaClipsDataset, idx: int, **kwargs) -> Figure: # noqa: ANN003 """Convenience function to visualize a sample. Args: diff --git a/tests/conftest.py b/tests/conftest.py index 67e27fe..6891f48 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,7 @@ import pytest from PIL import Image + from seaclips.dataset import ReferenceFrame, SeaClipsSample @@ -106,7 +107,7 @@ def dataset_root(tmp_path, sample_coco_data): img.save(split_dir / f"{i:06d}.png") annotation_file = tmp_path / f"seaclips-{split}.json" - with open(annotation_file, "w", encoding="utf-8") as f: + with open(annotation_file, "w", encoding="utf-8") as f: # noqa: PTH123 json.dump(sample_coco_data, f) return tmp_path From de48f6708258960d43547518afb76e38d15760f5 Mon Sep 17 00:00:00 2001 From: franziska-denk Date: Wed, 21 Jan 2026 15:38:59 +0100 Subject: [PATCH 4/6] fix --- tests/conftest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 6891f48..1ea23b7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,7 +5,6 @@ import pytest from PIL import Image - from seaclips.dataset import ReferenceFrame, SeaClipsSample From 4b6604cd42dd3f46920217a4b687eeb9e8fc5730 Mon Sep 17 00:00:00 2001 From: franziska-denk Date: Thu, 22 Jan 2026 08:06:49 +0100 Subject: [PATCH 5/6] add .vscode folder --- .vscode/extensions.json | 8 ++++++++ .vscode/settings.json | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..33639b7 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "ms-python.python", + "charliermarsh.ruff", + "ms-python.pylint" + ], + "unwantedRecommendations": [] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..09da394 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,20 @@ +{ + "[python]": { + "editor.defaultFormatter": "charliermarsh.ruff", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.fixAll.ruff": "explicit" + } + }, + "python.testing.pytestArgs": [ + "tests" + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "files.exclude": { + "**/.mypy_cache": true, + "**/.pytest_cache": true, + "**/.ruff_cache": true + } +} \ No newline at end of file From 3fd7b1df05d6e563cd1d52035e12e59d9261fd0e Mon Sep 17 00:00:00 2001 From: franziska-denk Date: Thu, 22 Jan 2026 08:08:23 +0100 Subject: [PATCH 6/6] make formatter happy --- .vscode/extensions.json | 2 +- .vscode/settings.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 33639b7..d4eca93 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -5,4 +5,4 @@ "ms-python.pylint" ], "unwantedRecommendations": [] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 09da394..fcdb532 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,4 +17,4 @@ "**/.pytest_cache": true, "**/.ruff_cache": true } -} \ No newline at end of file +}