def test_execution_json(self): std_root = TemporaryDirectory() self.addCleanup(std_root.cleanup) config = Configuration.from_toml(""" [[environment.objects]] __name__ = "results" __init__ = "repodono.model.testing:Results" [environment.paths] std_root = %r [bucket._] __roots__ = ['std_root'] accept = ["*/*"] [endpoint._."/json"] __provider__ = "results.sample_dict" """ % (std_root.name, ), execution_class=HttpExecution) response = config.request_execution('/json', {})() self.assertEqual(b'{"1": "example"}', response.content) self.assertEqual({'content-type': 'application/json'}, response.headers)
def test_execution_composed_reponse(self): std_root = TemporaryDirectory() self.addCleanup(std_root.cleanup) config = Configuration.from_toml(""" [environment.variables] default = "hello" [[environment.objects]] __name__ = "response" __init__ = "repodono.model.http:Response" content = "default" [environment.paths] std_root = %r [bucket._] __roots__ = ['std_root'] accept = ["*/*"] [endpoint._."/constructed"] __provider__ = "response" """ % (std_root.name, ), execution_class=HttpExecution) response = config.request_execution('/constructed', {})() self.assertEqual(b'hello', response.content) self.assertEqual({}, response.headers)
def test_execution_none(self): std_root = TemporaryDirectory() self.addCleanup(std_root.cleanup) config = Configuration.from_toml(""" [[environment.objects]] __name__ = "results" __init__ = "repodono.model.testing:Results" [environment.paths] std_root = %r [bucket._] __roots__ = ['std_root'] accept = ["*/*"] [endpoint._."/nothing"] __provider__ = "results.sample_none" """ % (std_root.name, ), execution_class=HttpExecution) with self.assertRaises(ExecutionNoResultError) as e: config.request_execution('/nothing', {})() self.assertEqual( e.exception.args[0], "provider 'results.sample_none' referenced by end point " "in bucket '_' with route '/nothing' produced no results")
def test_execution_locals_resource_shadowing(self): config = Configuration.from_toml(""" [environment.variables] one = "one" two = "two" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] [[resource."/"]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path = "one" # resource entries are shadowed in reverse order. [[resource."/"]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path = "two" [endpoint._."/"] __provider__ = "target" """) exe = config.request_execution('/', {}) self.assertEqual(exe.locals['thing'].path, 'two')
def test_execution_basic_call(self): std_root = TemporaryDirectory() self.addCleanup(std_root.cleanup) config = Configuration.from_toml(""" [environment.variables] some_result = "A simple text result" [environment.paths] std_root = %r [bucket._] __roots__ = ['std_root'] accept = ["*/*"] [endpoint._."/"] __provider__ = "some_result" """ % (std_root.name, )) exe = config.request_execution('/', {}, execution_class=HttpExecution) # Invoking execute object directly response = exe() self.assertEqual(b'A simple text result', response.content) self.assertEqual({ 'content-type': 'text/plain', }, response.headers)
def test_resource_int_argument(self): # Test for non string values config = Configuration.from_toml(""" [environment.variables] some_name = "the value" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] [[resource."/"]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path.digit = 1 path.truth = true [endpoint._."/entry/view"] __provider__ = "thing" """) exe = config.request_execution('/entry/view', {}) self.assertEqual(exe.locals['thing'].path, {'digit': 1, 'truth': True}) # this would have simply access the value like above also self.assertEqual(exe.execute().path, {'digit': 1, 'truth': True})
def test_endpoint_kwargs_missing(self): config = Configuration.from_toml(""" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] accept = ["*/*"] # A common shared mock object [[resource."/"]] __name__ = "a_mock" __init__ = "unittest.mock:Mock" [endpoint._."/entry/"] # the template is fixed, but to test this thing out the kwargs # can be remapped using the __kwargs__ key __provider__ = "a_mock" __kwargs__.mock_id = "no_such_thing" """) exe = config.request_execution('/entry/', {}) with self.assertRaises(MappingReferenceError) as e: exe.locals['a_mock'] self.assertEqual( e.exception.args[0], "remapping from 'mock_id' to 'no_such_thing' failed as latter not " "found in map")
def test_environment_shadowing(self): config_str = """ [environment.variables] var = 0 [environment.paths] foo = 'bar' [[environment.objects]] __name__ = "foo" __init__ = "repodono.model.testing:Thing" path = "foo" [bucket._] __roots__ = ["foo"] [endpoint._."/"] __provider__ = "var" """ config = Configuration.from_toml(config_str) self.assertEqual(str(config['environment']['paths']['foo']), 'bar') # entry is defined. self.assertEqual(config['environment']['objects'][0]['__name__'], 'foo') exe = config.request_execution('/', {}) self.assertEqual(str(exe.locals['foo']), 'bar') # auxilary check self.assertEqual(str(exe.locals['__root__']), 'bar') # sample execution call exe = config.request_execution('/', {}) self.assertEqual(0, exe.execute()) self.assertEqual(0, exe())
def test_resource_kwarg_dict(self): # Test that dictionary values passed to resource also resolved. config = Configuration.from_toml(""" [environment.variables] some_name = "the value" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] [[resource."/"]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path.key = "some_name" [endpoint._."/entry/view"] __provider__ = "thing" """) exe = config.request_execution('/entry/view', {}) self.assertEqual(exe.locals['thing'].path, {'key': 'the value'}) # this would have simply access the value like above also self.assertEqual(exe.execute().path, {'key': 'the value'})
def test_basic_roots(self): # note that the current setup captures everything. config = Configuration.from_toml(""" [environment.paths] default_root = "/default" generated_root = "/generated" xml_root = "/xml" json_root = "/json" [bucket._] __roots__ = ["default_root", "generated_root"] accept = ["*/*"] [bucket.json] __roots__ = ["json_root"] accept = ["application/json", "text/json"] [bucket.xml] __roots__ = ["xml_root"] accept = ["application/xml", "text/xml"] """) self.assertEqual([ PurePath('/default'), PurePath('/generated'), ], config.bucket['_'].roots) self.assertEqual({'accept': ['*/*']}, config.bucket['_'].environment) self.assertEqual([PurePath('/json')], config.bucket['json'].roots) self.assertEqual({'accept': ['application/json', 'text/json']}, config.bucket['json'].environment) self.assertEqual([PurePath('/xml')], config.bucket['xml'].roots) self.assertEqual({'accept': ['application/xml', 'text/xml']}, config.bucket['xml'].environment)
def test_resource_dot_access_argument(self): # Test that dictionary values passed to resource also resolved. config = Configuration.from_toml(""" [environment.variables] some_value = "the value" [environment.paths] somewhere = "/" [[environment.objects]] __name__ = "dot" __init__ = "repodono.model.testing:AttrBaseMapping" value = "some_value" [bucket._] __roots__ = ['somewhere'] [[resource."/"]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path = "dot.value" [endpoint._."/entry/view"] __provider__ = "thing" """) exe = config.request_execution('/entry/view', {}) self.assertEqual(exe.locals['thing'].path, "the value") self.assertEqual(exe.execute().path, "the value")
def test_endpoint_kwargs_nested_remap(self): config = Configuration.from_toml(""" [environment.variables] thing = "env" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] accept = ["*/*"] # A common shared mock object [[resource."/"]] __name__ = "a_mock" __init__ = "unittest.mock:Mock" [endpoint._."/entry/{entry_id}/{action}"] # the template is fixed, but to test this thing out the kwargs # can be remapped using the __kwargs__ key __provider__ = "a_mock" __kwargs__.thing.mock_id = "entry_id" __kwargs__.thing.mock_method = "action" __kwargs__.thing.mock_thing = "thing" """) exe = config.request_execution('/entry/{entry_id}/{action}', { 'entry_id': '123', 'action': 'blah', }) self.assertEqual(exe.locals['a_mock'].thing['mock_id'], '123') self.assertEqual(exe.locals['a_mock'].thing['mock_method'], 'blah') self.assertEqual(exe.locals['a_mock'].thing['mock_thing'], 'env')
def test_endpoint_kwargs_shadowing(self): config = Configuration.from_toml(""" [environment.variables] thing = "thing" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] accept = ["*/*"] # A common shared mock object [[resource."/"]] __name__ = "a_mock" __init__ = "unittest.mock:Mock" mock_id = "thing" mock_method = "thing" [endpoint._."/entry/{entry_id}/{action}"] __provider__ = "a_mock" __kwargs__.mock_id = "entry_id" """) exe = config.request_execution('/entry/{entry_id}/{action}', { 'entry_id': '123', 'action': 'blah', }) self.assertEqual(exe.locals['a_mock'].mock_id, '123') self.assertEqual(exe.locals['a_mock'].mock_method, 'thing')
def test_resource_referenced_kwargs_to_be_provided(self): # Test out the resource definition that specified a required # keyword argument with a reference, but then that reference is # to be defined later. config = Configuration.from_toml(""" [environment.variables] some_name = "the value" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] accept = ["*/*"] # A common shared mock object [[resource."/"]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path = "some_reference" [endpoint._."/entry/"] # the template is fixed, but to test this thing out the kwargs # can be remapped using the __kwargs__ key __provider__ = "thing" __kwargs__.path = "some_name" [endpoint._."/entry/other"] # this endpoint will also make use of thing, but it defines a # static reference as a endpoint environment value __provider__ = "thing" some_reference = "static_value" [endpoint._."/entry/both"] # this endpoint has the required reference provided, but will # have a specific kwargs specified __provider__ = "thing" __kwargs__.path = "some_name" some_reference = "static_value" """) # check the other thing first, show that this typical creation # is not impeded. other_exe = config.request_execution('/entry/other', {}) self.assertEqual(other_exe.locals['thing'].path, 'static_value') # now for the main test, show that the path in kwargs will make # a reference to some_name, and where some_name is from the root # environment; note that 'some_reference' is not defined in this # set of execution locals. exe = config.request_execution('/entry/', {}) self.assertEqual(exe.execute().path, 'the value') both_exe = config.request_execution('/entry/both', {}) # the one provided by kwargs will take precedence. self.assertEqual(both_exe.execute().path, 'the value')
def test_no_default_bucket(self): root = TemporaryDirectory() self.addCleanup(root.cleanup) config = Configuration.from_toml(""" [environment.variables] foo = "bar" [environment.paths] base_root = %(root)r json_root = %(root)r xml_root = %(root)r [bucket.json] __roots__ = ["json_root"] accept = ["application/json", "text/json"] [bucket.xml] __roots__ = ["xml_root"] accept = ["application/xml", "text/xml"] [endpoint.json."/entry/{entry_id}/details"] __provider__ = "blog_entry_details" details = true format = "simple" [endpoint.xml."/entry/{entry_id}/details"] __provider__ = "blog_entry_details" details = true format = "verbose" [endpoint.xml."/entry/{entry_id}/debug"] __provider__ = "blog_entry_details" debug = true """ % {'root': root.name}) details = config.request_execution('/entry/{entry_id}/details', {'entry_id': '123'}, { 'accept': 'application/json', }) self.assertEqual(details.locals['format'], 'simple') with self.assertRaises(KeyError): # simple KeyError check for now, we will likely need a more # explicit type for this. config.request_execution('/entry/{entry_id}/details', {'entry_id': '123'}, { 'accept': 'text/plain', }) with self.assertRaises(KeyError): config.request_execution('/entry/{entry_id}/debug', {'entry_id': '123'}, { 'accept': 'application/json', })
def test_paths(self): root = TemporaryDirectory() self.addCleanup(root.cleanup) config = Configuration.from_toml(""" [environment.variables] foo = "bar" [environment.paths] base_root = %r """ % (root.name, )) self.assertEqual(config.environment['foo'], 'bar') self.assertTrue(isinstance(config.environment['base_root'], Path))
def test_execution_locals_default_shadowing(self): config = Configuration.from_toml(""" [environment.variables] one = "one" two = "two" [environment.paths] somewhere = "/" [default.variables] two = 2 three = 3 four = 4 [bucket._] __roots__ = ['somewhere'] [[resource."/"]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path = "one" # resource entries are shadowed in reverse order. [[resource."/"]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path = "two" # resource entries are shadowed in reverse order. [[resource."/"]] __name__ = "default" __init__ = "repodono.model.testing:Thing" path = "three" # resource entries are shadowed in reverse order. [[resource."/"]] __name__ = "four" __init__ = "repodono.model.testing:Thing" path = "three" [endpoint._."/"] __provider__ = "target" """) exe = config.request_execution('/', {}) # the default value should be shadows as environment has it self.assertEqual(exe.locals['thing'].path, 'two') # default value should be available self.assertEqual(exe.locals['default'].path, 3) # had "four" defined at environment.variables, test fails here. self.assertTrue(hasattr(exe.locals.four, 'path')) self.assertNotEqual(exe.locals['four'], 4)
def test_metadata_object(self): root = TemporaryDirectory() self.addCleanup(root.cleanup) config = Configuration.from_toml(""" [metadata.variables] foo = "bar" [metadata.paths] base_root = %r [[metadata.objects]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path = "base_root" """ % (root.name, )) self.assertTrue(isinstance(config.metadata['thing'].path, Path))
def test_localmap(self): # Test out the resource definition that specified a required # keyword argument with a reference, but then that reference is # to be defined later. config = Configuration.from_toml(""" [environment.variables] some_name = "the value" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] accept = ["*/*"] # A common shared mock object [[resource."/"]] __name__ = "a_mock" __init__ = "unittest.mock:Mock" [localmap."/entry/"] key = "some_name" some_map.key1 = "some_name" some_map.key2 = "some_name" [endpoint._."/entry/"] __provider__ = "a_mock" __kwargs__.arg1 = "key" __kwargs__.arg2 = "some_map" [endpoint._."/entry/other"] # this endpoint will be invalid as the localmap entry would not # apply here. __provider__ = "a_mock" __kwargs__.arg1 = "key" """) exe = config.request_execution('/entry/', {}) self.assertEqual(exe.execute().arg1, 'the value') self.assertEqual(exe.execute().arg2, { 'key1': 'the value', 'key2': 'the value', }) # check the other thing first, show that this typical creation # is not impeded. other_exe = config.request_execution('/entry/other', {}) with self.assertRaises(MappingReferenceError): other_exe.locals['a_mock']
def test_basic_resource(self): root = TemporaryDirectory() self.addCleanup(root.cleanup) config = Configuration.from_toml(""" [environment.paths] root_path = %r [[resource."/entry/{entry_id}"]] __name__ = "blog_entry" __init__ = "repodono.model.testing:Thing" path = "root_path" """ % (root.name, )) self.assertEqual(1, len(config.resource['/entry/{entry_id}'])) self.assertIn('blog_entry', config.compiled_route_resources['/entry/{entry_id}'])
def test_resource_literal_eval(self): # Test that arguments for a resource may be a quoted literal # string, which will not be dereferenced. config = Configuration.from_toml(""" [environment.variables] some_name = "the value" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] [[resource."/"]] __name__ = "thing1" __init__ = "repodono.model.testing:Thing" path = "'literal'" [[resource."/"]] __name__ = "thing2" __init__ = "repodono.model.testing:Thing" path.key1 = "some_name" path.key2 = "'literal'" path.key3 = ["'literal1'", "'literal2'"] [endpoint._."/entry/view1"] __provider__ = "thing1" [endpoint._."/entry/view2"] __provider__ = "thing2" """) exe1 = config.request_execution('/entry/view1', {}) self.assertEqual(exe1.locals['thing1'].path, 'literal') self.assertEqual(exe1.execute().path, 'literal') exe2 = config.request_execution('/entry/view2', {}) self.assertEqual( exe2.locals['thing2'].path, { 'key1': 'the value', 'key2': 'literal', 'key3': ['literal1', 'literal2'] }) self.assertEqual( exe2.execute().path, { 'key1': 'the value', 'key2': 'literal', 'key3': ['literal1', 'literal2'] })
def test_execution_bytes_type(self): std_root = TemporaryDirectory() self.addCleanup(std_root.cleanup) config = Configuration.from_toml(""" [[environment.objects]] __name__ = "results" __init__ = "repodono.model.testing:Results" [environment.paths] std_root = %r [bucket._] __roots__ = ['std_root'] accept = ["*/*"] [endpoint._."/results{/path*}"] __provider__ = "results.sample_bytes" """ % (std_root.name, ), execution_class=HttpExecution) data = config.request_execution('/results{/path*}', {'path': ['data']}) response = data() self.assertEqual(b'example', response.content) self.assertEqual({ 'content-type': 'application/octet-stream', }, response.headers) self.assertEqual( { 'content-type': 'text/plain', }, config.request_execution('/results{/path*}', {'path': ['index.html']})().headers) self.assertEqual( { 'content-type': 'text/plain', }, config.request_execution('/results{/path*}', {'path': ['index.js']})().headers) self.assertEqual( { 'content-encoding': 'gzip', 'content-type': 'application/x-tar' }, config.request_execution('/results{/path*}', {'path': ['archive.tar.gz']})().headers)
def test_default_objects(self): root = TemporaryDirectory() self.addCleanup(root.cleanup) config = Configuration.from_toml(""" [default.variables] foo = "bar" [default.paths] base_root = %r [[default.objects]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path = "base_root" """ % (root.name, )) self.assertTrue(isinstance(config.default['thing'].path, Path)) self.assertEqual(config.default['foo'], 'bar')
def test_basic_endpoints_lists(self): config = Configuration.from_toml(""" [endpoint._."/entry/{entry_id}"] __provider__ = "blog_entry" item = 2 target = "html" [endpoint."json"."/entry/{entry_id}/debug"] __provider__ = "blog_entry" item = 2 target = "json" """) self.assertEqual([ '/entry/{entry_id}', '/entry/{entry_id}/debug', ], config.endpoint_keys)
def test_base(self): config_str = """ [config] foo = 'bar' [settings] foo = 'bar' [environment.variables] foo = 'bar' """ config = Configuration.from_toml(config_str) # this test that the raw import works. self.assertEqual(config['environment']['variables']['foo'], 'bar') # also that other arbitrary undefined key/values are kept self.assertEqual(config['config']['foo'], 'bar') self.assertEqual(config['settings']['foo'], 'bar')
def test_config_endpoint_root_usage(self): with self.assertRaises(TypeError) as e: config = Configuration.from_toml(""" [environment.variable] root = "foo" [endpoint._."/"] __provider__ = 'root' __root__ = 'root' """) config.endpoint['_']['/'].root self.assertEqual( e.exception.args[0], "'root' must be declared under environment.paths", # see above TODO )
def test_execution_locals_shadowing_environment(self): config = Configuration.from_toml(""" [environment.variables] value = "value" target = "the target" one = "one" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] # this should not be able to shadow the environment variables. [[resource."/"]] __name__ = "target" __init__ = "repodono.model.testing:Die" [[resource."/"]] __name__ = "die" __init__ = "repodono.model.testing:Die" [[resource."/"]] __name__ = "three" __init__ = "repodono.model.testing:Die" [endpoint._."/"] __provider__ = "target" one = 1 three = 3 """) exe = config.request_execution('/', {}) self.assertEqual(exe.locals['target'], 'the target') # environment has greatest precedence self.assertEqual(exe.locals['one'], 'one') # endpoint environment has second greatest self.assertEqual(exe.locals['three'], 3) with self.assertRaises(Exception): # just to ensure that this other definition will then # trigger the loading. exe.locals['die']
def test_endpoint_not_none(self): # Test that dictionary values passed to resource also resolved. config = Configuration.from_toml(""" [environment.variables] some_name = "Person" some_value = "Value" [[environment.objects]] __name__ = "a_mapping" __init__ = "repodono.model.base:BaseMapping" some_name = "some_name" some_value = "some_value" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] [[resource."/get/{key}"]] __name__ = "a_mapping_get" __call__ = "a_mapping.get" key = "key" [endpoint._."/get/{key}"] __provider__ = "a_mapping_get" __notnone__ = ["a_mapping_get"] """) # verify that the base case works exe = config.request_execution('/get/{key}', {'key': 'some_name'}) self.assertEqual(exe.locals['a_mapping_get'], 'Person') self.assertEqual(exe(), 'Person') exe = config.request_execution('/get/{key}', {'key': 'nothing'}) self.assertEqual(exe.locals['a_mapping_get'], None) with self.assertRaises(ExecutionNoResultError) as e: exe() self.assertEqual( e.exception.args[0], "'a_mapping_get' unexpectedly resolved to None for end point " "in bucket '_' with route '/get/{key}'")
def test_list_items_resolved(self): root = TemporaryDirectory() self.addCleanup(root.cleanup) config = Configuration.from_toml(""" [environment.variables] text = "hello" number = 0 [environment.paths] base_root = %r [[environment.objects]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" path = ["text", "number", "base_root"] """ % (root.name, )) env = config.environment self.assertEqual( [env['text'], env['number'], env['base_root']], env['thing'].path, )
def test_resource_missing_kwargs_provided_endpoint(self): # Test out the resource definition that did not define a # required argument with a reference, but then the provider has # provided one. config = Configuration.from_toml(""" [environment.variables] some_name = "the value" [environment.paths] somewhere = "/" [bucket._] __roots__ = ['somewhere'] accept = ["*/*"] # A common shared mock object [[resource."/"]] __name__ = "thing" __init__ = "repodono.model.testing:Thing" [endpoint._."/entry/"] # the template is fixed, but to test this thing out the kwargs # can be remapped using the __kwargs__ key __provider__ = "thing" __kwargs__.path = "some_name" [endpoint._."/entry/view"] # the provider is simply the value, but for this test the locals # will be requested from here but will test deferencing the # above. __provider__ = "some_name" """) exe = config.request_execution('/entry/', {}) self.assertEqual(exe.locals['thing'].path, 'the value') # this would have simply access the value like above also self.assertEqual(exe.execute().path, 'the value') # this other view did not directly inititate or provide a value other_exe = config.request_execution('/entry/view', {}) with self.assertRaises(TypeError): other_exe.locals['thing']