codelor-color 2.2.0__tar.gz → 2.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,36 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## [2.2.2] - 2026-10-21
6
+
7
+ Patch release fixing the remaining mypy error from CI.
8
+
9
+ ### Fixed
10
+
11
+ - `SobelEdge` declares its `sx`/`sy` buffers with class annotations so mypy
12
+ types them as `Tensor` (previously `Tensor | Module`, which broke
13
+ `F.conv2d`). No behaviour change: buffers and `state_dict` keys are identical.
14
+
15
+ ## [2.2.1] - 2026-10-21
16
+
17
+ Patch release: the 2.2.0 files already on PyPI cannot be replaced (PyPI
18
+ releases are immutable), so the CI/lint fixes ship as 2.2.1. No behaviour
19
+ change; weights and API are identical to 2.2.0.
20
+
21
+ ### Changed
22
+
23
+ - Python 3.8/3.9 support dropped: `requires-python` is now `>=3.10`
24
+ (matching current PyTorch). The 2.2.0 metadata on PyPI still advertises
25
+ `>=3.8`.
26
+ - Annotations use modern syntax (`tuple[...]`, `X | Y`,
27
+ `collections.abc.Sequence`) required by current ruff (UP006/UP007/UP045).
28
+
29
+ ### Fixed
30
+
31
+ - Lint errors reported by the GitHub Actions CI on the 2.2.0 tag.
32
+ - `CodelorColor._get()` now casts `nn.ModuleList` lookups so mypy accepts
33
+ the weight-tying indirection.
34
+
5
35
  ## [2.2.0] - 2026-10-21
6
36
 
7
37
  Architecture weights are unchanged: checkpoints trained for 2.1.0 load as-is.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codelor-color
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: A lightweight PyTorch Transformer architecture for Chroma Key (Green Screen).
5
5
  Author-email: PlimbAi <plimb.ai.contact@gmail.com>
6
6
  License-Expression: MIT
@@ -9,7 +9,7 @@ Project-URL: Bug Tracker, https://github.com/Plimb-ai/codelor-color/issues
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
12
- Requires-Python: >=3.8
12
+ Requires-Python: >=3.10
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: torch>=2.0.0
@@ -0,0 +1 @@
1
+ __version__ = "2.2.2"
@@ -10,8 +10,9 @@ from __future__ import annotations
10
10
  import json
11
11
  import logging
12
12
  import warnings
13
+ from collections.abc import Sequence
13
14
  from pathlib import Path
14
- from typing import Any, Dict, Optional, Sequence, Tuple, Union
15
+ from typing import Any, cast
15
16
 
16
17
  import torch
17
18
  import torch.nn as nn
@@ -25,7 +26,7 @@ logger = logging.getLogger(__name__)
25
26
  # ============================================================
26
27
 
27
28
  #: Default reference color used when none is supplied (RGB in [0, 1]).
28
- DEFAULT_REF_RGB: Tuple[float, float, float] = (0.20, 0.85, 0.30)
29
+ DEFAULT_REF_RGB: tuple[float, float, float] = (0.20, 0.85, 0.30)
29
30
 
30
31
  #: Channel width of the stem feature maps at 1/4 (``f4``) resolution.
31
32
  STEM_W1: int = 32
@@ -42,7 +43,7 @@ POS_EMB_STD: float = 0.02
42
43
  EPS: float = 1e-6
43
44
 
44
45
  #: Hyper-parameters accepted by :meth:`CodelorColor.config` / ``config.json``.
