# Path: doctor/flask.py
# def create_routes(routes: Tuple[Route]) -> List[Tuple[str, Resource]]:
#     """A thin wrapper around create_routes that passes in flask specific values.
# 
#     :param routes: A tuple containing the route and another tuple with
#         all http methods allowed for the route.
#     :returns: A list of tuples containing the route and generated handler.
#     """
#     return doctor_create_routes(
#         routes, handle_http, default_base_handler_class=Resource)
# 
# Path: doctor/routing.py
# def get(func: Callable, allowed_exceptions: List = None,
#         title: str = None, req_obj_type: Callable = None) -> HTTPMethod:
#     """Returns a HTTPMethod instance to create a GET route.
# 
#     :see: :class:`~doctor.routing.HTTPMethod`
#     """
#     return HTTPMethod('get', func, allowed_exceptions=allowed_exceptions,
#                       title=title, req_obj_type=req_obj_type)
# 
# class Route(object):
# 
#     """Represents a route.
# 
#     :param route: The route path, e.g. `r'^/foo/<int:foo_id>/?$'`
#     :param methods: A tuple of defined HTTPMethods for the route.
#     :param heading: An optional heading that this route should be grouped
#         under in the api documentation.
#     :param base_handler_class: The base handler class to use.
#     :param handler_name: The name that should be given to the handler class.
#     :param before: A function to be called before the logic function associated
#         with the route.
#     :param after: A function to be called after the logic function associated
#         with the route.
#     """
#     def __init__(self, route: str, methods: Sequence[HTTPMethod],
#                  heading: str = 'API', base_handler_class = None,
#                  handler_name: str = None, before: Callable = None,
#                  after: Callable = None):
#         self.after = after
#         self.base_handler_class = base_handler_class
#         self.before = before
#         self.handler_name = handler_name
#         self.heading = heading
#         self.methods = methods
#         self.route = route
# 
# Path: test/base.py
# class FlaskTestCase(flask_testing.TestCase):
# 
#     """
#     This test case base class is used for integration tests with flask
#     and doctor.
#     """
# 
#     #: Displays the full diff on failure.
#     maxDiff = None
# 
#     def shortDescription(self):
#         # Do not show first line of the docstring as a test description
#         return None
# 
#     def get_routes(self):
#         """Gets the routes for the app.
# 
#         This should return a tuple of tuples.  Each tuple contains the
#         route as a string and the instnace of a resource to route to.  e.g.
# 
#         (
#             ('/some/url/', doctor.router.Handler1),
#         )
# 
#         This method can be overridden in subclasses to change the routes and
#         add new ones.
# 
#         :returns: The tuple described above.
#         """
#         def logic_func(item_id: ItemId, name: Name=None):
#             return (item_id, name)
# 
#         routes = (
#             Route('/test/', methods=(
#                 get(logic_func),), heading='Test'),
#         )
#         return create_routes(routes)
# 
#     def create_app(self):
#         """This method creates the flask app.
# 
#         This is required to be implemented by flask_restful.
# 
#         :returns: Flask application instance.
#         """
#         app = Flask('test')
#         app.config['TESTING'] = True
# 
#         api = flask_restful.Api(app)
#         for url, handler in self.get_routes():
#             api.add_resource(handler, url)
# 
#         return api.app
# 
# Path: test/types.py
# def parse_comma_separated_str(value):
# class ExampleObject(Object):
# class FooInstance(Object):
# class AgeOrColor(UnionType):
# class ColorsOrObject(UnionType):


from functools import wraps
from doctor.flask import create_routes
from doctor.routing import get, Route
from .base import FlaskTestCase
from .types import ItemId, Name
import mock
def logic_func(pos_arg, item_id: ItemId, name: Name=None):
    return {
        'item_id': item_id,
        'name': name,
        'pos_arg': pos_arg,
    }


class RouterIntegrationTestCase(FlaskTestCase):

    before = mock.Mock()
    after = mock.Mock()

    def get_routes(self):
        routes = (
            Route('/test/', methods=[
                get(logic_func)], heading='Test', before=self.before,
                after=self.after),
        )
        return create_routes(routes)

    def test_decorated_logic_func_passes_arg_to_func(self):
        """
        This test verifies everything works properly if our logic function
        is decorated and the decorator passes an extra positional argument to
        it.  This was broken in v1.1.3 as it would cause a 400 saying that
        `pos_arg` is required as a request parameter since it was not taking
        into accout `omit_args` and just determining required arguments based
        on the function signature's non-keyword arguments.
        """

