2015-02-23 04:29:18 +00:00
|
|
|
"""Django/PostgreSQL implementation of the Meteor DDP service."""
|
2015-04-08 06:14:22 +00:00
|
|
|
from __future__ import unicode_literals
|
2015-02-23 04:29:18 +00:00
|
|
|
import os.path
|
|
|
|
|
from pkg_resources import get_distribution, DistributionNotFound
|
2015-03-04 07:29:07 +00:00
|
|
|
from gevent.local import local
|
2015-04-08 06:14:22 +00:00
|
|
|
from django.utils.module_loading import autodiscover_modules
|
2015-03-04 07:29:07 +00:00
|
|
|
from dddp import alea
|
2015-02-23 04:29:18 +00:00
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
_dist = get_distribution('django-ddp')
|
|
|
|
|
if not __file__.startswith(os.path.join(_dist.location, 'django-ddp', '')):
|
|
|
|
|
# not installed, but there is another version that *is*
|
|
|
|
|
raise DistributionNotFound
|
|
|
|
|
except DistributionNotFound:
|
|
|
|
|
__version__ = 'development'
|
|
|
|
|
else:
|
|
|
|
|
__version__ = _dist.version
|
|
|
|
|
|
|
|
|
|
default_app_config = 'dddp.apps.DjangoDDPConfig'
|
2015-03-04 07:29:07 +00:00
|
|
|
|
2015-04-08 06:14:22 +00:00
|
|
|
|
|
|
|
|
class AlreadyRegistered(Exception):
|
|
|
|
|
|
|
|
|
|
"""Raised when registering over the top of an existing registration."""
|
|
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
2015-03-04 07:29:07 +00:00
|
|
|
class ThreadLocal(local):
|
2015-04-08 06:14:22 +00:00
|
|
|
|
|
|
|
|
"""Thread local storage for greenlet state."""
|
|
|
|
|
|
2015-03-04 07:29:07 +00:00
|
|
|
_init_done = False
|
|
|
|
|
|
|
|
|
|
def __init__(self, **default_factories):
|
2015-04-08 06:14:22 +00:00
|
|
|
"""Create new thread storage instance."""
|
2015-03-04 07:29:07 +00:00
|
|
|
if self._init_done:
|
|
|
|
|
raise SystemError('__init__ called too many times')
|
|
|
|
|
self._init_done = True
|
|
|
|
|
self._default_factories = default_factories
|
|
|
|
|
|
|
|
|
|
def __getattr__(self, name):
|
2015-04-08 06:14:22 +00:00
|
|
|
"""Create missing attributes using default factories."""
|
2015-03-04 07:29:07 +00:00
|
|
|
try:
|
|
|
|
|
factory = self._default_factories[name]
|
|
|
|
|
except KeyError:
|
2015-04-08 06:14:22 +00:00
|
|
|
raise AttributeError(name)
|
2015-03-04 07:29:07 +00:00
|
|
|
obj = factory()
|
|
|
|
|
setattr(self, name, obj)
|
|
|
|
|
return obj
|
|
|
|
|
|
|
|
|
|
def get(self, name, factory, *factory_args, **factory_kwargs):
|
2015-04-08 06:14:22 +00:00
|
|
|
"""Get attribute, creating if required using specified factory."""
|
2015-03-04 07:29:07 +00:00
|
|
|
if not hasattr(self, name):
|
|
|
|
|
return setattr(self, name, factory(*factory_args, **factory_kwargs))
|
|
|
|
|
return getattr(self, name)
|
|
|
|
|
|
2015-04-08 06:14:22 +00:00
|
|
|
|
2015-03-04 07:29:07 +00:00
|
|
|
THREAD_LOCAL = ThreadLocal(alea_random=alea.Alea)
|
2015-04-08 06:14:22 +00:00
|
|
|
METEOR_ID_CHARS = u'23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def meteor_random_id():
|
|
|
|
|
return THREAD_LOCAL.alea_random.random_string(17, METEOR_ID_CHARS)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def autodiscover():
|
|
|
|
|
from dddp.api import API
|
|
|
|
|
autodiscover_modules('ddp', register_to=API)
|
|
|
|
|
return API
|