Skip to content

Commit 87a1de6

Browse files
committed
build: consolidate packaging in pyproject.toml and bump dependencies
- Removed requirements.txt and dev-requirements.txt - Bumped Flask, Flask-Babel, and redis-py to modern versions - Bumped fakeredis to natively support RESP3/HELLO protocol - Updated Makefile, Dockerfile, and tox pipelines to use pyproject.toml - Fixed pip-audit vulnerabilities by bumping pytest and wheel
1 parent 77370fd commit 87a1de6

10 files changed

Lines changed: 33 additions & 51 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ htmlcov/
4646
.coverage.*
4747
.cache
4848
.pytest_cache/
49+
.ruff_cache/
50+
.mypy_cache/
4951

5052
# virtualenv
5153
venv/

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ RUN groupadd -r snappass && \
88

99
WORKDIR $APP_DIR
1010

11-
COPY ["pyproject.toml", "requirements.txt", "README.rst", "AUTHORS.rst", "LICENSE", "$APP_DIR/"]
11+
COPY ["pyproject.toml", "README.rst", "AUTHORS.rst", "LICENSE", "$APP_DIR/"]
1212
COPY ["./snappass", "$APP_DIR/snappass"]
1313

14-
RUN pip install --no-cache-dir -r requirements.txt && \
14+
RUN pip install --no-cache-dir . && \
1515
pybabel compile -d snappass/translations && \
1616
pip install --no-cache-dir . && \
1717
chown -R snappass $APP_DIR && \

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
.PHONY: dev prod run test
22

3-
dev: dev-requirements.txt
4-
pip install -r dev-requirements.txt
3+
dev:
4+
pip install .[dev]
55

6-
prod: requirements.txt
7-
pip install -r requirements.txt
6+
prod:
7+
pip install .
88

99
run: prod
1010
FLASK_DEBUG=1 FLASK_APP=snappass.main NO_SSL=True flask run

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ Alternatively, you can use `Docker`_ and `Docker Compose`_ to install and run Sn
295295

296296
$ docker-compose up -d
297297

298-
This will pull all dependencies, i.e. Redis and appropriate Python version (3.7), then start up SnapPass and Redis server. SnapPass server is accessible at: http://localhost:5000
298+
This will pull all dependencies, i.e. Redis and appropriate Python version (3.14), then start up SnapPass and Redis server. SnapPass server is accessible at: http://localhost:5000
299299

300300
Similar Tools
301301
-------------

dev-requirements.txt

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

pyproject.toml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ classifiers = [
1717
"Programming Language :: Python :: 3",
1818
]
1919
dependencies = [
20-
"Flask>=1.1.1",
21-
"redis>=4.0.0,<5.0.0",
22-
"Flask-Babel>=1.0.0",
20+
"Flask>=3.1.0",
21+
"redis>=5.0.0",
22+
"Flask-Babel>=4.0.0",
2323
]
2424

2525
[project.urls]
@@ -33,3 +33,18 @@ select = ["E", "F", "S"]
3333

3434
[tool.ruff.lint.per-file-ignores]
3535
"tests.py" = ["S105", "S101"]
36+
37+
[project.optional-dependencies]
38+
dev = [
39+
"coverage==7.6.0",
40+
"fakeredis>=2.26.0",
41+
"ruff==0.6.2",
42+
"pip-audit==2.7.3",
43+
"freezegun==1.5.1",
44+
"pytest>=9.0.3",
45+
"pytest-cov==5.0.0",
46+
"tox==4.23.0",
47+
"bumpversion==0.6.0",
48+
"wheel>=0.46.2",
49+
"mypy==1.11.1"
50+
]

requirements.txt

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

snappass/storage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
if os.environ.get('MOCK_REDIS'):
1313
from fakeredis import FakeStrictRedis
1414

15-
redis_client = FakeStrictRedis(version=(6, 2), protocol=2) # type: ignore
15+
redis_client = FakeStrictRedis() # type: ignore
1616
elif os.environ.get('REDIS_URL'):
1717
redis_url = os.environ.get('REDIS_URL')
1818
if not redis_url:

tests.py

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
import time
44
import unittest
55
from unittest import TestCase
6-
from unittest import mock
76
from urllib.parse import quote
87
from urllib.parse import unquote
98

109
from freezegun import freeze_time
11-
from fakeredis import FakeStrictRedis
1210

1311
os.environ['MOCK_REDIS'] = 'true'
1412

@@ -21,7 +19,6 @@
2119

2220
class SnapPassTestCase(TestCase):
2321

24-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
2522
def test_get_password(self):
2623
password = "melatonin overdose 1337!$"
2724
key = snappass.set_password(password, 30)
@@ -46,13 +43,11 @@ def test_returned_token_format(self):
4643
# 16 bytes urlsafe base64 is 22 chars
4744
self.assertEqual(len(storage.REDIS_PREFIX) + 22, len(token))
4845

49-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
5046
def test_password_before_expiration(self):
5147
password = 'fidelio'
5248
key = snappass.set_password(password, 1)
5349
self.assertEqual(password, snappass.get_password(key))
5450

55-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
5651
def test_password_after_expiration(self):
5752
password = 'open sesame'
5853
key = snappass.set_password(password, 1)
@@ -92,29 +87,25 @@ def test_handle_password_missing_data(self):
9287
rv = self.app.post('/', data={})
9388
self.assertEqual(rv.status_code, 500)
9489

