Source code for datamodel.io.loaders

# !/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Filename: loaders.py
# Project: io
# Author: Brian Cherinka
# Created: Friday, 2nd April 2021 3:22:28 pm
# License: BSD 3-clause "New" or "Revised" License
# Copyright (c) 2021 Brian Cherinka
# Last Modified: Friday, 2nd April 2021 3:22:28 pm
# Modified By: Brian Cherinka


from __future__ import print_function, division, absolute_import
import pathlib
import os
import re
import yaml
from typing import Union

from datamodel import log


[docs] def include(loader, node): yamlref = loader.construct_scalar(node) if '#' not in yamlref: yamlfile = yamlref comps = None else: yamlfile, comps = yamlref.split('#') file = get_yaml_files(yamlfile) if not file: return None data = read_yaml(file) if comps: parts = comps.split('/') for part in parts: m = re.search(r'(?P<part>[a-z]+)(?P<item>\[(?P<index>.*?)\])?', part).groupdict() data=data.get(m['part']) if m['index']: if m['index'].isdigit(): data=data[int(m['index'])] elif ":" in m['index']: key,val=m['index'].split(':') data = [d for d in data if str(d.get(key))==val] return data[0] if data else None return data
[docs] def dm(loader, node): data = include(loader, node) if not isinstance(data, dict): raise ValueError('Referenced data is not a valid datamodel object!') return data
yaml.add_constructor('!include', include) yaml.add_constructor('!dm', dm)
[docs] def get_yaml_files(get: str = None) -> Union[str, list]: """ Get a list of yaml files Return a list of YAML files in the datamodel directory. Parameters ---------- get : str, optional type of yaml file to get, can be "releases" or "products", by default None Returns ------- Union[str, list] The yaml file path or list of yaml file paths """ envvar = os.environ.get('DATAMODEL_DIR', None) if not envvar: log.error('Cannot get yaml files. No DATAMODEL_DIR envvar set. Check your installation.') return None datamodel_dir = envvar / pathlib.Path('datamodel') files = datamodel_dir.rglob(f'*.yaml') if not get: return list(files) elif get == 'products': return [i for i in files if 'products' in str(i)] else: file = [i for i in files if get in str(i)] return file[0] if file else None
[docs] def read_yaml(ymlfile: Union[str, pathlib.Path]) -> dict: """ Opens and reads a YAML file Parameters ---------- ymlfile : Union[str, pathlib.Path] a file or pathlib.Path object Returns ------- dict the YAML content """ if isinstance(ymlfile, str): ymlfile = pathlib.Path(ymlfile) with open(ymlfile, 'r') as f: data = yaml.load(f, Loader=yaml.FullLoader) return data