# Path: jacquard/service/wsgi.py
# def get_wsgi_app(config):
#     """Get the main WSGI handler, by config."""
#     endpoints = _get_endpoints(config)
#     url_map = _get_url_map(endpoints)
# 
#     def application(environ, start_response):
#         """WSGI callable."""
#         try:
#             urls = url_map.bind_to_environ(environ)
# 
#             LOGGER.debug(
#                 "%s %s", environ["REQUEST_METHOD"], environ["PATH_INFO"] or "/"
#             )
# 
#             def reverse(name, **kwargs):
#                 endpoint = endpoints[name]
#                 return urls.build(endpoint, values=kwargs)
# 
#             request = werkzeug.wrappers.Request(environ)
# 
#             endpoint, kwargs = urls.match()
# 
#             endpoint = endpoint.bind(reverse=reverse, request=request)
# 
#             response = endpoint.handle(**kwargs)
# 
#             encoded_response = (json.dumps(response) + "\n").encode("utf-8")
#             start_response(
#                 "200 OK",
#                 [
#                     ("Content-Type", "application/json"),
#                     ("Content-Length", str(len(encoded_response))),
#                 ],
#             )
#             return [encoded_response]
#         except werkzeug.exceptions.HTTPException as e:
#             return e(environ, start_response)
# 
#     return application
# 
# Path: jacquard/storage/dummy.py
# class DummyStore(StorageEngine):
#     """Dummy, in-memory storage engine."""
# 
#     def __init__(self, connection_string, *, data=None):
#         """
#         Make it so.
# 
#         The connection string is ignored. If the magic keyword argument `data`
#         is provided it is used for the initial data - very handy for unit
#         tests!
#         """
#         if data is not None:
#             self.data = {key: json.dumps(value) for key, value in data.items()}
#         else:
#             self.data = {}
#         self.lock = threading.Lock()
# 
#     def __getitem__(self, key):
#         """Direct item access. This is for test usage."""
#         return json.loads(self.data.get(key, "null"))
# 
#     def begin(self):
#         """Begin transaction."""
#         self.lock.acquire()
# 
#     def commit(self, changes, deletions):
#         """Commit transaction."""
#         self.data.update(changes)
#         for deletion in deletions:
#             del self.data[deletion]
#         self.lock.release()
# 
#     def rollback(self):
#         """Roll back transaction."""
#         self.lock.release()
# 
#     def keys(self):
#         """All keys."""
#         return self.data.keys()
# 
#     def get(self, key):
#         """Get value."""
#         return self.data.get(key)
# 
# Path: jacquard/directory/base.py
# class Directory(metaclass=abc.ABCMeta):
#     def __init__(self, **kwargs):
#     def from_configuration(cls, config, options):
#     def lookup(self, user_id):
# 
# Path: jacquard/directory/dummy.py
# class DummyDirectory(Directory):
#     """Dummy user directory."""
# 
#     def __init__(self, users=()):
#         """
#         Initialise.
# 
#         If `users` is given it should be an iterable of `UserEntry` instances.
#         This is likely only to be useful in tests, given that one cannot
#         construct `UserEntry` instances in a config file.
#         """
#         self.users = {str(x.id): x for x in users}
# 
#     def lookup(self, user_id):
#         """Look up user by ID."""
#         return self.users.get(str(user_id))


import json
import datetime
import dateutil.tz
import werkzeug.test
from unittest.mock import Mock
from werkzeug.datastructures import MultiDict
from jacquard.service import get_wsgi_app
from jacquard.storage.dummy import DummyStore
from jacquard.directory.base import UserEntry
from jacquard.directory.dummy import DummyDirectory




