Esempio n. 1
0
    def test_import_attr(self):
        math = import_module('math')

        # valid module and attr
        actual = import_attr(['invalid_one', 'math'], 'pi')
        self.assertEqual(actual, math.pi)

        # invalid modules
        self.assertRaises(ImportError, import_attr,
                          ['invalid_one', 'invalid_2'], 'foo')

        # invalid modules and attr
        invalid = import_attr(['invalid_one', 'invalid_2'], 'foo',
                              raise_error=False)
        self.assertIsNone(invalid)

        # invalid attr
        invalid = import_attr(['invalid_one', 'math'], '_invalid_',
                              raise_error=False)
        self.assertIsNone(invalid)

        # multiple attrs
        actual = import_attr(['invalid_one', 'math'], ['sin', 'cos'])
        self.assertEqual(actual, (math.sin, math.cos))

        # one invalid attr in a list
        self.assertRaises(AttributeError, import_attr,
                          ['invalid_one', 'math'],
                          ['sin', '_invalid_', 'cos'])

        actual = import_attr(['invalid_one', 'math'],
                             ['sin', '_invalid_', 'cos'], raise_error=False)
        self.assertEqual(actual, (math.sin, None, math.cos))
Esempio n. 2
0
    def test_import_attr(self):
        math = import_module('math')

        # valid module and attr
        actual = import_attr(['invalid_one', 'math'], 'pi')
        self.assertEqual(actual, math.pi)

        # invalid modules
        self.assertRaises(ImportError, import_attr,
                          ['invalid_one', 'invalid_2'], 'foo')

        # invalid modules and attr
        invalid = import_attr(['invalid_one', 'invalid_2'],
                              'foo',
                              raise_error=False)
        self.assertIsNone(invalid)

        # invalid attr
        invalid = import_attr(['invalid_one', 'math'],
                              '_invalid_',
                              raise_error=False)
        self.assertIsNone(invalid)

        # multiple attrs
        actual = import_attr(['invalid_one', 'math'], ['sin', 'cos'])
        self.assertEqual(actual, (math.sin, math.cos))

        # one invalid attr in a list
        self.assertRaises(AttributeError, import_attr, ['invalid_one', 'math'],
                          ['sin', '_invalid_', 'cos'])

        actual = import_attr(['invalid_one', 'math'],
                             ['sin', '_invalid_', 'cos'],
                             raise_error=False)
        self.assertEqual(actual, (math.sin, None, math.cos))
Esempio n. 3
0
# -*- coding: utf-8 -*-
'''\
:mod:`baph.sites.models` -- The "sites" framework SQLAlchemy models
===================================================================
'''

from baph.db.models import Model
from baph.db.orm import ORM
from baph.decorators.db import sqlalchemy_session
from baph.utils.importing import import_attr
RequestSite = import_attr(['django.contrib.sites.models'], 'RequestSite')
from sqlalchemy import Column, Integer, String, Unicode

__all__ = ['orm', 'RequestSite', 'DjangoSite']

orm = ORM.get()
SITE_CACHE = {}


class DjangoSite(orm.Base, Model):
    '''A port of :class:`django.contrib.sites.models.DjangoSite`.'''
    __tablename__ = 'django_site'

    id = Column(Integer, primary_key=True)
    '''The ID corresponding to the :setting:`SITE_ID` of the given site.'''
    domain = Column(String(255), nullable=False)
    '''The full, ASCII domain name of the site.'''
    name = Column(Unicode(64), nullable=False)
    '''The human-readable, English name of the site.'''
    def __unicode__(self):
        return self.domain
Esempio n. 4
0
# -*- coding: utf-8 -*-
'''\
:mod:`baph.decorators.json` -- JSON-related decorators
======================================================

.. moduleauthor:: Mark Lee <*****@*****.**>
.. moduleauthor:: JT Thibault <*****@*****.**>
'''

from __future__ import absolute_import

from baph.utils.importing import import_any_module, import_attr
render_to_response = import_attr(['coffin.shortcuts'], 'render_to_response')
from django.http import (
    HttpResponse, HttpResponseRedirect, HttpResponseForbidden)
