Skip to content

Commit b791781

Browse files
Added tests, installed pngquant in GA
1 parent 41dfc44 commit b791781

File tree

4 files changed

+132
-41
lines changed

4 files changed

+132
-41
lines changed

.github/workflows/pythonapp.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
python-version: ${{ matrix.python-version }}
2626
- name: Install dependencies
2727
run: |
28+
sudo apt install pngquant
2829
python -m pip install --upgrade pip
2930
pip install -r requirements-dev.txt
3031
- name: Test with pytest

src/images/download.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
'Ubuntu/8.10 (intrepid) Firefox/3.0.5')
3737
}
3838

39+
# seconds to sleep before each retrial when downloading (starting from the end)
40+
RETRIES = [5, 1, .3]
41+
3942
# Turning off the PIL debug logs as are too noisy.
4043
logging.getLogger("PIL").setLevel(logging.INFO)
4144

@@ -86,16 +89,14 @@ def _download(url, fullpath):
8689
def download(data):
8790
"""Download image from url, retry on error."""
8891
url, fullpath = data
92+
retries = RETRIES.copy()
8993

9094
basedir, _ = os.path.split(fullpath)
9195
# call it directly with exist_ok=True; it's better than verify if it exists
9296
# and then create, as if it's done in two lines a race condition may happen
9397
# (this function internally just catches the error)
9498
os.makedirs(basedir, exist_ok=True)
9599

96-
# seconds to sleep before each retrial (starting from the end)
97-
retries = [5, 1, .3]
98-
99100
while True:
100101
try:
101102
_download(url, fullpath)

tests/test_images_download.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Copyright 2021 CDPedistas (see AUTHORS.txt)
2+
#
3+
# This program is free software: you can redistribute it and/or modify it
4+
# under the terms of the GNU General Public License version 3, as published
5+
# by the Free Software Foundation.
6+
#
7+
# This program is distributed in the hope that it will be useful, but
8+
# WITHOUT ANY WARRANTY; without even the implied warranties of
9+
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
10+
# PURPOSE. See the GNU General Public License for more details.
11+
#
12+
# You should have received a copy of the GNU General Public License along
13+
# with this program. If not, see <http://www.gnu.org/licenses/>.
14+
#
15+
# For further info, check https://github.com/PyAr/CDPedia/
16+
17+
import shutil
18+
from unittest.mock import patch
19+
20+
from src.images.download import optimize_png, download, FetchingError
21+
22+
import pytest
23+
24+
25+
@pytest.fixture
26+
def image_config(tmp_path):
27+
def f(name):
28+
img_test_name = 'tests/fixtures/image_to_optimize.png'
29+
test_path = tmp_path / name
30+
shutil.copy(img_test_name, str(test_path))
31+
init_size = test_path.stat().st_size
32+
return test_path, init_size
33+
yield f
34+
35+
36+
@pytest.mark.parametrize('filename', [
37+
'image.png', # simple
38+
'Image.PNG', # uppercase
39+
'moño.png', # unicode
40+
'the image.png', # spaces
41+
])
42+
def test_pngquant_optimize(image_config, filename):
43+
img_path, init_size = image_config(filename)
44+
optimize_png(str(img_path), init_size, init_size)
45+
final_size = img_path.stat().st_size
46+
assert init_size > final_size
47+
48+
49+
def test_download_ok(tmp_path):
50+
test_path = tmp_path / 'foo' / 'bar' / 'baz.png'
51+
52+
with patch('src.images.download.optimize_image') as _optimize_mock:
53+
with patch('src.images.download._download') as _download_mock:
54+
# real download will be ok, no need to patch RETRIES
55+
_download_mock.return_value = None
56+
57+
download(('test-url', str(test_path)))
58+
59+
# check directory were prepared ok
60+
assert test_path.parent.exists()
61+
62+
# download and optimization was called ok
63+
_download_mock.assert_called_once_with('test-url', str(test_path))
64+
_optimize_mock.assert_called_once_with(str(test_path))
65+
66+
67+
@pytest.mark.parametrize('extension', [
68+
'.svg',
69+
'.gif',
70+
'.Svg',
71+
'.Gif',
72+
'.SVG',
73+
'.GIF',
74+
])
75+
def test_download_no_optimization(extension, tmp_path):
76+
test_path = tmp_path / 'foo' / 'bar' / ('baz.' + extension)
77+
78+
with patch('src.images.download.optimize_image') as _optimize_mock:
79+
with patch('src.images.download._download') as _download_mock:
80+
# real download will be ok, no need to patch RETRIES
81+
_download_mock.return_value = None
82+
83+
download(('test-url', str(test_path)))
84+
85+
# optimization was NOT called
86+
_optimize_mock.assert_not_called()
87+
88+
89+
def test_download_retry_ok(tmp_path):
90+
test_path = tmp_path / 'foo' / 'bar' / 'baz.png'
91+
92+
with patch('src.images.download.optimize_image'):
93+
with patch('src.images.download._download') as _download_mock:
94+
with patch('src.images.download.RETRIES', [0]):
95+
# first time ends with error, second ok
96+
_download_mock.side_effect = [
97+
ValueError('pumba'),
98+
None,
99+
]
100+
download(('test-url', str(test_path)))
101+
102+
# check directory were prepared ok
103+
assert test_path.parent.exists()
104+
105+
# download was called twice
106+
assert _download_mock.call_count == 2
107+
108+
109+
def test_download_problems(tmp_path):
110+
test_path = tmp_path / 'foo' / 'bar' / 'baz.png'
111+
112+
with patch('src.images.download.optimize_image'):
113+
with patch('src.images.download._download') as _download_mock:
114+
with patch('src.images.download.RETRIES', [0]):
115+
# always in error
116+
_download_mock.side_effect = [
117+
ValueError('pumba'),
118+
ValueError('pumba'),
119+
]
120+
with pytest.raises(FetchingError):
121+
download(('test-url', str(test_path)))
122+
123+
# check directory were prepared ok
124+
assert test_path.parent.exists()
125+
126+
# download was called twice
127+
assert _download_mock.call_count == 2

tests/test_pngquant.py

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)