async def test_register_service_with_path(container_requester): cur_count = len(configure.get_configurations("guillotina.tests", "service")) class TestService(Service): async def __call__(self): path = self.request.matchdict["filepath"] component = self.request.matchdict["component"] return {"filepath": path, "component": component} configure.register_configuration( TestService, dict( context=IContainer, name="@foobar/endpoint/{component}/{filepath:path}", permission="guillotina.ViewContent", ), "service", ) assert len(configure.get_configurations( "guillotina.tests", "service")) == cur_count + 1 # noqa async with container_requester as requester: config = requester.root.app.config configure.load_configuration(config, "guillotina.tests", "service") config.execute_actions() response, status = await requester( "GET", "/db/guillotina/@foobar/endpoint/comp1/root/folder/another") assert response["filepath"] == "root/folder/another"
async def test_register_contenttype(container_requester): cur_count = len( configure.get_configurations('guillotina.tests', 'contenttype')) class IMyType(Interface): pass class MyType(Item): pass configure.register_configuration( MyType, dict(context=IContainer, schema=IMyType, type_name="MyType1", behaviors=["guillotina.behaviors.dublincore.IDublinCore"]), 'contenttype') assert len(configure.get_configurations( 'guillotina.tests', 'contenttype')) == cur_count + 1 # noqa async with container_requester as requester: config = requester.root.app.config # now test it... configure.load_configuration(config, 'guillotina.tests', 'contenttype') config.execute_actions() response, status = await requester('GET', '/db/guillotina/@types') assert any("MyType1" in s['title'] for s in response)
async def test_register_behavior(container_requester): cur_count = len( configure.get_configurations("guillotina.tests", "behavior")) from guillotina.interfaces import IResource from guillotina import schema class IMyBehavior(Interface): foobar = schema.Text() class IMyBehavior2(Interface): foobar = schema.Text() configure.behavior( title="MyBehavior", provides=IMyBehavior, factory="guillotina.behaviors.instance.AnnotationBehavior", for_="guillotina.interfaces.IResource", )() configure.behavior( title="MyBehavior2", provides=IMyBehavior2, factory="guillotina.behaviors.instance.AnnotationBehavior", for_="guillotina.interfaces.IResource", )() assert len(configure.get_configurations("guillotina.tests", "behavior")) == cur_count + 2 class IMyType(IResource): pass class MyType(Item): pass configure.register_configuration( MyType, dict(context=IContainer, schema=IMyType, type_name="MyType2", behaviors=[IMyBehavior]), "contenttype", ) root = get_utility(IApplication, name="root") config = root.app.config # now test it... configure.load_configuration(config, "guillotina.tests", "contenttype") configure.load_configuration(config, "guillotina.tests", "behavior") config.execute_actions() async with container_requester as requester: response, status = await requester("GET", "/db/guillotina/@types") type_ = [s for s in response if s["title"] == "MyType2"][0] assert "foobar" in type_["definitions"][ "guillotina.tests.test_configure.IMyBehavior"]["properties"] # also get_all_possible_schemas_for_type should come with this new behavior behaviors_schemas = get_all_possible_schemas_for_type("MyType2") assert IMyBehavior2 in behaviors_schemas
async def test_register_service_permission(container_requester): cur_count = len(configure.get_configurations('guillotina.tests', 'service')) class TestService(Service): async def __call__(self): return {"foo": "bar"} configure.permission('guillotina.NoBody', 'Nobody has access') configure.register_configuration( TestService, dict(context=IContainer, name="@foobar2", permission='guillotina.NoBody'), 'service') assert len(configure.get_configurations( 'guillotina.tests', 'service')) == cur_count + 1 # noqa async with container_requester as requester: config = requester.root.app.config configure.load_configuration(config, 'guillotina.tests', 'service') config.execute_actions() response, status = await requester('GET', '/db/guillotina/@foobar2') assert status == 401
async def test_creator_used_from_content_creation(dummy_guillotina): utils.login() async with transaction(db=await get_database("db")): container = await create_content("Container", id="guillotina", title="Guillotina") container.__name__ = "guillotina" utils.register(container) import guillotina.tests configure.register_configuration( Folder, dict( type_name="TestType2", behaviors=[], module=guillotina.tests ), # for registration initialization "contenttype", ) root = get_utility(IApplication, name="root") configure.load_configuration(root.app.config, "guillotina.tests", "contenttype") root.app.config.execute_actions() load_cached_schema() obj = await create_content_in_container( container, "TestType2", "foobar", creators=("root",), contributors=("root",) ) assert obj.creators == ("root",) assert obj.contributors == ("root",) behavior = IDublinCore(obj) assert behavior.creators == ("root",) assert behavior.contributors == ("root",)
async def test_allowed_types(dummy_guillotina): utils.login() async with transaction(db=await get_database("db")): container = await create_content("Container", id="guillotina", title="Guillotina") container.__name__ = "guillotina" utils.register(container) import guillotina.tests configure.register_configuration( Folder, dict( type_name="TestType", allowed_types=["Item"], module=guillotina.tests, # for registration initialization ), "contenttype", ) root = get_utility(IApplication, name="root") configure.load_configuration(root.app.config, "guillotina.tests", "contenttype") root.app.config.execute_actions() load_cached_schema() obj = await create_content_in_container(container, "TestType", "foobar") constrains = IConstrainTypes(obj, None) assert constrains.get_allowed_types() == ["Item"] assert constrains.is_type_allowed("Item") with pytest.raises(NotAllowedContentType): await create_content_in_container(obj, "TestType", "foobar") await create_content_in_container(obj, "Item", "foobar")
async def test_allowed_types(self, dummy_request): self.request = dummy_request utils.login(self.request) container = await create_content( 'Container', id='guillotina', title='Guillotina') container.__name__ = 'guillotina' utils._p_register(container) import guillotina.tests configure.register_configuration(Folder, dict( type_name="TestType", allowed_types=['Item'], module=guillotina.tests # for registration initialization ), 'contenttype') root = get_utility(IApplication, name='root') configure.load_configuration( root.app.config, 'guillotina.tests', 'contenttype') root.app.config.execute_actions() load_cached_schema() obj = await create_content_in_container(container, 'TestType', 'foobar') constrains = IConstrainTypes(obj, None) assert constrains.get_allowed_types() == ['Item'] assert constrains.is_type_allowed('Item') with pytest.raises(NotAllowedContentType): await create_content_in_container(obj, 'TestType', 'foobar') await create_content_in_container(obj, 'Item', 'foobar')
async def test_creator_used_from_content_creation(self, dummy_request): self.request = dummy_request utils.login(self.request) container = await create_content( 'Container', id='guillotina', title='Guillotina') container.__name__ = 'guillotina' utils._p_register(container) import guillotina.tests configure.register_configuration(Folder, dict( type_name="TestType2", behaviors=[], module=guillotina.tests # for registration initialization ), 'contenttype') root = get_utility(IApplication, name='root') configure.load_configuration( root.app.config, 'guillotina.tests', 'contenttype') root.app.config.execute_actions() load_cached_schema() obj = await create_content_in_container( container, 'TestType2', 'foobar', creators=('root',), contributors=('root',)) assert obj.creators == ('root',) assert obj.contributors == ('root',) behavior = IDublinCore(obj) assert behavior.creators == ('root',) assert behavior.contributors == ('root',)
async def test_register_behavior(container_requester): cur_count = len( configure.get_configurations('guillotina.tests', 'behavior')) from guillotina.interfaces import IFormFieldProvider, IResource from zope.interface import provider from guillotina import schema @provider(IFormFieldProvider) class IMyBehavior(Interface): foobar = schema.Text() class IMyBehavior2(Interface): foobar = schema.Text() configure.behavior( title="MyBehavior", provides=IMyBehavior, factory="guillotina.behaviors.instance.AnnotationBehavior", for_="guillotina.interfaces.IResource" )() configure.behavior( title="MyBehavior2", provides=IMyBehavior2, factory="guillotina.behaviors.instance.AnnotationBehavior", for_="guillotina.interfaces.IResource" )() assert len(configure.get_configurations('guillotina.tests', 'behavior')) == cur_count + 2 class IMyType(IResource): pass class MyType(Item): pass configure.register_configuration(MyType, dict( context=IContainer, schema=IMyType, type_name="MyType2", behaviors=[IMyBehavior] ), 'contenttype') root = getUtility(IApplication, name='root') config = root.app.config # now test it... configure.load_configuration(config, 'guillotina.tests', 'contenttype') configure.load_configuration(config, 'guillotina.tests', 'behavior') config.execute_actions() async with await container_requester as requester: response, status = await requester('GET', '/db/guillotina/@types') type_ = [s for s in response if s['title'] == 'MyType2'][0] assert 'foobar' in type_['definitions']['IMyBehavior']['properties'] # also get_all_possible_schemas_for_type should come with this new behavior behaviors_schemas = get_all_possible_schemas_for_type('MyType2') assert IMyBehavior2 in behaviors_schemas
def create_behaviors_factory(proto_name, proto_definition): if proto_definition.get("for", None) is None: raise Exception("We need a for interface") else: for_ = import_class(proto_definition.get("for")) if for_ is None: raise Exception("Wrong for interface") parent_class = import_class( proto_definition.get( "inherited_class", "guillotina.behaviors.instance.AnnotationBehavior")) schema_fields, tags = get_fields( properties=proto_definition.get("properties")) base_interface = proto_definition.get("base_interface", None) if base_interface is None: base_interface = Interface class_interface = InterfaceClass( "I" + proto_name, (base_interface, ), schema_fields, __module__="guillotina.contrib.dyncontent.interfaces", ) for field_id, tag in tags.items(): for tag_id, tag_metadata in tag.items(): if tag_id in SUPPORTED_DIRECTIVES: SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, tag_metadata) klass = type(proto_name, (parent_class, ), {}) klass.__module__ = "guillotina.contrib.dyncontent.behaviors" setattr(behaviors, proto_name, klass) behavior = { "for_": for_, "provides": class_interface, "data_key": proto_definition.get("data_key", "default"), "auto_serialize": proto_definition.get("auto_serialize", True), "name": proto_name, "name_only": proto_definition.get("name_only", False), "title": proto_definition.get("title", ""), "marker": proto_definition.get("marker", None), "description": proto_definition.get("description", ""), } configure.register_configuration(klass, behavior, "behavior")
async def __aenter__(self): configure.register_configuration(FoobarType, dict( schema=IFoobarType, portal_type="Foobar", behaviors=[] ), 'contenttype') requester = await super(CustomTypeSiteRequesterAsyncContextManager, self).__aenter__() config = requester.root.app.config # now test it... configure.load_configuration( config, 'guillotina.tests', 'contenttype') config.execute_actions() load_cached_schema() return requester
async def test_globally_addable_types(dummy_guillotina): utils.login() async with transaction(db=await get_database("db")): container = await create_content("Container", id="guillotina", title="Guillotina") container.__name__ = "guillotina" utils.register(container) import guillotina.tests # Define BarType which is not globally addable configure.register_configuration( Folder, dict(type_name="BarType", module=guillotina.tests, globally_addable=False), "contenttype") # Define the only content where BarType is addable configure.register_configuration( Folder, dict(type_name="FooType", allowed_types=["BarType"], module=guillotina.tests), "contenttype", ) root = get_utility(IApplication, name="root") configure.load_configuration(root.app.config, "guillotina.tests", "contenttype") root.app.config.execute_actions() load_cached_schema() # Check that BarType can be added in FooType foo = await create_content_in_container(container, "FooType", "foo") await create_content_in_container(foo, "BarType", "bar") # Check that BarType cannot be globally added with pytest.raises(NotAllowedContentType): await create_content_in_container(container, "BarType", "bar") # Check it can be bypassed await create_content_in_container(container, "BarType", "bar", check_constraints=False)
async def __aenter__(self): configure.register_configuration(FoobarType, dict( schema=IFoobarType, type_name="Foobar", behaviors=[ 'guillotina.behaviors.dublincore.IDublinCore' ] ), 'contenttype') requester = await super(CustomTypeContainerRequesterAsyncContextManager, self).__aenter__() config = requester.root.app.config # now test it... configure.load_configuration( config, 'guillotina.tests', 'contenttype') config.execute_actions() load_cached_schema() return requester
async def test_register_behavior(site_requester): cur_count = len( configure.get_configurations('guillotina.tests', 'behavior')) from guillotina.interfaces import IFormFieldProvider from zope.interface import provider from guillotina import schema @provider(IFormFieldProvider) class IMyBehavior(Interface): foobar = schema.Text() configure.behavior( title="MyBehavior", provides=IMyBehavior, factory="guillotina.behaviors.instance.AnnotationBehavior", for_="guillotina.interfaces.IResource")() assert len(configure.get_configurations('guillotina.tests', 'behavior')) == cur_count + 1 class IMyType(Interface): pass class MyType(Item): pass configure.register_configuration( MyType, dict(context=ISite, schema=IMyType, portal_type="MyType2", behaviors=[IMyBehavior]), 'contenttype') async with await site_requester as requester: config = requester.root.app.config # now test it... configure.load_configuration(config, 'guillotina.tests', 'contenttype') config.execute_actions() response, status = await requester('GET', '/db/guillotina/@types') type_ = [s for s in response if s['title'] == 'MyType2'][0] assert 'foobar' in type_['definitions']['IMyBehavior']['properties']
async def __aenter__(self): configure.register_configuration( FoobarType, dict( schema=IFoobarType, type_name="Foobar", behaviors=["guillotina.behaviors.dublincore.IDublinCore"], ), "contenttype", ) requester = await super( CustomTypeContainerRequesterAsyncContextManager, self).__aenter__() config = requester.root.app.config # now test it... configure.load_configuration(config, "guillotina.tests", "contenttype") config.execute_actions() load_cached_schema() return requester
async def test_register_service(container_requester): cur_count = len(configure.get_configurations("guillotina.tests", "service")) class TestService(Service): async def __call__(self): return {"foo": "bar"} configure.register_configuration( TestService, dict(context=IContainer, name="@foobar", permission="guillotina.ViewContent"), "service" ) assert len(configure.get_configurations("guillotina.tests", "service")) == cur_count + 1 # noqa async with container_requester as requester: config = requester.root.app.config configure.load_configuration(config, "guillotina.tests", "service") config.execute_actions() response, status = await requester("GET", "/db/guillotina/@foobar") assert response["foo"] == "bar"
async def test_register_service(site_requester): cur_count = len(configure.get_configurations('guillotina.tests', 'service')) class TestService(Service): async def __call__(self): return {"foo": "bar"} configure.register_configuration( TestService, dict(context=ISite, name="@foobar", permission='guillotina.ViewContent'), 'service') assert len(configure.get_configurations( 'guillotina.tests', 'service')) == cur_count + 1 # noqa async with await site_requester as requester: config = requester.root.app.config configure.load_configuration(config, 'guillotina.tests', 'service') config.execute_actions() response, status = await requester('GET', '/db/guillotina/@foobar') assert response['foo'] == 'bar'
file = CloudFileField(required=False) @configure.contenttype( schema=IFileContent, type_name="File", behaviors=[ "guillotina.behaviors.dublincore.IDublinCore" ]) class FileContent(Item): pass configure.register_configuration(Example, dict( context=IContainer, schema=IExample, type_name="Example", behaviors=[ "guillotina.behaviors.dublincore.IDublinCore" ] ), 'contenttype') @configure.service( context=IApplication, method='GET', permission='guillotina.AccessContent', name='@raise-http-exception') @configure.service( context=IApplication, method='POST', permission='guillotina.AccessContent', name='@raise-http-exception') async def raise_http_exception(context, request): raise HTTPUnprocessableEntity()
def create_content_factory(proto_name, proto_definition): parent_interface = import_class( proto_definition.get('inherited_interface', 'guillotina.interfaces.content.IFolder')) parent_class = import_class( proto_definition.get('inherited_class', 'guillotina.content.Folder')) schema_fields, tags = get_fields( properties=proto_definition.get('properties')) for fieldset_id, fieldset_list in proto_definition.get('fieldsets', {}).items(): for field_id in fieldset_list: tags.setdefault(field_id, {})['fieldset'] = fieldset_id class_interface = InterfaceClass('I' + proto_name, (parent_interface, ), schema_fields, __module__='guillotina_cms.interfaces') for field_id, tag in tags.items(): for tag_id, tag_metadata in tag.items(): if tag_id in SUPPORTED_DIRECTIVES: if tag_metadata is None: SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id) elif isinstance(tag_metadata, dict): SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, **tag_metadata) elif isinstance(tag_metadata, list): SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, *tag_metadata) elif tag_id == 'fieldset': SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, tag_metadata) elif isinstance(tag_metadata, str): SUPPORTED_DIRECTIVES[tag_id].apply( class_interface, **{field_id: tag_metadata}) klass = type(proto_name, (parent_class, ), {}) klass.__module__ = 'guillotina_cms.dyncontent' setattr(dyncontent, proto_name, klass) behaviors = [] for bhr in proto_definition.get('behaviors', []): if bhr in BEHAVIOR_CACHE: behaviors.append(BEHAVIOR_CACHE[bhr]) else: raise Exception(f"Behavior not found {bhr}") contenttype = { 'schema': class_interface, 'type_name': proto_name, 'allowed_types': proto_definition.get('allowed_types', []), 'add_permission': proto_definition.get('add_permission', 'guillotina.AddContent'), 'behaviors': behaviors } utility = query_utility(IResourceFactory, name=proto_name) if utility is not None: sm = get_global_components() sm.unregisterUtility(utility, IResourceFactory, proto_name) configure.register_configuration(klass, contenttype, 'contenttype') root = get_utility(IApplication, name='root') configure.load_configuration(root.app.config, 'guillotina_cms.dyncontent', 'contenttype') root.app.config.execute_actions() configure.clear() load_cached_schema() # Verify its created if proto_name in FACTORY_CACHE: del FACTORY_CACHE[proto_name] get_cached_factory(proto_name)
def create_behaviors_factory(proto_name, proto_definition): if proto_definition.get('for', None) is None: raise Exception('We need a for interface') else: for_ = import_class(proto_definition.get('for')) if for_ is None: raise Exception('Wrong for interface') parent_class = import_class( proto_definition.get( 'inherited_class', 'guillotina.behaviors.instance.AnnotationBehavior')) schema_fields, tags = get_fields( properties=proto_definition.get('properties')) base_interface = proto_definition.get('base_interface', None) if base_interface is None: base_interface = Interface class_interface = InterfaceClass('I' + proto_name, (base_interface, ), schema_fields, __module__='guillotina_cms.interfaces') for field_id, tag in tags.items(): for tag_id, tag_metadata in tag.items(): if tag_id in SUPPORTED_DIRECTIVES: SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, tag_metadata) klass = type(proto_name, (parent_class, ), {}) klass.__module__ = 'guillotina_cms.behaviors' behavior = { 'for_': for_, 'provides': class_interface, 'data_key': proto_definition.get('data_key', 'default'), 'auto_serialize': proto_definition.get('auto_serialize', True), 'name': proto_name, 'name_only': proto_definition.get('name_only', False), 'title': proto_definition.get('title', ''), 'marker': proto_definition.get('marker', None), 'description': proto_definition.get('description', '') } configure.register_configuration(klass, behavior, 'behavior') root = get_utility(IApplication, name='root') configure.load_configuration(root.app.config, 'guillotina_cms.behaviors', 'behavior') root.app.config.execute_actions() configure.clear() load_cached_schema() # Verify its created interface_name = 'guillotina_cms.interfaces.I' + proto_name utility = get_utility(IBehavior, name=interface_name) interface_name = 'guillotina_cms.interfaces.I' + proto_name utility2 = get_utility(IBehavior, name=proto_name) assert BEHAVIOR_CACHE[interface_name] == class_interface utility.interface == class_interface utility2.interface == class_interface
# this is for testing.py, do not import into other modules from guillotina import configure from guillotina.content import Item from guillotina.interfaces import IItem from guillotina.interfaces import ISite from guillotina.testing import Example from guillotina.testing import IExample configure.register_configuration( Item, dict(context=ISite, schema=IItem, portal_type="File", behaviors=["guillotina.behaviors.dublincore.IDublinCore"]), 'contenttype') configure.register_configuration( Example, dict(context=ISite, schema=IExample, portal_type="Example", behaviors=["guillotina.behaviors.dublincore.IDublinCore"]), 'contenttype')
async def foobar_sub(ob, evt): pass @configure.subscriber(for_=(IResource, IObjectAddedEvent), priority=-1000) def sync_foobar_sub(ob, evt): if not hasattr(evt, "called"): evt.called = 0 evt.called += 1 configure.register_configuration( Example, dict( context=IContainer, schema=IExample, type_name="Example", behaviors=["guillotina.behaviors.dublincore.IDublinCore"], ), "contenttype", ) class IExampleAddPermission(IResource): pass @implementer(IExampleAddPermission) class ExampleAddPermission(Resource): # type: ignore pass
def create_content_factory(proto_name, proto_definition): parent_interface = import_class( proto_definition.get("inherited_interface", "guillotina.interfaces.content.IFolder")) parent_class = import_class( proto_definition.get("inherited_class", "guillotina.content.Folder")) schema_fields, tags = get_fields( properties=proto_definition.get("properties")) class_interface = InterfaceClass( "I" + proto_name, (parent_interface, ), schema_fields, __module__="guillotina.contrib.dyncontent.interfaces", ) for field_id, tag in tags.items(): for tag_id, tag_metadata in tag.items(): if tag_id in SUPPORTED_DIRECTIVES: if tag_metadata is None: SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id) elif isinstance(tag_metadata, dict): SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, **tag_metadata) elif isinstance(tag_metadata, list): SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, *tag_metadata) elif tag_id == "fieldset": SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, tag_metadata) elif isinstance(tag_metadata, str): SUPPORTED_DIRECTIVES[tag_id].apply( class_interface, **{field_id: tag_metadata}) klass = type(proto_name, (parent_class, ), {}) klass.__module__ = "guillotina.contrib.dyncontent.contents" setattr(contents, proto_name, klass) behaviors = [] for bhr in proto_definition.get("behaviors", []): if bhr in BEHAVIOR_CACHE: behaviors.append(BEHAVIOR_CACHE[bhr]) else: raise Exception(f"Behavior not found {bhr}") contenttype = { "schema": class_interface, "type_name": proto_name, "allowed_types": proto_definition.get("allowed_types", []), "add_permission": proto_definition.get("add_permission", "guillotina.AddContent"), "behaviors": behaviors, } utility = query_utility(IResourceFactory, name=proto_name) if utility is not None: sm = get_global_components() sm.unregisterUtility(utility, IResourceFactory, proto_name) configure.register_configuration(klass, contenttype, "contenttype")