Skip to content

Commit 226fc20

Browse files
Imran Kocabiyikclaude
andcommitted
feat: support Python 3.14 and drop Python 3.9
- Add Python 3.14 to classifiers and the CI test matrix. - Drop Python 3.9: requires-python is now >=3.10, the 3.9 classifier, the onnxruntime pin for <3.10, and the 3.9 CI matrix entries are removed. - Target py310 for ruff and black; modernize annotations (Optional/Union -> X | None, isinstance tuples -> X | Y) and add explicit zip strict=False. - Regenerate uv.lock. - Point repository URLs at withoutbg-python. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
1 parent b2d0cca commit 226fc20

12 files changed

Lines changed: 140 additions & 639 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ jobs:
1111
if: github.event_name == 'pull_request'
1212
runs-on: ubuntu-latest
1313
steps:
14-
- uses: actions/checkout@v4
14+
- uses: actions/checkout@v7
1515
with:
1616
fetch-depth: 0
1717

1818
- name: Set up Python
19-
uses: actions/setup-python@v4
19+
uses: actions/setup-python@v7
2020
with:
2121
python-version: '3.11'
2222

@@ -31,19 +31,13 @@ jobs:
3131
strategy:
3232
matrix:
3333
os: [ubuntu-latest, windows-latest, macos-latest]
34-
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
35-
exclude:
36-
# Reduce matrix for faster CI
37-
- os: windows-latest
38-
python-version: '3.9'
39-
- os: macos-latest
40-
python-version: '3.9'
34+
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
4135

4236
steps:
43-
- uses: actions/checkout@v4
37+
- uses: actions/checkout@v7
4438

4539
- name: Set up Python ${{ matrix.python-version }}
46-
uses: actions/setup-python@v4
40+
uses: actions/setup-python@v7
4741
with:
4842
python-version: ${{ matrix.python-version }}
4943

@@ -66,19 +60,19 @@ jobs:
6660

6761
- name: Upload coverage to Codecov
6862
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
69-
uses: codecov/codecov-action@v3
63+
uses: codecov/codecov-action@v7
7064
with:
71-
file: ./coverage.xml
65+
files: ./coverage.xml
7266
token: ${{ secrets.CODECOV_TOKEN }}
7367
fail_ci_if_error: true
7468

7569
security:
7670
runs-on: ubuntu-latest
7771
steps:
78-
- uses: actions/checkout@v4
72+
- uses: actions/checkout@v7
7973

8074
- name: Set up Python
81-
uses: actions/setup-python@v4
75+
uses: actions/setup-python@v7
8276
with:
8377
python-version: '3.11'
8478

@@ -96,7 +90,7 @@ jobs:
9690
run: bandit -r src/ -f json -o bandit-report.json || true
9791

9892
- name: Upload security results
99-
uses: actions/upload-artifact@v4
93+
uses: actions/upload-artifact@v7
10094
with:
10195
name: bandit-results
10296
path: bandit-report.json

‎.github/workflows/release.yml‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ jobs:
1919
name: Quality gate
2020
runs-on: ubuntu-latest
2121
steps:
22-
- uses: actions/checkout@v4
22+
- uses: actions/checkout@v7
2323

2424
- name: Set up Python
25-
uses: actions/setup-python@v4
25+
uses: actions/setup-python@v7
2626
with:
2727
python-version: '3.11'
2828

@@ -49,13 +49,13 @@ jobs:
4949
new_release_version: ${{ steps.semantic.outputs.new_release_version }}
5050
steps:
5151
- name: Checkout code
52-
uses: actions/checkout@v4
52+
uses: actions/checkout@v7
5353
with:
5454
fetch-depth: 0
5555
persist-credentials: false
5656

5757
- name: Setup Node.js
58-
uses: actions/setup-node@v4
58+
uses: actions/setup-node@v7
5959
with:
6060
node-version: '20'
6161
cache: npm
@@ -65,7 +65,7 @@ jobs:
6565

6666
- name: Run semantic-release
6767
id: semantic
68-
uses: cycjimmy/semantic-release-action@v4
68+
uses: cycjimmy/semantic-release-action@v8
6969
env:
7070
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7171

@@ -82,12 +82,12 @@ jobs:
8282
url: https://pypi.org/project/withoutbg/
8383
steps:
8484
- name: Checkout release tag
85-
uses: actions/checkout@v4
85+
uses: actions/checkout@v7
8686
with:
8787
ref: v${{ needs.release.outputs.new_release_version }}
8888

