# Path: boardinghouse/middleware.py
# def change_schema(request, schema):
#     """
#     Change the schema for the current request's session.
# 
#     Note this does not actually _activate_ the schema, it only stores
#     the schema name in the current request's session.
#     """
#     session = request.session
#     user = request.user
# 
#     # Allow clearing out the current schema.
#     if not schema:
#         session.pop('schema', None)
#         return
# 
#     # Unauthenticated users may not select a schema.
#     # Should this be selectable?
#     if not user.is_authenticated:
#         session.pop('schema', None)
#         raise Forbidden()
# 
#     # Make sure we have a schema name, not a model representing a schema.
#     # This allows us to use a relation for User.visible_schemata, that contains
#     # a relationship to schema objects, rather than a queryset of actual schema
#     # objects.
#     if hasattr(schema, 'schema'):
#         schema = schema.schema
# 
#     # Don't allow anyone, even superusers, to select the template schema.
#     if schema == settings.TEMPLATE_SCHEMA:
#         raise TemplateSchemaActivation()
# 
#     # If the schema is already set to this name for this session, then
#     # we can just exit early, potentially saving some db access.
#     if schema == session.get('schema'):
#         return
# 
#     # Valid schema providers should listen for this signal, and do one of three
#     # things: return an object that has a 'schema' attribute, return None, or
#     # raise an exception. Returning an object with an attribute of 'schema' will
#     # cause no further handlers to run. Returning None or False will cause the next
#     # handler to attempt to find a valid schema, and raising an exception will
#     # bubble up the call stack.
#     for handler, response in session_requesting_schema_change.send(
#         sender=request,
#         schema=schema,
#         user=user,
#         session=session
#     ):
#         if response:
#             if hasattr(response, 'schema'):
#                 session.update({
#                     'schema': response.schema,
#                     'schema_name': getattr(response, 'name', None),
#                 })
#             if isinstance(response, dict) and 'schema' in response:
#                 session.update({
#                     'schema': response['schema'],
#                     'schema_name': response.get('name'),
#                 })
#             break
#     else:
#         # If no receivers stepped forwards to say they could handle it, that means
#         # this user/session is not permitted to change to that schema.
#         raise Forbidden()
#     # Allow 3rd-party applications to listen for a change, and act upon
#     # it accordingly.
#     session_schema_changed.send(
#         sender=request,
#         schema=schema,
#         user=user,
#         session=session,
#     )
# 
# Path: boardinghouse/models.py
# class Schema(AbstractSchema):
#     """
#     The default schema model.
# 
#     Unless you set `settings.BOARDINGHOUSE_SCHEMA_MODEL`, this model will
#     be used for storing the schema objects.
#     """
#     users = models.ManyToManyField(
#         settings.AUTH_USER_MODEL,
#         blank=True, related_name='schemata',
#         help_text=_(u'Which users may access data from this schema.')
#     )
# 
#     class Meta:
#         app_label = 'boardinghouse'
#         verbose_name_plural = 'schemata'
#         swappable = 'BOARDINGHOUSE_SCHEMA_MODEL'
# 
# Path: boardinghouse/schema.py
# LOGGER = logging.getLogger(__name__)
# REQUIRED_SHARED_MODELS = [
#     'auth.user',
#     'auth.permission',
#     'auth.group',
#     'boardinghouse.schema',
#     'sites.site',
#     'sessions.session',
#     'contenttypes.contenttype',
#     'admin.logentry',
#     'migrations.migration',
#     # In the case these are not the default values.
#     lazy(lambda: settings.BOARDINGHOUSE_SCHEMA_MODEL.lower())(),
#     lazy(lambda: settings.AUTH_USER_MODEL.lower())(),
# ]
# REQUIRED_SHARED_TABLES = [
#     'django_migrations',
# ]
# def get_schema_model():
# def _get_search_path():
# def _set_search_path(search_path):
# def _schema_exists(schema_name, cursor=None):
# def get_active_schema_name():
# def get_active_schema():
# def get_active_schemata():
# def _get_schema(schema_name):
# def activate_schema(schema_name):
# def activate_template_schema():
# def get_template_schema():
# def deactivate_schema(schema=None):
# def _is_join_model(model):
# def is_shared_model(model):
# def _get_models(apps, stack):
# def _get_join_model(table, table_map):
# def is_shared_table(table, apps=apps):
# def _table_exists(table_name, schema=None):
# def _schema_table_exists():
# 
# Path: boardinghouse/signals.py



    from unittest.mock import Mock, call
    from mock import Mock, call
