def setAlias(self, alias, identifier): """Sets an alias for an existing service. @param: string alias The alias to create @param string|Alias identifier The service to alias @raise InvalidArgumentException if the id is not a string or an Alias: @raise InvalidArgumentException if the alias is for itself: @api """ alias = self.__formatAlias(alias) if isinstance(identifier, str): identifier = Alias(identifier) elif not isinstance(identifier, Alias): raise InvalidArgumentException( '$id must be a string, or an Alias object.') if alias == str(identifier).lower(): raise InvalidArgumentException( 'An alias can not reference itself, got a circular reference ' 'on "{0}".'.format(alias)) self.__definitions.pop(alias, None) self.__aliases[alias] = identifier
def __validate(self, content, resource): """Validates a YAML file. @param content: mixed @param resource: string @return: dict @raise InvalidArgumentException: When service file is not valid """ if content is None: return if not isinstance(content, dict): raise InvalidArgumentException( 'The "{0}" file is not valid.'.format(resource)) for namespace in content.keys(): if namespace in ['imports', 'parameters', 'services']: continue if not self._container.hasExtension(namespace): extensionNamespaces = filter( None, map(lambda e: e.getAlias(), self._container.getExtensions())) raise InvalidArgumentException( 'There is no extension able to load the configuration ' 'for "{0}" (in {1}). Looked for namespace "{0}", found "{2}"' ''.format(namespace, resource, '", "'.join(extensionNamespaces))) return content
def addScope(self, scope): """Adds a scope to the container. @param: ScopeInterface scope @raise InvalidArgumentException @api """ assert isinstance(scope, ScopeInterface) name = scope.getName() parentScope = scope.getParentName() if (self.SCOPE_CONTAINER == name or self.SCOPE_PROTOTYPE == name): raise InvalidArgumentException( 'The scope "{0}" is reserved.'.format(name)) if name in self._scopes: raise InvalidArgumentException( 'A scope with name "{0}" already exists.'.format(name)) if self.SCOPE_CONTAINER != parentScope and parentScope not in self._scopes: raise InvalidArgumentException( 'The parent scope "{0}" does not exist, or is invalid.' ''.format(parentScope)) self._scopes[name] = parentScope self._scopeChildren[name] = list() # normalize the child relations while (parentScope != self.SCOPE_CONTAINER): self._scopeChildren[parentScope].append(name) parentScope = self._scopes[parentScope]
def replaceArgument(self, index, value): """You should always use this method when overwriting existing arguments of the parent definition. If you directly call setArguments() keep in mind that you must follow certain conventions when you want to overwrite the arguments of the parent definition, otherwise your arguments will only be appended. @param integer index @param mixed value @return DefinitionDecorator the current instance @raise InvalidArgumentException when index isn't an integer @api """ if not isinstance(index, int) or isinstance(index, bool): raise InvalidArgumentException('index must be an integer.') # UPDATED self.__overwriteArguments[index] = value return self
def set(self, identifier, service, scope=ContainerInterface.SCOPE_CONTAINER): """Sets a service. @param: string identifier The service identifier: @param object service The service instance @param string scope The scope of the service @raise RuntimeException When trying to set a service in an inactive scope @raise InvalidArgumentException When trying to set a service in the prototype scope @api """ if (self.SCOPE_PROTOTYPE == scope): raise InvalidArgumentException( 'You cannot set service "{0}" of scope "prototype".' ''.format(identifier)) identifier = self._formatIdentifier(identifier) if (self.SCOPE_CONTAINER != scope): if not scope in self._scopedServices: raise RuntimeException( 'You cannot set service "{0}" of inactive scope.' ''.format(identifier)) self._scopedServices[scope][identifier] = service self._services[identifier] = service
def getNode(self, identifier): """Gets a node by identifier.: @param: string id The id to retrieve @return ServiceReferenceGraphNode The node matching the supplied identifier: @raise InvalidArgumentException if no node matches the supplied identifier: """ if identifier not in self.__nodes: raise InvalidArgumentException( 'There is no node with id "{0}".'.format(identifier)) return self.__nodes[identifier]
def enterScope(self, name): """This is called when you enter a scope @param: string name @raise RuntimeException When the parent scope is inactive @raise InvalidArgumentException When the scope does not exist @api """ if name not in self._scopes: raise InvalidArgumentException( 'The scope "{0}" does not exist.'.format(name)) if self.SCOPE_CONTAINER != self._scopes[name] and self._scopes[ name] not in self._scopedServices: raise RuntimeException( 'The parent scope "{0}" must be active when entering this ' 'scope.'.format(self._scopes[name])) # check if a scope of this name is already active, if so we need to # remove all services of this scope, and those of any of its child # scopes from the global services map if name in self._scopedServices: services = OrderedDict() services[0] = self._services services[name] = self._scopedServices[name] self._scopedServices.pop(name, None) for child in self._scopeChildren[name]: if child in self._scopedServices: services[child] = self._scopedServices[child] self._scopedServices.pop(child, None) # update global map self._services = Array.diffKey(*services.values()) services.pop(0) # add stack entry for this scope so we can restore the removed services later if name not in self._scopeStacks: self._scopeStacks[name] = list() self._scopeStacks[name].append(services) self._scopedServices[name] = dict()
def getAlias(self, identifier): """Gets an alias. @param: string id The service identifier: @return Alias An Alias instance @raise InvalidArgumentException if the alias does not exist: @api """ identifier = self.__formatAlias(identifier) if not self.hasAlias(identifier): raise InvalidArgumentException( 'The service alias "{0}" does not exist.' ''.format(identifier)) return self.__aliases[identifier]
def getDefinition(self, identifier): """Gets a service definition. @param: string id The service identifier: @return Definition A Definition instance @raise InvalidArgumentException if the service definition does not exist: @api """ identifier = self._formatIdentifier(identifier) if not self.hasDefinition(identifier): raise InvalidArgumentException( 'The service definition "{0}" does not exist.' ''.format(identifier)) return self.__definitions[identifier]
def _parseFile(self, filename): """Parses a INI file. @param filename: string The path file @return: dict The file content @raise InvalidArgumentException: When INI file is not valid """ content = dict() cfgParser = ConfigParser() result = cfgParser.read(filename) if not result: raise InvalidArgumentException( 'The "{0]" file is not valid.'.format(filename)) for section in cfgParser.sections(): content[section] = dict() for key, value in cfgParser.items(section): content[section][key] = value return content
def addPass(self, cPass, cType=TYPE_BEFORE_OPTIMIZATION): """Adds a pass. @param: CompilerPassInterface pass A Compiler pass @param string type The pass type @raise InvalidArgumentException when a pass type doesn't exist @api """ assert isinstance(cPass, CompilerPassInterface) getPropertyName = "get{0}Passes".format(cType) setPropertyName = "set{0}Passes".format(cType) if not hasattr(self, getPropertyName): raise InvalidArgumentException('Invalid type "{0}".'.format(cType)) passes = getattr(self, getPropertyName)() passes.append(cPass) getattr(self, setPropertyName)(passes)
def addMethodCall(self, method, arguments=None): """Adds a method to call after service initialization. @param: string method The method name to call @param array arguments An array of arguments to pass to the method call @return Definition The current instance @raise InvalidArgumentException on empty method param @api """ if arguments is None: arguments = list() arguments = list(arguments) method = str(method) if not method: raise InvalidArgumentException('Method name cannot be empty.') self.__calls.append([method, arguments]) return self
def _parseFile(self, filename): """Parses a JSON file. @param filename: string The path file @return: dict The file content @raise InvalidArgumentException: When JSON file is not valid """ f = open(filename) s = f.read().strip() f.close() del f if not s: return None try: result = json.loads(s) except ValueError as e: raise InvalidArgumentException(e) return self.__validate(result, filename)
def process(self, container): """Process the Container to replace aliases with service definitions. @param ContainerBuilder container @raise InvalidArgumentException if the service definition does not exist: """ assert isinstance(container, ContainerBuilder) self.__compiler = container.getCompiler() self.__formatter = self.__compiler.getLoggingFormatter() for identifier, alias in container.getAliases().items(): aliasId = str(alias) try: definition = container.getDefinition(aliasId) except InvalidArgumentException as e: raise InvalidArgumentException( 'Unable to replace alias "{0}" with "{1}".'.format( alias, identifier), None, e) if (definition.isPublic()): continue definition.setPublic(True) container.setDefinition(identifier, definition) container.removeDefinition(aliasId) self.__updateReferences(container, aliasId, identifier) # we have to restart the process due to concurrent modification of: # the container self.process(container) break
def __init__(self, passes): """Constructor. @param RepeatablePassInterface[] passes An array of RepeatablePassInterface objects @raise InvalidArgumentException when the passes don't implement RepeatablePassInterface """ assert isinstance(passes, list) self.__repeat = False # @var Boolean self.__passes = None # @var RepeatablePassInterface[] for cPass in passes: if (not isinstance(cPass, RepeatablePassInterface)): raise InvalidArgumentException( 'passes must be an array of RepeatablePassInterface.') cPass.setRepeatedPass(self) self.__passes = passes
def leaveScope(self, name): """This is called to leave the current scope, and move back to the parent scope. @param: string name The name of the scope to leave @raise InvalidArgumentException if the scope is not active: @api """ if name not in self._scopedServices: raise InvalidArgumentException( 'The scope "{0}" is not active.'.format(name)) # remove all services of this scope, or any of its child scopes from # the global service map services = [self._services, self._scopedServices[name]] self._scopedServices.pop(name, None) for child in self._scopeChildren[name]: if child not in self._scopedServices: continue services.append(self._scopedServices[child]) self._scopedServices.pop(child, None) self._services = Array.diffKey(*services) # check if we need to restore services of a previous scope of this type: if name in self._scopeStacks and self._scopeStacks[name]: services = self._scopeStacks[name].pop() self._scopedServices.update(services) for scopeServices in services.values(): self._services.update(scopeServices)
def __createService(self, definition, identifier): """Creates a service for a service definition. @param: Definition definition A service definition instance @param string id The service identifier: @return object The service described by the service definition @raise RuntimeException When the scope is inactive @raise RuntimeException When the factory definition is incomplete @raise RuntimeException When the service is a synthetic service @raise InvalidArgumentException When configure callable is not callable """ assert isinstance(definition, Definition) if definition.isSynthetic(): raise RuntimeException( 'You have requested a synthetic service ("{0}"). ' 'The DIC does not know how to construct this service.' ''.format(identifier)) parameterBag = self.getParameterBag() if None is not definition.getFile(): path = parameterBag.resolveValue(definition.getFile()) module = SourceFileLoader.load(path) else: module = None value = parameterBag.resolveValue(definition.getArguments()) value = parameterBag.unescapeValue(value) arguments = self.resolveServices(value) if not definition.getFactoryMethod() is None: if not definition.getFactoryClass() is None: factory = parameterBag.resolveValue( definition.getFactoryClass()) if module is not None: factory = getattr(module, factory) else: factory = ClassLoader.load(factory) elif not definition.getFactoryService() is None: factory = self.get( parameterBag.resolveValue(definition.getFactoryService())) else: raise RuntimeException( 'Cannot create service "{0}" from factory method without ' 'a factory service or factory class.' ''.format(identifier)) service = getattr(factory, definition.getFactoryMethod())(*arguments) else: className = parameterBag.resolveValue(definition.getClass()) if module is not None: service = getattr(module, className)(*arguments) else: service = ClassLoader.load(className)(*arguments) scope = definition.getScope() if self.SCOPE_PROTOTYPE != scope: if self.SCOPE_CONTAINER != scope and scope not in self._scopedServices: raise RuntimeException( 'You tried to create the "{0}" service of an inactive ' 'scope.'.format(identifier)) lowerId = self._formatIdentifier(identifier) self._services[lowerId] = service if (self.SCOPE_CONTAINER != scope): self._scopedServices[scope][lowerId] = service for call in definition.getMethodCalls(): services = self.getServiceConditionals(call[1]) ok = True for s in services: if not self.has(s): ok = False break if ok: args = self.resolveServices(parameterBag.resolveValue(call[1])) getattr(service, call[0])(*args) properties = self.resolveServices( parameterBag.resolveValue(definition.getProperties())) for name, value in properties.items(): setattr(service, name, value) closure = definition.getConfigurator() if closure: if isinstance(closure, list): if isinstance(closure[0], Reference): closure[0] = self.get(str(closure[0])) else: closure[0] = parameterBag.resolveValue(closure[0]) closure[0] = ClassLoader.load(closure[0]) closure = getattr(closure[0], closure[1]) if not Tool.isCallable(closure): raise InvalidArgumentException( 'The configure callable for class "{0}" is not a callable.' ''.format(type(service).__name__)) closure(service) return service
def __parseDefinition(self, identifier, service, resource): """Parses a definition. @param identifier: string @param service: dict @param resource: string @raise InvalidArgumentException: When tags are invalid """ if isinstance(service, String) and service.startswith('@'): self._container.setAlias(identifier, service[1:]) return elif 'alias' in service: public = 'public' not in service or bool(service['public']) self._container.setAlias(identifier, Alias(service['alias'], public)) return if 'parent' in service: definition = DefinitionDecorator(service['parent']) else: definition = Definition() if 'class' in service: definition.setClass(service['class']) if 'scope' in service: definition.setScope(service['scope']) if 'synthetic' in service: definition.setSynthetic(service['synthetic']) if 'public' in service: definition.setPublic(service['public']) if 'abstract' in service: definition.setAbstract(service['abstract']) if 'factory_class' in service: definition.setFactoryClass(service['factory_class']) if 'factory_method' in service: definition.setFactoryMethod(service['factory_method']) if 'factory_service' in service: definition.setFactoryService(service['factory_service']) if 'file' in service: definition.setFile(service['file']) if 'arguments' in service: definition.setArguments( self.__resolveServices(service['arguments'])) if 'properties' in service: definition.setProperties( self.__resolveServices(service['properties'])) if 'configurator' in service: if isinstance(service['configurator'], String): definition.setConfigurator(service['configurator']) else: definition.setConfigurator([ self.__resolveServices(service['configurator'][0]), service['configurator'][1] ]) if 'calls' in service: for call in service['calls']: args = self.__resolveServices( call[1]) if len(call) >= 2 else [] definition.addMethodCall(call[0], args) if 'tags' in service: if not isinstance(service['tags'], list): raise InvalidArgumentException( 'Parameter "tags" must be a list for service ' '"{0}" in {1}.'.format(identifier, resource)) for tag in service['tags']: if not isinstance(tag, dict) or 'name' not in tag: raise InvalidArgumentException( 'A "tags" entry is missing a "name" key for service ' '"{0}" in {1}.'.format(identifier, resource)) name = tag['name'] del tag['name'] for value in tag.values(): if not isinstance(value, (type(None), String, int, float, bool)): raise InvalidArgumentException( 'A "tags" attribute must be of a scalar-type ' 'for service "{0}", tag "{1}" in {2}.' ''.format(identifier, name, resource)) definition.addTag(name, tag) self._container.setDefinition(identifier, definition)