def test_body_template(self): class Login(types.Model): email = types.String() password = types.String() # check that GET request raises exception if body template is attempted to be set get_request = Request(environ={"REQUEST_METHOD": VERB.GET}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) self.assertRaises(AssertionError, setattr, get_request, "body_template", Login()) # check that None is ignored when setting body template post_request = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) post_request.body_template = None self.assertIsNone(post_request.body_template) # check that exception raised for non DataCollection sub class self.assertRaises(AssertionError, setattr, post_request, "body_template", "string")
def test_body_template(self): class Login(types.Model): email = types.String() password = types.String() # check that GET request raises exception if body template is attempted to be set get_request = Request( environ={ "REQUEST_METHOD": VERB.GET }, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON() ) self.assertRaises(AssertionError, setattr, get_request, "body_template", Login()) # check that None is ignored when setting body template post_request = Request( environ={ "REQUEST_METHOD": VERB.POST }, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON() ) post_request.body_template = None self.assertIsNone(post_request.body_template) # check that exception raised for non DataCollection sub class self.assertRaises(AssertionError, setattr, post_request, "body_template", "string")
def test_template_filter_none_returns_none(self): request = Request(environ={"REQUEST_METHOD": VERB.GET}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) self.assertIsNone( request.get_response_attribute_filter(template_filter=None))
def test_attribute_filter(self): attribute_filter = AttributeFilter() request = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) request.attribute_filter = attribute_filter self.assertEqual(request.attribute_filter, attribute_filter)
def test_parameter_set(self): parameter_set = ParameterSet() request = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) request.parameter_set = parameter_set self.assertEqual(request.parameter_set, parameter_set)
def test_header_not_found_returns_none(self): request = Request( environ={ "REQUEST_METHOD": VERB.GET }, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON() ) self.assertIsNone(request.get_response_attribute_filter(template_filter=AttributeFilter()))
def test_parameter_set(self): parameter_set = ParameterSet() request = Request( environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON() ) request.parameter_set = parameter_set self.assertEqual(request.parameter_set, parameter_set)
def test_attribute_filter(self): attribute_filter = AttributeFilter() request = Request( environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON() ) request.attribute_filter = attribute_filter self.assertEqual(request.attribute_filter, attribute_filter)
def setUp(self): import logging logging.basicConfig() self.logger = logging.getLogger("prestans") from prestans.deserializer import JSON charset = "utf-8" serializers = [JSON()] default_serializer = JSON() class AuthProvider(Base): def is_authorized_user(self, config): return config["name"] == "Jack" class HandlerWithoutProvider(RequestHandler): @access_required({"name": "Jack"}) def get(self): self.response.status = STATUS.NO_CONTENT self.handler_without_provider = HandlerWithoutProvider class HandlerWithProvider(RequestHandler): __provider_config__ = Config(authentication=AuthProvider()) @access_required({"name": "Jack"}) def get(self): self.response.status = STATUS.NO_CONTENT @access_required({"name": "Jill"}) def post(self): self.response.status = STATUS.NO_CONTENT self.handler_with_provider = HandlerWithProvider self.get_environ = {"REQUEST_METHOD": VERB.GET} self.post_environ = {"REQUEST_METHOD": VERB.POST} self.get_request = Request(environ=self.get_environ, charset=charset, logger=self.logger, deserializers=serializers, default_deserializer=default_serializer) self.post_request = Request(environ=self.post_environ, charset=charset, logger=self.logger, deserializers=serializers, default_deserializer=default_serializer) self.response = Response(charset=charset, logger=self.logger, serializers=serializers, default_serializer=default_serializer)
def test_register_deserializers(self): json_dsz = JSON() plist_dsz = XMLPlist() request = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[json_dsz], default_deserializer=json_dsz) self.assertEqual(request.supported_mime_types, ["application/json"]) request.register_deserializers(plist_dsz) self.assertEqual(request.supported_mime_types, ["application/json", "application/xml"]) self.assertRaises(TypeError, request.register_deserializers, "string")
def test_delete(self): request = Request(environ={"REQUEST_METHOD": VERB.DELETE}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) self.assertEqual(request.method, VERB.DELETE)
def test_none_raises_attribute_error(self): request = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON], default_deserializer=JSON) self.assertRaises(AttributeError, getattr, request, "parsed_body")
def test_default_false(self): is_minified_missing = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) self.assertFalse(is_minified_missing.is_minified)
def test_options(self): request = Request(environ={"REQUEST_METHOD": VERB.OPTIONS}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON], default_deserializer=JSON) self.assertEqual(request.method, VERB.OPTIONS)
def test_selected_deserializer(self): request = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) self.assertIsNone(request.selected_deserializer)
def test_set_deserializer_by_mime_type(self): json_dsz = JSON() plist_dsz = XMLPlist() request = Request( environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[json_dsz, plist_dsz], default_deserializer=json_dsz ) self.assertIsNone(request.selected_deserializer) request.set_deserializer_by_mime_type("application/json") self.assertEqual(request.selected_deserializer, json_dsz) request.set_deserializer_by_mime_type("application/xml") self.assertEqual(request.selected_deserializer, plist_dsz) self.assertRaises(exception.UnsupportedContentTypeError, request.set_deserializer_by_mime_type, "text/plain")
def test_logger_passed_via_init(self): custom_logger = logging.getLogger("custom") request = Request(environ={"REQUEST_METHOD": VERB.GET}, charset="utf-8", logger=custom_logger, deserializers=[JSON()], default_deserializer=JSON()) self.assertEqual(request.logger, custom_logger)
def test_register_deserializers(self): json_dsz = JSON() plist_dsz = XMLPlist() request = Request( environ={ "REQUEST_METHOD": VERB.POST }, charset="utf-8", logger=logging.getLogger(), deserializers=[json_dsz], default_deserializer=json_dsz ) self.assertEqual(request.supported_mime_types, ["application/json"]) request.register_deserializers(plist_dsz) self.assertEqual(request.supported_mime_types, ["application/json", "application/xml"]) self.assertRaises(TypeError, request.register_deserializers, "string")
def test_default_deserializer(self): json_dsz = JSON() request = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[json_dsz], default_deserializer=json_dsz) self.assertEqual(request.default_deserializer, json_dsz)
def test_get_body(self): request = Request(environ={ "REQUEST_METHOD": VERB.POST, "CONTENT_TYPE": "application/json" }, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) class Person(types.Model): first_name = types.String() last_name = types.String() request.body = b'{"first_name": "John", "last_name": "Smith"}' request.body_template = Person() self.assertTrue(isinstance(request.parsed_body, Person)) self.assertEqual(request.parsed_body.first_name, "John") self.assertEqual(request.parsed_body.last_name, "Smith")
def test_off_is_false(self): is_minified_off = Request(environ={ "REQUEST_METHOD": VERB.POST, "HTTP_PRESTANS_MINIFICATION": "OFF" }, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) self.assertFalse(is_minified_off.is_minified)
def test_header_correctly_parsed(self): request = Request( environ={ "REQUEST_METHOD": VERB.GET, "HTTP_PRESTANS_RESPONSE_ATTRIBUTE_LIST": '{"first_name": true, "last_name": false}' }, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON() ) class Person(types.Model): first_name = types.String() last_name = types.String() response_filter = request.get_response_attribute_filter(template_filter=AttributeFilter.from_model(Person())) self.assertIsInstance(response_filter, AttributeFilter) self.assertTrue(response_filter.first_name) self.assertFalse(response_filter.last_name)
def test_supported_mime_types_str(self): json_dsz = JSON() plist_dsz = XMLPlist() request = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[json_dsz], default_deserializer=json_dsz) self.assertEqual(request.supported_mime_types_str, json_dsz.content_type()) request = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[json_dsz, plist_dsz], default_deserializer=json_dsz) self.assertEqual( request.supported_mime_types_str, json_dsz.content_type() + "," + plist_dsz.content_type())
def test_header_correctly_parsed(self): request = Request(environ={ "REQUEST_METHOD": VERB.GET, "HTTP_PRESTANS_RESPONSE_ATTRIBUTE_LIST": '{"first_name": true, "last_name": false}' }, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON()) class Person(types.Model): first_name = types.String() last_name = types.String() response_filter = request.get_response_attribute_filter( template_filter=AttributeFilter.from_model(Person())) self.assertIsInstance(response_filter, AttributeFilter) self.assertTrue(response_filter.first_name) self.assertFalse(response_filter.last_name)
def test_get_body(self): request = Request( environ={ "REQUEST_METHOD": VERB.POST, "CONTENT_TYPE": "application/json" }, charset="utf-8", logger=logging.getLogger(), deserializers=[JSON()], default_deserializer=JSON() ) class Person(types.Model): first_name = types.String() last_name = types.String() request.body = b'{"first_name": "John", "last_name": "Smith"}' request.body_template = Person() self.assertTrue(isinstance(request.parsed_body, Person)) self.assertEqual(request.parsed_body.first_name, "John") self.assertEqual(request.parsed_body.last_name, "Smith")
def test_init(self): from prestans.rest import Request import logging logging.basicConfig() self.logger = logging.getLogger("prestans") from prestans.deserializer import JSON charset = "utf-8" serializers = [JSON()] default_serializer = JSON() request_environ = { "REQUEST_METHOD": VERB.GET, "PATH_INFO": "/url", "HTTP_USER_AGENT": "chrome", "wsgi.url_scheme": "https", "SERVER_NAME": "localhost", "SERVER_PORT": "8080" } request = Request(environ=request_environ, charset=charset, logger=self.logger, deserializers=serializers, default_deserializer=default_serializer) handler_exception = exception.HandlerException(STATUS.FORBIDDEN, "message") handler_exception.request = request self.assertEqual(handler_exception.http_status, STATUS.FORBIDDEN) self.assertEqual(handler_exception.message, "message") self.assertEqual(handler_exception.request, request) self.assertEqual(handler_exception.log_message, 'GET https://localhost:8080/url chrome "message"') self.assertEqual(str(handler_exception), 'GET https://localhost:8080/url chrome "message"') handler_exception_without_request = exception.HandlerException( STATUS.NOT_FOUND, "message") self.assertEqual(handler_exception_without_request.http_status, STATUS.NOT_FOUND) self.assertEqual(handler_exception_without_request.message, "message") self.assertEqual(handler_exception_without_request.log_message, "message") self.assertEqual(str(handler_exception_without_request), "message")
def test_set_deserializer_by_mime_type(self): json_dsz = JSON() plist_dsz = XMLPlist() request = Request(environ={"REQUEST_METHOD": VERB.POST}, charset="utf-8", logger=logging.getLogger(), deserializers=[json_dsz, plist_dsz], default_deserializer=json_dsz) self.assertIsNone(request.selected_deserializer) request.set_deserializer_by_mime_type("application/json") self.assertEqual(request.selected_deserializer, json_dsz) request.set_deserializer_by_mime_type("application/xml") self.assertEqual(request.selected_deserializer, plist_dsz) self.assertRaises(exception.UnsupportedContentTypeError, request.set_deserializer_by_mime_type, "text/plain")
def setUp(self): import logging logging.basicConfig() self.logger = logging.getLogger("prestans") from prestans.deserializer import JSON self.charset = "utf-8" self.serializers = [JSON()] self.default_serializer = JSON() self.get_environ = {"REQUEST_METHOD": VERB.GET} self.get_request = Request( environ=self.get_environ, charset=self.charset, logger=self.logger, deserializers=self.serializers, default_deserializer=self.default_serializer) self.response = Response(charset=self.charset, logger=self.logger, serializers=self.serializers, default_serializer=self.default_serializer) class HandlerWithoutProvider(RequestHandler): @login_required def get(self): pass self.handler_without_provider = HandlerWithoutProvider class AuthenticatedProvider(Base): def is_authenticated_user(self): return True class AuthenticatedHandler(RequestHandler): __provider_config__ = Config( authentication=AuthenticatedProvider()) @login_required def get(self): self.response.status = STATUS.NO_CONTENT self.authenticated_handler = AuthenticatedHandler class UnauthenticatedProvider(Base): def is_authenticated_user(self): return False class UnauthenticatedHandler(RequestHandler): __provider_config__ = Config( authentication=UnauthenticatedProvider()) @login_required def get(self): self.response.status = STATUS.NO_CONTENT self.unauthenticated_handler = UnauthenticatedHandler
def __call__(self, environ, start_response): # say hello self.logger.info( "%s exposes %i end-points; prestans %s; charset %s; debug %s" % (self._application_name, len( self._routes), __version__, self._charset, self._debug)) # validate serializers and deserializers; are subclasses of prestans.serializer.Base _default_outgoing_mime_types = list() for available_serializer in self._serializers: if not isinstance(available_serializer, serializer.Base): msg = "registered serializer %s.%s does not inherit from prestans.serializer.Serializer" % ( available_serializer.__module__, available_serializer.__class__.__name__) raise TypeError(msg) _default_outgoing_mime_types.append( available_serializer.content_type()) _default_incoming_mime_types = list() for available_deserializer in self._deserializers: if not isinstance(available_deserializer, deserializer.Base): msg = "registered deserializer %s.%s does not inherit from prestans.serializer.DeSerializer" % ( available_deserializer.__module__, available_deserializer.__class__.__name__) raise TypeError(msg) _default_incoming_mime_types.append( available_deserializer.content_type()) # report on the acceptable mime types self._logger.info("generally accepts %s; speaks %s" % (str(_default_outgoing_mime_types).strip("[]'"), str(_default_incoming_mime_types).strip("[]'"))) # attempt to parse the HTTP request request = Request(environ=environ, charset=self._charset, logger=self._logger, deserializers=self._deserializers, default_deserializer=self._default_deserializer) # initialise the route map route_map = self.generate_route_map(self._routes) try: # check if the requested URL has a valid registered handler for regexp, handler_class in route_map: # if absent, can assume to be empty string # https://www.python.org/dev/peps/pep-3333/#environ-variables match = regexp.match(environ.get("PATH_INFO", "")) # if we've found a match; ensure its a handler subclass and return it's callable if match: # assemble the args and kwargs args = match.groups() kwargs = {} for key, value in iter(regexp.groupindex.items()): kwargs[key] = args[value - 1] if len(kwargs) > 0: args = () if issubclass(handler_class, BlueprintHandler): response = DictionaryResponse( charset=self._charset, logger=self._logger, serializers=self._serializers, default_serializer=self._default_deserializer) request_handler = handler_class(args=args, kwargs=kwargs, request=request, response=response, logger=self._logger, debug=self._debug, route_map=self._routes) else: response = Response( charset=self._charset, logger=self._logger, serializers=self._serializers, default_serializer=self._default_deserializer) response.minify = request.is_minified request_handler = handler_class(args=args, kwargs=kwargs, request=request, response=response, logger=self._logger, debug=self._debug) return request_handler(environ, start_response) # request does not have a matched handler no_endpoint = exception.NoEndpointError() no_endpoint.request = request raise no_endpoint except exception.Base as exp: self.logger.error(exp) error_response = ErrorResponse(exp, self._default_serializer) return error_response(environ, start_response)
def setUp(self): import logging logging.basicConfig() self.logger = logging.getLogger("prestans") from prestans.deserializer import JSON charset = "utf-8" serializers = [JSON()] default_serializer = JSON() self.get_environ = {"REQUEST_METHOD": VERB.GET} self.post_environ = {"REQUEST_METHOD": VERB.POST} self.put_environ = {"REQUEST_METHOD": VERB.PUT} self.get_request = Request(environ=self.get_environ, charset=charset, logger=self.logger, deserializers=serializers, default_deserializer=default_serializer) self.post_request = Request(environ=self.post_environ, charset=charset, logger=self.logger, deserializers=serializers, default_deserializer=default_serializer) self.put_request = Request(environ=self.put_environ, charset=charset, logger=self.logger, deserializers=serializers, default_deserializer=default_serializer) self.response = Response(charset=charset, logger=self.logger, serializers=serializers, default_serializer=default_serializer) class AuthProvider(Base): def current_user_has_role(self, role_name): return role_name == "Admin" class HandlerWithoutProvider(RequestHandler): @role_required("Admin") def get(self): pass self.handler_without_provider = HandlerWithoutProvider class HandlerWithProvider(RequestHandler): __provider_config__ = Config(authentication=AuthProvider()) @role_required(None) def get(self): self.response.status = STATUS.NO_CONTENT @role_required("Manager") def post(self): self.response.status = STATUS.NO_CONTENT @role_required("Admin") def put(self): self.response.status = STATUS.NO_CONTENT self.handler_with_provider = HandlerWithProvider