def get_test_client():
    config = Mock()
    config.storage = DummyStore(
        "",
        data={
            "defaults": {"pony": "gravity"},
            "active-experiments": ["foo"],
            "experiments/foo": {
                "id": "foo",
                "constraints": {"excluded_tags": ["excluded"]},
                "branches": [{"id": "bar", "settings": {"pony": "horse"}}],
            },
        },
    )
    now = datetime.datetime.now(dateutil.tz.tzutc())
    config.directory = DummyDirectory(
        users=(
            UserEntry(id=1, join_date=now, tags=("excluded",)),

# Path: jacquard/service/wsgi.py
# def get_wsgi_app(config):
#     """Get the main WSGI handler, by config."""
#     endpoints = _get_endpoints(config)
#     url_map = _get_url_map(endpoints)
# 
#     def application(environ, start_response):
#         """WSGI callable."""
#         try:
#             urls = url_map.bind_to_environ(environ)
# 
#             LOGGER.debug(
#                 "%s %s", environ["REQUEST_METHOD"], environ["PATH_INFO"] or "/"
#             )
# 
#             def reverse(name, **kwargs):
#                 endpoint = endpoints[name]
#                 return urls.build(endpoint, values=kwargs)
# 
#             request = werkzeug.wrappers.Request(environ)
# 
#             endpoint, kwargs = urls.match()
# 
#             endpoint = endpoint.bind(reverse=reverse, request=request)
# 
#             response = endpoint.handle(**kwargs)
# 
#             encoded_response = (json.dumps(response) + "\n").encode("utf-8")
#             start_response(
#                 "200 OK",
#                 [
#                     ("Content-Type", "application/json"),
#                     ("Content-Length", str(len(encoded_response))),
#                 ],
#             )
#             return [encoded_response]
#         except werkzeug.exceptions.HTTPException as e:
#             return e(environ, start_response)
# 
#     return application
# 
# Path: jacquard/storage/dummy.py
# class DummyStore(StorageEngine):
#     """Dummy, in-memory storage engine."""
# 
#     def __init__(self, connection_string, *, data=None):
#         """
#         Make it so.
# 
#         The connection string is ignored. If the magic keyword argument `data`
#         is provided it is used for the initial data - very handy for unit
#         tests!
#         """
#         if data is not None:
#             self.data = {key: json.dumps(value) for key, value in data.items()}
#         else:
#             self.data = {}
#         self.lock = threading.Lock()
# 
#     def __getitem__(self, key):
#         """Direct item access. This is for test usage."""
#         return json.loads(self.data.get(key, "null"))
# 
#     def begin(self):
#         """Begin transaction."""
#         self.lock.acquire()
# 
#     def commit(self, changes, deletions):
#         """Commit transaction."""
#         self.data.update(changes)
#         for deletion in deletions:
#             del self.data[deletion]
#         self.lock.release()
# 
#     def rollback(self):
#         """Roll back transaction."""
#         self.lock.release()
# 
#     def keys(self):
#         """All keys."""
#         return self.data.keys()
# 
#     def get(self, key):
#         """Get value."""
#         return self.data.get(key)
# 
# Path: jacquard/directory/base.py
# class Directory(metaclass=abc.ABCMeta):
#     def __init__(self, **kwargs):
#     def from_configuration(cls, config, options):
#     def lookup(self, user_id):
# 
# Path: jacquard/directory/dummy.py
# class DummyDirectory(Directory):
#     """Dummy user directory."""
# 
#     def __init__(self, users=()):
#         """
#         Initialise.
# 
#         If `users` is given it should be an iterable of `UserEntry` instances.
#         This is likely only to be useful in tests, given that one cannot
#         construct `UserEntry` instances in a config file.
#         """
#         self.users = {str(x.id): x for x in users}
# 
#     def lookup(self, user_id):
#         """Look up user by ID."""
#         return self.users.get(str(user_id))


# Path: jacquard/service/tests/test_http.py
import json
import datetime
import dateutil.tz
import werkzeug.test
from unittest.mock import Mock
from werkzeug.datastructures import MultiDict
from jacquard.service import get_wsgi_app
from jacquard.storage.dummy import DummyStore
from jacquard.directory.base import UserEntry
from jacquard.directory.dummy import DummyDirectory





def get_test_client():
    config = Mock()
    config.storage = DummyStore(
        "",
        data={
            "defaults": {"pony": "gravity"},
            "active-experiments": ["foo"],
            "experiments/foo": {
                "id": "foo",
                "constraints": {"excluded_tags": ["excluded"]},
                "branches": [{"id": "bar", "settings": {"pony": "horse"}}],
            },
        },
    )
    now = datetime.datetime.now(dateutil.tz.tzutc())
    config.directory = DummyDirectory(
        users=(
            UserEntry(id=1, join_date=now, tags=("excluded",)),

            UserEntry(id=2, join_date=now, tags=("excluded",)),