# Path: doctor/flask.py
# def create_routes(routes: Tuple[Route]) -> List[Tuple[str, Resource]]:
#     """A thin wrapper around create_routes that passes in flask specific values.
# 
#     :param routes: A tuple containing the route and another tuple with
#         all http methods allowed for the route.
#     :returns: A list of tuples containing the route and generated handler.
#     """
#     return doctor_create_routes(
#         routes, handle_http, default_base_handler_class=Resource)
# 
# Path: doctor/routing.py
# def get(func: Callable, allowed_exceptions: List = None,
#         title: str = None, req_obj_type: Callable = None) -> HTTPMethod:
#     """Returns a HTTPMethod instance to create a GET route.
# 
#     :see: :class:`~doctor.routing.HTTPMethod`
#     """
#     return HTTPMethod('get', func, allowed_exceptions=allowed_exceptions,
#                       title=title, req_obj_type=req_obj_type)
# 
# class Route(object):
# 
#     """Represents a route.
# 
#     :param route: The route path, e.g. `r'^/foo/<int:foo_id>/?$'`
#     :param methods: A tuple of defined HTTPMethods for the route.
#     :param heading: An optional heading that this route should be grouped
#         under in the api documentation.
#     :param base_handler_class: The base handler class to use.
#     :param handler_name: The name that should be given to the handler class.
#     :param before: A function to be called before the logic function associated
#         with the route.
#     :param after: A function to be called after the logic function associated
#         with the route.
#     """
#     def __init__(self, route: str, methods: Sequence[HTTPMethod],
#                  heading: str = 'API', base_handler_class = None,
#                  handler_name: str = None, before: Callable = None,
#                  after: Callable = None):
#         self.after = after
#         self.base_handler_class = base_handler_class
#         self.before = before
#         self.handler_name = handler_name
#         self.heading = heading
#         self.methods = methods
#         self.route = route
# 
# Path: test/base.py
# class FlaskTestCase(flask_testing.TestCase):
# 
#     """
#     This test case base class is used for integration tests with flask
#     and doctor.
#     """
# 
#     #: Displays the full diff on failure.
#     maxDiff = None
# 
#     def shortDescription(self):
#         # Do not show first line of the docstring as a test description
#         return None
# 
#     def get_routes(self):
#         """Gets the routes for the app.
# 
#         This should return a tuple of tuples.  Each tuple contains the
#         route as a string and the instnace of a resource to route to.  e.g.
# 
#         (
#             ('/some/url/', doctor.router.Handler1),
#         )
# 
#         This method can be overridden in subclasses to change the routes and
#         add new ones.
# 
#         :returns: The tuple described above.
#         """
#         def logic_func(item_id: ItemId, name: Name=None):
#             return (item_id, name)
# 
#         routes = (
#             Route('/test/', methods=(
#                 get(logic_func),), heading='Test'),
#         )
#         return create_routes(routes)
# 
#     def create_app(self):
#         """This method creates the flask app.
# 
#         This is required to be implemented by flask_restful.
# 
#         :returns: Flask application instance.
#         """
#         app = Flask('test')
#         app.config['TESTING'] = True
# 
#         api = flask_restful.Api(app)
#         for url, handler in self.get_routes():
#             api.add_resource(handler, url)
# 
#         return api.app
# 
# Path: test/types.py
# def parse_comma_separated_str(value):
# class ExampleObject(Object):
# class FooInstance(Object):
# class AgeOrColor(UnionType):
# class ColorsOrObject(UnionType):


# Path: test/test_router_integration.py
from functools import wraps
from doctor.flask import create_routes
from doctor.routing import get, Route
from .base import FlaskTestCase
from .types import ItemId, Name
import mock

def logic_func(pos_arg, item_id: ItemId, name: Name=None):
    return {
        'item_id': item_id,
        'name': name,
        'pos_arg': pos_arg,
    }


class RouterIntegrationTestCase(FlaskTestCase):

    before = mock.Mock()
    after = mock.Mock()

    def get_routes(self):
        routes = (
            Route('/test/', methods=[
                get(logic_func)], heading='Test', before=self.before,
                after=self.after),
        )
        return create_routes(routes)

    def test_decorated_logic_func_passes_arg_to_func(self):
        """
        This test verifies everything works properly if our logic function
        is decorated and the decorator passes an extra positional argument to
        it.  This was broken in v1.1.3 as it would cause a 400 saying that
        `pos_arg` is required as a request parameter since it was not taking
        into accout `omit_args` and just determining required arguments based
        on the function signature's non-keyword arguments.
        """

        response = self.client.get('/test/', query_string={'item_id': 1})