RequestContext = import_attr(['django.template'], 'RequestContext')
from functools import wraps
json = import_any_module(['json', 'simplejson', 'django.utils.simplejson'])


def data_to_json_response(data, **kwargs):
    '''Takes any input and converts it to JSON, wraps it in an
    :class:`~django.http.HttpResponse`, and sets the proper MIME type.

    :param data: The data to be serialized.
    :param \*\*kwargs: extra keyword parameters given to :func:`json.dumps`.
    :rtype: :class:`~django.http.HttpResponse`
    '''
    return HttpResponse(json.dumps(data, **kwargs),
                        mimetype='application/json')
Esempio n. 5
0
# -*- coding: utf-8 -*-

from baph.utils.importing import import_attr
import os

__all__ = ['relpath']

relpath = import_attr(['os.path'], 'relpath', raise_error=False)
if not relpath:
    # Adapted from http://jimmyg.org/work/code/barenecessities/
    # License: MIT

    def relpath(path, start=os.path.curdir):
        '''Return a relative version of a path'''
        if not path:
            raise ValueError('no path specified')
        start_list = os.path.abspath(start).split(os.path.sep)
        path_list = os.path.abspath(path).split(os.path.sep)
        # Work out how much of the filepath is shared by start and path.
        i = len(os.path.commonprefix([start_list, path_list]))
        rel_list = [os.path.pardir] * (len(start_list) - i) + path_list[i:]
        if not rel_list:
            return os.path.curdir
        return os.path.join(*rel_list)
Esempio n. 6
0
# -*- coding: utf-8 -*-

import inspect

from baph.utils.importing import import_all_attrs, import_attr

globals().update(import_all_attrs(['django.test.client']))
Client = import_attr(['django.test.client'], 'Client')
login = import_attr(['baph.auth'], 'login')
StringIO = import_attr(['cStringIO', 'StringIO'], 'StringIO')

# monkeypatching Client to use baph.auth
exec inspect.getsource(Client)
Esempio n. 7
0
# -*- coding: utf-8 -*-

import inspect

from baph.db.shortcuts import get_object_or_404
from baph.utils.importing import import_attr
render_to_response = import_attr(['coffin.shortcuts'], 'render_to_response')
from coffin.template import RequestContext
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.views import (password_reset_complete,
                                       password_reset_done)
from django.core.urlresolvers import reverse

from django.http import Http404, HttpResponseRedirect
from django.utils.http import base36_to_int
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
import re
from uuid import UUID
# avoid shadowing
from . import login as auth_login, logout as auth_logout
from .forms import PasswordResetForm, SetPasswordForm
from .models import User

# fun with monkeypatching
exec inspect.getsource(password_reset_done)
exec inspect.getsource(password_reset_complete)
Esempio n. 8
0
# -*- coding: utf-8 -*-
'''\
:mod:`baph.decorators.json` -- JSON-related decorators
======================================================

.. moduleauthor:: Mark Lee <*****@*****.**>
.. moduleauthor:: JT Thibault <*****@*****.**>
'''

from __future__ import absolute_import

from baph.utils.importing import import_any_module, import_attr

render_to_response = import_attr(['coffin.shortcuts'], 'render_to_response')
from django.http import (HttpResponse, HttpResponseRedirect,
                         HttpResponseForbidden)

RequestContext = import_attr(['django.template'], 'RequestContext')
from functools import wraps

json = import_any_module(['json', 'simplejson', 'django.utils.simplejson'])


def data_to_json_response(data, **kwargs):
    '''Takes any input and converts it to JSON, wraps it in an
    :class:`~django.http.HttpResponse`, and sets the proper MIME type.

    :param data: The data to be serialized.
    :param \*\*kwargs: extra keyword parameters given to :func:`json.dumps`.
    :rtype: :class:`~django.http.HttpResponse`
    '''
Esempio n. 9
0
# -*- coding: utf-8 -*-

from baph.utils.importing import import_attr
base_render_to_response = import_attr(['coffin.shortcuts'],
                                      ['render_to_response'])
