Skip to content

Commit ea74d0f

Browse files
authored
Merge pull request #18 from rkoopmans/master
Update python support & add CI/CD on github actions
2 parents 368164b + 8120146 commit ea74d0f

File tree

9 files changed

+196
-36
lines changed

9 files changed

+196
-36
lines changed

.github/workflows/ci-cd.yml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: CI_CD
2+
3+
on: [push, pull_request]
4+
5+
permissions: {}
6+
jobs:
7+
Unit_tests:
8+
runs-on: ${{ matrix.os }}
9+
timeout-minutes: 10
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
python-version: [
14+
"2.7",
15+
"3.7", "3.8", "3.9", "3.10", "3.11-dev",
16+
"pypy-2.7", "pypy-3.8"
17+
]
18+
os: [ubuntu-latest, macOS-latest, windows-latest]
19+
20+
steps:
21+
- uses: actions/checkout@v3
22+
- name: Set up Python ${{ matrix.python-version }}
23+
uses: actions/setup-python@v4
24+
with:
25+
python-version: ${{ matrix.python-version }}
26+
- name: Install dependencies
27+
run: |
28+
pip install -r test-requirements.txt -r requirements.txt
29+
- name: Run tests
30+
run: |
31+
pytest
32+
33+
Integration_tests:
34+
runs-on: ${{ matrix.os }}
35+
timeout-minutes: 10
36+
needs: Unit_tests
37+
strategy:
38+
fail-fast: false
39+
matrix:
40+
python-version: [
41+
"3.10",
42+
]
43+
os: [ubuntu-latest, macOS-latest, windows-latest]
44+
steps:
45+
- uses: actions/checkout@v3
46+
- name: Set up Python ${{ matrix.python-version }}
47+
uses: actions/setup-python@v4
48+
with:
49+
python-version: ${{ matrix.python-version }}
50+
- name: Install dependencies
51+
run: |
52+
pip install -r test-requirements.txt -r requirements.txt
53+
- name: Run tests
54+
env:
55+
TINIFY_KEY: ${{ secrets.TINIFY_KEY }}
56+
run: |
57+
pytest test/integration.py
58+
59+
Publish:
60+
if: |
61+
github.repository == 'tinify/tinify-python' &&
62+
startsWith(github.ref, 'refs/tags') &&
63+
github.event_name == 'push'
64+
timeout-minutes: 10
65+
needs: [Unit_tests, Integration_tests]
66+
runs-on: ubuntu-latest
67+
steps:
68+
- uses: actions/checkout@v3
69+
with:
70+
fetch-depth: 0
71+
persist-credentials: false
72+
- name: Set up Python
73+
uses: actions/setup-python@v4
74+
with:
75+
python-version: "3.10"
76+
- name: Install dependencies
77+
run: |
78+
pip install -r requirements.txt
79+
pip install build wheel
80+
- name: Build package (sdist & wheel)
81+
run: |
82+
python -m build --sdist --wheel --outdir dist/
83+
- name: Test sdist install
84+
run: |
85+
python -m venv sdist_env
86+
./sdist_env/bin/pip install dist/tinify*.tar.gz
87+
- name: Test wheel install
88+
run: |
89+
python -m venv wheel_env
90+
./wheel_env/bin/pip install dist/tinify*.whl
91+
- name: Publish package to PyPI
92+
uses: pypa/gh-action-pypi-publish@master
93+
with:
94+
user: __token__
95+
password: ${{ secrets.PYPI_ACCESS_TOKEN }}
96+
# Use the test repository for testing the publish feature
97+
# repository_url: https://test.pypi.org/legacy/
98+
packages_dir: dist/
99+
print_hash: true
100+

