# Path: pycnic/core.py
# class WSGI:
# 
#     routes = []
#     debug = False
#     logger = None
#     before = None
#     teardown = None
#     after = None
#     headers = None
#     strip_path = True
#     json_cls = None
# 
#     def __init__(self, environ, start_response):
# 
#         if not self.logger:
#             self.logger = logging.Logger(__name__)
# 
#         self.logger.debug("WSGI __init__ called")
# 
#         path = environ["PATH_INFO"]
#         if self.strip_path and len(path) > 1 and path.endswith("/"):
#             path = path[0:-1]
# 
#         self.request = Request(
#             path=path,
#             method=environ["REQUEST_METHOD"],
#             environ=environ
#         )
# 
#         self.response = Response(status_code=200)
# 
#         self.environ = environ
#         self.start = start_response
#         self.response.set_header("Content-Type", "application/json")
# 
#     def __iter__(self):
#         try:
#             if self.before:
#                 self.before()
#             resp = self.delegate()
#             if self.after:
#                 self.after()
#             headers = self.response.headers
#             if self.headers:
#                 headers += self.headers
#             self.start(self.response.status, headers)
# 
#         except errors.HTTPError as err:
#             self.response.status_code = err.status_code
#             headers = [("Content-Type", "application/json")]
#             if self.headers:
#                 headers += self.headers
#             if err.headers:
#                 headers += err.headers
#             self.start(self.response.status, headers)
#             resp = err.response()
# 
#         except Exception as err:
#             self.logger.exception(err)
#             headers = [("Content-Type", "application/json")]
#             self.start(STATUSES[500], headers)
#             if self.debug:
#                 resp = {"error": traceback.format_exc().split("\n")}
#             else:
#                 resp = {"error": "Internal server error encountered."}
# 
#         if self.teardown:
#             self.teardown()
# 
#         if isinstance(resp, (dict, list)):
#             try:
#                 if self.debug:
#                     jresp = json.dumps(resp, indent=4, cls=self.json_cls)
#                 else:
#                     jresp = json.dumps(resp, cls=self.json_cls)
#             except Exception:
#                 if self.debug:
#                     msg = traceback.format_exc().split("\n")
#                     jresp = json.dumps({"error": msg}, indent=4)
#                 else:
#                     msg = "An unhandled exception occured during response"
#                     jresp = json.dumps({"error": msg})
#             self.logger.debug("Sending JSON response: %s", jresp)
#             return iter([jresp.encode('utf-8')])
#         elif isinstance(resp, str):
#             self.logger.debug("Sending string response: %s", resp)
#             return iter([resp.encode('utf-8')])
#         else:
#             self.logger.debug("Sending unknown response: %s", resp)
#             return iter(resp)
# 
#     def delegate(self):
#         path = self.request.path
#         method = self.request.method
# 
#         for pattern, handler in self.routes:
#             # Set defaults for handler
#             handler.request = self.request
#             handler.response = self.response
# 
#             m = re.match('^' + pattern + '$', path)
#             if m:
#                 if hasattr(handler, 'before'):
#                     handler.before()
# 
#                 args = m.groups()
#                 funcname = method.lower()
#                 try:
#                     func = getattr(handler, funcname)
#                 except AttributeError:
#                     raise errors.HTTP_405("%s not allowed" % (method.upper()))
# 
#                 output = func(*args)
# 
#                 if hasattr(handler, 'after'):
#                     handler.after()
# 
#                 return output
# 
#         raise errors.HTTP_404("Path %s not found" % (path))
# 
# class Handler(object):
# 
#     request = None
#     response = None
# 
#     def options(self, *args, **kwargs):
#         """Default implementation of OPTIONS method.
# 
#         Checks which methods are implemented, and sets the Allow header
#         accordingly.
#         """
#         # Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
#         http_methods = [
#             'get',
#             'head',
#             'post',
#             'put',
#             'delete',
#             'connect',
#             'options',
#             'trace',
#             'patch'
#         ]
# 
#         supported_methods = []
# 
#         for method in http_methods:
#             if method in dir(self):
#                 supported_methods.append(method.upper())
# 
#         self.response.set_header('Allow', ', '.join(supported_methods))
#         return {}
# 
# Path: pycnic/errors.py
# class HTTP_401(HTTPNumeric):
#     status_code = 401
# 
# class HTTP_400(HTTPNumeric):
#     status_code = 400


from functools import wraps
from pycnic.core import WSGI, Handler
from pycnic.errors import HTTP_401, HTTP_400
from models import User, UserSession, Session, Base, engine
    from wsgiref.simple_server import make_server
    if not sess:
        return None
    if not sess.user:
        return None
    return { "username": sess.user.username }

def requires_login():
    """ Wrapper for methods that require login """

    def wrapper(f):
        @wraps(f)
        def wrapped(*args, **kwargs):
            if not get_user(args[0].request):
                raise HTTP_401("I can't let you do that")
            return f(*args, **kwargs)
        return wrapped
    return wrapper

class Home(Handler):
    """ Handler for a message with the user's name """    

    @requires_login()
    def get(self):
        user = get_user(self.request)
        return { "message":"Hello, %s"%(user.get("username")) }

    @requires_login()
    def post(self):
        return self.get()