45
- HYPERPARAM_KEYS: Tuple[str, ...] = (
46
+ HYPERPARAM_KEYS: tuple[str, ...] = (
46
47
  "dim",
47
48
  "depth",
48
49
  "heads",
@@ -108,7 +109,7 @@ class DropPath(nn.Module):
108
109
  return x * mask / keep
109
110
 
110
111
 
111
- def rope_2d(q: Tensor, k: Tensor, h: int, w: int, base: float = ROPE_BASE) -> Tuple[Tensor, Tensor]:
112
+ def rope_2d(q: Tensor, k: Tensor, h: int, w: int, base: float = ROPE_BASE) -> tuple[Tensor, Tensor]:
112
113
  """Apply 2D rotary position embeddings, splitting the head dim in half for x and y."""
113
114
  B, Hh, N, D = q.shape
114
115
  d4 = D // 4
@@ -243,7 +244,7 @@ class ConvNeXtStem(nn.Module):
243
244
  self.down8 = AntiAliasDownsample(STEM_W1, STEM_W2)
244
245
  self.down16 = AntiAliasDownsample(STEM_W2, dim)
245
246
 
246
- def forward(self, x: Tensor) -> Tuple[Tensor, Tensor, Tensor]:
247
+ def forward(self, x: Tensor) -> tuple[Tensor, Tensor, Tensor]:
247
248
  x = self.patch(x)
248
249
  x = x + self.block1(x)
249
250
  f4 = x
@@ -255,6 +256,9 @@ class ConvNeXtStem(nn.Module):
255
256
  class SobelEdge(nn.Module):
256
257
  """Fixed Sobel X/Y filters returning the gradient magnitude of a gray image."""
257
258
 
259
+ sx: Tensor
260
+ sy: Tensor
261
+
258
262
  def __init__(self) -> None:
259
263
  super().__init__()
260
264
  sx = torch.tensor([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]).float().view(1, 1, 3, 3)
@@ -304,7 +308,7 @@ class GatedDecoder(nn.Module):
304
308
 
305
309
  def forward(
306
310
  self, latent: Tensor, f4: Tensor, f8: Tensor, img: Tensor, ref_rgb: Tensor
307
- ) -> Tuple[Tensor, Tensor]:
311
+ ) -> tuple[Tensor, Tensor]:
308
312
  B, _, H, W = img.shape
309
313
  x = self.proj16(latent)
310
314
  aux = self.aux_head(x)
@@ -380,14 +384,13 @@ class CodelorColor(nn.Module):
380
384
  self.norm_out = RMSNorm(dim)
381
385
  self.decoder = GatedDecoder(dim)
382
386
 
383
- def _get(self, i: int) -> Tuple[Block, ColorCrossAttention]:
384
- if self.tied_after > 0 and i >= self.tied_after:
385
- return self.blocks[i - self.tied_after], self.color_xattn[i - self.tied_after]
386
- return self.blocks[i], self.color_xattn[i]
387
+ def _get(self, i: int) -> tuple[Block, ColorCrossAttention]:
388
+ idx = i - self.tied_after if self.tied_after > 0 and i >= self.tied_after else i
389
+ return cast(Block, self.blocks[idx]), cast(ColorCrossAttention, self.color_xattn[idx])
387
390
 
388
391
  def forward(
389
392
  self, img: Tensor, ref_rgb: Tensor, return_aux: bool = False
390
- ) -> Union[Tensor, Tuple[Tensor, Tensor]]:
393
+ ) -> Tensor | tuple[Tensor, Tensor]:
391
394
  """Predict foreground logits.
392
395
 
393
396
  Args:
@@ -435,7 +438,7 @@ class CodelorColor(nn.Module):
435
438
  main, aux = self.decoder(latent, f4, f8, img, ref_rgb)
436
439
  return (main, aux) if return_aux else main
437
440
 
438
- def config(self) -> Dict[str, Any]:
441
+ def config(self) -> dict[str, Any]:
439
442
  """Return the hyper-parameters needed to rebuild this model.
440
443
 
441
444
  The result is accepted both directly and nested under a
@@ -464,7 +467,7 @@ class CodelorColor(nn.Module):
464
467
  # ============================================================
465
468
 
466
469
  def load_from_pretrained(
467
- path_or_repo: Union[str, Path], device: Union[str, torch.device] = "cpu"
470
+ path_or_repo: str | Path, device: str | torch.device = "cpu"
468
471
  ) -> CodelorColor:
469
472
  """Build a :class:`CodelorColor` and load ``model.safetensors`` from it.
470
473
 
@@ -513,7 +516,7 @@ def load_from_pretrained(
513
516
  return model.eval().to(device)
514
517
 
515
518
 
516
- def _as_batch(image_tensor: Tensor, name: str = "image_tensor") -> Tuple[Tensor, bool]:
519
+ def _as_batch(image_tensor: Tensor, name: str = "image_tensor") -> tuple[Tensor, bool]:
517
520
  """Validate an image tensor and return it with a batch dimension plus a squeeze flag."""
518
521
  if not isinstance(image_tensor, Tensor):
519
522
  raise TypeError(f"{name} must be a torch.Tensor, got {type(image_tensor).__name__}")
@@ -547,10 +550,10 @@ def _sync_model_device(model: nn.Module, device: torch.device) -> None:
547
550
  def predict_mask(
548
551
  model: nn.Module,
549
552
  image_tensor: Tensor,
550
- color_rgb: Optional[Sequence[float]] = None,
553
+ color_rgb: Sequence[float] | None = None,
551
554
  threshold: float = 0.5,
552
- device: Union[str, torch.device] = "cpu",
553
- ) -> Tuple[Any, Any]:
555
+ device: str | torch.device = "cpu",
556
+ ) -> tuple[Any, Any]:
554
557
  """Compute a foreground mask for an image.
555
558
 
556
559
  Args:
@@ -592,9 +595,9 @@ def predict_mask(
592
595
  def remove_green(
593
596
  image_tensor: Tensor,
594
597
  model: nn.Module,
595
- color_rgb: Optional[Sequence[float]] = None,
598
+ color_rgb: Sequence[float] | None = None,
596
599
  threshold: float = 0.5,
597
- device: Union[str, torch.device] = "cpu",
600
+ device: str | torch.device = "cpu",
598
601
  ) -> Tensor:
599
602
  """Return an RGBA tensor where the alpha channel is ``1 - P(foreground)``.
600
603
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codelor-color
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: A lightweight PyTorch Transformer architecture for Chroma Key (Green Screen).
5
5
  Author-email: PlimbAi <plimb.ai.contact@gmail.com>
6
6
  License-Expression: MIT
@@ -9,7 +9,7 @@ Project-URL: Bug Tracker, https://github.com/Plimb-ai/codelor-color/issues
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
12
- Requires-Python: >=3.8
12
+ Requires-Python: >=3.10
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: torch>=2.0.0
@@ -7,7 +7,7 @@ name = "codelor-color"
7
7
  dynamic = ["version"]
8
8
  description = "A lightweight PyTorch Transformer architecture for Chroma Key (Green Screen)."
9
9
  readme = "README.md"
10
- requires-python = ">=3.8"
10
+ requires-python = ">=3.10"
11
11
  license = "MIT"
12
12
  authors = [
13
13
  {name = "PlimbAi", email = "plimb.ai.contact@gmail.com"}
@@ -50,7 +50,7 @@ addopts = "-q"
50
50
 
51
51
  [tool.ruff]
52
52
  line-length = 100
53
- target-version = "py38"
53
+ target-version = "py310"
54
54
  exclude = ["build", "dist"]
55
55
 
56
56
  [tool.ruff.lint]
@@ -58,6 +58,6 @@ select = ["E", "F", "W", "I", "UP", "B"]
58
58
  ignore = ["E501"]
59
59
 
60
60
  [tool.mypy]
61
- python_version = "3.8"
61
+ python_version = "3.10"
62
62
  ignore_missing_imports = true
63
63
  check_untyped_defs = true
@@ -6,7 +6,7 @@ import json
6
6
  import re
7
7
  import warnings
8
8
  from pathlib import Path
9
- from typing import Any, Dict
9
+ from typing import Any
10
10
 
11
11
  import numpy as np
12
12
  import pytest
@@ -26,7 +26,7 @@ ROOT = Path(__file__).resolve().parents[1]
26
26
 
27
27
 
28
28
  def small_model(**kwargs) -> CodelorColor:
29
- params: Dict[str, Any] = dict(
29
+ params: dict[str, Any] = dict(
30
30
  dim=32, depth=2, heads=4, tied_after=1, max_tokens=64, drop_path_rate=0.1
31
31
  )
32
32
  params.update(kwargs)
@@ -1 +0,0 @@
1
- __version__ = "2.2.0"
File without changes
File without changes
File without changes
File without changes