95-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
9690
def test_preview_password(self):
9791
password = "I like novelty kitten statues!"
9892
key = snappass.set_password(password, 30)
9993
rv = self.app.get('/{0}'.format(key))
10094
# The password payload should not be visible in preview
10195
self.assertNotIn(password, rv.get_data(as_text=True))
10296

103-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
10497
def test_preview_password_not_found(self):
10598
rv = self.app.get('/invalid_key')
10699
self.assertEqual(rv.status_code, 404)
107100
self.assertIn('Secret Not Found', rv.get_data(as_text=True))
108101

109-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
110102
def test_show_password(self):
111103
password = "I like novelty kitten statues!"
112104
key = snappass.set_password(password, 30)
113105
rv = self.app.post('/{0}'.format(key))
114106
# The payload (encrypted text) is shown in the text area
115107
self.assertIn(password, rv.get_data(as_text=True))
116108

117-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
118109
def test_show_password_not_found(self):
119110
rv = self.app.post('/invalid_key')
120111
self.assertEqual(rv.status_code, 404)
@@ -126,7 +117,6 @@ def test_url_prefix(self):
126117
rv = self.app.post('/', data={'password': password, 'ttl': 'hour'})
127118
self.assertIn("localhost/test/prefix/", rv.get_data(as_text=True))
128119

129-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
130120
def test_set_password_json(self):
131121
with freeze_time("2020-05-08 12:00:00") as frozen_time:
132122
password = 'my name is my passport. verify me.'
@@ -147,7 +137,6 @@ def test_set_password_json(self):
147137
frozen_time.move_to("2020-05-22 12:00:00")
148138
self.assertIsNone(snappass.get_password(key))
149139

150-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
151140
def test_set_password_api(self):
152141
with freeze_time("2020-05-08 12:00:00") as frozen_time:
153142
password = 'my name is my passport. verify me.'
@@ -176,7 +165,6 @@ def test_api_handle_password_missing_data(self):
176165
)
177166
self.assertEqual(rv.status_code, 500)
178167

179-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
180168
def test_set_password_api_default_ttl(self):
181169
with freeze_time("2020-05-08 12:00:00") as frozen_time:
182170
password = 'my name is my passport. verify me.'
@@ -229,7 +217,6 @@ def test_uses_host_override_with_untrusted_host_header(self):
229217
json_content['link'].startswith('https://snappass.example.org/')
230218
)
231219

232-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
233220
def test_set_password_api_v2(self):
234221
with freeze_time("2020-05-08 12:00:00") as frozen_time:
235222
password = 'my name is my passport. verify me.'
@@ -248,7 +235,6 @@ def test_set_password_api_v2(self):
248235
frozen_time.move_to("2020-05-22 12:00:00")
249236
self.assertIsNone(snappass.get_password(key))
250237

251-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
252238
def test_set_password_api_v2_default_ttl(self):
253239
with freeze_time("2020-05-08 12:00:00") as frozen_time:
254240
password = 'my name is my passport. verify me.'
@@ -315,7 +301,6 @@ def test_set_password_api_v2_no_password_and_too_big_ttl(self):
315301
bad_ttl = invalid_params[1]
316302
self.assertEqual(bad_ttl['name'], 'ttl')
317303

318-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
319304
def test_check_password_api_v2(self):
320305
password = 'my name is my passport. verify me.'
321306
rv = self.app.post(
@@ -330,7 +315,6 @@ def test_check_password_api_v2(self):
330315
rvc = self.app.head('/api/v2/passwords/' + quote(key))
331316
self.assertEqual(rvc.status_code, 200)
332317

333-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
334318
def test_check_password_api_v2_bad_keys(self):
335319
password = 'my name is my passport. verify me.'
336320
rv = self.app.post(
@@ -345,7 +329,6 @@ def test_check_password_api_v2_bad_keys(self):
345329
rvc = self.app.head('/api/v2/passwords/' + quote(key[::-1]))
346330
self.assertEqual(rvc.status_code, 404)
347331

348-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
349332
def test_retrieve_password_api_v2(self):
350333
password = 'my name is my passport. verify me.'
351334
rv = self.app.post(
@@ -364,7 +347,6 @@ def test_retrieve_password_api_v2(self):
364347
retrieved_password = json_content_retrieved['password']
365348
self.assertEqual(retrieved_password, password)
366349

367-
@mock.patch('redis.client.StrictRedis', FakeStrictRedis)
368350
def test_retrieve_password_api_v2_bad_keys(self):
369351
password = 'my name is my passport. verify me.'
370352
rv = self.app.post(

tox.ini

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,21 @@ setenv =
77
MOCK_REDIS = 1
88
SECRET_KEY = test-secret-key-1234567890
99
commands =
10-
pip install -r requirements.txt
11-
pip install -r dev-requirements.txt
10+
pip install .[dev]
1211
pytest --cov=snappass --cov-report=term-missing tests.py
1312

1413
[testenv:ruff]
1514
commands =
16-
pip install -r dev-requirements.txt
15+
pip install .[dev]
1716
ruff check .
1817

1918
[testenv:pip-audit]
2019
commands =
21-
pip install -r dev-requirements.txt
22-
pip-audit -r requirements.txt
20+
pip install .[dev]
21+
pip-audit
2322

2423
[testenv:mypy]
2524
commands =
26-
pip install -r dev-requirements.txt
25+
pip install .[dev]
2726
mypy snappass
2827

0 commit comments

Comments
 (0)