RequestContext = import_attr(['coffin.template'], 'RequestContext')
get_template, select_template = \
    import_attr(['coffin.template.loader'],
                ['get_template', 'select_template'])

__all__ = ['render_to_string', 'render_to_response']


def render_to_response(template_name, dictionary=None, request=None,
                       mimetype=None):
    '''Render a template into a response object. Meant to be compatible with
    the function in :mod:`djangojinja2` of the same name, distributed with
    Jinja2, as opposed to the shortcut from Django. For that, see
    :func:`coffin.shortcuts.render_to_response`.
    '''
    request_context = RequestContext(request) if request else None
    return base_render_to_response(template_name, dictionary=dictionary,
                                   context_instance=request_context,
                                   mimetype=mimetype)


def render_to_string(template_or_template_name, dictionary=None, request=None):
    '''Render a template into a string. Meant to be compatible with the
    function in :mod:`djangojinja2` of the same name, distributed with Jinja2,
    as opposed to the shortcut from Django. For that, see
    :func:`coffin.shortcuts.render_to_string`.
Esempio n. 10
0
# -*- coding: utf-8 -*-
'''\
:mod:`baph.auth.registration.models` -- Registration-related SQLAlchemy Models
==============================================================================
'''

from baph.auth.models import User, AUTH_USER_FIELD
from baph.db.models import Model
from baph.db.orm import ORM
from baph.decorators.db import sqlalchemy_session
from baph.utils.importing import import_attr
render_to_string = import_attr(['coffin.shortcuts'], 'render_to_string')
from datetime import datetime, timedelta
from django.conf import settings
from django.utils.hashcompat import sha_constructor
import random
import re
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import relation

orm = ORM.get()
SHA1_RE = re.compile(r'^[a-f0-9]{40}$')


class RegistrationProfile(orm.Base, Model):
    '''A simple profile which stores an activation key for use during user
    account registration.

    While it is possible to use this model as the value of the
    :setting:`AUTH_PROFILE_MODULE` setting, it's not recommended that you do
    so. This model's sole purpose is to store data temporarily during
Esempio n. 11
0
# -*- coding: utf-8 -*-

import inspect

from baph.db.shortcuts import get_object_or_404
from baph.utils.importing import import_attr

render_to_response = import_attr(["coffin.shortcuts"], "render_to_response")
from coffin.template import RequestContext
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.views import password_reset_complete, password_reset_done
from django.core.urlresolvers import reverse

from django.http import Http404, HttpResponseRedirect
from django.utils.http import base36_to_int
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
import re
from uuid import UUID

# avoid shadowing
from . import login as auth_login, logout as auth_logout
from .forms import PasswordResetForm, SetPasswordForm
from .models import User

# fun with monkeypatching
exec inspect.getsource(password_reset_done)
Esempio n. 12
0
# -*- coding: utf-8 -*-

from baph.utils.importing import import_attr

base_render_to_response = import_attr(["coffin.shortcuts"], ["render_to_response"])
RequestContext = import_attr(["coffin.template"], "RequestContext")
get_template, select_template = import_attr(["coffin.template.loader"], ["get_template", "select_template"])

__all__ = ["render_to_string", "render_to_response"]


def render_to_response(template_name, dictionary=None, request=None, mimetype=None):
    """Render a template into a response object. Meant to be compatible with
    the function in :mod:`djangojinja2` of the same name, distributed with
    Jinja2, as opposed to the shortcut from Django. For that, see
    :func:`coffin.shortcuts.render_to_response`.
    """
    request_context = RequestContext(request) if request else None
    return base_render_to_response(
        template_name, dictionary=dictionary, context_instance=request_context, mimetype=mimetype
    )


def render_to_string(template_or_template_name, dictionary=None, request=None):
    """Render a template into a string. Meant to be compatible with the
    function in :mod:`djangojinja2` of the same name, distributed with Jinja2,
    as opposed to the shortcut from Django. For that, see
    :func:`coffin.shortcuts.render_to_string`.
    """
    dictionary = dictionary or {}
    request_context = RequestContext(request) if request else None
Esempio n. 13
0
# -*- coding: utf-8 -*-

