async def _PGConfigurationFactory(key, dbconfig, loop=None, storage_factory=PostgresqlStorage): if isinstance(dbconfig['dsn'], str): dsn = dbconfig['dsn'] else: dsn = _convert_dsn(dbconfig['dsn']) partition_object = None if 'partition' in dbconfig: partition_object = resolve_dotted_name(dbconfig['partition']) dbconfig.update({ 'dsn': dsn, 'name': key, 'partition': partition_object, 'pool_size': dbconfig.get('pool_size', 13) }) connection_options = _get_connection_options(dbconfig) aps = storage_factory(**dbconfig) if loop is not None: await aps.initialize(loop=loop, **connection_options) else: await aps.initialize(**connection_options) if 'transaction_manager' in dbconfig: transaction_manager = resolve_dotted_name(dbconfig['transaction_manager']) else: transaction_manager = TransactionManager db = Database(key, aps, transaction_manager) await db.initialize() return db
def load_contenttype(_context, contenttype): conf = contenttype['config'] klass = contenttype['klass'] if 'schema' in conf: classImplements(klass, conf['schema']) Factory = resolve_dotted_name( conf.get('factory', 'guillotina.content.ResourceFactory') ) factory = Factory( klass, title='', description='', type_name=conf['type_name'], schema=resolve_dotted_name(conf.get('schema', Interface)), behaviors=[resolve_dotted_name(b) for b in conf.get('behaviors', []) or ()], add_permission=conf.get('add_permission') or DEFAULT_ADD_PERMISSION, allowed_types=conf.get('allowed_types', None) ) component.utility( _context, provides=IResourceFactory, component=factory, name=conf['type_name'], )
def make_aiohttp_application(): middlewares = [resolve_dotted_name(m) for m in app_settings.get('middlewares', [])] router_klass = app_settings.get('router', TraversalRouter) router = resolve_dotted_name(router_klass)() return GuillotinaAIOHTTPApplication( router=router, middlewares=middlewares, **app_settings.get('aiohttp_settings', {}))
def load_service(_context, service): # prevent circular import from guillotina.security.utils import protect_view service_conf = service['config'] factory = resolve_dotted_name(service['klass']) permission = service_conf.get( 'permission', app_settings.get('default_permission', None)) protect_view(factory, permission) method = service_conf.get('method', 'GET') default_layer = resolve_dotted_name( app_settings.get('default_layer', IDefaultLayer)) layer = service_conf.get('layer', default_layer) name = service_conf.get('name', '') content = service_conf.get('context', Interface) logger.debug('Defining adapter for ' # noqa '{0:s} {1:s} {2:s} to {3:s} name {4:s}'.format( content.__identifier__, app_settings['http_methods'][method].__identifier__, layer.__identifier__, str(factory), name)) if not getattr(factory, '__route__', None): factory.__route__ = routes.Route(name) else: factory.__route__.service_configuration = service_conf component.adapter( _context, factory=(factory,), provides=app_settings['http_methods'][method], for_=(content, layer), name=factory.__route__.view_name ) api = app_settings['api_definition'] ct_name = content.__identifier__ if ct_name not in api: api[ct_name] = OrderedDict() ct_api = api[ct_name] if name: if 'endpoints' not in ct_api: ct_api['endpoints'] = OrderedDict() if name not in ct_api['endpoints']: ct_api['endpoints'][name] = OrderedDict() ct_api['endpoints'][name][method] = OrderedDict(service_conf) else: ct_api[method] = OrderedDict(service_conf)
def load_subscriber(_context, subscriber): conf = subscriber['config'] conf['handler'] = resolve_dotted_name(conf.get('handler') or subscriber['klass']) _component_conf(conf) component.subscriber( _context, **conf )
def optimize_settings(settings): ''' pre-render settings that come in as strings but are used by the app ''' for name in _dotted_name_settings: if name not in settings: continue val = settings[name] if isinstance(val, str): settings[name] = resolve_dotted_name(val) elif isinstance(val, list): new_val = [] for v in val: if isinstance(v, str): v = resolve_dotted_name(v) new_val.append(v) settings[name] = resolve_dotted_name(new_val)
def load_utility(_context, _utility): conf = _utility['config'] if 'factory' in conf: conf['factory'] = resolve_dotted_name(conf['factory']) elif 'component' in conf: conf['component'] = resolve_dotted_name(conf['component']) else: # use provided klass klass = _utility['klass'] if isinstance(klass, type): # is a class type, use factory setting conf['factory'] = klass else: # not a factory conf['component'] = klass component.utility( _context, **conf )
async def delete_behavior(context, behavior): factory = get_cached_factory(context.type_name) behavior_class = resolve_dotted_name(behavior) if behavior_class is not None: if behavior_class in factory.behaviors: return Response(content={ 'reason': 'Behaviors defined on this type must be present and cannot be dynamically removed' }, status=412) if behavior not in context.__behaviors__: return Response(content={ 'reason': 'Not in behaviors' }, status=412) context.remove_behavior(behavior) return {}
def load_adapter(_context, adapter): conf = adapter['config'] klass = resolve_dotted_name(adapter['klass']) factory = conf.pop('factory', None) or klass _component_conf(conf) if 'provides' in conf and isinstance(klass, type): # not sure if this is what we want or not for sure but # we are automatically applying the provides interface to # registered class objects classImplements(klass, conf['provides']) component.adapter( _context, factory=(factory,), **conf )
def configure_application(self, module_name): if module_name in self.configured: return module = resolve_dotted_name(module_name) if hasattr(module, 'app_settings') and app_settings != module.app_settings: # load dependencies if necessary for dependency in module.app_settings.get('applications') or []: if dependency not in self.configured and module_name != dependency: self.configure_application(dependency) self.config.begin(module_name) self.load_application(module) self.config.execute_actions() self.config.commit() self.configured.append(module_name)
def command_runner(): parser = argparse.ArgumentParser( description='Guillotina command runner', add_help=False) parser.add_argument('command', nargs='?') parser.add_argument('-c', '--configuration', default='config.yaml', help='Configuration file') parser.add_argument('-h', '--help', action='store_true', dest='help', help='Help', default=False) arguments, _ = parser.parse_known_args() settings = get_settings(arguments.configuration) _commands = app_settings['commands'].copy() _commands.update(settings.get('commands', {})) for module_name in settings.get('applications', []): load_commands(module_name, _commands) if not arguments.command and arguments.help: # for other commands, pass through and allow those parsers to print help parser.print_help() return print(''' Available commands: {}\n\n'''.format('\n - '.join(c for c in _commands.keys()))) if not arguments.command: # default to serve command arguments.command = 'serve' if arguments.command not in _commands: return print('''Invalid command "{}". Available commands: {}\n\n'''.format(arguments.command, '\n - '.join(c for c in _commands.keys()))) app_settings['_command'] = arguments.command Command = resolve_dotted_name(_commands[arguments.command]) if Command is None: return print('Could not resolve command {}:{}'.format( arguments.command, _commands[arguments.command] )) app_settings['__run_command__'] = arguments.command # finally, run it... command = Command() command.run_command()
def get_configurations(module_name, type_=None, excluded=None): results = [] for reg_type, registration in _registered_configurations: if type_ is not None and reg_type != type_: continue config = registration['config'] module = config.get('module', registration.get('klass')) normalized_name = get_module_dotted_name(resolve_dotted_name(module)) if (normalized_name + '.').startswith(module_name + '.'): valid = True for excluded_module in excluded or []: if (normalized_name + '.').startswith(excluded_module + '.'): valid = False break if valid: results.append((reg_type, registration)) return results
async def __call__(self): if self.key is _marker: # No option to write the root of registry return ErrorResponse('InvalidRequest', 'Needs the registry key', status=412) data = await self.request.json() if 'value' in data: value = data['value'] else: value = data assert '.' in self.key, 'Registry key must be dotted.iface.name.fieldname' # noqa iface, name = self.key.rsplit('.', 1) iface = resolve_dotted_name(iface) assert iface is not None, 'Must provide valid registry interface' # noqa try: field = iface[name] except KeyError: return ErrorResponse( 'DeserializationError', 'Invalid field name {}'.format(str(name)), status=412) try: new_value = get_adapter((field), IJSONToValue, args=[value, self.context]) except ComponentLookupError: return ErrorResponse( 'DeserializationError', 'Cannot deserialize type {}'.format(str(self.field)), status=412) try: self.request.container_settings[self.key] = new_value except DeserializationError as e: return ErrorResponse( 'DeserializationError', str(e), exc=e, status=412) return Response(status=204)
def run_command(self, settings=None, loop=None): if loop is not None: self.loop = loop if settings is None: settings = get_settings(self.arguments.configuration, self.arguments.override) if settings.get('loop_policy'): loop_policy = resolve_dotted_name(settings['loop_policy']) asyncio.set_event_loop_policy(loop_policy()) app = self.make_app(settings) if self.arguments.line_profiler: if not HAS_LINE_PROFILER: sys.stderr.write( 'You must first install line_profiler for the --line-profiler option to work.\n' 'Use `pip install line_profiler` to install line_profiler.\n' ) return 1 self.line_profiler = line_profiler.LineProfiler() for func in profile.get_profilable_functions(): if fnmatch(get_dotted_name(func), self.arguments.line_profiler_matcher or '*'): self.line_profiler.add_function(func) self.line_profiler.enable_by_count() run_func = self.__run if self.arguments.monitor: if not HAS_AIOMONITOR: sys.stderr.write( 'You must install aiomonitor for the ' '--monitor option to work.\n' 'Use `pip install aiomonitor` to install aiomonitor.\n') return 1 run_func = self.__run_with_monitor if self.arguments.profile: self.profiler = cProfile.Profile() self.profiler.runcall(run_func, app, settings) else: run_func(app, settings)
async def default_patch(context, request): data = await request.json() behavior = data.get('behavior', None) try: behavior_class = resolve_dotted_name(behavior) except ModuleNotFoundError: behavior_class = None if behavior_class is None: return Response(content={ 'reason': 'Could not find behavior' }, status=404) factory = get_cached_factory(context.type_name) if behavior_class in factory.behaviors: return Response(content={ 'reason': 'Already in behaviors' }, status=412) if behavior in context.__behaviors__: return Response(content={ 'reason': 'Already in behaviors' }, status=412) context.add_behavior(behavior) return {}
def run_command(self, settings=None, loop=None): if loop is not None: self.loop = loop if settings is None: settings = get_settings(self.arguments.configuration) if settings.get('loop_policy'): loop_policy = resolve_dotted_name(settings['loop_policy']) asyncio.set_event_loop_policy(loop_policy()) app = self.make_app(settings) if self.arguments.line_profiler: if not HAS_LINE_PROFILER: sys.stderr.write( 'You must first install line_profiler for the --line-profiler option to work.\n' 'Use `pip install line_profiler` to install line_profiler.\n' ) return 1 self.line_profiler = line_profiler.LineProfiler() for func in profile.get_profilable_functions(): if fnmatch(get_dotted_name(func), self.arguments.line_profiler_matcher or '*'): self.line_profiler.add_function(func) self.line_profiler.enable_by_count() run_func = self.__run if self.arguments.monitor: if not HAS_AIOMONITOR: sys.stderr.write( 'You must install aiomonitor for the ' '--monitor option to work.\n' 'Use `pip install aiomonitor` to install aiomonitor.\n') return 1 run_func = self.__run_with_monitor if self.arguments.profile: self.profiler = cProfile.Profile() self.profiler.runcall(run_func, app, settings) else: run_func(app, settings)
async def __call__(self): if self.key is _marker: # No option to write the root of registry return ErrorResponse('InvalidRequest', 'Needs the registry key', status=412) data = await self.request.json() if 'value' in data: value = data['value'] else: value = data assert '.' in self.key, 'Registry key must be dotted.iface.name.fieldname' # noqa iface, name = self.key.rsplit('.', 1) iface = resolve_dotted_name(iface) field = iface[name] try: new_value = get_adapter((field), IJSONToValue, args=[value, self.context]) except ComponentLookupError: return ErrorResponse('DeserializationError', 'Cannot deserialize type {}'.format( str(self.field)), status=412) try: self.request.container_settings[self.key] = new_value except DeserializationError as e: return ErrorResponse('DeserializationError', str(e), exc=e, status=412) return Response(status=204)
async def __call__(self): user = get_authenticated_user() self.policy = get_security_policy(user) definition = copy.deepcopy(app_settings["swagger"]["base_configuration"]) vhm = self.request.headers.get("X-VirtualHost-Monster") if not app_settings["swagger"].get("base_url"): if vhm: parsed_url = urlparse(vhm) host = parsed_url.netloc scheme = parsed_url.scheme base_path = parsed_url.path else: host = self.request.host scheme = get_request_scheme(self.request) base_path = "" url = os.path.join(f"{scheme}://{host}", base_path) else: url = app_settings["swagger"]["base_url"] definition["servers"][0]["url"] = url if "version" not in definition["info"]: definition["info"]["version"] = pkg_resources.get_distribution("guillotina").version api_defs = app_settings["api_definition"] path = get_full_content_path(self.context) for dotted_iface in api_defs.keys(): iface = resolve_dotted_name(dotted_iface) if iface.providedBy(self.context): iface_conf = api_defs[dotted_iface] self.get_endpoints(iface_conf, path, definition["paths"]) definition["components"]["schemas"] = app_settings["json_schema_definitions"] return definition
async def _build_security_query( self, container, query, doc_type=None, size=10, request=None, scroll=None): if query is None: query = {} build_security_query = resolve_dotted_name( app_settings['elasticsearch']['security_query_builder']) permission_query = await build_security_query(container, request) result = { 'body': merge_dicts(query, permission_query), 'size': size } if scroll: result['scroll'] = scroll logger.debug(result) return result
def make_app(config_file=None, settings=None, loop=None, server_app=None): app_settings.update(_delayed_default_settings) if loop is None: loop = asyncio.get_event_loop() loop.set_task_factory(aiotask_context.task_factory) if config_file is not None: with open(config_file, 'r') as config: settings = json.load(config) elif settings is None: raise Exception('Neither configuration or settings') # Create root Application root = ApplicationRoot(config_file) provide_utility(root, IApplication, 'root') # Initialize global (threadlocal) ZCA configuration config = root.config = ConfigurationMachine() import guillotina import guillotina.db.factory import guillotina.db.writer import guillotina.db.db configure.scan('guillotina.translation') configure.scan('guillotina.renderers') configure.scan('guillotina.api') configure.scan('guillotina.content') configure.scan('guillotina.registry') configure.scan('guillotina.auth') configure.scan('guillotina.json') configure.scan('guillotina.behaviors') configure.scan('guillotina.languages') configure.scan('guillotina.permissions') configure.scan('guillotina.security.security_local') configure.scan('guillotina.security.policy') configure.scan('guillotina.auth.participation') configure.scan('guillotina.catalog.index') configure.scan('guillotina.catalog.catalog') configure.scan('guillotina.framing') configure.scan('guillotina.files') configure.scan('guillotina.annotations') configure.scan('guillotina.constraintypes') configure.scan('guillotina.subscribers') configure.scan('guillotina.db.strategies') configure.scan('guillotina.db.cache') load_application(guillotina, root, settings) config.execute_actions() config.commit() for module_name in settings.get('applications', []): config.begin(module_name) load_application(resolve_dotted_name(module_name), root, settings) config.execute_actions() config.commit() # XXX we clear now to save some memory # it's unclear to me if this is necesary or not but it seems to me that # we don't need things registered in both components AND here. configure.clear() # update *after* plugins loaded update_app_settings(settings) if 'logging' in app_settings: logging.config.dictConfig(app_settings['logging']) # Make and initialize aiohttp app if server_app is None: server_app = make_aiohttp_application() root.app = server_app server_app.root = root server_app.config = config content_type = ContentNegotiatorUtility('content_type', app_settings['renderers'].keys()) language = ContentNegotiatorUtility('language', app_settings['languages'].keys()) provide_utility(content_type, IContentNegotiation, 'content_type') provide_utility(language, IContentNegotiation, 'language') for database in app_settings['databases']: for key, dbconfig in database.items(): factory = get_utility(IDatabaseConfigurationFactory, name=dbconfig['storage']) if asyncio.iscoroutinefunction(factory): future = asyncio.ensure_future(factory(key, dbconfig, server_app), loop=loop) loop.run_until_complete(future) root[key] = future.result() else: root[key] = factory(key, dbconfig) for key, file_path in list_or_dict_items(app_settings['static']): path = resolve_path(file_path).resolve() if not path.exists(): raise Exception('Invalid static directory {}'.format(file_path)) if path.is_dir(): root[key] = StaticDirectory(path) else: root[key] = StaticFile(path) for key, file_path in list_or_dict_items(app_settings['jsapps']): path = resolve_path(file_path).resolve() if not path.exists() or not path.is_dir(): raise Exception('Invalid jsapps directory {}'.format(file_path)) root[key] = JavaScriptApplication(path) root.set_root_user(app_settings['root_user']) if RSA is not None and not app_settings.get('rsa'): key = RSA.generate(2048) pub_jwk = {'k': key.publickey().exportKey('PEM')} priv_jwk = {'k': key.exportKey('PEM')} app_settings['rsa'] = {'pub': pub_jwk, 'priv': priv_jwk} # Set router root server_app.router.set_root(root) for utility in get_all_utilities_registered_for(IAsyncUtility): # In case there is Utilties that are registered if hasattr(utility, 'initialize'): task = asyncio.ensure_future(lazy_apply(utility.initialize, app=server_app), loop=loop) root.add_async_task(utility, task, {}) else: logger.warn(f'No initialize method found on {utility} object') server_app.on_cleanup.append(close_utilities) for util in app_settings['utilities']: root.add_async_utility(util, loop=loop) # Load cached Schemas load_cached_schema() optimize_settings(app_settings) return server_app
def load_commands(module_name, commands): module = resolve_dotted_name(module_name) if hasattr(module, 'app_settings') and app_settings != module.app_settings: commands.update(module.app_settings.get('commands', {})) for dependency in module.app_settings.get('applications') or []: load_commands(dependency, commands)
def load_behavior(_context, behavior): conf = behavior['config'] klass = resolve_dotted_name(behavior['klass']) factory = conf.get('factory') or klass real_factory = resolve_dotted_name(factory) if IInterface.providedBy(real_factory): # create concret class to register for behavior schema = real_factory from guillotina.behaviors.instance import AnnotationBehavior class real_factory(AnnotationBehavior): __annotations_data_key__ = conf.get('data_key', 'default') auto_serialize = conf.get('auto_serialize', True) else: schema = resolve_dotted_name(conf['provides']) classImplements(real_factory, schema) name = conf.get('name') name_only = conf.get('name_only', False) title = conf.get('title', '') for_ = resolve_dotted_name(conf.get('for_')) marker = resolve_dotted_name(conf.get('marker')) if marker is None and real_factory is None: marker = schema if marker is not None and real_factory is None and marker is not schema: raise ConfigurationError( u"You cannot specify a different 'marker' and 'provides' if " u"there is no adapter factory for the provided interface." ) if name_only and name is None: raise ConfigurationError( u"If you decide to only register by 'name', a name must be given." ) # Instantiate the real factory if it's the schema-aware type. We do # this here so that the for_ interface may take this into account. if factory is not None and IBehaviorSchemaAwareFactory.providedBy(factory): factory = factory(schema) registration = BehaviorRegistration( title=conf.get('title', ''), description=conf.get('description', ''), interface=schema, marker=marker, factory=real_factory, name=name, for_=for_ ) if not name_only: # behavior registration by provides interface identifier component.utility( _context, provides=IBehavior, name=schema.__identifier__, component=registration ) if name is not None: # for convinience we register with a given name component.utility( _context, provides=IBehavior, name=name, component=registration ) if factory is None: if for_ is not None: logger.warning( u"Specifying 'for' in behavior '{0}' if no 'factory' is given " u"has no effect and is superfluous.".format(title) ) # w/o factory we're done here return if for_ is None: # Attempt to guess the factory's adapted interface and use it as # the 'for_'. # Fallback to '*' (=Interface). adapts = getattr(factory, '__component_adapts__', None) or [Interface] if len(adapts) != 1: raise ConfigurationError( u"The factory can not be declared as multi-adapter." ) for_ = adapts[0] adapter_factory = BehaviorAdapterFactory(registration) component.adapter( _context, factory=(adapter_factory,), provides=schema, for_=(for_,) )
def load_subscriber(_context, subscriber): conf = subscriber['config'] conf['handler'] = resolve_dotted_name( conf.get('handler') or subscriber['klass']) _component_conf(conf) component.subscriber(_context, **conf)
def load_subscriber(_context, subscriber): conf = subscriber["config"] conf["handler"] = resolve_dotted_name( conf.get("handler") or subscriber["klass"]) _component_conf(conf) component.subscriber(_context, **conf)
async def _connect(self): klass = resolve_dotted_name(self._settings["driver"]) self._driver = await klass.get_driver() await self._driver.initialize(self._loop) self._initialized = True
def load_commands(module_name, commands): module = resolve_dotted_name(module_name) if hasattr(module, 'app_settings') and app_settings != module.app_settings: commands.update(module.app_settings.get('commands', {})) for dependency in module.app_settings.get('applications') or []: load_commands(dependency, commands)
def api(self, path, method='get', file_type_name=None, **kwargs): if path != '/': path = path.rstrip('/') print('Getting {} {}'.format(method, path)) kwargs['auth'] = ('root', 'root') kwargs['headers'] = DEFAULT_HEADERS.copy() kwargs['headers'].update(kwargs.get('headers', {})) url = self._base_url + path response = getattr(requests, method)(url, **kwargs) self._store_type_name(response, url, kwargs) service = self.get_service_def(path, method.upper()) # path scheme used for things like traversing to registry value... name = service.get('name') path_scheme = kwargs.pop('path_scheme', name) iface = resolve_dotted_name(self.get_service_type_name(path)[-1]) dotted = get_dotted_name(iface) responses = self._function_swagger_param(service.get('responses'), url) parameters = self._function_swagger_param(service.get('parameters'), url) data = { 'path': path, 'path_scheme': path_scheme, 'method': method, 'options': kwargs, 'request': self.dump_request(response.request), 'response': self.dump_response(response), 'service': { 'name': service.get('name'), 'title': service.get('title'), 'summary': service.get('summary'), 'parameters': parameters, 'responses': responses, 'method': service.get('method', 'GET'), 'context': get_dotted_name(iface), 'permission': service.get('permission') } } if file_type_name is None: file_type_name = dotted.split('.')[-1][1:].lower() filepath = '{}/{}-{}'.format(self._output_dir, file_type_name, method.lower()) if path_scheme != name: # use special name here... name, _, rest = path_scheme.partition('/') filepath += '-{}:{}'.format( name.replace('@', ''), ''.join([l for l in rest.split(':')[0] if l not in '[]():-'])) elif service.get('name'): filepath += '-' + service.get('name').replace('@', '') filepath += '.json' fi = open(filepath, 'w') fi.write(json.dumps(data, indent=4, sort_keys=True)) fi.close()
def load_behavior(_context, behavior): conf = behavior['config'] klass = resolve_dotted_name(behavior['klass']) factory = conf.get('factory') or klass real_factory = resolve_dotted_name(factory) if IInterface.providedBy(real_factory): # create concret class to register for behavior schema = real_factory from guillotina.behaviors.instance import AnnotationBehavior class real_factory(AnnotationBehavior): __annotations_data_key__ = conf.get('data_key', 'default') auto_serialize = conf.get('auto_serialize', True) else: schema = resolve_dotted_name(conf['provides']) classImplements(real_factory, schema) name = conf.get('name') name_only = conf.get('name_only', False) title = conf.get('title', '') for_ = resolve_dotted_name(conf.get('for_')) marker = resolve_dotted_name(conf.get('marker')) if marker is None and real_factory is None: marker = schema if marker is not None and real_factory is None and marker is not schema: raise ConfigurationError( u"You cannot specify a different 'marker' and 'provides' if " u"there is no adapter factory for the provided interface." ) if name_only and name is None: raise ConfigurationError( u"If you decide to only register by 'name', a name must be given." ) # Instantiate the real factory if it's the schema-aware type. We do # this here so that the for_ interface may take this into account. if factory is not None and IBehaviorSchemaAwareFactory.providedBy(factory): factory = factory(schema) registration = BehaviorRegistration( title=conf.get('title', ''), description=conf.get('description', ''), interface=schema, marker=marker, factory=real_factory, name=name, for_=for_ ) if not name_only: # behavior registration by provides interface identifier component.utility( _context, provides=IBehavior, name=schema.__identifier__, component=registration ) if name is not None: # for convinience we register with a given name component.utility( _context, provides=IBehavior, name=name, component=registration ) if factory is None: if for_ is not None: logger.warning( u"Specifying 'for' in behavior '{0}' if no 'factory' is given " u"has no effect and is superfluous.".format(title) ) # w/o factory we're done here return if for_ is None: # Attempt to guess the factory's adapted interface and use it as # the 'for_'. # Fallback to '*' (=Interface). adapts = getattr(factory, '__component_adapts__', None) or [Interface] if len(adapts) != 1: raise ConfigurationError( u"The factory can not be declared as multi-adapter." ) for_ = adapts[0] adapter_factory = BehaviorAdapterFactory(registration) component.adapter( _context, factory=(adapter_factory,), provides=schema, for_=(for_,) )