def _mergeValues(self, leftSide, rightSide): """Merges values together. @param leftSide: mixed The left side to merge. @param rightSide: mixed The right side to merge. @return mixed The merged values @raise InvalidConfigurationException: @raise RuntimeException: """ if rightSide is False: # if this is still false after the last config has been merged the # finalization pass will take care of removing this key entirely return False; if not leftSide or not self._performDeepMerging: return rightSide; if isinstance(leftSide, list): leftSide = Array.toDict(leftSide); if isinstance(rightSide, list): rightSide = Array.toDict(rightSide); i = -1; for k, v in rightSide.items(): i += 1; # prototype, and key is irrelevant, so simply append the element if self._keyAttribute is None: # dict: append index = 0; while index in leftSide: index += 1; leftSide[index] = v; continue; # no conflict if k not in leftSide: if not self._allowNewKeys: ex = InvalidConfigurationException( 'You are not allowed to define new elements for path ' '"{0}". Please define all elements for this path in ' 'one config file. If you are trying to overwrite an ' 'element, make sure you redefine it with the same ' 'name.'.format(self.getPath()) ); ex.setPath(self.getPath()); raise ex; leftSide[k] = v; continue; self._prototype.setName(k); leftSide[k] = self._prototype.merge(leftSide[k], v); return leftSide;
def _mergeValues(self, leftSide, rightSide): """Merges values together. @param leftSide: mixed The left side to merge. @param rightSide: mixed The right side to merge. @return mixed The merged values @raise InvalidConfigurationException: @raise RuntimeException: """ if rightSide is False: # if this is still false after the last config has been merged the # finalization pass will take care of removing this key entirely return False if not leftSide or not self._performDeepMerging: return rightSide if isinstance(leftSide, list): leftSide = Array.toDict(leftSide) if isinstance(rightSide, list): rightSide = Array.toDict(rightSide) i = -1 for k, v in rightSide.items(): i += 1 # prototype, and key is irrelevant, so simply append the element if self._keyAttribute is None: # dict: append index = 0 while index in leftSide: index += 1 leftSide[index] = v continue # no conflict if k not in leftSide: if not self._allowNewKeys: ex = InvalidConfigurationException( 'You are not allowed to define new elements for path ' '"{0}". Please define all elements for this path in ' 'one config file. If you are trying to overwrite an ' 'element, make sure you redefine it with the same ' 'name.'.format(self.getPath())) ex.setPath(self.getPath()) raise ex leftSide[k] = v continue self._prototype.setName(k) leftSide[k] = self._prototype.merge(leftSide[k], v) return leftSide
def __writeArray(self, array, depth): assert isinstance(array, (list, dict)); isIndexed = False; if isinstance(array, dict): for key in array.keys(): if not isinstance(key, int): isIndexed = False; break; else: isIndexed = True; array = Array.toDict(array); for key, value in array.items(): if isinstance(value, (list, dict)) : val = ''; else : val = value; if (isIndexed) : self.__writeLine('- '+val, depth * 4); else : self.__writeLine('{0:20} {1}'.format( key+':', val), depth * 4); if isinstance(value, (list, dict)) : self.__writeArray(value, depth + 1);
def __writeArray(self, array, depth): assert isinstance(array, (list, dict)) isIndexed = False if isinstance(array, dict): for key in array.keys(): if not isinstance(key, int): isIndexed = False break else: isIndexed = True array = Array.toDict(array) for key, value in array.items(): if isinstance(value, (list, dict)): val = '' else: val = value if (isIndexed): self.__writeLine('- ' + val, depth * 4) else: self.__writeLine('{0:20} {1}'.format(key + ':', val), depth * 4) if isinstance(value, (list, dict)): self.__writeArray(value, depth + 1)
def ifNotInArray(self, target): """Tests if the value is not in an array @param target: dict @return: ExprBuilder """ self.ifPart = lambda v: v not in Array.toDict(target).values(); return self;
def setDefaultValue(self, value): """Sets the default value of this node. @param value: dict @raise InvalidArgumentException: if the default value is not an array """ if isinstance(value, list): value = Array.toDict(value) if not isinstance(value, dict): raise InvalidArgumentException( '{0}: the default value of an array node has to be an array.' ''.format(self.getPath())) self._defaultValue = value
def _mergeValues(self, leftSide, rightSide): """Merges values together. @param leftSide: mixed The left side to merge. @param rightSide: mixed The right side to merge. @return: mixed The merged values @rasie InvalidConfigurationException: @rasie RuntimeException: """ if rightSide is False: # if this is still false after the last config has been merged the # finalization pass will take care of removing this key entirely return False; if not leftSide or not self._performDeepMerging: return rightSide; if isinstance(rightSide, list): rightSide = Array.toDict(rightSide); for k, v in rightSide.items(): # no conflict if k not in leftSide: if not self._allowNewKeys: ex = InvalidConfigurationException( 'You are not allowed to define new elements for path ' '"{0}". Please define all elements for this path in ' 'one config file. If you are trying to overwrite an ' 'element, make sure you redefine it with the same ' 'name.'.format(self.getPath()) ); ex.setPath(self.getPath()); raise ex; leftSide[k] = v; continue; if k not in self._children: raise RuntimeException( 'merge() expects a normalized config array.' ); leftSide[k] = self._children[k].merge(leftSide[k], v); return leftSide;
def setDefaultValue(self, value): """Sets the default value of this node. @param value: dict @raise InvalidArgumentException: if the default value is not an array """ if isinstance(value, list): value = Array.toDict(value); if not isinstance(value, dict): raise InvalidArgumentException( '{0}: the default value of an array node has to be an array.' ''.format(self.getPath()) ); self._defaultValue = value;
def _mergeValues(self, leftSide, rightSide): """Merges values together. @param leftSide: mixed The left side to merge. @param rightSide: mixed The right side to merge. @return: mixed The merged values @rasie InvalidConfigurationException: @rasie RuntimeException: """ if rightSide is False: # if this is still false after the last config has been merged the # finalization pass will take care of removing this key entirely return False if not leftSide or not self._performDeepMerging: return rightSide if isinstance(rightSide, list): rightSide = Array.toDict(rightSide) for k, v in rightSide.items(): # no conflict if k not in leftSide: if not self._allowNewKeys: ex = InvalidConfigurationException( 'You are not allowed to define new elements for path ' '"{0}". Please define all elements for this path in ' 'one config file. If you are trying to overwrite an ' 'element, make sure you redefine it with the same ' 'name.'.format(self.getPath())) ex.setPath(self.getPath()) raise ex leftSide[k] = v continue if k not in self._children: raise RuntimeException( 'merge() expects a normalized config array.') leftSide[k] = self._children[k].merge(leftSide[k], v) return leftSide
def setAddChildrenIfNoneSet(self, children=None): """Adds default children when none are set. @param children: integer|string|dict|null The number of children|The child name|The children names to be added """ if children is None: children = ['defaults']; elif isinstance(children, int) and children > 0: children = list(range(1, children+1)); elif isinstance(children, String): children = [children]; if isinstance(children, list): children = Array.toDict(children); assert isinstance(children, dict); self._defaultChildren = children;
def setAddChildrenIfNoneSet(self, children=None): """Adds default children when none are set. @param children: integer|string|dict|null The number of children|The child name|The children names to be added """ if children is None: children = ['defaults'] elif isinstance(children, int) and children > 0: children = list(range(1, children + 1)) elif isinstance(children, String): children = [children] if isinstance(children, list): children = Array.toDict(children) assert isinstance(children, dict) self._defaultChildren = children
def _normalizeValue(self, value): """Normalizes the value. @param value: mixed The value to normalize @return: mixed The normalized value @raise InvalidConfigurationException: """ if value is False: return value; if isinstance(value, list): value = Array.toDict(value); assert isinstance(value, dict); value = self._remapXml(value); normalized = dict(); valueCopy = value.copy(); for name, child in self._children.items(): assert isinstance(child, NodeInterface) if name in valueCopy: normalized[name] = child.normalize(value[name]); valueCopy.pop(name); # if extra fields are present, throw exception if valueCopy and not self._ignoreExtraKeys: ex = InvalidConfigurationException( 'Unrecognized options "{0}" under "{1}"' ''.format(", ".join(value.keys()), self.getPath()) ); ex.setPath(self.getPath()); raise ex; return normalized;
def _normalizeValue(self, value): """Normalizes the value. @param value: mixed The value to normalize @return: mixed The normalized value @raise InvalidConfigurationException: """ if value is False: return value if isinstance(value, list): value = Array.toDict(value) assert isinstance(value, dict) value = self._remapXml(value) normalized = dict() valueCopy = value.copy() for name, child in self._children.items(): assert isinstance(child, NodeInterface) if name in valueCopy: normalized[name] = child.normalize(value[name]) valueCopy.pop(name) # if extra fields are present, throw exception if valueCopy and not self._ignoreExtraKeys: ex = InvalidConfigurationException( 'Unrecognized options "{0}" under "{1}"' ''.format(", ".join(value.keys()), self.getPath())) ex.setPath(self.getPath()) raise ex return normalized
def _normalizeValue(self, value): """Normalizes the value. @param value: mixed The value to normalize @return mixed The normalized value @raise InvalidConfigurationException: @raise DuplicateKeyException: """ if value is False: return value; if isinstance(value, list): value = Array.toDict(value); assert isinstance(value, dict); value = self._remapXml(value); isAssoc = list(value.keys()) != list(range(len(value))); normalized = dict(); i = -1; for k, v in value.items(): i += 1; if self._keyAttribute is not None and isinstance(v, (dict, list)): if isinstance(v, list): v = Array.toDict(v); if self._keyAttribute not in v \ and isinstance(k, int) \ and not isAssoc: ex = InvalidConfigurationException( 'The attribute "{0}" must be set for path "{1}".' ''.format(self._keyAttribute, self.getPath()) ); ex.setPath(self.getPath()); raise ex; elif self._keyAttribute in v: k = v[self._keyAttribute]; # remove the key attribute when required if self._removeKeyAttribute: del v[self._keyAttribute]; # if only "value" is left if 1 == len(v) and 'value' in v: v = v['value']; if k in normalized: ex = DuplicateKeyException( 'Duplicate key "{0}" for path "{1}".' ''.format(k, self.getPath()) ); ex.setPath(self.getPath()); raise ex; self._prototype.setName(k); if not self._keyAttribute is None or isAssoc: normalized[k] = self._prototype.normalize(v); else: normalized[i] = self._prototype.normalize(v); return normalized;
def get(self, path, default = None, deep = False): """Returns a parameter by name. @param string path The key @param mixed default The default value if the parameter key does not exist @param boolean deep If True, a path like foo[bar] will find deeper items @return mixed @raise InvalidArgumentException @api """ try: pos = str(path).index('['); except ValueError: pos = False; if ( not deep or False is pos) : if path in self._parameters: return self._parameters[path]; else: return default; root = str(path)[0:pos]; if not root in self._parameters : return default; value = self._parameters[root]; currentKey = None; i = pos - 1; for char in range(len(path)): i += 1; if ('[' == char) : if (None is not currentKey) : raise InvalidArgumentException( 'Malformed path. Unexpected "[" at position {0}.' ''.format(str(i)) ); currentKey = ''; elif (']' == char) : if (None is currentKey) : raise InvalidArgumentException( 'Malformed path. Unexpected "]" at position {0}.' ''.format(str(i)) ); if isinstance(value, list): value = Array.toDict(value, True); if not isinstance(value, dict) or currentKey not in value : return default; value = value[currentKey]; currentKey = None; else : if (None is currentKey) : raise InvalidArgumentException( 'Malformed path. Unexpected "{0}" at position {1}.' ''.format(char, str(i)) ); currentKey += char; if (None is not currentKey) : raise InvalidArgumentException( 'Malformed path. Path must end with "]".' ); return value;
def _normalizeValue(self, value): """Normalizes the value. @param value: mixed The value to normalize @return mixed The normalized value @raise InvalidConfigurationException: @raise DuplicateKeyException: """ if value is False: return value if isinstance(value, list): value = Array.toDict(value) assert isinstance(value, dict) value = self._remapXml(value) isAssoc = list(value.keys()) != list(range(len(value))) normalized = dict() i = -1 for k, v in value.items(): i += 1 if self._keyAttribute is not None and isinstance(v, (dict, list)): if isinstance(v, list): v = Array.toDict(v) if self._keyAttribute not in v \ and isinstance(k, int) \ and not isAssoc: ex = InvalidConfigurationException( 'The attribute "{0}" must be set for path "{1}".' ''.format(self._keyAttribute, self.getPath())) ex.setPath(self.getPath()) raise ex elif self._keyAttribute in v: k = v[self._keyAttribute] # remove the key attribute when required if self._removeKeyAttribute: del v[self._keyAttribute] # if only "value" is left if 1 == len(v) and 'value' in v: v = v['value'] if k in normalized: ex = DuplicateKeyException( 'Duplicate key "{0}" for path "{1}".' ''.format(k, self.getPath())) ex.setPath(self.getPath()) raise ex self._prototype.setName(k) if not self._keyAttribute is None or isAssoc: normalized[k] = self._prototype.normalize(v) else: normalized[i] = self._prototype.normalize(v) return normalized