from baph.utils.importing import import_attr
from django.conf import settings
from django.core.handlers.wsgi import WSGIRequest
from django.http import SimpleCookie
from django.utils.encoding import smart_str
from django.utils.http import urlencode
from django.utils.itercompat import is_iterable
import mimetypes
import os
import re
import urllib
from urlparse import urlparse

StringIO = import_attr(['cStringIO', 'StringIO'], 'StringIO')

BOUNDARY = 'BoUnDaRyStRiNg'
MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')


class FakePayload(object):
    """
    A wrapper around StringIO that restricts what can be read since data from
    the network can't be seeked and cannot be read outside of its content
    length. This makes sure that views can't do anything under the test client
    that wouldn't work in Real Life.
    """
    def __init__(self, content):
        self.__content = StringIO(content)
Esempio n. 14
0
# -*- coding: utf-8 -*-

from baph.utils.importing import import_any_attr, import_attr
from django.conf import settings
from django.core import mail
from django.core.mail.backends import locmem
from django.core.urlresolvers import clear_url_caches
RequestFactory = \
    import_any_attr(['django.test.client', 'baph.test.requestfactory'],
                    'RequestFactory')
template_rendered = import_attr(['django.test.signals'], 'template_rendered')
DjangoTestCase = import_attr(['django.test.testcases'], 'TestCase')
from django.utils.translation import deactivate
from jinja2 import Template
from .client import Client

# Requires unittest2 or unittest in Python >= 2.7.
from django.utils.importlib import import_module
import sys
if sys.version_info < (2, 7):
    module = 'unittest2'
else:
    module = 'unittest'
mod = import_module(module)
TestCase = mod.TestCase

__all__ = ['BaseTestCase', 'Client', 'TestCase']