8989
- name: Set up Python
90-
uses: actions/setup-python@v4
90+
uses: actions/setup-python@v7
9191
with:
9292
python-version: '3.11'
9393

‎CONTRIBUTING.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ Contributions are welcome. This document covers everything you need to get from
55
## Quick setup
66

77
```bash
8-
git clone https://github.com/withoutbg/withoutbg
9-
cd withoutbg
8+
git clone https://github.com/withoutbg/withoutbg-python
9+
cd withoutbg-python
1010

1111
# Recommended: install with uv
1212
uv sync --extra dev
@@ -125,7 +125,7 @@ Use the [pull request template](.github/PULL_REQUEST_TEMPLATE.md). Keep PRs focu
125125

126126
## Reporting bugs
127127

128-
Open an [issue](https://github.com/withoutbg/withoutbg/issues) using the bug report template. Include:
128+
Open an [issue](https://github.com/withoutbg/withoutbg-python/issues) using the bug report template. Include:
129129

130130
- Python version and OS
131131
- Whether you are using **Local** (`open_weights()`) or **Cloud** (`api()`)

‎README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
[![PyPI](https://img.shields.io/pypi/v/withoutbg.svg)](https://pypi.org/project/withoutbg/)
88
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
9-
[![CI](https://github.com/withoutbg/withoutbg/actions/workflows/ci.yml/badge.svg)](https://github.com/withoutbg/withoutbg/actions/workflows/ci.yml)
9+
[![CI](https://github.com/withoutbg/withoutbg-python/actions/workflows/ci.yml/badge.svg)](https://github.com/withoutbg/withoutbg-python/actions/workflows/ci.yml)
1010

1111
Same API for both paths: run open weights on your machine (private, offline, unlimited) or call the Cloud API (sharper edges on hair and fur, no local GPU). Built for scripts, notebooks, backends, and batch jobs.
1212

@@ -249,6 +249,6 @@ See [THIRD_PARTY_LICENSES.md](THIRD_PARTY_LICENSES.md) for complete attribution.
249249

250250
## Support
251251

252-
- **Bugs / questions:** [GitHub Issues](https://github.com/withoutbg/withoutbg/issues)
252+
- **Bugs / questions:** [GitHub Issues](https://github.com/withoutbg/withoutbg-python/issues)
253253
- **Commercial:** [contact@withoutbg.com](mailto:contact@withoutbg.com)
254254
- **Security:** [contact@withoutbg.com](mailto:contact@withoutbg.com) (see [SECURITY.md](SECURITY.md))

‎pyproject.toml‎

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ name = "withoutbg"
77
dynamic = ["version"]
88
description = "Python SDK for local and cloud background removal"
99
readme = "README.md"
10-
requires-python = ">=3.9"
10+
requires-python = ">=3.10"
1111
license = {text = "Apache-2.0"}
1212
authors = [
1313
{name = "withoutbg", email = "contact@withoutbg.com"}
@@ -29,18 +29,17 @@ classifiers = [
2929
"Intended Audience :: Developers",
3030
"License :: OSI Approved :: Apache Software License",
3131
"Programming Language :: Python :: 3",
32-
"Programming Language :: Python :: 3.9",
3332
"Programming Language :: Python :: 3.10",
3433
"Programming Language :: Python :: 3.11",
3534
"Programming Language :: Python :: 3.12",
3635
"Programming Language :: Python :: 3.13",
36+
"Programming Language :: Python :: 3.14",
3737
"Topic :: Scientific/Engineering :: Artificial Intelligence",
3838
"Topic :: Multimedia :: Graphics :: Graphics Conversion",
3939
]
4040
dependencies = [
4141
"numpy>=1.21.0",
4242
"pillow>=8.0.0",
43-
"onnxruntime>=1.12.0,<1.20; python_version < '3.10'",
4443
"onnxruntime>=1.12.0,<1.24; python_version == '3.10.*'",
4544
"onnxruntime>=1.12.0; python_version >= '3.11'",
4645
"requests>=2.25.0",
@@ -65,10 +64,10 @@ dev = [
6564

6665
[project.urls]
6766
Homepage = "https://withoutbg.com"
68-
Repository = "https://github.com/withoutbg/withoutbg"
67+
Repository = "https://github.com/withoutbg/withoutbg-python"
6968
Documentation = "https://withoutbg.com/docs/open-model/python"
70-
"Bug Reports" = "https://github.com/withoutbg/withoutbg/issues"
71-
Changelog = "https://github.com/withoutbg/withoutbg/blob/main/CHANGELOG.md"
69+
"Bug Reports" = "https://github.com/withoutbg/withoutbg-python/issues"
70+
Changelog = "https://github.com/withoutbg/withoutbg-python/blob/main/CHANGELOG.md"
7271
"Docker / Self-Hosted" = "https://github.com/withoutbg/withoutbg-inference"
7372

7473
[project.scripts]
@@ -104,11 +103,11 @@ include = [
104103

105104
[tool.black]
106105
line-length = 88
107-
target-version = ['py39']
106+
target-version = ['py310']
108107

109108
[tool.ruff]
110109
line-length = 88
111-
target-version = "py39"
110+
target-version = "py310"
112111

113112
[tool.ruff.lint]
114113
select = [

‎src/withoutbg/api.py‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
import base64
44
import io
5+
from collections.abc import Callable
56
from pathlib import Path
6-
from typing import Any, Callable, Optional, Union
7+
from typing import Any
78

89
import requests
910
from PIL import Image
@@ -16,7 +17,7 @@ class WithoutBGAPIClient:
1617
"""Client for the withoutBG API."""
1718

1819
def __init__(
19-
self, api_key: Optional[str] = None, base_url: str = "https://api.withoutbg.com"
20+
self, api_key: str | None = None, base_url: str = "https://api.withoutbg.com"
2021
):
2122
"""Initialize the withoutBG API client.
2223
@@ -31,9 +32,9 @@ def __init__(
3132
if api_key:
3233
self.session.headers.update({"X-API-Key": api_key})
3334

34-
def _encode_image(self, image: Union[str, Path, Image.Image, bytes]) -> str:
35+
def _encode_image(self, image: str | Path | Image.Image | bytes) -> str:
3536
"""Encode image to base64 for API transmission."""
36-
if isinstance(image, (str, Path)):
37+
if isinstance(image, str | Path):
3738
with open(image, "rb") as f:
3839
image_bytes = f.read()
3940
elif isinstance(image, Image.Image):
@@ -117,8 +118,8 @@ def _apply_alpha_channel(
117118

118119
def remove_background(
119120
self,
120-
input_image: Union[str, Path, Image.Image, bytes],
121-
progress_callback: Optional[Callable] = None,
121+
input_image: str | Path | Image.Image | bytes,
122+
progress_callback: Callable | None = None,
122123
**kwargs: Any,
123124
) -> Image.Image:
124125
"""Remove background using the withoutBG API.
@@ -142,7 +143,7 @@ def remove_background(
142143
progress_callback(0.1)
143144

144145
# Store original image for local alpha application
145-
if isinstance(input_image, (str, Path)):
146+
if isinstance(input_image, str | Path):
146147
with Image.open(input_image) as img:
147148
original_image = img.copy()
148149
elif isinstance(input_image, Image.Image):

‎src/withoutbg/cli.py‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import sys
44
import warnings
55
from pathlib import Path
6-
from typing import Any, Optional
6+
from typing import Any
77

88
import click
99
from click._termui_impl import ProgressBar
@@ -59,12 +59,12 @@
5959
@click.version_option(version=__version__)
6060
def main(
6161
input_path: Path,
62-
output: Optional[Path],
63-
api_key: Optional[str],
62+
output: Path | None,
63+
api_key: str | None,
6464
use_api: bool,
6565
model: str,
6666
batch: bool,
67-
output_dir: Optional[Path],
67+
output_dir: Path | None,
6868
format: str,
6969
quality: int,
7070
verbose: bool,
@@ -158,7 +158,7 @@ def main(
158158
def _process_single(
159159
model: WithoutBG,
160160
input_path: Path,
161-
output_path: Optional[Path],
161+
output_path: Path | None,
162162
format: str,
163163
quality: int,
164164
verbose: bool,
@@ -223,7 +223,7 @@ def progress_callback(progress: float) -> None:
223223
def _process_batch(
224224
model: WithoutBG,
225225
input_dir: Path,
226-
output_dir: Optional[Path],
226+
output_dir: Path | None,
227227
format: str,
228228
quality: int,
229229
verbose: bool,

0 commit comments

Comments
 (0)