from django.contrib.auth.models import User, Group, Permission
from django.http import HttpRequest
from django.test import TestCase
from boardinghouse.middleware import change_schema
from boardinghouse.models import Schema
from boardinghouse.schema import TemplateSchemaActivation
from boardinghouse.signals import (
    session_requesting_schema_change, schema_aware_operation, session_schema_changed,
    find_schema,
)

    def test_session_requesting_schema_change_may_return_dict(self):
        DATA = {
            'schema': '_spam',
            'name': 'eggs'
        }

        def pre_handler(**kwargs):
            return DATA

        post_handler = Mock()
        request = Mock(spec=HttpRequest,
                       user=Mock(wraps=User(), schemata=Mock()),
                       session={})

        session_requesting_schema_change.connect(pre_handler, sender=None)
        session_schema_changed.connect(post_handler, sender=None)

        change_schema(request, schema=Schema(**DATA))

        session_requesting_schema_change.disconnect(pre_handler, sender=None)
        session_schema_changed.disconnect(post_handler, sender=None)

        self.assertEqual(request.session, {
            'schema': '_spam',
            'schema_name': 'eggs'
        })
        self.assertEqual(1, post_handler.call_count)

    def test_session_schema_change_clears_permissions_caches(self):

# Path: boardinghouse/middleware.py
# def change_schema(request, schema):
#     """
#     Change the schema for the current request's session.
# 
#     Note this does not actually _activate_ the schema, it only stores
#     the schema name in the current request's session.
#     """
#     session = request.session
#     user = request.user
# 
#     # Allow clearing out the current schema.
#     if not schema:
#         session.pop('schema', None)
#         return
# 
#     # Unauthenticated users may not select a schema.
#     # Should this be selectable?
#     if not user.is_authenticated:
#         session.pop('schema', None)
#         raise Forbidden()
# 
#     # Make sure we have a schema name, not a model representing a schema.
#     # This allows us to use a relation for User.visible_schemata, that contains
#     # a relationship to schema objects, rather than a queryset of actual schema
#     # objects.
#     if hasattr(schema, 'schema'):
#         schema = schema.schema
# 
#     # Don't allow anyone, even superusers, to select the template schema.
#     if schema == settings.TEMPLATE_SCHEMA:
#         raise TemplateSchemaActivation()
# 
#     # If the schema is already set to this name for this session, then
#     # we can just exit early, potentially saving some db access.
#     if schema == session.get('schema'):
#         return
# 
#     # Valid schema providers should listen for this signal, and do one of three
#     # things: return an object that has a 'schema' attribute, return None, or
#     # raise an exception. Returning an object with an attribute of 'schema' will
#     # cause no further handlers to run. Returning None or False will cause the next
#     # handler to attempt to find a valid schema, and raising an exception will
#     # bubble up the call stack.
#     for handler, response in session_requesting_schema_change.send(
#         sender=request,
#         schema=schema,
#         user=user,
#         session=session
#     ):
#         if response:
#             if hasattr(response, 'schema'):
#                 session.update({
#                     'schema': response.schema,
#                     'schema_name': getattr(response, 'name', None),
#                 })
#             if isinstance(response, dict) and 'schema' in response:
#                 session.update({
#                     'schema': response['schema'],
#                     'schema_name': response.get('name'),
#                 })
#             break
#     else:
#         # If no receivers stepped forwards to say they could handle it, that means
#         # this user/session is not permitted to change to that schema.
#         raise Forbidden()
#     # Allow 3rd-party applications to listen for a change, and act upon
#     # it accordingly.
#     session_schema_changed.send(
#         sender=request,
#         schema=schema,
#         user=user,
#         session=session,
#     )
# 
# Path: boardinghouse/models.py
# class Schema(AbstractSchema):
#     """
#     The default schema model.
# 
#     Unless you set `settings.BOARDINGHOUSE_SCHEMA_MODEL`, this model will
#     be used for storing the schema objects.
#     """
#     users = models.ManyToManyField(
#         settings.AUTH_USER_MODEL,
#         blank=True, related_name='schemata',
#         help_text=_(u'Which users may access data from this schema.')
#     )
# 
#     class Meta:
#         app_label = 'boardinghouse'
#         verbose_name_plural = 'schemata'
#         swappable = 'BOARDINGHOUSE_SCHEMA_MODEL'
# 
# Path: boardinghouse/schema.py
# LOGGER = logging.getLogger(__name__)
# REQUIRED_SHARED_MODELS = [
#     'auth.user',
#     'auth.permission',
#     'auth.group',
#     'boardinghouse.schema',
#     'sites.site',
#     'sessions.session',
#     'contenttypes.contenttype',
#     'admin.logentry',
#     'migrations.migration',
#     # In the case these are not the default values.
#     lazy(lambda: settings.BOARDINGHOUSE_SCHEMA_MODEL.lower())(),
#     lazy(lambda: settings.AUTH_USER_MODEL.lower())(),
# ]
# REQUIRED_SHARED_TABLES = [
#     'django_migrations',
# ]
# def get_schema_model():
# def _get_search_path():
# def _set_search_path(search_path):
# def _schema_exists(schema_name, cursor=None):
# def get_active_schema_name():
# def get_active_schema():
# def get_active_schemata():
# def _get_schema(schema_name):
# def activate_schema(schema_name):
# def activate_template_schema():
# def get_template_schema():
# def deactivate_schema(schema=None):
# def _is_join_model(model):
# def is_shared_model(model):
# def _get_models(apps, stack):
# def _get_join_model(table, table_map):
# def is_shared_table(table, apps=apps):
# def _table_exists(table_name, schema=None):
# def _schema_table_exists():
# 
# Path: boardinghouse/signals.py



