def execute(self, factory, config, protect_get, protect_set, **kw): get_names = {} for permission, attrs in protect_get: for name in attrs: if name in get_names: raise GrokError( "Duplicate read protection for %r " "attribute on %r." % (name, factory), factory) get_names[name] = permission set_names = {} for permission, attrs in protect_set: for name in attrs: if name in set_names: raise GrokError( "Duplicate write protection for %r " "attribute on %r." % (name, factory), factory) set_names[name] = permission for name, permission in get_names.items(): config.action( discriminator=('protectName', factory, name), callable=protect_getattr, args=(factory, name, permission), ) for name, permission in set_names.items(): config.action( discriminator=('protectSetAttribute', factory, name), callable=protect_setattr, args=(factory, name, permission), ) return True
def grok(self, name, module, context, module_info, templates): # we're only interested in static resources if this module # happens to be a package if not module_info.isPackage(): return False resource_path = module_info.getResourcePath('static') if os.path.isdir(resource_path): static_module = module_info.getSubModuleInfo('static') if static_module is not None: if static_module.isPackage(): raise GrokError( "The 'static' resource directory must not " "be a python package.", module_info.getModule()) else: raise GrokError( "A package can not contain both a 'static' " "resource directory and a module named " "'static.py'", module_info.getModule()) resource_factory = components.DirectoryResourceFactory( resource_path, module_info.dotted_name) component.provideAdapter( resource_factory, (IDefaultBrowserLayer,), interface.Interface, name=module_info.dotted_name) return True
def check_implements_one_from_list(list, class_): if len(list) < 1: raise GrokError("%r must implement at least one interface " "(use grok.implements to specify)." % class_, class_) elif len(list) > 1: raise GrokError("%r is implementing more than one interface " "(use grok.provides to specify which one to use)." % class_, class_)
def _register_template_file(self, module_info, template_path): template_dir, template_file = os.path.split(template_path) for pattern in self._ignored_patterns: if pattern.search(template_file): return template_name, extension = os.path.splitext(template_file) if (template_dir, template_name) in self._reg: raise GrokError( "Conflicting templates found for name '%s' " "in directory '%s': multiple templates with " "the same name and different extensions." % (template_name, template_dir), None) # verify no inline template exists with the same name try: inline_template_registry.lookup(module_info, template_name) except TemplateLookupError: pass else: raise GrokError( "Conflicting templates found for name '%s': " "the inline template in module '%s' conflicts " "with the file template in directory '%s'" % (template_name, module_info.dotted_name, template_dir), None) extension = extension[1:] # Get rid of the leading dot. template_factory = zope.component.queryUtility( grokcore.view.interfaces.ITemplateFileFactory, name=extension) if template_factory is None: # Warning when importing files. This should be # allowed because people may be using editors that generate # '.bak' files and such. if extension == 'pt': warnings.warn( "You forgot to embed the zcml slug for " "grokcore.view. It provides a renderer " "for pt files. Now the file '%s' in '%s' " "cannot be rendered" % (template_file, template_dir), UserWarning, 2) elif extension == '': """Don't choke on subdirs or files without extensions.""" return else: warnings.warn( "File '%s' has an unrecognized extension in " "directory '%s'" % (template_file, template_dir), UserWarning, 2) return template = template_factory(template_file, template_dir) template._annotateGrokInfo(template_name, template_path) self._reg[(template_dir, template_name)] = template self._unassociated.add(template_path)
def check_provides_one(obj): provides = list(interface.providedBy(obj)) if len(provides) < 1: raise GrokError( "%r must provide at least one interface " "(use zope.interface.classProvides to specify)." % obj, obj) if len(provides) > 1: raise GrokError( "%r provides more than one interface " "(use grok.provides to specify which one to use)." % obj, obj)
def get_default(cls, component, module=None, **data): components = list(scan_for_classes(module, IViewletManager)) if len(components) == 0: raise GrokError( "No module-level viewletmanager for %r, please use the " "'viewletmanager' directive." % (component), component) elif len(components) == 1: component = components[0] else: raise GrokError( "Multiple possible viewletmanagers for %r, please use the " "'viewletmanager' directive." % (component), component) return component
def get_default(cls, component, module=None, **data): components = list(scan_for_classes(module, IMenu)) if len(components) == 0: raise GrokError( "No module-level menu for %r, please use the " "'menu' directive." % (component), component) elif len(components) == 1: component = components[0] else: raise GrokError( "Multiple possible menus for %r, please use the " "'menu' directive." % (component), component) return component
def get_default(cls, component, module=None, **data): components = list(scan_for_classes(module, IContext)) if len(components) == 0: raise GrokError( "No module-level context for %r, please use the 'context' " "directive." % (component), component) elif len(components) == 1: component = components[0] else: raise GrokError( "Multiple possible contexts for %r, please use the 'context' " "directive." % (component), component) return component
def setup(self, catalog, name, context, module_info): # If the user supplied attribute= when instantiating us, we # allow that value to override the attribute name under which we # are actually stored inside of the `grokcore.catalog.Indexes` # instance. if self._attribute is not None: field_name = self._attribute else: field_name = name if IInterface.providedBy(context): try: method = context[field_name] except KeyError: raise GrokError( "grokcore.catalog.Indexes in %r refers to an attribute or " "method %r on interface %r, but this does not " "exist." % (module_info.getModule(), field_name, context), None) call = IMethod.providedBy(method) else: call = callable(getattr(context, field_name, None)) context = None # no interface lookup catalog[name] = self.index_class( field_name=field_name, interface=context, field_callable=call, *self._args, **self._kw)
def grok(self, name, interface, module_info, config, **kw): # This `InstanceGrokker` will be called for every instance of # `InterfaceClass` - that is, for every interface defined in an # application module! So we have to do our own filtering, by # checking whether each interface includes the `grok.restskin()` # directive, and skipping those that do not. restskin = grokcore.rest.restskin.bind( default=_restskin_not_used).get(interface) if restskin is _restskin_not_used: # The restskin directive is not actually used on the found # interface. return False if not interface.extends(grokcore.rest.IRESTLayer): # For REST layers it is required to extend IRESTLayer. raise GrokError( "The grok.restskin() directive is used on interface %r. " "However, %r does not extend IRESTLayer which is " "required for interfaces that are used as layers and are to " "be registered as a restskin." % (interface.__identifier__, interface.__identifier__), interface) config.action(discriminator=('restprotocol', restskin), callable=grokcore.component.provideInterface, args=(restskin, interface, grokcore.rest.IRESTSkinType)) return True
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
def grok(self, name, factory, module_info, config, **kw): site = grokcore.site.site.bind().get(factory) context = grokcore.component.context.bind().get( factory, module_info.getModule()) install_on = grokcore.site.install_on.bind( default=IObjectAddedEvent).get(factory) catalog_name = grokcore.component.name.bind().get(factory) if site is None: raise GrokError( "No site specified for grokcore.catalog.Indexes " "subclass in module %r. " "Use grokcore.site.site() to specify." % module_info.getModule(), factory) indexes = getattr(factory, '__grok_indexes__', None) if indexes is None: return False subscriber = IndexesSetupSubscriber(catalog_name, indexes, context, module_info) subscribed = (site, install_on) config.action(discriminator=None, callable=grokcore.component.provideHandler, args=(subscriber, subscribed)) return True
def grok(self, name, class_, module_info=None, **kw): module = None if module_info is not None: module = module_info.getModule() # Populate the data dict with information from class or module directives = directive.bind().get(self.__class__) for d in directives: kw[d.name] = d.get(class_, module, **kw) # Ignore methods that are present on the component baseclass. basemethods = set(util.public_methods_from_class( component.bind().get(self.__class__))) methods = set(util.public_methods_from_class(class_)) - basemethods if not methods: raise GrokError("%r does not define any public methods. " "Please add methods to this class to enable " "its registration." % class_, class_) results = [] for method in methods: # Directives may also be applied to methods, so let's # check each directive and potentially override the # class-level value with a value from the method *locally*. data = kw.copy() for bound_dir in directives: d = bound_dir.directive class_value = data[bound_dir.name] data[bound_dir.name] = d.store.get(d, method, default=class_value) results.append(self.execute(class_, method, **data)) return max(results)
def grok(self, name, module, **kw): grokked_status = False # prepare module grok - this can also influence the kw dictionary if self.prepare is not None: self.prepare(name, module, kw) # sort grokkers by priority grokkers = sorted(self.grokkers(name, module), key=_grokker_sort_key, reverse=True) for g, name, obj in grokkers: grokked = g.grok(name, obj, **kw) if grokked not in (True, False): raise GrokError( "%r returns %r instead of True or False." % (g, grokked), None) if grokked: grokked_status = True # finalize module grok if self.finalize is not None: self.finalize(name, module, kw) return grokked_status
def grok(self, name, factory, module_info, config, **kw): rdb_key = rdb.key.bind().get(factory) if rdb_key and hasattr(factory, 'keyfunc'): raise GrokError( "It is not allowed to specify a custom 'keyfunc' method " "for rdb.Container %r, when a rdb.key directive has also " "been given." % factory, factory) return True
def check_permission(factory, permission): """Check whether a permission is defined. If not, raise error for factory. """ if queryUtility(IPermission, name=permission) is None: raise GrokError( 'Undefined permission %r in %r. Use ' 'grok.Permission first.' % (permission, factory), factory)
def get(self, directive, component, default): permissions = getattr(component, directive.dotted_name(), default) if (permissions is default) or not permissions: return default if len(permissions) > 1: raise GrokError( 'grok.require was called multiple times in ' '%r. It may only be set once for a class.' % component, component) return permissions[0]
def finalize_grok(name, module, kw): module_info = kw['module_info'] templates = kw['templates'] unassociated = list(templates.listUnassociated()) if unassociated: raise GrokError( "Found the following unassociated template(s) when " "grokking %r: %s. Define view classes inheriting " "from grok.View to enable the template(s)." % (module_info.dotted_name, ', '.join(unassociated)), module_info)
def execute(self, factory, config, context, **kw): # Set up form_fields from context class if they haven't been # configured manually already. if getattr(factory, 'form_fields', None) is None: factory.form_fields = formlib.get_auto_fields(context) if not getattr(factory.render, 'base_method', False): raise GrokError( "It is not allowed to specify a custom 'render' " "method for form %r. Forms either use the default " "template or a custom-supplied one." % factory, factory) return True
def grok(self, name, factory, module_info, config, *kws): factory.module_info = module_info self.factory_name = factory.__name__.lower() self.view_layer = determine_class_directive( 'grok.layer', factory, module_info, default=IDefaultBrowserLayer) self.view_name = util.class_annotation(factory, 'grok.name', self.factory_name) self.view_context = determine_class_directive( 'grok.context', factory, module_info, default=zope.interface.Interface) # is name defined for template? # if defined a named template is looked up factory._template_name = util.class_annotation(factory, 'grok.template', '') # __view_name__ is needed to support IAbsoluteURL on views # TODO check how this is working for these views factory.__view_name__ = self.view_name # don't know if this would ever need to be set self.provides = util.class_annotation(factory, 'grok.provides', self.provides) # 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 getattr(method, '__grok_require__', None) 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) # sub classes must provide the registration self.register(factory, config) #print '\n'.join([str(factory), str(self.view_context), # str(self.view_layer), str(self.view_name), str(self.provides)]) permission = get_default_permission(factory) config.action( discriminator=('protectName', factory, '__call__'), callable=make_checker, args=(factory, factory, permission), ) return True
def grok(self, name, factory, context, module_info, templates): permission_name = util.class_annotation(factory, 'grok.name', None) if permission_name is None: raise GrokError( "A permission needs to have a dotted name for its id. Use " "grok.name to specify one.", factory) permission_name = unicode(permission_name) title = unicode( util.class_annotation(factory, 'grok.title', permission_name)) # TODO permission description component.provideUtility(Permission(permission_name, title=title), name=permission_name) return True
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
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
def grok(self, name, obj, **kw): grokked_status = False for g, name, obj in self.grokkers(name, obj): grokked = g.grok(name, obj, **kw) if grokked not in (True, False): raise GrokError( "%r returns %r instead of True or False." % (g, grokked), None) if grokked: grokked_status = True return grokked_status
def grok(self, name, factory, context, module_info, templates): role_name = util.class_annotation(factory, 'grok.name', None) if role_name is None: raise GrokError( "A role needs to have a dotted name for its id. Use " "grok.name to specify one.", factory) title = unicode(util.class_annotation(factory, 'grok.title', role_name)) component.provideUtility(Role(role_name, title=title), name=role_name) permissions = util.class_annotation(factory, 'grok.permissions', ()) for permission in permissions: rolePermissionManager.grantPermissionToRole(permission, role_name) return True
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
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) 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
def grok(self, name, factory, module_info, config, *kws): factory.module_info = module_info factory_name = factory.__name__.lower() # we need a path to the file containing the template template_name = util.class_annotation(factory, 'grok.template', factory_name) filepath = os.path.join(os.path.dirname(module_info.path), template_name) if not os.path.exists(filepath): filepath = None if os.path.exists(template_name): filepath = template_name if filepath is None: raise GrokError("No template found for %s." " Please use grok.template to define path to the" " file containing the template" % (factory.__name__), factory) macro = util.class_annotation(factory, 'mars.template.macro', None) contentType = util.class_annotation(factory, 'mars.template.content_type', 'text/html') view_layer = determine_class_directive('grok.layer', factory, module_info, default=IDefaultBrowserLayer) view_name = util.class_annotation(factory, 'grok.name', u'') view_context = determine_class_directive('grok.context', factory, module_info, default=zope.interface.Interface) provides = util.class_annotation(factory, 'grok.provides', self.provides) # now make the template factory proper factory = TemplateFactory(filepath, contentType, macro) zope.interface.directlyProvides(factory, provides) adapts = (view_context, view_layer) # print '\n',view_name,'\n',factory,'\n',provides,'\n',adapts config.action( discriminator=('adapter', adapts, provides, view_name), callable=zope.component.provideAdapter, args=(factory, adapts, provides, view_name), ) return True
def get_default_permission(factory): """Determine the default permission for a view. There can be only 0 or 1 default permission. """ permissions = class_annotation(factory, 'grok.require', []) if not permissions: return None if len(permissions) > 1: raise GrokError('grok.require was called multiple times in ' '%r. It may only be set once for a class.' % factory, factory) result = permissions[0] check_permission(factory, result) return result
def __call__(self, site, event): # make sure we have an intids self._createIntIds(site) # get the catalog catalog = self._createCatalog(site) # now install indexes for name, index in self.indexes.items(): try: index.setup(catalog, name, self.context, self.module_info) except DuplicationError: raise GrokError( "grok.Indexes in module %r causes " "creation of catalog index %r in catalog %r, " "but an index with that name is already present." % (self.module_info.getModule(), name, self.catalog_name), None)