cherry-pick newer version of extractOptions, in order to avoid large discrepancy between 0.10 and 0.9 config-parsers:

allow to use dual parameter lists (coming through substitutions), e. g.: `name[p1=0, p2="..."][p3='...']`;
simplified explanation: `][` treats as `,` in new version.
cherry-picked from 0.10.
pull/1908/head
sebres 2018-01-10 10:55:19 +01:00
parent 82f8bd8639
commit 3d9a112c8f
2 changed files with 33 additions and 23 deletions

View File

@ -27,14 +27,13 @@ __license__ = "GPL"
import glob
import json
import os.path
import re
from .configreader import ConfigReaderUnshared, ConfigReader
from .filterreader import FilterReader
from .actionreader import ActionReader
from ..version import version
from ..helpers import getLogger
from ..helpers import splitwords
from ..helpers import extractOptions, splitwords
# Gets the instance of the logger.
logSys = getLogger(__name__)
@ -42,10 +41,6 @@ logSys = getLogger(__name__)
class JailReader(ConfigReader):
optionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$")
optionExtractRE = re.compile(
r'([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,]*))(?:,|$)')
def __init__(self, name, force_enable=False, **kwargs):
ConfigReader.__init__(self, **kwargs)
self.__name = name
@ -121,7 +116,7 @@ class JailReader(ConfigReader):
if self.isEnabled():
# Read filter
if self.__opts["filter"]:
filterName, filterOpt = JailReader.extractOptions(
filterName, filterOpt = extractOptions(
self.__opts["filter"])
self.__filter = FilterReader(
filterName, self.__name, filterOpt, share_config=self.share_config, basedir=self.getBaseDir())
@ -150,7 +145,7 @@ class JailReader(ConfigReader):
try:
if not act: # skip empty actions
continue
actName, actOpt = JailReader.extractOptions(act)
actName, actOpt = extractOptions(act)
if actName.endswith(".py"):
self.__actions.append([
"set",
@ -244,18 +239,4 @@ class JailReader(ConfigReader):
stream.insert(0, ["add", self.__name, backend])
return stream
@staticmethod
def extractOptions(option):
match = JailReader.optionCRE.match(option)
if not match:
# TODO proper error handling
return None, None
option_name, optstr = match.groups()
option_opts = dict()
if optstr:
for optmatch in JailReader.optionExtractRE.finditer(optstr):
opt = optmatch.group(1)
value = [
val for val in optmatch.group(2,3,4) if val is not None][0]
option_opts[opt.strip()] = value.strip()
return option_name, option_opts
JailReader.extractOptions = staticmethod(extractOptions)

View File

@ -137,3 +137,32 @@ def splitwords(s):
if not s:
return []
return filter(bool, map(str.strip, re.split('[ ,\n]+', s)))
#
# Following function used for parse options from parameter (e.g. `name[p1=0, p2="..."][p3='...']`).
#
# regex, to extract list of options:
OPTION_CRE = re.compile(r"^([^\[]+)(?:\[(.*)\])?\s*$", re.DOTALL)
# regex, to iterate over single option in option list, syntax:
# `action = act[p1="...", p2='...', p3=...]`, where the p3=... not contains `,` or ']'
# since v0.10 separator extended with `]\s*[` for support of multiple option groups, syntax
# `action = act[p1=...][p2=...]`
OPTION_EXTRACT_CRE = re.compile(
r'([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,\]]*))(?:,|\]\s*\[|$)', re.DOTALL)
def extractOptions(option):
match = OPTION_CRE.match(option)
if not match:
# TODO proper error handling
return None, None
option_name, optstr = match.groups()
option_opts = dict()
if optstr:
for optmatch in OPTION_EXTRACT_CRE.finditer(optstr):
opt = optmatch.group(1)
value = [
val for val in optmatch.group(2,3,4) if val is not None][0]
option_opts[opt.strip()] = value.strip()
return option_name, option_opts