README.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
[<img src="https://travis-ci.org/tinify/tinify-python.svg?branch=master" alt="Build Status">](https://travis-ci.org/tinify/tinify-python)
1+
[![MIT License](http://img.shields.io/badge/license-MIT-green.svg) ](https://github.com/tinify/tinify-python/blob/main/LICENSE)
2+
[![CI](https://github.com/tinify/tinify-python/actions/workflows/run-tests.yml/badge.svg)](https://github.com/tinify/tinify-python/actions/workflows/run-tests.yml)
3+
![PyPI](https://img.shields.io/pypi/v/tinify)
4+
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/tinify)
5+
![PyPI - Wheel](https://img.shields.io/pypi/wheel/tinify)
6+
27

38
# Tinify API client for Python
49

@@ -29,14 +34,22 @@ tinify.from_file('unoptimized.png').to_file('optimized.png')
2934

3035
```
3136
pip install -r requirements.txt -r test-requirements.txt
32-
nosetests
37+
py.test
38+
```
39+
40+
To test more runtimes, tox can be used
41+
3342
```
43+
tox
44+
```
45+
46+
3447

3548
### Integration tests
3649

3750
```
3851
pip install -r requirements.txt -r test-requirements.txt
39-
TINIFY_KEY=$YOUR_API_KEY nosetests test/integration.py
52+
TINIFY_KEY=$YOUR_API_KEY py.test test/integration.py
4053
```
4154

4255
## License

setup.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from version import __version__
1212

1313
install_require = ['requests >= 2.7.0, < 3.0.0']
14-
tests_require = ['nose >= 1.3, < 2.0', 'httpretty >= 0.8.10, < 1.0.0']
14+
tests_require = ['pytest', 'httpretty < 1.1.5']
1515

1616
if sys.version_info < (2, 7):
1717
tests_require.append('unittest2')
@@ -26,6 +26,7 @@
2626
author_email='[email protected]',
2727
license='MIT',
2828
long_description='Python client for the Tinify API. Tinify compresses your images intelligently. Read more at https://tinify.com.',
29+
long_description_content_type='text/markdown',
2930
url='https://tinify.com/developers',
3031

3132
packages=['tinify'],
@@ -44,10 +45,12 @@
4445
'Natural Language :: English',
4546
'License :: OSI Approved :: MIT License',
4647
'Programming Language :: Python',
47-
'Programming Language :: Python :: 2.6',
4848
'Programming Language :: Python :: 2.7',
4949
'Programming Language :: Python :: 3',
50-
'Programming Language :: Python :: 3.3',
51-
'Programming Language :: Python :: 3.4'
50+
'Programming Language :: Python :: 3.7',
51+
'Programming Language :: Python :: 3.8',
52+
'Programming Language :: Python :: 3.9',
53+
'Programming Language :: Python :: 3.10',
54+
'Programming Language :: Python :: 3.11',
5255
),
5356
)

test/helper.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import absolute_import, division, print_function, unicode_literals
3-
3+
from contextlib import contextmanager
4+
from tempfile import NamedTemporaryFile
45
import json
56
import sys
67
import os
78
import httpretty
8-
from nose.exc import SkipTest
99

1010
if sys.version_info < (3, 3):
1111
from mock import DEFAULT
@@ -56,3 +56,18 @@ def assertJsonEqual(self, expected, actual):
5656
@property
5757
def request(self):
5858
return httpretty.last_request()
59+
60+
61+
62+
@contextmanager
63+
def create_named_tmpfile():
64+
# Due to NamedTemporaryFile requiring to be closed when used on Windows
65+
# we create our own NamedTemporaryFile contextmanager
66+
# See note: https://docs.python.org/3/library/tempfile.html#tempfile.NamedTemporaryFile
67+
68+
tmp = NamedTemporaryFile(delete=False)
69+
try:
70+
tmp.close()
71+
yield tmp.name
72+
finally:
73+
os.unlink(tmp.name)

test/integration.py

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
import sys, os
2+
from contextlib import contextmanager
3+
import tinify, unittest, tempfile
24

35
if not os.environ.get("TINIFY_KEY"):
46
sys.exit("Set the TINIFY_KEY environment variable.")
57

6-
import tinify, unittest, tempfile
8+
@contextmanager
9+
def create_named_tmpfile():
10+
# Due to NamedTemporaryFile requiring to be closed when used on Windows
11+
# we create our own NamedTemporaryFile contextmanager
12+
# See note: https://docs.python.org/3/library/tempfile.html#tempfile.NamedTemporaryFile
13+
14+
tmp = tempfile.NamedTemporaryFile(delete=False)
15+
try:
16+
tmp.close()
17+
yield tmp.name
18+
finally:
19+
os.unlink(tmp.name)
20+
721

822
class ClientIntegrationTest(unittest.TestCase):
923
tinify.key = os.environ.get("TINIFY_KEY")
@@ -13,11 +27,13 @@ class ClientIntegrationTest(unittest.TestCase):
1327
optimized = tinify.from_file(unoptimized_path)
1428

1529
def test_should_compress_from_file(self):
16-
with tempfile.NamedTemporaryFile() as tmp:
17-
self.optimized.to_file(tmp.name)
30+
with create_named_tmpfile() as tmp:
31+
self.optimized.to_file(tmp)
32+
33+
size = os.path.getsize(tmp)
1834

19-
size = os.path.getsize(tmp.name)
20-
contents = tmp.read()
35+
with open(tmp, 'rb') as f:
36+
contents = f.read()
2137

2238
self.assertTrue(1000 < size < 1500)
2339

@@ -27,11 +43,12 @@ def test_should_compress_from_file(self):
2743

2844
def test_should_compress_from_url(self):
2945
source = tinify.from_url('https://raw.githubusercontent.com/tinify/tinify-python/master/test/examples/voormedia.png')
30-
with tempfile.NamedTemporaryFile() as tmp:
31-
source.to_file(tmp.name)
46+
with create_named_tmpfile() as tmp:
47+
source.to_file(tmp)
3248

33-
size = os.path.getsize(tmp.name)
34-
contents = tmp.read()
49+
size = os.path.getsize(tmp)
50+
with open(tmp, 'rb') as f:
51+
contents = f.read()
3552

3653
self.assertTrue(1000 < size < 1500)
3754

@@ -40,11 +57,12 @@ def test_should_compress_from_url(self):
4057
self.assertNotIn(b'Copyright Voormedia', contents)
4158

4259
def test_should_resize(self):
43-
with tempfile.NamedTemporaryFile() as tmp:
44-
self.optimized.resize(method="fit", width=50, height=20).to_file(tmp.name)
60+
with create_named_tmpfile() as tmp:
61+
self.optimized.resize(method="fit", width=50, height=20).to_file(tmp)
4562

46-
size = os.path.getsize(tmp.name)
47-
contents = tmp.read()
63+
size = os.path.getsize(tmp)
64+
with open(tmp, 'rb') as f:
65+
contents = f.read()
4866

4967
self.assertTrue(500 < size < 1000)
5068

@@ -53,14 +71,15 @@ def test_should_resize(self):
5371
self.assertNotIn(b'Copyright Voormedia', contents)
5472

5573
def test_should_preserve_metadata(self):
56-
with tempfile.NamedTemporaryFile() as tmp:
57-
self.optimized.preserve("copyright", "creation").to_file(tmp.name)
74+
with create_named_tmpfile() as tmp:
75+
self.optimized.preserve("copyright", "creation").to_file(tmp)
5876

59-
size = os.path.getsize(tmp.name)
60-
contents = tmp.read()
77+
size = os.path.getsize(tmp)
78+
with open(tmp, 'rb') as f:
79+
contents = f.read()
6180

6281
self.assertTrue(1000 < size < 2000)
6382

6483
# width == 137
6584
self.assertIn(b'\x00\x00\x00\x89', contents)
66-
self.assertIn(b'Copyright Voormedia', contents)
85+
self.assertIn(b'Copyright Voormedia', contents)

test/tinify_client_test.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import tinify
88
from tinify import Client, AccountError, ClientError, ConnectionError, ServerError
99
import requests
10+
import pytest
1011

1112
from helper import *
1213

@@ -75,10 +76,9 @@ def setUp(self):
7576
'compression-count': 12
7677
})
7778

79+
@pytest.mark.skip(reason="https://github.com/gabrielfalcao/HTTPretty/issues/122")
7880
def test_should_issue_request_with_proxy_authorization(self):
79-
raise SkipTest('https://github.com/gabrielfalcao/HTTPretty/issues/122')
8081
Client('key', None, 'http://user:pass@localhost:8080').request('GET', '/')
81-
8282
self.assertEqual(self.request.headers['proxy-authorization'], 'Basic dXNlcjpwYXNz')
8383

8484
class TinifyClientRequestWithTimeoutRepeatedly(TestHelper):
@@ -165,9 +165,8 @@ def test_should_raise_server_error(self):
165165

166166
with self.assertRaises(ServerError) as context:
167167
Client('key').request('GET', '/')
168-
169-
msg = r'Error while parsing response: .* \(HTTP 543/ParseError\)'
170-
self.assertRegexpMatches(str(context.exception), msg)
168+
msg = r'Error while parsing response: .* \(HTTP 543/ParseError\)'
169+
self.assertRegex(str(context.exception), msg)
171170

172171
class TinifyClientRequestWithBadServerResponseOnce(TestHelper):
173172
def test_should_issue_request(self):

test/tinify_source_test.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ def test_to_file_with_path_should_store_image_data(self):
147147
self.assertEqual(b'compressed file', tmp.read())
148148

149149
def test_to_file_with_file_object_should_store_image_data(self):
150-
with tempfile.NamedTemporaryFile() as tmp:
151-
Source.from_buffer('png file').to_file(tmp.name)
152-
self.assertEqual(b'compressed file', tmp.read())
150+
with create_named_tmpfile() as name:
151+
Source.from_buffer('png file').to_file(name)
152+
with open(name, 'rb') as f:
153+
self.assertEqual(b'compressed file', f.read())

test/tinify_test.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from base64 import b64encode
55

66
import tinify
7+
import pytest
78
from helper import *
89

910
class TinifyKey(TestHelper):
@@ -27,13 +28,14 @@ def test_should_reset_client_with_new_app_identifier(self):
2728
self.assertEqual(self.request.headers['user-agent'], tinify.Client.USER_AGENT + " MyApp/2.0")
2829

2930
class TinifyProxy(TestHelper):
31+
32+
@pytest.mark.skip(reason="https://github.com/gabrielfalcao/HTTPretty/issues/122")
3033
def test_should_reset_client_with_new_proxy(self):
3134
httpretty.register_uri(httpretty.CONNECT, 'http://localhost:8080')
3235
tinify.key = 'abcde'
3336
tinify.proxy = 'http://localhost:8080'
3437
tinify.get_client()
3538
tinify.proxy = 'http://localhost:8080'
36-
raise SkipTest('https://github.com/gabrielfalcao/HTTPretty/issues/122')
3739
tinify.get_client().request('GET', '/')
3840
self.assertEqual(self.request.headers['user-agent'], tinify.Client.USER_AGENT + " MyApp/2.0")
3941

tox.ini

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[tox]
2+
envlist = py27,py36,py37,py38,py39,py310,py311,pypy2,pypy3
3+
4+
[testenv]
5+
deps = -rtest-requirements.txt
6+
-rrequirements.txt
7+
commands =
8+
pytest {posargs}

0 commit comments

Comments
 (0)