Skip to content

Commit 270ea92

Browse files
bajnokkc00kiemon5ter
authored andcommitted
storage: make pymongo and redis dependency optional
Fail only if the module required by the storage wrapper is not available. Since the library is usable without any persistent storage driver at all, the database-specific module requirements have been moved to extras_require.
1 parent a07a54b commit 270ea92

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
description='OpenID Connect Provider (OP) library in Python.',
1313
install_requires=[
1414
'oic >= 1.2.1',
15+
],
16+
extras_require=[
1517
'pymongo',
16-
'redis'
18+
'redis',
1719
]
1820
)

src/pyop/storage.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,22 @@
33
from abc import ABC, abstractmethod
44
import copy
55
import json
6-
import pymongo
7-
from redis.client import Redis
86
from datetime import datetime
97

8+
try:
9+
import pymongo
10+
except ImportError:
11+
_has_pymongo = False
12+
else:
13+
_has_pymongo = True
14+
15+
try:
16+
from redis.client import Redis
17+
except ImportError:
18+
_has_redis = False
19+
else:
20+
_has_redis = True
21+
1022

1123
class StorageBase(ABC):
1224
_ttl = None
@@ -55,6 +67,8 @@ def ttl(self):
5567

5668
class MongoWrapper(StorageBase):
5769
def __init__(self, db_uri, db_name, collection, ttl=None):
70+
if not _has_pymongo:
71+
raise ImportError("pymongo module is required but it is not available")
5872
self._db_uri = db_uri
5973
self._coll_name = collection
6074
self._db = MongoDB(db_uri, db_name=db_name)
@@ -105,6 +119,8 @@ class RedisWrapper(StorageBase):
105119
"""
106120

107121
def __init__(self, db_uri, collection, ttl=None):
122+
if not _has_redis:
123+
raise ImportError("redis module is required but it is not available")
108124
self._db = Redis.from_url(db_uri, decode_responses=True)
109125
self._collection = collection
110126
if ttl is None or (isinstance(ttl, int) and ttl >= 0):

tests/pyop/test_storage.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import pymongo
1212
import time
1313

14-
from pyop.storage import StorageBase
14+
import pyop.storage
1515

1616
__author__ = 'lundberg'
1717

@@ -32,7 +32,9 @@ def mock_mongo():
3232
class TestStorage(object):
3333
@pytest.fixture(params=uri_list)
3434
def db(self, request):
35-
return StorageBase.from_uri(request.param, db_name="pyop", collection='test')
35+
return pyop.storage.StorageBase.from_uri(
36+
request.param, db_name="pyop", collection="test"
37+
)
3638

3739
def test_write(self, db):
3840
db['foo'] = 'bar'
@@ -79,7 +81,7 @@ def test_items(self, db):
7981
],
8082
)
8183
def test_from_uri(self, args, kwargs):
82-
store = StorageBase.from_uri(*args, **kwargs)
84+
store = pyop.storage.StorageBase.from_uri(*args, **kwargs)
8385
store["test"] = "value"
8486
assert store["test"] == "value"
8587

@@ -118,12 +120,12 @@ def test_from_uri(self, args, kwargs):
118120
)
119121
def test_from_uri_invalid_parameters(self, error, args, kwargs):
120122
with pytest.raises(error):
121-
StorageBase.from_uri(*args, **kwargs)
123+
pyop.storage.StorageBase.from_uri(*args, **kwargs)
122124

123125

124126
class StorageTTLTest(ABC):
125127
def prepare_db(self, uri, ttl):
126-
self.db = StorageBase.from_uri(
128+
self.db = pyop.storage.StorageBase.from_uri(
127129
uri,
128130
collection="test",
129131
ttl=ttl,
@@ -169,6 +171,13 @@ def new_time():
169171
def test_ttl(self):
170172
self.execute_ttl_test("redis://localhost/0", 3600)
171173

174+
def test_missing_module(self):
175+
pyop.storage._has_redis = False
176+
self.prepare_db("mongodb://localhost/0", None)
177+
with pytest.raises(ImportError):
178+
self.prepare_db("redis://localhost/0", None)
179+
pyop.storage._has_redis = True
180+
172181

173182
class TestMongoTTL(StorageTTLTest):
174183
def set_time(self, offset, monkeypatch):
@@ -180,3 +189,10 @@ def new_time():
180189

181190
def test_ttl(self):
182191
self.execute_ttl_test("mongodb://localhost/pyop", 3600)
192+
193+
def test_missing_module(self):
194+
pyop.storage._has_pymongo = False
195+
self.prepare_db("redis://localhost/0", None)
196+
with pytest.raises(ImportError):
197+
self.prepare_db("mongodb://localhost/0", None)
198+
pyop.storage._has_pymongo = True

0 commit comments

Comments
 (0)