Skip to content

Commit 4239789

Browse files
committed
Migrate to uv and fix issue with case sensitive filenames
1 parent c0d73dd commit 4239789

File tree

6 files changed

+113
-119
lines changed

6 files changed

+113
-119
lines changed

.github/workflows/test-lint.yaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ jobs:
2020
- '3.10'
2121
- '3.11'
2222
- '3.12'
23+
- '3.13'
2324

2425
steps:
2526
- name: Checkout code
@@ -30,16 +31,16 @@ jobs:
3031
with:
3132
python-version: ${{ matrix.python-version }}
3233

33-
- name: Install Poetry
34+
- name: Install UV
3435
run: |
35-
curl -sSL https://install.python-poetry.org | python3 -
36+
curl -LsSf https://astral.sh/uv/install.sh | sh
3637
3738
- name: Install dependencies
38-
run: poetry install
39+
run: uv sync
3940

4041
- name: Run pytest
41-
run: poetry run pytest
42+
run: uv run pytest
4243

4344
- name: Run ruff
44-
run: poetry run ruff check --output-format=github
45+
run: uv run ruff check --output-format=github
4546
continue-on-error: true

pyproject.toml

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
[tool.poetry]
1+
[project]
22
name = "tstickers"
3-
version = "2024.1.3"
4-
license = "mit"
3+
version = "2025"
54
description = "Download sticker packs from Telegram"
6-
authors = ["FredHappyface"]
5+
authors = [{ name = "FredHappyface" }]
6+
requires-python = ">=3.9"
7+
readme = "README.md"
8+
license = "mit"
79
classifiers = [
810
"Development Status :: 5 - Production/Stable",
911
"Intended Audience :: Developers",
@@ -15,38 +17,34 @@ classifiers = [
1517
"Topic :: Utilities",
1618
"Topic :: Multimedia :: Graphics",
1719
]
18-
homepage = "https://github.com/FHPythonUtils/TStickers"
19-
repository = "https://github.com/FHPythonUtils/TStickers"
20-
documentation = "https://github.com/FHPythonUtils/TStickers/blob/master/README.md"
21-
readme = "README.md"
22-
23-
[tool.poetry.dependencies]
24-
python = ">=3.9,<4.0"
25-
requests = "<3,>=2.32.3"
26-
Pillow = "<11,>=10.4.0"
27-
emoji = "<3,>=2.12.1"
28-
requests-cache = "<2,>=1.2.1"
29-
rlottie-python = { version = "<2,>=1.3.6", optional = true }
30-
pyrlottie = "<2026,>=2024.0.1"
31-
loguru = "<2,>=0.7.2"
20+
dependencies = [
21+
"emoji>=2.14.1",
22+
"loguru>=0.7.3",
23+
"pillow>=10.4.0",
24+
"requests>=2.32.3",
25+
"requests-cache>=1.2.1",
26+
"rlottie-python>=1.3.6",
27+
]
3228

33-
[tool.poetry.scripts]
34-
tstickers = "tstickers:cli"
29+
[project.optional-dependencies]
30+
pyrlottie = ["pyrlottie<2026,>=2024.0.1"]
3531

36-
[tool.poetry.extras]
37-
rlottie-python = ["rlottie-python"]
38-
pyrlottie = ["pyrlottie"]
32+
[project.urls]
33+
Homepage = "https://github.com/FHPythonUtils/TStickers"
34+
Repository = "https://github.com/FHPythonUtils/TStickers"
35+
Documentation = "https://github.com/FHPythonUtils/TStickers/blob/master/README.md"
3936

40-
[tool.poetry.group.dev.dependencies]
41-
pytest = "^8.1.1"
42-
handsdown = "^2.1.0"
43-
coverage = "^7.4.4"
44-
ruff = "^0.3.3"
45-
pyright = "^1.1.354"
37+
[project.scripts]
38+
tstickers = "tstickers:cli"
4639

47-
[build-system]
48-
requires = ["poetry-core"]
49-
build-backend = "poetry.core.masonry.api"
40+
[dependency-groups]
41+
dev = [
42+
"coverage>=7.6.12",
43+
"handsdown>=2.1.0",
44+
"pyright>=1.1.394",
45+
"pytest>=8.3.4",
46+
"ruff>=0.9.6",
47+
]
5048

5149
[tool.ruff]
5250
line-length = 100
@@ -89,14 +87,18 @@ branch = true
8987
legacy_tox_ini = """
9088
[tox]
9189
env_list =
90+
py313
91+
py312
9292
py311
9393
py310
9494
py39
95-
py38
9695
9796
[testenv]
9897
deps =
99-
imgcompare
10098
pytest
10199
commands = pytest tests
102100
"""
101+
102+
[build-system]
103+
requires = ["hatchling"]
104+
build-backend = "hatchling.build"

tests/test_main.py

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
sys.path.insert(0, str(PROJECT_DIR))
1111

1212
from tstickers.convert import Backend
13-
from tstickers.downloader import StickerDownloader
13+
from tstickers.manager import StickerManager
1414

1515
token = ""
1616
for candidate in [PROJECT_DIR / "env.txt", PROJECT_DIR / "env"]:
@@ -24,36 +24,30 @@
2424
raise RuntimeError(msg)
2525

2626

27-
downloader = StickerDownloader(token)
28-
downloader.cwd = Path(THISDIR) / "data"
27+
stickerManager = StickerManager(token)
28+
stickerManager.cwd = Path(THISDIR) / "data"
2929

3030
packs = [{"pack": "DonutTheDog", "len": 31}]
3131

3232

3333
def test_getPack() -> None:
34-
stickerPack = downloader.getPack(packs[0]["pack"])
34+
stickerPack = stickerManager.getPack(packs[0]["pack"])
3535
assert stickerPack is not None
3636
assert len(stickerPack["files"]) == packs[0]["len"]
3737

3838

3939
def test_downloadPack() -> None:
40-
stickerPack = downloader.getPack(packs[0]["pack"])
41-
assert stickerPack is not None
42-
downloader.downloadPack(stickerPack)
43-
assert len(list(Path(f"{downloader.cwd}/donutthedog/tgs").iterdir())) == packs[0]["len"]
40+
stickerManager.downloadPack(packs[0]["pack"])
41+
assert len(list(Path(f"{stickerManager.cwd}/donutthedog/tgs").iterdir())) == packs[0]["len"]
4442

4543

4644
def test_convertPack() -> None:
47-
stickerPack = downloader.getPack(packs[0]["pack"])
48-
assert stickerPack is not None
49-
downloader.downloadPack(stickerPack)
50-
downloader.convertPack(packs[0]["pack"], scale=0.05, noCache=True, backend=Backend.PYRLOTTIE)
51-
assert len(list(Path(f"{downloader.cwd}/donutthedog/webp").iterdir())) == packs[0]["len"]
45+
stickerManager.downloadPack(packs[0]["pack"])
46+
stickerManager.convertPack(packs[0]["pack"], scale=0.05, noCache=True, backend=Backend.RLOTTIE_PYTHON)
47+
assert len(list(Path(f"{stickerManager.cwd}/donutthedog/webp").iterdir())) == packs[0]["len"]
5248

5349

5450
# def test_convertPack_slow() -> None:
55-
# stickerPack = downloader.getPack(packs[0]["pack"])
56-
# assert stickerPack is not None
57-
# downloader.downloadPack(stickerPack)
58-
# downloader.convertPack(packs[0]["pack"], scale=1, noCache=True, backend=Backend.PYRLOTTIE)
59-
# assert len(list(Path(f"{downloader.cwd}/donutthedog/webp").iterdir())) == packs[0]["len"]
51+
# stickerManager.downloadPack(packs[0]["pack"])
52+
# stickerManager.convertPack(packs[0]["pack"], scale=1, noCache=True, backend=Backend.PYRLOTTIE)
53+
# assert len(list(Path(f"{stickerManager.cwd}/donutthedog/webp").iterdir())) == packs[0]["len"]

tstickers/cli.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,9 @@
1212
from loguru import logger
1313

1414
from tstickers.convert import Backend
15-
from tstickers.downloader import StickerDownloader
15+
from tstickers.manager import StickerManager
1616

1717

18-
def is_library_installed(library_name: str) -> bool:
19-
return importlib.util.find_spec(library_name) is not None
20-
2118

2219
def cli() -> None: # pragma: no cover
2320
"""Cli entry point."""
@@ -76,7 +73,7 @@ def cli() -> None: # pragma: no cover
7673
# Get the backend
7774
backend = args.backend
7875

79-
if not is_library_installed(backend):
76+
if importlib.util.find_spec(backend) is None:
8077
logger.error(f'!! {backend} is not installed! Install with "pip install {backend}"')
8178
sysexit(2)
8279

@@ -97,14 +94,10 @@ def cli() -> None: # pragma: no cover
9794
packs.append(name)
9895
packs = [name.split("/")[-1] for name in packs]
9996

100-
downloader = StickerDownloader(token)
97+
downloader = StickerManager(token)
10198
for pack in packs:
102-
logger.info("=" * 60)
103-
stickerPack = downloader.getPack(pack)
104-
if stickerPack is None:
105-
continue
10699
logger.info("-" * 60)
107-
_ = downloader.downloadPack(stickerPack)
100+
_ = downloader.downloadPack(pack)
108101
logger.info("-" * 60)
109102

110103
backend_map = {"rlottie-python": Backend.RLOTTIE_PYTHON, "pyrlottie": Backend.PYRLOTTIE}

tstickers/convert.py

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,6 @@ def convertAnimatedFunc(_swd: Path, _threads: int, _frameSkip: int, _scale: floa
3535
from tstickers.convert_pyrlottie import convertAnimated as convertPyRlottie
3636

3737

38-
def assure_dir_exists(*parts: Path | str) -> Path:
39-
"""Make the directory if it does not exist.
40-
41-
Args:
42-
----
43-
parts (Path): path parts
44-
45-
Returns:
46-
-------
47-
Path: the full path
48-
49-
"""
50-
full_path = Path(*parts)
51-
full_path.mkdir(parents=True, exist_ok=True)
52-
return full_path
53-
54-
5538
def convertWithPIL(inputFile: str) -> str:
5639
"""Convert the webp file to png.
5740
@@ -87,8 +70,10 @@ def convertStatic(swd: Path, threads: int = 4) -> int:
8770
"""
8871
converted = 0
8972
start = time.time()
90-
assure_dir_exists(swd, "png")
91-
assure_dir_exists(swd, "gif")
73+
(swd/ "png").mkdir(parents=True, exist_ok=True)
74+
(swd/ "gif").mkdir(parents=True, exist_ok=True)
75+
76+
9277
with ThreadPoolExecutor(max_workers=threads) as executor:
9378
for _ in as_completed(
9479
[
@@ -133,9 +118,10 @@ def convertAnimated(
133118
msg = "You must specify a conversion backend"
134119
raise RuntimeError(msg)
135120
start = time.time()
136-
assure_dir_exists(swd, "apng")
137-
assure_dir_exists(swd, "gif")
138-
assure_dir_exists(swd, "webp")
121+
122+
(swd/ "apng").mkdir(parents=True, exist_ok=True)
123+
(swd/ "gif").mkdir(parents=True, exist_ok=True)
124+
(swd/ "webp").mkdir(parents=True, exist_ok=True)
139125

140126
convertMap = {
141127
Backend.UNDEFINED: convertAnimatedFunc,

0 commit comments

Comments
 (0)