# Path: tests/tests/test_signals.py
    from unittest.mock import Mock, call
    from mock import Mock, call
from django.contrib.auth.models import User, Group, Permission
from django.http import HttpRequest
from django.test import TestCase
from boardinghouse.middleware import change_schema
from boardinghouse.models import Schema
from boardinghouse.schema import TemplateSchemaActivation
from boardinghouse.signals import (
    session_requesting_schema_change, schema_aware_operation, session_schema_changed,
    find_schema,
)


    def test_session_requesting_schema_change_may_return_dict(self):
        DATA = {
            'schema': '_spam',
            'name': 'eggs'
        }

        def pre_handler(**kwargs):
            return DATA

        post_handler = Mock()
        request = Mock(spec=HttpRequest,
                       user=Mock(wraps=User(), schemata=Mock()),
                       session={})

        session_requesting_schema_change.connect(pre_handler, sender=None)
        session_schema_changed.connect(post_handler, sender=None)

        change_schema(request, schema=Schema(**DATA))

        session_requesting_schema_change.disconnect(pre_handler, sender=None)
        session_schema_changed.disconnect(post_handler, sender=None)

        self.assertEqual(request.session, {
            'schema': '_spam',
            'schema_name': 'eggs'
        })
        self.assertEqual(1, post_handler.call_count)

    def test_session_schema_change_clears_permissions_caches(self):

        schema = Schema.objects.mass_create('a')[0]