# Path: pycnic/core.py
# class WSGI:
# 
#     routes = []
#     debug = False
#     logger = None
#     before = None
#     teardown = None
#     after = None
#     headers = None
#     strip_path = True
#     json_cls = None
# 
#     def __init__(self, environ, start_response):
# 
#         if not self.logger:
#             self.logger = logging.Logger(__name__)
# 
#         self.logger.debug("WSGI __init__ called")
# 
#         path = environ["PATH_INFO"]
#         if self.strip_path and len(path) > 1 and path.endswith("/"):
#             path = path[0:-1]
# 
#         self.request = Request(
#             path=path,
#             method=environ["REQUEST_METHOD"],
#             environ=environ
#         )
# 
#         self.response = Response(status_code=200)
# 
#         self.environ = environ
#         self.start = start_response
#         self.response.set_header("Content-Type", "application/json")
# 
#     def __iter__(self):
#         try:
#             if self.before:
#                 self.before()
#             resp = self.delegate()
#             if self.after:
#                 self.after()
#             headers = self.response.headers
#             if self.headers:
#                 headers += self.headers
#             self.start(self.response.status, headers)
# 
#         except errors.HTTPError as err:
#             self.response.status_code = err.status_code
#             headers = [("Content-Type", "application/json")]
#             if self.headers:
#                 headers += self.headers
#             if err.headers:
#                 headers += err.headers
#             self.start(self.response.status, headers)
#             resp = err.response()
# 
#         except Exception as err:
#             self.logger.exception(err)
#             headers = [("Content-Type", "application/json")]
#             self.start(STATUSES[500], headers)
#             if self.debug:
#                 resp = {"error": traceback.format_exc().split("\n")}
#             else:
#                 resp = {"error": "Internal server error encountered."}
# 
#         if self.teardown:
#             self.teardown()
# 
#         if isinstance(resp, (dict, list)):
#             try:
#                 if self.debug:
#                     jresp = json.dumps(resp, indent=4, cls=self.json_cls)
#                 else:
#                     jresp = json.dumps(resp, cls=self.json_cls)
#             except Exception:
#                 if self.debug:
#                     msg = traceback.format_exc().split("\n")
#                     jresp = json.dumps({"error": msg}, indent=4)
#                 else:
#                     msg = "An unhandled exception occured during response"
#                     jresp = json.dumps({"error": msg})
#             self.logger.debug("Sending JSON response: %s", jresp)
#             return iter([jresp.encode('utf-8')])
#         elif isinstance(resp, str):
#             self.logger.debug("Sending string response: %s", resp)
#             return iter([resp.encode('utf-8')])
#         else:
#             self.logger.debug("Sending unknown response: %s", resp)
#             return iter(resp)
# 
#     def delegate(self):
#         path = self.request.path
#         method = self.request.method
# 
#         for pattern, handler in self.routes:
#             # Set defaults for handler
#             handler.request = self.request
#             handler.response = self.response
# 
#             m = re.match('^' + pattern + '$', path)
#             if m:
#                 if hasattr(handler, 'before'):
#                     handler.before()
# 
#                 args = m.groups()
#                 funcname = method.lower()
#                 try:
#                     func = getattr(handler, funcname)
#                 except AttributeError:
#                     raise errors.HTTP_405("%s not allowed" % (method.upper()))
# 
#                 output = func(*args)
# 
#                 if hasattr(handler, 'after'):
#                     handler.after()
# 
#                 return output
# 
#         raise errors.HTTP_404("Path %s not found" % (path))
# 
# class Handler(object):
# 
#     request = None
#     response = None
# 
#     def options(self, *args, **kwargs):
#         """Default implementation of OPTIONS method.
# 
#         Checks which methods are implemented, and sets the Allow header
#         accordingly.
#         """
#         # Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
#         http_methods = [
#             'get',
#             'head',
#             'post',
#             'put',
#             'delete',
#             'connect',
#             'options',
#             'trace',
#             'patch'
#         ]
# 
#         supported_methods = []
# 
#         for method in http_methods:
#             if method in dir(self):
#                 supported_methods.append(method.upper())
# 
#         self.response.set_header('Allow', ', '.join(supported_methods))
#         return {}
# 
# Path: pycnic/errors.py
# class HTTP_401(HTTPNumeric):
#     status_code = 401
# 
# class HTTP_400(HTTPNumeric):
#     status_code = 400


# Path: examples/full-auth.py
from functools import wraps
from pycnic.core import WSGI, Handler
from pycnic.errors import HTTP_401, HTTP_400
from models import User, UserSession, Session, Base, engine
    from wsgiref.simple_server import make_server

    if not sess:
        return None
    if not sess.user:
        return None
    return { "username": sess.user.username }

def requires_login():
    """ Wrapper for methods that require login """

    def wrapper(f):
        @wraps(f)
        def wrapped(*args, **kwargs):
            if not get_user(args[0].request):
                raise HTTP_401("I can't let you do that")
            return f(*args, **kwargs)
        return wrapped
    return wrapper

class Home(Handler):
    """ Handler for a message with the user's name """    

    @requires_login()
    def get(self):
        user = get_user(self.request)
        return { "message":"Hello, %s"%(user.get("username")) }

    @requires_login()
    def post(self):
        return self.get()


class Login(Handler):