pyhocon icon indicating copy to clipboard operation
pyhocon copied to clipboard

include syntax

Open WheatMaThink opened this issue 4 years ago • 1 comments

Hi Can the following include syntax be supported

#dev prod Environment: "dev"

#include "conf.d/dev/*.conf" include` "conf.d/${Environment}/*.conf"

Looking forward to reply, thank you.

WheatMaThink avatar Dec 08 '20 07:12 WheatMaThink

same issue with "dynamic include": https://github.com/lightbend/config/issues/122

@darthbear would you consider implement this nice feature for python?

haobibo avatar Apr 11 '21 15:04 haobibo

` ## Modify config_parser.py file

        elif file is not None:
            path = file if basedir is None else os.path.join(basedir, file)
	    #------  start  --------
            try:
                # 动态路径赋值
                from includeTools import IncludeTools
                includeSub = IncludeTools(instring)
                path = includeSub.getConfigPath(path)
                # extend configTree _merge(a, b)
            except Exception as e:
                # traceback.print_exc()
                pass

            #------  end  --------
            def _make_prefix(path):
                return ('<root>' if path is None else '[%s]' % path).ljust(55).replace('\\', '/')

import pyparsing as pp

class IncludeTools():

def __init__(self, inContent: str = None) -> None:
    self.content = inContent
    self.configTree = pyhocon.ConfigTree()
    self.parse(self.content)

def parse(self, content: str) -> None:
   
    try:
        localsContent = self.content
        lines = pp.LineStart() + pp.Combine(pp.Keyword("include") + pp.OneOrMore(pp.CharsNotIn('\n', exact=1)))

        for tokens, start, end in lines.scanString(content):
            localsContent = localsContent.replace(tokens[0], " ")

        conf = pyhocon.ConfigFactory.parse_string(localsContent)
        self.configTree.merge_configs(self.configTree, conf, True)
    except pp.ParseException as err:
        print(err)

def getConfigPath(self, path: str) -> str:

    substitution_expr = pp.Regex(r'[ \t]*\$\{[^\}]+\}[ \t]*').setParseAction(self.create_substitution)
    name = substitution_expr.searchString(path)
    if len(name) == 1:
        return path.replace(name[0][0], name[0][1])
    else:
        return path

def create_substitution(self, instring, loc, token):
    # remove the ${ and } 创建一个替代
    SUBSTITUTION_PATTERN = r"\$\{(?P<optional>\?)?(?P<variable>[^}]+)\}(?P<ws>[ \t]*)"
    match = pp.re.match(SUBSTITUTION_PATTERN, token[0])
    variable = match.group('variable')
    value = self.configTree.get(variable, None)
    if value is None:
        return None
    return [token[0], value]

def extendConfigTree(self, conf):
    """
    load include new file merge_configs it
    :param conf:
    :return:
    """
    self.configTree.merge_configs(self.configTree, conf, True)

`

WheatMaThink avatar Nov 12 '22 02:11 WheatMaThink

@wheatma38 could you please create a PR for this idea? This is a greate fetarue and improvement!

haobibo avatar Nov 13 '22 03:11 haobibo

@haobibo

This is a small function, just have a look. Or would you please do it for me. :|)

WheatMaThink avatar Nov 14 '22 16:11 WheatMaThink