def construct_env_tag(loader: yaml.Loader, node: yaml.Node) -> Any: """Assign value of ENV variable referenced at node.""" default = None if isinstance(node, yaml.nodes.ScalarNode): vars = [loader.construct_scalar(node)] elif isinstance(node, yaml.nodes.SequenceNode): child_nodes = node.value if len(child_nodes) > 1: # default is resolved using YAML's (implicit) types. default = loader.construct_object(child_nodes[-1]) child_nodes = child_nodes[:-1] # Env Vars are resolved as string values, ignoring (implicit) types. vars = [loader.construct_scalar(child) for child in child_nodes] else: raise yaml.constructor.ConstructorError( None, None, f'expected a scalar or sequence node, but found {node.id}', node.start_mark) for var in vars: if var in os.environ: value = os.environ[var] # Resolve value to Python type using YAML's implicit resolvers tag = loader.resolve(yaml.nodes.ScalarNode, value, (True, False)) return loader.construct_object(yaml.nodes.ScalarNode(tag, value)) return default
def env_var_constructor(loader: yaml.Loader, node: yaml.ScalarNode) -> Optional[str]: if node.id != "scalar": raise TypeError("Expected a string") value = loader.construct_scalar(node) key = str(value) return os.getenv(key)
def construct_tagless_yaml(loader: yaml.Loader, node: yaml.Node): # From yaml.constructor.BaseConstructor#construct_object if isinstance(node, yaml.ScalarNode): return loader.construct_scalar(node) elif isinstance(node, yaml.SequenceNode): return loader.construct_sequence(node) elif isinstance(node, yaml.MappingNode): return loader.construct_mapping(node) raise NotImplementedError('invalid node')
def construct_custom_class(cls, loader: yaml.Loader, node: yaml.Node): result = cls.__new__(cls) yield result if isinstance(node, yaml.ScalarNode): value = loader.construct_scalar(node) elif isinstance(node, yaml.SequenceNode): value = loader.construct_sequence(node) elif isinstance(node, yaml.MappingNode): value = loader.construct_mapping(node) else: assert False result.__init__(value)
def inner(loader: yaml.Loader, node): value = loader.construct_scalar(node) for env_code in pattern.findall(value): env_name, _, env_type = env_code.partition(":") env = os.environ.get(env_name) if not env: return None value = value.replace(f"${{{env_code}}}", env) if env_type == "bool": return value.lower().strip() == "true" return types.get(env_type, str)(value) return value
def _env_var_constructor(loader: yaml.Loader, node: yaml.Node): '''Implements a custom YAML tag for loading optional environment variables. If the environment variable is set it returns its value. Otherwise returns `None`. Example usage: key: !ENV 'KEY' ''' if node.id == 'scalar': # type: ignore value = loader.construct_scalar(node) key = str(value) else: raise TypeError('Expected a string') return HiddenRepr(os.getenv(key))
def _env_yaml(loader: yaml.Loader, node: yaml.nodes.Node): """Extracts the environment variable from the node's value :param loader: the yaml loader :param node: the current node in the yaml :return: the parsed string that contains the value of the environment variable """ value = loader.construct_scalar(node) match = _ENV_pattern.findall(value) # to find all env variables in line if match: full_value = value for g in match: full_value = full_value.replace(f'${{{g}}}', os.environ.get(g, g)) return full_value return value
def intrinsics_multi_constructor( # pylint: disable=unused-argument loader: yaml.Loader, tag_prefix: str, node: yaml.Node) -> Dict[str, Any]: """YAML constructor to parse CloudFormation intrinsics. This will return a dictionary with key being the intrinsic name """ # Get the actual tag name excluding the first exclamation tag = node.tag[1:] # Some intrinsic functions doesn't support prefix "Fn::" prefix = "Fn::" if tag in ["Ref", "Condition"]: prefix = "" cfntag = prefix + tag if tag == "GetAtt" and isinstance(node.value, str): # ShortHand notation for !GetAtt accepts Resource.Attribute format # while the standard notation is to use an array # [Resource, Attribute]. Convert shorthand to standard format value = node.value.split(".", 1) elif isinstance(node, yaml.ScalarNode): # Value of this node is scalar value = loader.construct_scalar(node) elif isinstance(node, yaml.SequenceNode): # Value of this node is an array (Ex: [1,2]) value = cast(MutableSequence[Any], loader.construct_sequence(node)) else: # Value of this node is an mapping (ex: {foo: bar}) value = cast(MutableMapping[Any, Any], loader.construct_mapping(node)) return {cfntag: value}
def constructor(loader: yaml.Loader, node: yaml.Node): ids = [int(x) for x in loader.construct_scalar(node).split()] return Object(ids[-1], lambda: func(*ids))
def _from_yaml(cls, loader: yaml.Loader, node: yaml.Node) -> "YamlModifier": """Load an internal yaml node parsing, defaulting to a scalar value.""" value = loader.construct_scalar(typing.cast(yaml.ScalarNode, node)) return cls(value)
def _from_yaml(cls, loader: yaml.Loader, node: yaml.Node) -> "InjectString": """Load an internal yaml node parsing.""" raw = loader.construct_scalar(typing.cast(yaml.ScalarNode, node)) value = json.loads(typing.cast(str, raw).strip("\"'")) return cls(value)
def _path_constructor(loader: yaml.Loader, node): value = loader.construct_scalar(node) return Path(value)
def _construct_config(self, loader: yaml.Loader, node: yaml.Node): key = loader.construct_scalar(node) return self.Config.get(key)
def _construct_include(self, loader: yaml.Loader, node: yaml.Node): """Include file referenced at node.""" identifier = loader.construct_scalar(node) declaration = self.read(identifier) return self.parse(declaration, identifier)
def env_constructor(loader: yaml.Loader, node: yaml.Node) -> str: value = loader.construct_scalar(node) if value not in os.environ: raise YAMLEnvVariableError(value) return os.environ.get(value)
def string_module_constructor(loader: yaml.Loader, node: yaml.Node) -> str: value = loader.construct_scalar(node) if value in POSSIBLE_SYMBOLS_VALUES: return getattr(string, value) raise YAMLStringValueError(value)
def time_constructor(loader: yaml.Loader, node: yaml.ScalarNode) -> time: value = loader.construct_scalar(node) data = time.fromisoformat(value) return data
def timedelta_constructor(loader: yaml.Loader, node: yaml.ScalarNode) -> Optional[timedelta]: value = loader.construct_scalar(node) data = parse_timedelta(value) return data