Implement a config parser


ID: 661
PHID: PHID-TASK-7w6xmwr5qkkajazooty3
Author: dau
Status at Migration Time: open
Priority at Migration Time: Normal


The [[ proposals/635-listen-port-convention.txt at master · Kicksecure/proposals · GitHub | Listen Port Convention proposal ]] depends on the parsing of specific files within specific directories. A config parser with the following features should be implemented:

  • Provide a Python package
  • Provide a command-line interface for non-Python apps
  • Provide json and eval serializers
  • Allow different parts of it to be customized

I will create a repo and post it here once I start working on this. Here is the initial code:

import argparse

class Parser:
    def parse_global(cls, filepath):
        """Read `filepath`, parse it and return all directory paths found.

        The directories in the list are in the order they are intended to be

    def is_config_file(cls, filename):
        """Return `True` if `filename` is a config file. `False` otherwise."""

    def find_config_files(cls, dirpath):
        """Walk through the directory and return all file paths found.

        Depending on `is_config_file`, each file is prepended by the
        directory's path and added to the list. The files in the list are in
        the order they are intended to be read.

    def parse_file(cls, filepath, configs=None):
        """Read `filepath`, parse it and return a `config: value` dict.

        If no configs are provided, a new dict is created. As the file is read,
        values are added to the configs with
        `add_config(configs, config, value)`."""

    def add_config(cls, configs, config, value):
        """Add `config: value` to the configs dict and return it.

        In case the config did not exist, it is added to the dict. Otherwise,
        it replaces or merges to the existing one.

    def parse(cls, name):
        """Read the name of the config and return a `config: value` dict.

        The name defaults to a `/etc/<name>.conf` file path but can optionally
        specify a different path and extension. Its format should be something
        like `[/custom/path/]name[.custom]`.
        cfgs = dict()

        for dirpath in cls.parse_global(name):
            for filepath in cls.find_config_files(dirpath):
                cfgs = cls.parse_file(filepath, cfgs)

        return cfgs

    def serialize(cls, configs):
        """Serialize the configs dict into a convenient format."""

    def parse_to_serialized(cls, name):
        """Parse configs and return them serialized."""
        return cls.serialize(cls.parse(name))

def call_parse():
    """Read a config name and print the serialized configs.

    This function should be accessed through an entry point. The name is passed
    via a command-line call and returns the configs in a format that
    applications are able to read in the language they use.
    argparser = argparse.ArgumentParser()
    args = argparser.parse_args()

    print Parser.parse_to_serialized(

A Python app would use the parser to retrieve the listen_ip config of the listen convention with the following code:

import Parser

cfgs = Parser.parse('listen')
listen_ip = cfgs['listen_ip']

# bind on `listen_ip`

A non-Python app would receive the serialized configs with the following call:

$ configparser listen

P.S. We need a good name for this.

This is a follow-up ticket to T635