class SiteGrokker(martian.ClassGrokker): """Grokker for subclasses of `grokcore.site.Site`.""" martian.component(grokcore.site.components.BaseSite) martian.priority(500) martian.directive(grokcore.site.local_utility, name='infos') martian.directive(grokcore.site.install_on, default=IObjectAddedEvent) def execute(self, factory, config, infos, install_on, **kw): if not infos: return False infos = infos.values() for info in infos: if info.public and not IContainer.implementedBy(factory): raise GrokError( "Cannot set public to True with grok.local_utility as " "the site (%r) is not a container." % factory, factory) # Store the list of info objects in their "natural" order on the # site class. They will be picked up by a subscriber doing the # actual registrations in definition order. factory.__grok_utilities_to_install__ = sorted(infos) adapts = (factory, install_on) config.action( discriminator=None, callable=grokcore.component.provideHandler, args=(localUtilityRegistrationSubscriber, adapts), ) return True
class MenuGrokker(martian.ClassGrokker): martian.component(uvc.menus.components.Menu) martian.directive(grokcore.component.context, default=Interface) martian.directive(grokcore.view.layer, default=IDefaultBrowserLayer) martian.directive(grokcore.viewlet.view, default=Interface) martian.directive(grokcore.component.name, get_default=default_view_name) martian.directive(grokcore.security.require, name='permission') def grok(self, name, factory, module_info, **kw): # Need to store the module info object on the view class so that it # can look up the 'static' resource directory. factory.module_info = module_info return super(MenuGrokker, self).grok( name, factory, module_info, **kw) def execute(self, factory, config, context, layer, view, name, permission, **kw): # This will be used to support __name__ on the viewlet manager factory.__view_name__ = name config.action( discriminator=('Menu', context, layer, view, name), callable=grokcore.component.provideAdapter, args=(factory, (context, layer, view), uvc.menus.components.IMenu , name)) config.action( discriminator=('protectName', factory), callable=make_checker, args=(factory, factory, permission, ['available'])) return True
class ContentGrokker(martian.ClassGrokker): martian.component(DexterityContent) martian.directive(add_permission, default=None) martian.directive(grokcore.component.name, default=None) def execute(self, class_, config, add_permission, name, **kw): # Register class if a meta type was specified. # (most types will probably not need this.) if add_permission: meta_type = getattr(class_, 'meta_type', None) registerClass(config, class_, meta_type, add_permission) # Register a factory utility - defer this to the end of ZCML # processing, since there may have been another utility manually # registered if name: config.action( discriminator=('dexterity:registerFactory', class_, name), callable=register_factory, args=(class_, name), order=9999, ) # Initialise class security config.action(discriminator=('dexterity:registerClass', class_), callable=InitializeClass, args=(class_, )) return True
class StepGrokker(martian.ClassGrokker): """Grokker to register sub forms. """ martian.component(WizardStep) martian.directive(grokcore.component.context) martian.directive(grokcore.view.layer, default=IDefaultBrowserLayer) martian.directive(grokcore.view.view) martian.directive(grokcore.view.name, get_default=default_view_name) def grok(self, name, factory, module_info, **kw): factory.module_info = module_info return super().grok(name, factory, module_info, **kw) def execute(self, factory, config, context, layer, view, name, **kw): if not factory.__dict__.get('prefix'): factory.prefix = '%s.%s' % (view.prefix, name) adapts = (context, view, layer) config.action( discriminator=('adapter', adapts, IStep, name), callable=grokcore.component.util.provideAdapter, args=(factory, adapts, IStep, name), ) return True
class ViewGrokker(martian.ClassGrokker): martian.component(components.View) martian.directive(grokcore.component.context) martian.directive(grokcore.view.layer, default=IDefaultBrowserLayer) martian.directive(grokcore.component.provides, default=interface.Interface) martian.directive(grokcore.component.name, get_default=default_view_name) def execute(self, factory, config, context, layer, provides, name, **kw): # safety belt: make sure that the programmer didn't use # @grok.require on any of the view's methods. methods = util.methods_from_class(factory) for method in methods: if grokcore.security.require.bind().get(method) is not None: raise GrokError( 'The @grok.require decorator is used for ' 'method %r in view %r. It may only be used ' 'for XML-RPC methods.' % (method.__name__, factory), factory) # __view_name__ is needed to support IAbsoluteURL on views factory.__view_name__ = name adapts = (context, layer) config.action( discriminator=('adapter', adapts, provides, name), callable=grokcore.component.provideAdapter, args=(factory, adapts, provides, name), ) return True
class AnnotationGrokker(martian.ClassGrokker): """Grokker for components subclassed from `grok.Annotation`. """ martian.component(grokcore.annotation.Annotation) martian.directive(grokcore.annotation.context, name='adapter_context') martian.directive(grokcore.annotation.provides, get_default=default_annotation_provides) martian.directive(grokcore.annotation.name, get_default=default_annotation_name) def execute(self, factory, config, adapter_context, provides, name, **kw): @component.adapter(adapter_context) @interface.implementer(provides) def getAnnotation(context): annotations = IAnnotations(context) try: result = annotations[name] except KeyError: result = factory() annotations[name] = result if result.__parent__ is None: result.__parent__ = context result.__name__ = name return result config.action( discriminator=('adapter', adapter_context, provides, ''), callable=grokcore.component.provideAdapter, args=(getAnnotation, ), ) return True
class PermissionGrokker(martian.ClassGrokker): martian.component(grokcore.security.Permission) martian.priority(1500) martian.directive(grokcore.component.name) martian.directive(grokcore.component.title, get_default=default_fallback_to_name) martian.directive(grokcore.component.description) def execute(self, factory, config, name, title, description, **kw): if not name: raise GrokError( "A permission needs to have a dotted name for its id. Use " "grok.name to specify one.", factory) # We can safely convert to unicode, since the directives make sure # it is either unicode already or ASCII. permission = factory(unicode(name), unicode(title), unicode(description)) config.action( discriminator=('utility', IPermission, name), callable=grokcore.component.provideUtility, args=(permission, IPermission, name), order=-1 # need to do this early in the process ) return True
class StoreGrokker(martian.ClassGrokker): martian.component(megrok.storm.Store) martian.directive(megrok.storm.storename) martian.directive(megrok.storm.uri) def execute(self, factory, config, storename, uri, **kw): store(config, storename, uri) return True
class AppRootGrokker(martian.ClassGrokker): martian.component(megrok.storm.AppRoot) martian.directive(megrok.storm.key) martian.directive(megrok.storm.rdb_object) def execute(self, class_, key, rdb_object, **kw): class_.key = key class_.rdb_object = rdb_object return True
class WizardStepGrokker(martian.ClassGrokker): martian.component(components.BaseStep) martian.directive(grokcore.component.context) martian.directive(grokcore.component.name, get_default=default_view_name) def execute(self, factory, config, context, name, **kw): wizardStepDirective(config, factory, name, 'zope.Public', wizard=context) return True
class SubscriptionGrokker(martian.ClassGrokker): martian.component(grokcore.component.Subscription) martian.directive(grokcore.component.context) martian.directive(grokcore.component.provides) martian.directive(grokcore.component.name) def execute(self, factory, config, context, provides, name, **kw): config.action( discriminator=None, callable=grokcore.component.provideSubscriptionAdapter, args=(factory, (context, ), provides), ) return True
class TraverserGrokker(martian.ClassGrokker): """Grokker for subclasses of `grok.Traverser`.""" martian.component(grokcore.traverser.Traverser) martian.directive(grokcore.component.context) martian.directive(grokcore.view.layer, default=IDefaultBrowserLayer) def execute(self, factory, config, context, layer, **kw): adapts = (context, layer) config.action( discriminator=('adapter', adapts, IBrowserPublisher, ''), callable=grokcore.component.provideAdapter, args=(factory, adapts, IBrowserPublisher), ) return True
class FormSchemaGrokker(martian.InstanceGrokker): """Grok form schema hints.""" martian.component(Schema.__class__) martian.directive(depends) def execute(self, interface, config, **kw): if not interface.extends(Schema): return False # Copy from temporary to real value directiveSupplied = interface.queryTaggedValue(TEMP_KEY, None) if directiveSupplied is not None: for key, tgv in list(directiveSupplied.items()): existingValue = interface.queryTaggedValue(key, None) if existingValue is not None: if type(existingValue) != type(tgv): # Don't overwrite if we have a different type continue elif isinstance(existingValue, list): existingValue.extend(tgv) tgv = existingValue elif isinstance(existingValue, dict): existingValue.update(tgv) tgv = existingValue interface.setTaggedValue(key, tgv) interface.setTaggedValue(TEMP_KEY, None) return True
class ViewletSecurityGrokker(martian.ClassGrokker): martian.component(five.grok.Viewlet) martian.directive(grokcore.security.require, name='permission') def execute(self, factory, config, permission, **kw): if permission is None: permission = 'zope.Public' attributes = [ 'update', 'render', ] config.action(discriminator=('five:protectClass', factory), callable=protectClass, args=(factory, permission)) for attribute in attributes: config.action(discriminator=('five:protectName', factory, attribute), callable=protectName, args=(factory, attribute, permission)) # Protect the class config.action(discriminator=('five:initialize:class', factory), callable=initializeClass, args=(factory, )) return True
class DirectoryResourceGrokker(martian.ClassGrokker): martian.component(components.ZopeTwoDirectoryResource) martian.directive(grokcore.view.name, default=None) martian.directive(grokcore.view.path) martian.directive(grokcore.view.layer, default=IDefaultBrowserLayer) def grok(self, name, factory, module_info, **kw): # Need to store the module info object on the directory resource # class so that it can look up the actual directory. factory.module_info = module_info return super(DirectoryResourceGrokker, self).grok(name, factory, module_info, **kw) def execute(self, factory, config, name, path, layer, **kw): resource_path = _get_resource_path(factory.module_info, path) name = name or factory.module_info.dotted_name return _register_resource(config, resource_path, name, layer)
class ExtModelGrokker(martian.ClassGrokker): martian.component(ExtBaseModel) martian.directive(schema) martian.directive(namedirective) def execute(self, class_, schema, name, **kw): if schema is None: raise GrokError( 'Class %s is missing directive "schema". Need a Interface\ to create the model.' % class_, class_) if not name: name = class_.__name__ gsm = component.getGlobalSiteManager() transformer = ModelTransfomerUtility(class_, schema) gsm.registerUtility(transformer, IModelTransformer, name) return True
class ModelGrokker(martian.ClassGrokker): martian.component(megrok.storm.Model) martian.directive(megrok.storm.tablename, get_default=default_tablename) def execute(self, class_, tablename, **kw): class_.__storm_table__ = tablename # we associate the _decl_registry with the metadata object # to make sure it's unique per metadata. A bit of a hack.. return True
class MultiSubscriptionGrokker(martian.ClassGrokker): martian.component(grokcore.component.MultiSubscription) martian.directive(grokcore.component.provides) martian.directive(grokcore.component.name) def execute(self, factory, config, provides, name, **kw): adapts = component.adaptedBy(factory) if adapts is None: raise GrokError( "%r must specify which contexts it adapts " "(use the 'adapts' directive to specify)." % factory, factory) config.action( discriminator=None, callable=grokcore.component.provideSubscriptionAdapter, args=(factory, adapts, provides), ) return True
class LayoutGrokker(martian.ClassGrokker): martian.component(Layout) martian.directive(grokcore.component.context) martian.directive(grokcore.view.layer, default=IDefaultBrowserLayer) martian.directive(grokcore.component.provides, default=ILayout) def grok(self, name, factory, module_info, **kw): factory.module_info = module_info return super(LayoutGrokker, self).grok(name, factory, module_info, **kw) def execute(self, factory, config, context, layer, provides, **kw): adapts = (layer, context) config.action( discriminator=('adapter', adapts, provides), callable=grokcore.component.provideAdapter, args=(factory, adapts, provides), ) return True
class ClassImplementerGrokker(martian.ClassGrokker): martian.component(object) martian.directive(grokcore.component.implements) martian.priority(2000) def execute(self, class_, implements, **kw): if implements is None: return True classImplements(class_, implements) return True
class RoleGrokker(martian.ClassGrokker): """Grokker for components subclassed from `grok.Role`. Each role is registered as a global utility providing the service `IRole` under its own particular name, and then granted every permission named in its `grok.permission()` directive. """ martian.component(Role) martian.priority(martian.priority.bind().get(PermissionGrokker()) - 1) martian.directive(grokcore.component.name) martian.directive(grokcore.component.title, get_default=default_fallback_to_name) martian.directive(grokcore.component.description) martian.directive(permissions) def execute(self, factory, config, name, title, description, permissions, **kw): if not name: raise GrokError( "A role needs to have a dotted name for its id. Use " "grok.name to specify one.", factory) # We can safely convert to unicode, since the directives makes sure # it is either unicode already or ASCII. if not isinstance(title, Message): title = unicode(title) if not isinstance(description, Message): description = unicode(description) role = factory(unicode(name), title, description) config.action( discriminator=('utility', IRole, name), callable=grokcore.component.provideUtility, args=(role, IRole, name), ) for permission in permissions: config.action( discriminator=('grantPermissionToRole', permission, name), callable=rolePermissionManager.grantPermissionToRole, args=(permission, name), ) return True
class ProductFolderGrokker(martian.ClassGrokker): martian.component(ProductFolder) martian.directive(contenttype) martian.directive(grokcore.component.name, get_default=default_name) def execute(self, factory, config, contenttype, name): if not contenttype: raise GrokError( "%r must specify which contenttype should " "go into this ProductFolder. Please use the" "direcitve 'contenttype' for it." % factory, factory) name = name.capitalize() config.action( discriminator=('utility', IProductFolder, name), callable=zope.component.zcml.handler, args=('registerUtility', factory, IProductFolder, name), ) return True
class FormGrokker(martian.ClassGrokker): martian.component(components.GrokForm) martian.directive(grokcore.component.context) martian.priority(800) # Must be run before real formlib grokker. def execute(self, factory, config, context, **kw): # Set up form_fields from context class if they haven't been # configured manually already using our version of get_auto_fields if getattr(factory, 'form_fields', None) is None: factory.form_fields = formlib.get_auto_fields(context) return True
class CheckRequireGrokker(martian.ClassGrokker): """Ensure every grok.View has a grok.require directive""" martian.component(grok.View) martian.directive(grok.require, default=_require_marker) def execute(self, factory, config, require, **kw): if require is _require_marker: raise SecurityError( 'megrok.strictrequire requires %r to use the grok.require ' 'directive!' % factory, factory) return True
class CheckRequireGrokker(martian.ClassGrokker): """Ensure every grok.View has a grok.require directive""" martian.component(grok.View) martian.directive(grok.require, default=_require_marker) def execute(self, factory, config, require, **kw): if os.environ.get('UVC_SEC_CHECK') == '1': if require is _require_marker: context = grok.context.bind().get(factory) uvcsite.log('%r --> %r' % (factory, context)) return True
class CmdGrokker(martian.ClassGrokker): martian.component(Cmd) martian.directive(command) def execute(self, class_, command, **kw): if command is None: return False registry.commands()[command] = class_ class_.name = command return True
class CheckRequireRESTGrokker(martian.MethodGrokker): """Ensure every grok.REST has a grok.require directive""" martian.component(grok.REST) martian.directive(grok.require, default=_require_marker) def execute(self, factory, method, config, require, **kw): if require is _require_marker: raise SecurityError( 'megrok.strictrequire requires %r to use the grok.require ' 'directive on the method: %s!' % (factory, method), factory) return True
class RESTGrokker(martian.MethodGrokker): """Grokker for methods of a `grok.REST` subclass. When an application defines a `grok.REST` view, we do not actually register the view with the Component Architecture. Instead, we grok each of its methods separately, placing them each inside of a new class that we create on-the-fly by calling `type()`. We make each method the `__call__()` method of its new class, since that is how Zope always invokes views. And it is this new class that is then made the object of the two configuration actions that we schedule: one to activate it as a REST adapter for the context, and the other to prepare a security check for the adapter. This results in several registered views, typically with names like `GET`, `PUT`, and `POST` - one for each method that the `grok.REST` subclass defines. """ martian.component(grokcore.rest.REST) martian.directive(grokcore.component.context) martian.directive(grokcore.view.layer, default=grokcore.rest.IRESTLayer) martian.directive(grokcore.security.require, name='permission') def execute(self, factory, method, config, permission, context, layer, **kw): name = method.__name__ method_view = type(factory.__name__, (factory, ), {'__call__': method}) adapts = (context, layer) config.action( discriminator=('adapter', adapts, interface.Interface, name), callable=grokcore.component.provideAdapter, args=(method_view, adapts, interface.Interface, name), ) config.action( discriminator=('protectName', method_view, '__call__'), callable=make_checker, args=(factory, method_view, permission), ) return True
class ViewSecurityGrokker(martian.ClassGrokker): martian.component(components.View) martian.directive(grokcore.security.require, name='permission') def execute(self, factory, config, permission, **kw): for method_name in IBrowserPage: config.action( discriminator=('protectName', factory, method_name), callable=protect_getattr, args=(factory, method_name, permission), ) return True
class ActionGrokker(martian.ClassGrokker): martian.component(Subscription) martian.directive(action) def execute(self, class_, action, **kw): if action is None: return False if getattr(class_, 'cmd', None) is None: class_.cmd = _action_decorator_parametrized(class_)(class_.execute) class_._name = action return True