[matter] add support for external .spec parsers
This commit is contained in:
@@ -18,6 +18,7 @@ import sys
|
||||
|
||||
from matter.binpms.base import BaseBinaryResourceLock, \
|
||||
BaseBinaryPMS
|
||||
from matter.spec import MatterSpec, MatterSpecParser, GenericSpecFunctions
|
||||
from matter.output import print_info, print_warning, print_error
|
||||
from matter.utils import print_traceback
|
||||
|
||||
@@ -363,3 +364,29 @@ class EntropyBinaryPMS(BaseBinaryPMS):
|
||||
|
||||
BaseBinaryPMS.register(EntropyBinaryPMS)
|
||||
BaseBinaryPMS.DEFAULT = False
|
||||
|
||||
|
||||
class EntropySpecParser(MatterSpecParser):
|
||||
"""
|
||||
External .spec parser object which implements
|
||||
extra .spec parameters support.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(EntropySpecParser, self).__init__()
|
||||
self._funcs = GenericSpecFunctions()
|
||||
|
||||
def vital_parameters(self):
|
||||
"""
|
||||
Overridden from MatterSpecParser.
|
||||
"""
|
||||
return []
|
||||
|
||||
def data(self):
|
||||
"""
|
||||
Overridden from MatterSpecParser.
|
||||
"""
|
||||
return {}
|
||||
|
||||
|
||||
MatterSpec.register_parser(EntropySpecParser())
|
||||
|
||||
@@ -229,7 +229,7 @@ def main():
|
||||
avail_binpms = BaseBinaryPMS.available_pms
|
||||
|
||||
matter_spec = MatterSpec()
|
||||
parser_data = matter_spec.parser_data_path()
|
||||
parser_data = matter_spec.data()
|
||||
matter_spec_params = ""
|
||||
for spec_key in sorted(parser_data.keys()):
|
||||
par = parser_data[spec_key]
|
||||
|
||||
@@ -108,18 +108,19 @@ class GenericSpecFunctions(object):
|
||||
self.valid_path_string(y) and y.strip()]
|
||||
|
||||
|
||||
class MatterSpec(GenericSpecFunctions):
|
||||
class MatterSpecParser(object):
|
||||
"""
|
||||
Base class for implementing external .spec parsers
|
||||
that can be used to extend the list of supported statements.
|
||||
"""
|
||||
|
||||
def vital_parameters(self):
|
||||
"""
|
||||
Return a list of vital .spec file parameters
|
||||
|
||||
@return: list of vital .spec file parameters
|
||||
@rtype: list
|
||||
Return a list of vital parameters.
|
||||
"""
|
||||
return ["packages", "repository"]
|
||||
raise NotImplementedError()
|
||||
|
||||
def parser_data_path(self):
|
||||
def data(self):
|
||||
"""
|
||||
Return a dictionary containing parameter names as key and
|
||||
dict containing keys 've' and 'cb' which values are three
|
||||
@@ -129,119 +130,164 @@ class MatterSpec(GenericSpecFunctions):
|
||||
@return: data path dictionary (see ChrootSpec code for more info)
|
||||
@rtype: dict
|
||||
"""
|
||||
return {
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class MatterSpec(MatterSpecParser):
|
||||
|
||||
_external_parsers = []
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
MatterSpec constructor.
|
||||
"""
|
||||
self._funcs = GenericSpecFunctions()
|
||||
|
||||
@classmethod
|
||||
def register_parser(cls, parser):
|
||||
"""
|
||||
Register an external parser object.
|
||||
|
||||
@param parser: a MatterSpecParser subclass
|
||||
@type parser: MatterSpecParser
|
||||
"""
|
||||
MatterSpec._external_parsers.append(parser)
|
||||
|
||||
def vital_parameters(self):
|
||||
"""
|
||||
Return a list of vital .spec file parameters
|
||||
|
||||
@return: list of vital .spec file parameters
|
||||
@rtype: list
|
||||
"""
|
||||
vital = set(["packages", "repository"])
|
||||
for parser in MatterSpec._external_parsers:
|
||||
vital |= set(parser.vital_parameters())
|
||||
return sorted(vital)
|
||||
|
||||
def data(self):
|
||||
"""
|
||||
Return a dictionary containing parameter names as key and
|
||||
dict containing keys 've' and 'cb' which values are three
|
||||
callable functions that respectively do value extraction (ve),
|
||||
value verification (cb) and value modding (mod).
|
||||
|
||||
@return: data path dictionary (see ChrootSpec code for more info)
|
||||
@rtype: dict
|
||||
"""
|
||||
data = {
|
||||
"build-args": {
|
||||
"cb": self.ne_string,
|
||||
"ve": self.ve_string_shlex_splitter,
|
||||
"cb": self._funcs.ne_string,
|
||||
"ve": self._funcs.ve_string_shlex_splitter,
|
||||
"default": ["--verbose", "--nospinner"],
|
||||
"desc": "Portage build arguments (default is --verbose\n "
|
||||
"--nospinner)",
|
||||
},
|
||||
"build-only": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "no",
|
||||
"desc": "Only build the packages without merging them\n "
|
||||
"into the system.",
|
||||
},
|
||||
"dependencies": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "no",
|
||||
"desc": "Allow dependencies to be pulled in? (yes/no)",
|
||||
},
|
||||
"downgrade": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "no",
|
||||
"desc": "Allow package downgrades? (yes/no)",
|
||||
},
|
||||
"keep-going": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "no",
|
||||
"desc": "Make possible to continue if one \n\t"
|
||||
"or more packages fail to build? (yes/no)",
|
||||
},
|
||||
"new-useflags": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "no",
|
||||
"desc": "Allow new USE flags? (yes/no)",
|
||||
},
|
||||
"removed-useflags": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "no",
|
||||
"desc": "Allow removed USE flags? (yes/no)",
|
||||
},
|
||||
"rebuild": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "no",
|
||||
"desc": "Allow package rebuilds? (yes/no)",
|
||||
},
|
||||
"spm-repository-change": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "no",
|
||||
"desc": "Allow Source Package Manager (Portage) \n\t"
|
||||
"repository change? (yes/no)",
|
||||
},
|
||||
"spm-repository-change-if-upstreamed": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "no",
|
||||
"desc": "In case of Source Package Manager \n\trepository "
|
||||
"changes, allow execution if the original repository "
|
||||
"\n\tdoes not contain the package anymore? (yes/no)",
|
||||
},
|
||||
"not-installed": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "no",
|
||||
"desc": "Allow compiling packages even if they "
|
||||
"are not \n\tactually installed on the System? (yes/no)",
|
||||
},
|
||||
"soft-blocker": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "yes",
|
||||
"desc": "Allow soft-blockers in the merge queue?\n "
|
||||
"Packages will be unmerged if yes. (yes/no)",
|
||||
},
|
||||
"unmerge": {
|
||||
"cb": self.valid_yes_no,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "yes",
|
||||
"desc": "Allow package unmerges due to Portage\n "
|
||||
"soft-blockers resolution. (yes/no)",
|
||||
},
|
||||
"pkgpre": {
|
||||
"cb": self.not_none,
|
||||
"ve": self.ve_string_open_file_read,
|
||||
"cb": self._funcs.not_none,
|
||||
"ve": self._funcs.ve_string_open_file_read,
|
||||
"default": None,
|
||||
"desc": "Package pre execution script hook path, "
|
||||
"executed \n\tfor each package (also see example files)",
|
||||
},
|
||||
"pkgpost": {
|
||||
"cb": self.not_none,
|
||||
"ve": self.ve_string_open_file_read,
|
||||
"cb": self._funcs.not_none,
|
||||
"ve": self._funcs.ve_string_open_file_read,
|
||||
"default": None,
|
||||
"desc": "Package build post execution script hook path, "
|
||||
"executed \n\tfor each package (also see example files)",
|
||||
},
|
||||
"buildfail": {
|
||||
"cb": self.not_none,
|
||||
"ve": self.ve_string_open_file_read,
|
||||
"cb": self._funcs.not_none,
|
||||
"ve": self._funcs.ve_string_open_file_read,
|
||||
"default": None,
|
||||
"desc": "Package build failure execution script hook "
|
||||
"path, \n\texecuted for each failing package (also see "
|
||||
"example files)",
|
||||
},
|
||||
"packages": {
|
||||
"cb": self.always_valid,
|
||||
"ve": self.valid_comma_sep_list_list,
|
||||
"cb": self._funcs.always_valid,
|
||||
"ve": self._funcs.valid_comma_sep_list_list,
|
||||
"mod": lambda l_l: [x for x in l_l if x],
|
||||
"desc": "List of packages to scrape, separated by "
|
||||
"comma. \n\tIf you want to let Portage consider a group "
|
||||
@@ -249,19 +295,27 @@ class MatterSpec(GenericSpecFunctions):
|
||||
"no commas",
|
||||
},
|
||||
"repository": {
|
||||
"cb": self.ne_string,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.ne_string,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"desc": "Binary Package Manager repository in where "
|
||||
"newly built \n\tpackages will be put and pushed to",
|
||||
},
|
||||
"stable": {
|
||||
"cb": self.valid_yes_no_inherit,
|
||||
"ve": self.ve_string_stripper,
|
||||
"cb": self._funcs.valid_yes_no_inherit,
|
||||
"ve": self._funcs.ve_string_stripper,
|
||||
"default": "inherit",
|
||||
"desc": "Only accept Portage stable packages (no "
|
||||
"unstable keywords)",
|
||||
},
|
||||
}
|
||||
for parser in MatterSpec._external_parsers:
|
||||
parser_data = parser.data()
|
||||
common_keys = set(data.keys()) & set(parser_data.keys())
|
||||
if common_keys:
|
||||
raise ValueError("Parser %s duplicates support for %s" % (
|
||||
parser, " ".join(sorted(common_keys)),))
|
||||
data.update(parser_data)
|
||||
return data
|
||||
|
||||
|
||||
class SpecPreprocessor:
|
||||
@@ -372,9 +426,9 @@ class SpecParser:
|
||||
self.file_object = file_object
|
||||
self._preprocessor = SpecPreprocessor(self.file_object)
|
||||
|
||||
self.__plugin = MatterSpec()
|
||||
self.vital_parameters = self.__plugin.vital_parameters()
|
||||
self._parser_data_path = self.__plugin.parser_data_path()
|
||||
self.__parser = MatterSpec()
|
||||
self.vital_parameters = self.__parser.vital_parameters()
|
||||
self._data = self.__parser.data()
|
||||
|
||||
def _parse_line_statement(self, line_stmt):
|
||||
try:
|
||||
@@ -400,7 +454,7 @@ class SpecParser:
|
||||
key = None
|
||||
value = None
|
||||
v_key, v_value = self._parse_line_statement(line)
|
||||
check_dict = self._parser_data_path.get(v_key)
|
||||
check_dict = self._data.get(v_key)
|
||||
if check_dict is not None:
|
||||
key, value = v_key, v_value
|
||||
old_key = key
|
||||
@@ -410,7 +464,7 @@ class SpecParser:
|
||||
if not value:
|
||||
continue
|
||||
# gather again... key is changed
|
||||
check_dict = self._parser_data_path.get(key)
|
||||
check_dict = self._data.get(key)
|
||||
if not isinstance(check_dict, dict):
|
||||
continue
|
||||
value = check_dict["ve"](value)
|
||||
@@ -450,7 +504,7 @@ class SpecParser:
|
||||
Extend parsed data with default values for statements with
|
||||
default option available.
|
||||
"""
|
||||
for statement, opts in self._parser_data_path.items():
|
||||
for statement, opts in self._data.items():
|
||||
if "default" in opts and (statement not in mydata):
|
||||
mydata[statement] = opts["default"]
|
||||
|
||||
@@ -459,7 +513,7 @@ class SpecParser:
|
||||
For parser data exposing a mod, execute the mod against
|
||||
the data itself.
|
||||
"""
|
||||
for statement, opts in self._parser_data_path.items():
|
||||
for statement, opts in self._data.items():
|
||||
if statement in mydata and "mod" in opts:
|
||||
mydata[statement] = opts["mod"](mydata[statement])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user