def instrumented_test_render(self, *args, **kwargs):
    template_rendered.send(sender=self,
Esempio n. 15
0
# -*- coding: utf-8 -*-
'''\
:mod:`baph.auth.registration.models` -- Registration-related SQLAlchemy Models
==============================================================================
'''

from baph.auth.models import User, AUTH_USER_FIELD
from baph.db.models import Model
from baph.db.orm import ORM
from baph.decorators.db import sqlalchemy_session
from baph.utils.importing import import_attr
render_to_string = import_attr(['coffin.shortcuts'], 'render_to_string')
from datetime import datetime, timedelta
from django.conf import settings
from django.utils.hashcompat import sha_constructor
import random
import re
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import relation

orm = ORM.get()
SHA1_RE = re.compile(r'^[a-f0-9]{40}$')


class RegistrationProfile(orm.Base, Model):
    '''A simple profile which stores an activation key for use during user
    account registration.

    While it is possible to use this model as the value of the
    :setting:`AUTH_PROFILE_MODULE` setting, it's not recommended that you do
    so. This model's sole purpose is to store data temporarily during
Esempio n. 16
0
def _get_country_divisions(country, div_type):
    country_code = country.strip(u'_')
    module = 'django.contrib.localflavor.%s.%s_%ss' % \
             (country, country_code, div_type)
    attr = '%s_CHOICES' % div_type.upper()
    return (country_code.upper(), import_attr([module], attr))
Esempio n. 17
0
# -*- coding: utf-8 -*-

import inspect

from baph.db.shortcuts import get_object_or_404
from baph.sites.models import get_current_site
from baph.utils.importing import import_attr
render_to_response = import_attr(['coffin.shortcuts'], 'render_to_response')
from coffin.template import RequestContext
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.views import (
    password_reset_complete, password_reset_done)
from django.core.urlresolvers import reverse

from django.http import Http404, HttpResponseRedirect
from django.utils.http import base36_to_int
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
import re
from uuid import UUID
# avoid shadowing
from . import login as auth_login, logout as auth_logout
from .forms import PasswordResetForm, SetPasswordForm
from .models import User

# fun with monkeypatching
exec inspect.getsource(password_reset_done)
Esempio n. 18
0
The default hash algorithm used to set passwords with. Defaults to ``sha1``.
'''
from datetime import datetime
import hashlib
from oauth import oauth
import random
import urllib
import uuid

from baph.utils.importing import import_attr
from django.conf import settings
(AnonymousUser, check_password, SiteProfileNotAvailable,
 UNUSABLE_PASSWORD) = \
    import_attr(['django.contrib.auth.models'],
                ['AnonymousUser', 'check_password',
                 'SiteProfileNotAvailable', 'UNUSABLE_PASSWORD'])
from django.core.exceptions import ImproperlyConfigured
try:
    # global variable needed for django 1.3
    from django.utils.crypto import constant_time_compare
except:
    pass
from django.utils.encoding import smart_str
from django.utils.importlib import import_module
from django.utils.translation import ugettext as _
from sqlalchemy import *
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declared_attr, clsregistry
from sqlalchemy.ext.declarative.base import _add_attribute
from sqlalchemy.orm import synonym, relationship, backref, RelationshipProperty
Esempio n. 19
0
# -*- coding: utf-8 -*-

from baph.utils.importing import import_attr
from django.conf import settings
from django.core.handlers.wsgi import WSGIRequest
from django.http import SimpleCookie
from django.utils.encoding import smart_str
from django.utils.http import urlencode
from django.utils.itercompat import is_iterable
import mimetypes
import os
import re
import urllib
from urlparse import urlparse

StringIO = import_attr(['cStringIO', 'StringIO'], 'StringIO')

BOUNDARY = 'BoUnDaRyStRiNg'
MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')


class FakePayload(object):
    """
    A wrapper around StringIO that restricts what can be read since data from
    the network can't be seeked and cannot be read outside of its content
    length. This makes sure that views can't do anything under the test client
    that wouldn't work in Real Life.
    """
    def __init__(self, content):
        self.__content = StringIO(content)
Esempio n. 20
0
# -*- coding: utf-8 -*-
'''Views which allow users to create and activate accounts.'''

from baph.utils.importing import import_attr
import inspect
(activate, register) = \
    import_attr(['registration.views'], ['activate', 'register'])

# replace the Django imports, per
# http://www.davidcramer.net/code/486/jinja2-and-django-registration.html
(redirect, render_to_response) = \
    import_attr(['coffin.shortcuts'], ['redirect', 'render_to_response'])
RequestContext = import_attr(['coffin.template'], 'RequestContext')
get_backend = import_attr(['registration.backends'], 'get_backend')

exec inspect.getsource(activate)
exec inspect.getsource(register)
Esempio n. 21
0
def _get_country_divisions(country, div_type):
    country_code = country.strip(u'_')
    module = 'django.contrib.localflavor.%s.%s_%ss' % \
             (country, country_code, div_type)
    attr = '%s_CHOICES' % div_type.upper()
    return (country_code.upper(), import_attr([module], attr))
Esempio n. 22
0
# -*- coding: utf-8 -*-

from baph.auth.models import User
from baph.db.models import Model
from baph.db.orm import ORM
from baph.db.types import UUID
from baph.decorators.db import sqlalchemy_session
from baph.utils.importing import import_attr
from datetime import datetime
(CONSUMER_STATES, generate_random, KEY_SIZE, SECRET_SIZE, DjangoUser,
 VERIFIER_SIZE) = \
    import_attr(['piston.models'],
                ['CONSUMER_STATES', 'generate_random', 'KEY_SIZE',
                 'SECRET_SIZE', 'User', 'VERIFIER_SIZE'])
from sqlalchemy import (Boolean, Column, DateTime, ForeignKey, Integer, String,
                        Unicode, UnicodeText)
from sqlalchemy.orm import relation, validates
import urllib
import urlparse
import uuid

orm = ORM.get()


class Nonce(orm.Base, Model):
    '''Nonces for OAuth.'''
    __tablename__ = 'oauth_nonces'

    id = Column(UUID, primary_key=True, default=uuid.uuid4)
    token_key = Column(String(KEY_SIZE), nullable=False)
    consumer_key = Column(String(KEY_SIZE), nullable=False)
Esempio n. 23
0
# -*- coding: utf-8 -*-
'''\
:mod:`baph.sites.models` -- The "sites" framework SQLAlchemy models
===================================================================
'''

from baph.db.models import Model
from baph.db.orm import ORM
from baph.decorators.db import sqlalchemy_session
from baph.utils.importing import import_attr
RequestSite = import_attr(['django.contrib.sites.models'], 'RequestSite')
from sqlalchemy import Column, Integer, String, Unicode

__all__ = ['orm', 'RequestSite', 'DjangoSite']

orm = ORM.get()
SITE_CACHE = {}


class DjangoSite(orm.Base, Model):
    '''A port of :class:`django.contrib.sites.models.DjangoSite`.'''
    __tablename__ = 'django_site'

    id = Column(Integer, primary_key=True)
    '''The ID corresponding to the :setting:`SITE_ID` of the given site.'''
    domain = Column(String(255), nullable=False)
    '''The full, ASCII domain name of the site.'''
    name = Column(Unicode(64), nullable=False)
    '''The human-readable, English name of the site.'''

    def __unicode__(self):
Esempio n. 24
0
# -*- coding: utf-8 -*-

from baph.auth.models import User
from baph.db.models import Model
from baph.db.orm import ORM
from baph.db.types import UUID
from baph.decorators.db import sqlalchemy_session
from baph.utils.importing import import_attr
from datetime import datetime
(CONSUMER_STATES, generate_random, KEY_SIZE, SECRET_SIZE, DjangoUser,
 VERIFIER_SIZE) = \
    import_attr(['piston.models'],
                ['CONSUMER_STATES', 'generate_random', 'KEY_SIZE',
                 'SECRET_SIZE', 'User', 'VERIFIER_SIZE'])
from sqlalchemy import (
    Boolean, Column, DateTime, ForeignKey, Integer, String, Unicode,
    UnicodeText)
from sqlalchemy.orm import relation, validates
import urllib
import urlparse
import uuid

orm = ORM.get()


class Nonce(orm.Base, Model):
    '''Nonces for OAuth.'''
    __tablename__ = 'oauth_nonces'

    id = Column(UUID, primary_key=True, default=uuid.uuid4)
    token_key = Column(String(KEY_SIZE), nullable=False)
Esempio n. 25
0
The default hash algorithm used to set passwords with. Defaults to ``sha1``.
'''
from datetime import datetime
import hashlib
from oauth import oauth
import random
import urllib
import uuid

from baph.utils.importing import import_attr
from django.conf import settings
(AnonymousUser, check_password, SiteProfileNotAvailable,
 UNUSABLE_PASSWORD) = \
    import_attr(['django.contrib.auth.models'],
                ['AnonymousUser', 'check_password',
                 'SiteProfileNotAvailable', 'UNUSABLE_PASSWORD'])
from django.core.exceptions import ImproperlyConfigured
try:
    # global variable needed for django 1.3
    from django.utils.crypto import constant_time_compare
except:
    pass
from django.utils.encoding import smart_str
from django.utils.importlib import import_module
from django.utils.translation import ugettext as _
from sqlalchemy import *
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declared_attr, clsregistry
from sqlalchemy.ext.declarative.base import _add_attribute
from sqlalchemy.orm import synonym, relationship, backref, RelationshipProperty
Esempio n. 26
0
# -*- coding: utf-8 -*-
"""\
:mod:`baph.auth.registration.models` -- Registration-related SQLAlchemy Models
==============================================================================
"""

from baph.auth.models import User, AUTH_USER_FIELD
from baph.db.models import Model
from baph.db.orm import ORM
from baph.decorators.db import sqlalchemy_session
from baph.utils.importing import import_attr

render_to_string = import_attr(["coffin.shortcuts"], "render_to_string")
from datetime import datetime, timedelta
from django.conf import settings
from django.utils.hashcompat import sha_constructor
import random
import re
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import relation

orm = ORM.get()
SHA1_RE = re.compile(r"^[a-f0-9]{40}$")


class RegistrationProfile(orm.Base, Model):
    """A simple profile which stores an activation key for use during user
    account registration.

    While it is possible to use this model as the value of the
    :setting:`AUTH_PROFILE_MODULE` setting, it's not recommended that you do