Information
ID: 661
PHID: PHID-TASK-7w6xmwr5qkkajazooty3
Author: dau
Status at Migration Time: open
Priority at Migration Time: Normal
Description
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:
@classmethod
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
read.
"""
@classmethod
def is_config_file(cls, filename):
"""Return `True` if `filename` is a config file. `False` otherwise."""
@classmethod
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.
"""
@classmethod
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)`."""
@classmethod
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.
"""
@classmethod
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
@classmethod
def serialize(cls, configs):
"""Serialize the configs dict into a convenient format."""
@classmethod
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()
argparser.add_argument('name')
args = argparser.parse_args()
print Parser.parse_to_serialized(args.name)
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