Commit 48141b0d by Gustav Arngården

Merge pull request #1 from quantopian/master

setup.py, robustness, user-friendliness
parents 26c9333d 9d3c77b5
......@@ -2,22 +2,30 @@
import time
import pymongo
EXECUTABLE_MONGO_METHODS = set([typ for typ in dir(pymongo.collection.Collection) if not typ.startswith('_')])
EXECUTABLE_MONGO_METHODS.update(set([typ for typ in dir(pymongo.Connection) if not typ.startswith('_')]))
EXECUTABLE_MONGO_METHODS.update(set([typ for typ in dir(pymongo) if not typ.startswith('_')]))
def get_methods(obj):
attrs = (attr for attr in dir(obj))
attrs = (attr for attr in attrs if not attr.startswith('_'))
return set([attr for attr in attrs if hasattr(getattr(obj, attr), '__call__')])
EXECUTABLE_MONGO_METHODS = get_methods(pymongo.collection.Collection)
EXECUTABLE_MONGO_METHODS.update(get_methods(pymongo.Connection))
EXECUTABLE_MONGO_METHODS.update(get_methods(pymongo))
def safe_mongocall(call):
""" Decorator for automatic handling of AutoReconnect-exceptions.
"""
def _safe_mongocall(*args, **kwargs):
for i in xrange(5):
for i in xrange(4):
try:
return call(*args, **kwargs)
except pymongo.errors.AutoReconnect:
print 'AutoReconnecting, try', i
print 'AutoReconnecting, try %d' % i
time.sleep(pow(2, i))
print 'Error: Failed operation!'
# Try one more time, but this time, if it fails, let the
# exception bubble up to the caller.
return call(*args, **kwargs)
return _safe_mongocall
......@@ -33,6 +41,14 @@ class Executable:
def __call__(self, *args, **kwargs):
return self.method(*args, **kwargs)
def __dir__(self):
return dir(self.method)
def __str__(self):
return self.method.__str__()
def __repr__(self):
return self.method.__repr__()
class MongoProxy:
""" Proxy for MongoDB connection.
......@@ -51,17 +67,22 @@ class MongoProxy:
named "key".
"""
return MongoProxy(getattr(self.conn, key))
item = self.conn[key]
if hasattr(item, '__call__'):
return MongoProxy(item)
return item
def __getattr__(self, key):
""" If key is the name of an executable method in the MongoDB connection,
for instance find or insert, wrap this method in Executable-class that
handles AutoReconnect-Exception.
"""
if key in EXECUTABLE_MONGO_METHODS:
return Executable(getattr(self.conn, key))
return self[key]
attr = getattr(self.conn, key)
if hasattr(attr, '__call__') and key in EXECUTABLE_MONGO_METHODS:
return Executable(attr)
return attr
def __call__(self, *args, **kwargs):
return self.conn(*args, **kwargs)
......@@ -69,6 +90,9 @@ class MongoProxy:
def __dir__(self):
return dir(self.conn)
def __str__(self):
return self.conn.__str__()
def __repr__(self):
return self.conn.__repr__()
......
from setuptools import setup, find_packages
LONG_DESCRIPTION = None
README_MARKDOWN = None
with open('README.md') as markdown_source:
README_MARKDOWN = markdown_source.read()
try:
import pandoc
pandoc.core.PANDOC_PATH = 'pandoc'
# Converts the README.md file to ReST, since PyPI uses ReST for formatting,
# This allows to have one canonical README file, being the README.md
doc = pandoc.Document()
doc.markdown = README_MARKDOWN
LONG_DESCRIPTION = doc.rst
except ImportError:
# If pandoc isn't installed, e.g. when downloading from pip,
# just use the regular README.
LONG_DESCRIPTION = README_MARKDOWN
setup(
name='MongoDBProxy',
py_modules=['mongodb_proxy'],
# version='',
description='Proxy around MongoDB connection that automatically handles AutoReconnect exceptions.',
# author='',
# author_email='',
long_description=LONG_DESCRIPTION,
# license='',
# classifiers=[
# ],
setup_requires=['pyandoc'],
install_requires=['pymongo'],
url="https://github.com/arngarden/MongoDBProxy"
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment