Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility with Python 3 and pymongo >= 3.0.0 #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.eggs
*.egg-info
.venv*
*.pyc
31 changes: 23 additions & 8 deletions mongodb_gridfs_beaker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,16 @@
from beaker.synchronization import file_synchronizer
from beaker.util import SyncDict, verify_directory

# Compatibility between pymongo<>3.0.0.
import pymongo
from distutils.version import LooseVersion
try:
from pymongo import MongoClient as Connection
from pymongo.read_preferences import ReadPreference
except ImportError:
from pymongo.connection import Connection

from pymongo.uri_parser import parse_uri
from pymongo.connection import Connection
from pymongo import ASCENDING, DESCENDING

from gridfs import GridFS
Expand All @@ -33,7 +41,7 @@
import pickle

class MongoDBGridFSNamespaceManager(NamespaceManager):

clients = SyncDict()

def __init__(self, namespace, url=None, data_dir=None, lock_dir=None, **params):
Expand All @@ -49,7 +57,7 @@ def __init__(self, namespace, url=None, data_dir=None, lock_dir=None, **params):
if not url:
raise MissingCacheParameter("MongoDB url is required")

for k, v in parse_uri(url).iteritems():
for k, v in parse_uri(url).items():
setattr(self, "url_%s"%k, v)

if not self.url_database or not self.url_nodelist:
Expand All @@ -64,16 +72,23 @@ def _create_mongo_connection(self):
'mongodb://%s' % (",".join(["%s:%s" % h for h in self.url_nodelist]))
log.info("[MongoDBGridFS] Host URI: %s" % host_uri)

is_pymongo3 = LooseVersion(pymongo.version) >= LooseVersion('3.0.0')

params = {}
params['slaveok'] = self.url_options.get("slaveok", False)
if self.url_options.has_key("replicaset"):
if "slaveok" in self.url_options and self.url_options['slaveok']:
if is_pymongo3:
params['readPreference'] = ReadPreference.SECONDARY_PREFERRED
else:
params['slaveok'] = True

if "replicaset" in self.url_options:
params['replicaset'] = self.url_options["replicaset"] or ""

conn = Connection(host_uri, **params)
db = conn[self.url_database]

if self.url_username:
log.info("[MongoDBGridFS] Attempting to authenticate %s/%s " %
log.info("[MongoDBGridFS] Attempting to authenticate %s/%s " %
(self.url_username, self.url_password))
if not db.authenticate(self.url_username, self.url_password):
raise InvalidCacheBackendError('Cannot authenticate to MongoDB.')
Expand Down Expand Up @@ -123,7 +138,7 @@ def __getitem__(self, key):

try:
value = pickle.loads(value)
except Exception, e:
except Exception as e:
log.exception("[MongoDBGridFS] Failed to unpickle value.")
return None

Expand All @@ -138,7 +153,7 @@ def __contains__(self, key):
def has_key(self, key):
return key in self

def set_value(self, key, value):
def set_value(self, key, value, expiretime=None):
query = {'namespace': self.namespace, 'filename': key}
log.debug("[MongoDBGridFS %s] Set Key: %s" % (self.gridfs, query))

Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@

setup(
name = 'mongodb_gridfs_beaker',
version = '0.5.4',
version = '0.6.0dev1',
description = 'Beaker backend to write sessions and caches to a MongoDB GridFS',
long_description = '\n' + open('README.rst').read(),
author='Lukasz Biedrycki',
author_email = '[email protected]',
keywords = 'mongo mongodb gridfs beaker cache session',
license = 'New BSD License',
url = 'https://github.com/loucash/mongodb_gridfs_beaker',
tests_require = ['nose', 'webtest'],
tests_require = ['nose', 'WebTest'],
test_suite='nose.collector',
classifiers = [
'Development Status :: 4 - Beta',
Expand Down
35 changes: 26 additions & 9 deletions tests/test_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,18 @@
from beaker.exceptions import InvalidCacheBackendError
from nose import SkipTest
from webtest import TestApp
from pymongo.connection import Connection
import unittest
import time

# Compatibility between Python 2 <=> Python 3
IS_PYTHON_3 = (sys.version_info[0] >= 3)

# Compatibility between pymongo<>3.0.0.
try:
from pymongo import MongoClient as Connection
except ImportError:
from pymongo.connection import Connection

try:
clsmap['mongodb_gridfs']._init_dependencies()
except InvalidCacheBackendError:
Expand Down Expand Up @@ -49,8 +57,8 @@ def simple_session_app(environ, start_response):
if not environ['PATH_INFO'].startswith('/nosave'):
session.save()
start_response('200 OK', [('Content-type', 'text/plain')])
return ['The current value is: %d, session id is %s' % (session['value'],
session.id)]
return [_b('The current value is: %d, session id is %s' % (session['value'],
session.id))]

def simple_app(environ, start_response):
extra_args = {}
Expand All @@ -70,7 +78,7 @@ def simple_app(environ, start_response):
value = 0
cache.set_value('value', value+1)
start_response('200 OK', [('Content-type', 'text/plain')])
return ['The current value is: %s' % cache.get_value('value')]
return [_b('The current value is: %s' % cache.get_value('value'))]


def using_none_app(environ, start_response):
Expand All @@ -91,24 +99,33 @@ def using_none_app(environ, start_response):
value = 10
cache.set_value('value', None)
start_response('200 OK', [('Content-type', 'text/plain')])
return ['The current value is: %s' % value]
return [_b('The current value is: %s' % value)]


def cache_manager_app(environ, start_response):
cm = environ['beaker.cache']
cm.get_cache('test')['test_key'] = 'test value'

start_response('200 OK', [('Content-type', 'text/plain')])
yield "test_key is: %s\n" % cm.get_cache('test')['test_key']
yield _b("test_key is: %s\n" % cm.get_cache('test')['test_key'])
cm.get_cache('test').clear()

try:
test_value = cm.get_cache('test')['test_key']
except KeyError:
yield "test_key cleared"
yield _b("test_key cleared")
else:
yield _b("test_key wasn't cleared, is: %s\n" % \
cm.get_cache('test')['test_key'])


def _b(value):
# Utility function as WebTest and its machinery want
# to yield byte-responses when running on Python3.
if IS_PYTHON_3:
return bytes(value, 'ascii')
else:
yield "test_key wasn't cleared, is: %s\n" % \
cm.get_cache('test')['test_key']
return value


def test_session():
Expand Down