Re: Schema-by-interface options
"Martin Aspeli" <[email protected]> Thu, 21 Sep 2006 13:55:31 +0100
| Newsgroups | gmane.comp.web.zope.plone.archetypes.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi Kapil, > okay let's say i have an article content type, i have several different > flavors so to speak of article, feature, book review, movie review, > biography, etc. ie. a common base type w/ different applicable schemas and > views based on usage. > > another example... i have a places content type, which has movie theaters, > restaurants, museums, parks, bars, etc (ad nauseum). this is a better > example of the notion of wanting multiple flavors on a content type, ie. a > place is both a bar and a restaurant, both flavors contribute additional > specific schema. > > last example, plone.rules ;-) firing to add a press release flavor to a > news items put in press folder. Cool. :) Could you elaborate a bit more on how the "global" flavour thing may look? For example, imagine a scenario where you have a "global" 'tagging' flavour that adds a 'tag' field to any object marked with ITaggable. Let's say that you then *also* want to add a specific 'article' flavour or whatever. How would this look? > ContentFlavors does not store schemas persistently per instance or > persistently at all, all schemas are preeminent on disk. changing the on > disk schema definition, and restarting zope, instantly refreshes content > schema as it would with a normal class defined schema. there are two > persistent changes to the instance when applying flavors, an annotation of > flavor names, and optionally if a flavor marker interface is specified a > directly provides declaration on the content. Ah, get you - sounds good. > > The two use cases I find most difficult at the moment (that my/whit's > > branches are trying to solve) are: > > > > - Install product MyNews and the News type gets an extra two fields, a > > new view template and a new action. > > > > In b-org, this is done by registering an appropriate (possibly local) > > adapter for the schema, and possibly changing the FTI upon install. > > > > in content flavors, > this would be done by applying a custom interface to news type, > registering a flavor with an at schema for the two fields, > registering views (with browser menus) against the custom interface > (cmonfive does action conversion) > registering a (possibly local) flavor provider that provides the new > flavor schema and marker to the news type interface. > > since contentflavors doesn't touch the atcore, it requires the news type > to mixin flavoraware, although once their is any sort of delegation it > falls out just as well. configuring the interface application in zcml, > means that the lifecycle management for markers isn't nesc. Nice. I think that kind of delegation will land in 1.5 now, following the work that whit and I are doing, making ContentFlavors able to work without a mixin. > > - Install product MyTagging, which applies ITaggable to a bunch of > > content types. ITaggable implies that these content types also have a > > 'tag' field in their schema. > > > > In b-org, this is done by registering a new ISchemaExtender adapter. On > > my branch, I've tried to generalise this a bit - you adapt self to > > ISchemaComposer to get back a single schema, and this in turn look up > > all adapters from (context, composer) to ISchemaProvider, which can > > provide fragments of a schema. The default provider just looks as > > klass.schema (and there is caching going on). Providers are ordered. > > this scenario is pretty much the same with contentflavors, with the > registration of the flavor and the adapter to flavor provider. in fact it > comes out exactly the same as the previous scenario. Good. > >>> - Is it possible for a particular flavor to be installed in one Plone > >>> site but not in another (in the same Zope instance) > >> flavors are mostly just sugar around adapters, a local component > >> registry, and changing all the adaptation lookups to provide context ( > >> assuming some appropriate icomponentlookup adapters for AT content) > >> would allow for this. > > > > You don't need to pass 'context' to adapter/utility lookups to have it > > prefer local adapters over global ones (at least not in Zope 2.10) - > > Zope 3's threadlocal acquistion knows which component registry to use, > > and falls back on the global by default. In *tests* you need to call > > setHooks(), setSite(ploneSite), but that's about it. > > interesting. i need to checkout the site stuff in zope.app.component.. the > stuff in zope.component assumes an adapter from context to IComponentLookup Local components as of Zope 2.10 are sooo much nicer. Take a look at http://svn.plone.org/svn/plone/plone.portlets/trunk/plone/portlets/README.txt Look at the example immediately above the header "Registering portlet managers" and the use of it immediately below that header. Also take a look at GSLocalAddons in the collective. > aye, variableschemasupport had some borked and expensive hash method which > always failed afaicr, volatile caches are compariatively fast and well > known. True, but it also depends on the lifetime of that cache. The hash was expensive (and did the opposite of what it was trying to do), but running ClassGen when it's not necessary is expensive too. > if the object is in memory its _v_schema is only going to be > composed once till the object is either ghosted or mutated, Yeah - which may be reasonably often still, especially if it's per-instance. Also, I assume you generate methods on the instance and not on the __class__? > incidentally, > contentflavors already does instance cache invalidation via event, though > moving to the cache keys i proposed previously, you never need to > invalidate a composed schema, just signal accessor/mutator gen on instance. Why is it that you'd never need to invalidate? > > That's true. But if AT says, "I support the application of schemas by an > > adapter lookup", then that *does not work* without calling a > > ClassGen'ish thing at least once (after the lookup of the schema has > > been made the first time). This is because AT's basic ClassGen works at > > class loading time, and cannot do the adapter lookup (no context), and > > it relies on the .schema class-variable, which cannot be made dynamic > > like an instance-variable could wither @property. So, I think it'd dumb > > to support some way of delegating schemas to an adapter if you know that > > anyone who actually uses that functionality *must* do a dance with > > generating methods, opening that up to re-invention and bugs and > > possibly conflicts. > > > but those schema adapters are all going to have different semantics > potentially different semantics about lifecycle (ie. the always on case, > really only needs once in a process, instance mutation on mutation ).. > which is exactly why people have reimplemented classgen semantics that > work for their use cases, coming up with a base set of common primitives > for doing the drudgery is a step forward, but the application is always > going to be adapter driven. you can separate out to two stage adapters > which is what contentflavors does (although it takes a step further in > that you don't need an adapter just point a zcml flavor to a schema), such > that folks just wanting to use the framework to add schema don't have to > deal with class gen semantics, but the top level integration adapter > ( schemasetprovider for lack of a better term) has to know when it needs > to apply accessor/mutator generation (or defer via event to an adapter who > does). ie when you talk about changing things at runtime which need > initialization, you have to know there was a change, and knowing that > depends on what your doing. I think you're right - at least insofar as we're talking about per-instance versions. I think that for the per-class variations, having a generalised re-class-gen is acceptable, since the semantics there really are the same (it must happen *once*, on the first load of the Schema of that content type, and probably not again unless it's explicitly invalidated). Maybe we should consider having an adapter in AT for this stuff, with a default implementation that does what b-org does (generate for the __class__), and let things that need per-instance semantics override this? It just feels a bit wrong to me to not make it explicit that this stuff *is* needed. And further, if at some point in the future we manage to refactor AT so that it's no longer needed (the main reason it's needed now, I think, is that the security checks on fields rely on the method and its security assertions, but there may be others) we would be better insulated. An event that's fired on-schema-lookup may be another option . So - this stuff is in production and keeping you happy? Good :) My three main concerns then are: - How well does it handle the global per-class (possibly "global" only to a Plone site, via a local adapter) use case (i.e. the ITagger scenario above). - Are we in the clear about performance of composing schemas and possibly re-generating methods. Again, an explicitly invalidated cache of (class, flavours-tuple) may make sense. - What is the best way of doing the delegation in AT to avoid the mixin, but still keep ContentFlavours as an optional dependency for third party products? In particular, if ContentFlavours ends up being dependent on an overrides.zcml to override the Schem adapter on IBaseObject, then it will be incompatible with any other generalised solution that does the same. Not necessarily a huge problem, but it would be nice to avoid it. Cheers, Martin ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV