def test01_Config(self): """Test Config class.""" c1 = Config() c1.a = 'a' c1.b = 'b' c2 = Config(c1) self.assertEqual(c2.a, 'a') self.assertEqual(c2.b, 'b')
def test12_top_level_index_page(self): """Test top_level_index_page().""" c = Config() c.host = 'ex.org' c.prefixes = {'pa1a': 'pa1b', 'pa2a': 'pa2b'} html = top_level_index_page(c) self.assertIn('ex.org', html) self.assertIn('pa1a', html)
def test28_iiif_info_handler(self): """Test iiif_info_handler().""" c = Config() c.api_version = '2.1' c.klass_name = 'dummy' c.image_dir = os.path.join(os.path.dirname(__file__), '../testimages') c.tile_height = 512 c.tile_width = 512 c.scale_factors = [1, 2] c.host = 'example.org' c.port = 80 environ = WSGI_ENVIRON() with self.test_app.request_context(environ): resp = iiif_info_handler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulator) self.assertEqual(resp.status_code, 200) # Auth and both authn, authz auth = mock.Mock(**{ 'info_authz.return_value': True, 'info_authn.return_value': True }) with self.test_app.request_context(environ): resp = iiif_info_handler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulator, auth=auth) self.assertEqual(resp.status_code, 200) # Auth and authn but not authz -> 401 auth = mock.Mock(**{ 'info_authz.return_value': False, 'info_authn.return_value': True }) with self.test_app.request_context(environ): # actually werkzeug.exceptions.Unauthorized self.assertRaises(Exception, iiif_info_handler, prefix='p', identifier='starfish', config=c, klass=IIIFManipulator, auth=auth) # Auth but not authn -> redirect auth = mock.Mock(**{ 'info_authz.return_value': False, 'info_authn.return_value': False }) with self.test_app.request_context(environ): resp = iiif_info_handler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulator, auth=auth) self.assertEqual(resp.status_code, 302)
def test20_osd_page_handler(self): """Test osd_page_handler() -- rather trivial check it runs with expected params.""" c = Config() c.api_version = '2.1' with self.test_app.app_context(): resp = osd_page_handler(c, 'an-unusual-id', 'a-prefix') html = resp.response[0] # Trivial tests on content... self.assertIn(b'openseadragon.min.js', html) self.assertIn(b'an-unusual-id', html)
def test24_IIIFHandler_add_compliance_header(self): """Test IIIFHandler.add_compliance_header property.""" # No auth c = Config() c.api_version = '2.1' i = IIIFHandler(prefix='/p', identifier='iii', config=c, klass=IIIFManipulator, auth=None) i.add_compliance_header() self.assertNotIn('Link', i.headers) i = IIIFHandler(prefix='/p', identifier='iii', config=c, klass=IIIFManipulatorPIL, auth=None) i.add_compliance_header() self.assertIn('/level2', i.headers['Link'])
def test28_iiif_image_handler(self): """Test iiif_image_handler().""" c = Config() c.api_version = '2.1' c.klass_name = 'dummy' c.image_dir = os.path.join(os.path.dirname(__file__), '../testimages') c.tile_height = 512 c.tile_width = 512 c.scale_factors = [1, 2] c.host = 'example.org' c.port = 80 environ = WSGI_ENVIRON() with self.test_app.request_context(environ): resp = iiif_image_handler(prefix='p', identifier='starfish', path='full/full/0/default', config=c, klass=IIIFManipulator) resp.direct_passthrough = False # avoid Flask complaint when reading .data self.assertEqual(len(resp.data), 3523302) # Auth and both authz, authn auth = mock.Mock(**{ 'image_authz.return_value': True, 'image_authn.return_value': True }) with self.test_app.request_context(environ): resp = iiif_image_handler(prefix='p', identifier='starfish', path='full/full/0/default', config=c, klass=IIIFManipulator, auth=auth) resp.direct_passthrough = False # avoid Flask complaint when reading .data self.assertEqual(len(resp.data), 3523302) # Auth but not authn -> redirect auth = mock.Mock(**{ 'image_authz.return_value': False, 'image_authn.return_value': False }) with self.test_app.request_context(environ): resp = iiif_image_handler(prefix='p', identifier='starfish', path='full/full0/default.jpg', config=c, klass=IIIFManipulator, auth=auth) self.assertEqual(resp.status_code, 302) resp.direct_passthrough = False # avoid Flask complaint when reading .data self.assertTrue(resp.data.startswith(b'<!DOCTYPE HTML'))
def test21_IIIFHandler_init(self): """Test IIIFHandler class init.""" # No auth c = Config() c.api_version = '2.1' i = IIIFHandler(prefix='/p', identifier='i', config=c, klass=IIIFManipulator, auth=None) self.assertTrue(i.manipulator.api_version, '2.1') # Basic auth a = IIIFAuthBasic() c.host = 'example.org' c.port = 80 c.prefix = '/p' i = IIIFHandler(prefix='/p', identifier='i', config=c, klass=IIIFManipulator, auth=a) self.assertTrue(i.manipulator.api_version, '2.1')
def test23_IIIFHandler_file(self): """Test IIIFHandler.file property.""" # No auth c = Config() c.api_version = '2.1' # Generator c.klass_name = 'gen' c.generator_dir = os.path.join(os.path.dirname(__file__), '../iiif/generators') i = IIIFHandler(prefix='/p', identifier='sierpinski_carpet', config=c, klass=IIIFManipulator, auth=None) self.assertEqual(os.path.basename(i.file), 'sierpinski_carpet.py') # Image c.klass_name = 'dummy' c.image_dir = os.path.join(os.path.dirname(__file__), '../testimages') i = IIIFHandler(prefix='/p', identifier='starfish', config=c, klass=IIIFManipulator, auth=None) self.assertEqual(os.path.basename(i.file), 'starfish.jpg') # Failure i = IIIFHandler(prefix='/p', identifier='no-image', config=c, klass=IIIFManipulator, auth=None) self.assertRaises(IIIFError, lambda: i.file)
def test26_IIIFHandler_image_request_response(self): """Test IIIFHandler.image_request_response().""" c = Config() c.api_version = '2.1' c.klass_name = 'dummy' c.image_dir = os.path.join(os.path.dirname(__file__), '../testimages') c.tile_height = 512 c.tile_width = 512 c.scale_factors = [1, 2] c.host = 'example.org' c.port = 80 i = IIIFHandler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulator, auth=None) environ = WSGI_ENVIRON() with self.test_app.request_context(environ): # request too long self.assertRaises(IIIFError, i.image_request_response, 'x' * 2000) # bad path self.assertRaises(IIIFError, i.image_request_response, 'a/b') self.assertRaises(IIIFError, i.image_request_response, '/') self.assertRaises(IIIFError, i.image_request_response, 'starfish') # normal resp = i.image_request_response('full/full/0/default') resp.direct_passthrough = False # avoid Flask complaint when reading .data self.assertEqual(len(resp.data), 3523302) # PIL manipularor and degraded i = IIIFHandler(prefix='p', identifier='starfish-deg', config=c, klass=IIIFManipulatorPIL, auth=None) environ = WSGI_ENVIRON() with self.test_app.request_context(environ): resp = i.image_request_response('full/full/0/default.jpg') resp.direct_passthrough = False # avoid Flask complaint when reading .data self.assertTrue(len(resp.data) > 1000000) self.assertTrue(len(resp.data) < 2000000) # Conneg for v1.1 c.api_version = '1.1' i = IIIFHandler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulatorPIL, auth=None) environ = WSGI_ENVIRON() environ['HTTP_ACCEPT'] = 'image/png' with self.test_app.request_context(environ): resp = i.image_request_response('full/full/0/native') resp.direct_passthrough = False # avoid Flask complaint when reading .data self.assertTrue(len(resp.data) > 1000000) self.assertEqual(resp.mimetype, 'image/png')
def test25_IIIFHandler_make_response(self): """Test IIIFHandler.make_response.""" c = Config() c.api_version = '2.1' i = IIIFHandler(prefix='/p', identifier='iii', config=c, klass=IIIFManipulator, auth=None) with self.test_app.app_context(): resp = i.make_response('hello1') self.assertEqual(resp.response[0], b'hello1') self.assertEqual(resp.headers['Access-control-allow-origin'], '*') # Add a custom header i = IIIFHandler(prefix='/p', identifier='iii', config=c, klass=IIIFManipulator, auth=None) with self.test_app.app_context(): resp = i.make_response('hello2', headers={'Special-header': 'ba'}) self.assertEqual(resp.response[0], b'hello2') self.assertEqual(resp.headers['Special-header'], 'ba') self.assertEqual(resp.headers['Access-control-allow-origin'], '*')
def create_testserver_flask_app(cfg): """Create testserver Flask application with one or more IIIF handlers.""" # Create Flask app app = Flask(__name__, static_url_path='/' + cfg.pages_dir) Flask.secret_key = "SECRET_HERE" app.debug = cfg.debug # Create shared configuration dict based on options config = Config(cfg) config.homedir = os.path.dirname(os.path.realpath(__file__)) config.gauth_client_secret_file = os.path.join( config.homedir, config.gauth_client_secret) # Install request handlers client_prefixes = dict() for api_version in cfg.api_versions: for klass_name in cfg.manipulators: for auth_type in cfg.auth_types: # auth only for >=2.1 if (auth_type != 'none' and float(api_version) < 2.1): continue handler_config = Config(config) handler_config.api_version = api_version handler_config.klass_name = klass_name handler_config.auth_type = auth_type prefix = make_prefix(api_version, klass_name, auth_type) client_prefix = os.path.join(config.container_prefix, prefix) logging.debug("prefix = %s, client_prefix = %s" % (prefix, client_prefix)) client_prefixes[client_prefix] = prefix handler_config.prefix = prefix handler_config.client_prefix = client_prefix add_handler(app, handler_config) # Index page config.prefixes = client_prefixes app.add_url_rule('/', 'top_level_index_page', top_level_index_page, defaults={'config': config}) if cfg.include_osd: # OpenSeadragon files app.add_url_rule('/openseadragon200/<path:filename>', 'OSD pages', serve_static, defaults={'prefix': 'openseadragon200'}) return(app)
def test14_prefix_index_page(self): """Test prefix_index_page().""" c = Config() c.client_prefix = 'pfx' c.host = 'ex.org' c.api_version = '2.1' c.manipulator = 'pil' c.auth_type = 'none' c.include_osd = True c.klass_name = 'pil' c.image_dir = os.path.join(os.path.dirname(__file__), '../testimages') html = prefix_index_page(c) self.assertIn('/pfx/', html) self.assertIn('osd.html', html) # No OSD c.include_osd = False html = prefix_index_page(c) self.assertIn('/pfx/', html) self.assertNotIn('osd.html', html)
def test27_IIIFHandler_error_response(self): """Test IIIFHandler.error_response().""" c = Config() c.api_version = '2.1' c.klass_name = 'dummy' c.image_dir = os.path.join(os.path.dirname(__file__), '../testimages') c.tile_height = 512 c.tile_width = 512 c.scale_factors = [1, 2] c.host = 'example.org' c.port = 80 i = IIIFHandler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulator, auth=None) environ = WSGI_ENVIRON() with self.test_app.request_context(environ): resp = i.error_response(IIIFError(999, 'bwaa')) self.assertEqual(resp.status_code, 999)
def test22_IIIFHandler_json_mime_type(self): """Test IIIFHandler.json_mime_type property.""" # No auth, no test for API 1.0 c = Config() c.api_version = '1.0' i = IIIFHandler(prefix='/p', identifier='i', config=c, klass=IIIFManipulator, auth=None) self.assertEqual(i.json_mime_type, "application/json") # No auth, connecg for API 1.1 c = Config() c.api_version = '1.1' i = IIIFHandler(prefix='/p', identifier='i', config=c, klass=IIIFManipulator, auth=None) environ = WSGI_ENVIRON() with self.test_app.request_context(environ): self.assertEqual(i.json_mime_type, "application/json") environ['HTTP_ACCEPT'] = 'application/ld+json' with self.test_app.request_context(environ): self.assertEqual(i.json_mime_type, "application/ld+json") environ['HTTP_ACCEPT'] = 'text/plain' with self.test_app.request_context(environ): self.assertEqual(i.json_mime_type, "application/json")
def test13_identifiers(self): """Test identifiers().""" c = Config() # Generator case c.klass_name = 'gen' c.generator_dir = os.path.join(os.path.dirname(__file__), '../iiif/generators') ids = identifiers(c) self.assertIn('sierpinski_carpet', ids) self.assertNotIn('red-19000x19000', ids) # Non-gerenator case c = Config() c.klass_name = 'anything-not-gen' c.image_dir = os.path.join(os.path.dirname(__file__), '../testimages') ids = identifiers(c) self.assertNotIn('sierpinski_carpet', ids) self.assertIn('red-19000x19000', ids)
def test28_iiif_info_handler(self): """Test iiif_info_handler().""" c = Config() c.api_version = '2.1' c.klass_name = 'dummy' c.image_dir = os.path.join(os.path.dirname(__file__), '../testimages') c.tile_height = 512 c.tile_width = 512 c.scale_factors = [1, 2] c.host = 'example.org' c.port = 80 environ = WSGI_ENVIRON() with self.test_app.request_context(environ): resp = iiif_info_handler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulator) self.assertEqual(resp.status_code, 200) # Auth and both authn, authz auth = mock.Mock(**{'info_authz.return_value': True, 'info_authn.return_value': True}) with self.test_app.request_context(environ): resp = iiif_info_handler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulator, auth=auth) self.assertEqual(resp.status_code, 200) # Auth and authn but not authz -> 401 auth = mock.Mock(**{'info_authz.return_value': False, 'info_authn.return_value': True}) with self.test_app.request_context(environ): # actually werkzeug.exceptions.Unauthorized self.assertRaises(Exception, iiif_info_handler, prefix='p', identifier='starfish', config=c, klass=IIIFManipulator, auth=auth) # Auth but not authn -> redirect auth = mock.Mock(**{'info_authz.return_value': False, 'info_authn.return_value': False}) with self.test_app.request_context(environ): resp = iiif_info_handler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulator, auth=auth) self.assertEqual(resp.status_code, 302)
def test28_iiif_image_handler(self): """Test iiif_image_handler().""" c = Config() c.api_version = '2.1' c.klass_name = 'dummy' c.image_dir = os.path.join(os.path.dirname(__file__), '../testimages') c.tile_height = 512 c.tile_width = 512 c.scale_factors = [1, 2] c.host = 'example.org' c.port = 80 environ = WSGI_ENVIRON() with self.test_app.request_context(environ): resp = iiif_image_handler(prefix='p', identifier='starfish', path='full/full/0/default', config=c, klass=IIIFManipulator) resp.direct_passthrough = False # avoid Flask complaint when reading .data self.assertEqual(len(resp.data), 3523302) # Auth and both authz, authn auth = mock.Mock(**{'image_authz.return_value': True, 'image_authn.return_value': True}) with self.test_app.request_context(environ): resp = iiif_image_handler(prefix='p', identifier='starfish', path='full/full/0/default', config=c, klass=IIIFManipulator, auth=auth) resp.direct_passthrough = False # avoid Flask complaint when reading .data self.assertEqual(len(resp.data), 3523302) # Auth but not authn -> redirect auth = mock.Mock(**{'image_authz.return_value': False, 'image_authn.return_value': False}) with self.test_app.request_context(environ): resp = iiif_image_handler(prefix='p', identifier='starfish', path='full/full0/default.jpg', config=c, klass=IIIFManipulator, auth=auth) self.assertEqual(resp.status_code, 302) resp.direct_passthrough = False # avoid Flask complaint when reading .data self.assertTrue(resp.data.startswith(b'<!DOCTYPE HTML'))
def create_reference_server_flask_app(cfg): """Create referece server Flask application with one or more IIIF handlers.""" # Create Flask app app = Flask(__name__) Flask.secret_key = "SECRET_HERE" app.debug = cfg.debug # Install request handlers client_prefixes = dict() for api_version in cfg.api_versions: handler_config = Config(cfg) handler_config.api_version = api_version handler_config.klass_name = 'pil' handler_config.auth_type = 'none' # Set same prefix on local server as expected on iiif.io handler_config.prefix = "api/image/%s/example/reference" % ( api_version) handler_config.client_prefix = handler_config.prefix add_handler(app, handler_config) return app
def create_reference_server_flask_app(cfg): """Create referece server Flask application with one or more IIIF handlers.""" # Create Flask app app = Flask(__name__) Flask.secret_key = "SECRET_HERE" app.debug = cfg.debug # Install request handlers client_prefixes = dict() for api_version in cfg.api_versions: handler_config = Config(cfg) handler_config.api_version = api_version handler_config.klass_name = 'pil' handler_config.auth_type = 'none' # Set same prefix on local server as expected on iiif.io handler_config.prefix = "api/image/%s/example/reference" % (api_version) handler_config.client_prefix = handler_config.prefix add_handler(app, handler_config) return app
def test51_add_handler(self): """Test add_handler.""" c = Config() c.klass_name = 'pil' c.api_version = '2.1' c.include_osd = False c.gauth_client_secret_file = 'file' c.access_cookie_lifetime = 10 c.access_token_lifetime = 10 # Auth types for auth in ('none', 'gauth', 'basic', 'clickthrough', 'kiosk', 'external'): c.auth_type = auth c.prefix = 'pfx1_' + auth c.client_prefix = c.prefix self.assertTrue(add_handler(self.test_app, Config(c))) # Manipulator types c.auth_type = 'none' for klass in ('pil', 'netpbm', 'gen', 'dummy'): c.klass_name = klass c.prefix = 'pfx2_' + klass c.client_prefix = c.prefix self.assertTrue(add_handler(self.test_app, Config(c))) # Include OSD c.include_osd = True self.assertTrue(add_handler(self.test_app, Config(c))) # Bad cases c.auth_type = 'bogus' self.assertFalse(add_handler(self.test_app, Config(c))) c.auth_type = 'none' c.klass_name = 'no-klass' self.assertFalse(add_handler(self.test_app, Config(c)))
def test26_IIIFHandler_image_information_response(self): """Test IIIFHandler.image_information_response().""" c = Config() c.api_version = '2.1' c.klass_name = 'dummy' c.image_dir = os.path.join(os.path.dirname(__file__), '../testimages') c.tile_height = 512 c.tile_width = 512 c.scale_factors = [1, 2] c.host = 'example.org' c.port = 80 i = IIIFHandler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulator, auth=IIIFAuthBasic()) environ = WSGI_ENVIRON() with self.test_app.request_context(environ): resp = i.image_information_response() jsonb = resp.response[0] self.assertIn(b'default', jsonb) self.assertNotIn(b'native', jsonb) self.assertIn(b'starfish', jsonb) self.assertIn(b'scaleFactors', jsonb) self.assertIn(b'login', jsonb) # v1.1, auto scale factors c.api_version = '1.1' c.scale_factors = ['auto'] i = IIIFHandler(prefix='p', identifier='starfish', config=c, klass=IIIFManipulator, auth=None) with self.test_app.request_context(environ): resp = i.image_information_response() jsonb = resp.response[0] self.assertNotIn(b'default', jsonb) self.assertIn(b'native', jsonb) self.assertIn(b'starfish', jsonb) self.assertNotIn(b'scaleFactors', jsonb) # degraded c.api_version = '2.1' i = IIIFHandler(prefix='p', identifier='starfish-deg', config=c, klass=IIIFManipulator, auth=None) with self.test_app.request_context(environ): resp = i.image_information_response() jsonb = resp.response[0] self.assertIn(b'starfish-deg', jsonb)
def create_testserver_flask_app(cfg): """Create testserver Flask application with one or more IIIF handlers.""" # Create Flask app app = Flask(__name__, static_url_path='/' + cfg.pages_dir) Flask.secret_key = "SECRET_HERE" app.debug = cfg.debug # Create shared configuration dict based on options config = Config(cfg) config.homedir = os.path.dirname(os.path.realpath(__file__)) config.gauth_client_secret_file = os.path.join(config.homedir, config.gauth_client_secret) # Install request handlers client_prefixes = dict() for api_version in cfg.api_versions: for klass_name in cfg.manipulators: for auth_type in cfg.auth_types: # auth only for >=2.1 if (auth_type != 'none' and float(api_version) < 2.1): continue handler_config = Config(config) handler_config.api_version = api_version handler_config.klass_name = klass_name handler_config.auth_type = auth_type prefix = make_prefix(api_version, klass_name, auth_type) client_prefix = os.path.join(config.container_prefix, prefix) logging.debug("prefix = %s, client_prefix = %s" % (prefix, client_prefix)) client_prefixes[client_prefix] = prefix handler_config.prefix = prefix handler_config.client_prefix = client_prefix add_handler(app, handler_config) # Index page config.prefixes = client_prefixes app.add_url_rule('/', 'top_level_index_page', top_level_index_page, defaults={'config': config}) if cfg.include_osd: # OpenSeadragon files app.add_url_rule('/openseadragon200/<path:filename>', 'OSD pages', serve_static, defaults={'prefix': 'openseadragon200'}) return (app)