def testSet(self): """ @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag.set @expectedException LogicException """ try: bag = FrozenParameterBag({}) bag.set('foo', 'bar') self.fail() except Exception as e: self.assertTrue(isinstance(e, LogicException))
def testSet(self): """ @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag.set @expectedException LogicException """ try: bag = FrozenParameterBag({}); bag.set('foo', 'bar'); self.fail() except Exception as e: self.assertTrue(isinstance(e, LogicException));
class Container(IntrospectableContainerInterface): """Container is a dependency injection container. It gives access to object instances (services). Services and parameters are simple key/pair stores. Parameter and service keys are case insensitive. A service id can contain lowercased letters, digits, underscores, and dots. Underscores are used to separate words, and dots to group services under namespaces: <ul> <li>request</li> <li>mysql_session_storage</li> <li>symfony.mysql_session_storage</li> </ul> A service can also be defined by creating a method named getXXXService(), where XXX is the camelized version of the id: <ul> <li>request -> getRequestService()</li> <li>mysql_session_storage -> getMysqlSessionStorageService()</li> <li>symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()</li> </ul> The container can have three possible behaviors when a service does not exist: * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) * None_ON_INVALID_REFERENCE: Returns None * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference (for instance, ignore a setter if the service does not exist): @author: Fabien Potencier <*****@*****.**> @author: Johannes M. Schmitt <*****@*****.**> @api: """ def __init__(self, parameterBag=None): """Constructor. @param: ParameterBagInterface parameterBag A ParameterBagInterface instance @api """ self._services = dict() self._scopes = dict() self._scopeChildren = dict() self._scopedServices = dict() self._scopeStacks = dict() self._parameterBag = None self._loading = dict() if parameterBag is None: self._parameterBag = ParameterBag() else: assert isinstance(parameterBag, ParameterBagInterface) self._parameterBag = parameterBag self.set('service_container', self) def compile(self): """Compiles the container. This method does two things: Parameter values are resolved; The parameter bag is frozen. @api: """ self._parameterBag.resolve() self._parameterBag = FrozenParameterBag(self._parameterBag.all()) def isFrozen(self): """Returns True if the container parameter bag are frozen.: @return: Boolean True if the container parameter bag are frozen, False otherwise @api: """ return isinstance(self._parameterBag, FrozenParameterBag) def getParameterBag(self): """Gets the service container parameter bag. @return: ParameterBagInterface A ParameterBagInterface instance @api """ return self._parameterBag def getParameter(self, name): """Gets a parameter. @param: string name The parameter name @return mixed The parameter value @raise InvalidArgumentException if the parameter is not defined: @api """ return self._parameterBag.get(name) def hasParameter(self, name): """Checks if a parameter exists.: @param: string name The parameter name @return Boolean The presence of parameter in container @api """ return self._parameterBag.has(name) def setParameter(self, name, value): """Sets a parameter. @param: string name The parameter name @param mixed value The parameter value @api """ self._parameterBag.set(name, value) 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 has(self, identifier): """Returns True if the given service is defined.: @param: string id The service identifier: @return Boolean True if the service is defined, False otherwise: @api """ identifier = self._formatIdentifier(identifier) method = 'get' + self.camelize(identifier) + 'Service' return identifier in self._services.keys() or ( hasattr(self, method) and isinstance(getattr(self, method), type(self.has))) def get(self, identifier, invalidBehavior=ContainerInterface.EXCEPTION_ON_INVALID_REFERENCE): """Gets a service. If a service is defined both through a set() method and with a getidService() method, the former has always precedence. @param: string id The service identifier: @param integer invalidBehavior The behavior when the service does not exist @return object The associated service @raise InvalidArgumentException if the service is not defined: @raise ServiceCircularReferenceException When a circular reference is detected @raise ServiceNotFoundException When the service is not defined @see Reference @api """ identifier = self._formatIdentifier(identifier) if identifier in self._services.keys(): return self._services[identifier] if identifier in self._loading.keys(): raise ServiceCircularReferenceException(identifier, list(self._loading.keys())) method = 'get' + self.camelize(identifier) + 'Service' if (hasattr(self, method) and isinstance(getattr(self, method), type(self.get))): self._loading[identifier] = True try: service = getattr(self, method)() except Exception as e: self._loading.pop(identifier, None) self._services.pop(identifier, None) raise e self._loading.pop(identifier, None) return service if (self.EXCEPTION_ON_INVALID_REFERENCE == invalidBehavior): raise ServiceNotFoundException(identifier) def initialized(self, identifier): """Returns True if the given service has actually been initialized: @param: string id The service identifier: @return Boolean True if service has already been initialized, False otherwise: """ identifier = self._formatIdentifier(identifier) return identifier in self._services def getServiceIds(self): """Gets all service ids. @return: list An array of all defined service ids """ ids = list() r = ReflectionObject(self) for method in r.getMethods(): match = re.search('^get(.+)Service$', method.getName()) if match: ids.append(self.underscore(match.group(1))) return Array.uniq(ids + list(self._services.keys())) 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 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 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 hasScope(self, name): """Returns whether this container has a certain scope @param: string name The name of the scope @return Boolean @api """ return name in self._scopes def isScopeActive(self, name): """Returns whether this scope is currently active This does not actually check if the passed scope actually exists.: @param: string name @return Boolean @api """ return name in self._scopedServices @classmethod def camelize(self, identifier): """Camelizes a string. @param: string identifier A string to camelize @return string The camelized string """ def callback(match): if '.' == match.group(1): return '_' + str(match.group(2)).upper() else: return '' + str(match.group(2)).upper() return re.sub('(^|_|\.)+(.)', callback, identifier) @classmethod def underscore(cls, identifier): """A string to underscore. @param identifier: string The string to underscore @return: string The underscored string """ value = str(identifier) # value = value.replace("_", "."); patterns = [ r"([A-Z]+)([A-Z][a-z])", r"([a-z\d])([A-Z])", ] repls = [ '\\1_\\2', '\\1_\\2', ] for i in range(len(patterns)): value = re.sub(patterns[i], repls[i], value) return value.lower() def _formatIdentifier(self, identifier): return str(identifier).lower()