Manager of the list of required external features of the software.
Module sppas.preinstall
Class Features
Description
Constructor
Create a new Features instance.
A Features instance is a container for a list of features. It parses a '.ini' file to get each feature config.
Parameters
- req: (str)
- cmdos: (str)
View Source
def __init__(self, req='', cmdos='', filename=None):
"""Create a new Features instance.
A Features instance is a container for a list of features.
It parses a '.ini' file to get each feature config.
:param req: (str)
:param cmdos: (str)
"""
self.__req = req
self.__cmdos = cmdos
self.__features = list()
self.__filename = None
if filename is not None:
if os.path.exists(filename) and filename.endswith('.ini'):
self.__filename = filename
self.set_features()
Public functions
get_features_filename
Return the name of the file with the features descriptions.
View Source
def get_features_filename(self):
"""Return the name of the file with the features descriptions."""
if self.__filename is not None:
return self.__filename
return os.path.join(paths.etc, 'features.ini')
get_ids
Return the list of feature identifiers of the given type.
Parameters
- feat_type: (str) Feature type, or None to get all ids
Returns
- (list) Feature identifiers
View Source
def get_ids(self, feat_type=None):
"""Return the list of feature identifiers of the given type.
:param feat_type: (str) Feature type, or None to get all ids
:return: (list) Feature identifiers
"""
if feat_type is None:
return [f.get_id() for f in self.__features]
return [f.get_id() for f in self.__features if f.get_type() == feat_type]
feature_type
Return the feature type: deps, lang, annot.
Parameters
- fid: (str) Identifier of a feature
View Source
def feature_type(self, fid):
"""Return the feature type: deps, lang, annot.
:param fid: (str) Identifier of a feature
"""
for feat in self.__features:
if feat.get_id() == fid:
return feat.get_type()
logging.error('Unknown feature {}'.format(fid))
return None
enable
Return True if the feature is enabled and/or set it.
Parameters
- fid: (str) Identifier of a feature
- value: (bool or None) Enable of disable the feature.
View Source
def enable(self, fid, value=None):
"""Return True if the feature is enabled and/or set it.
:param fid: (str) Identifier of a feature
:param value: (bool or None) Enable of disable the feature.
"""
for feat in self.__features:
if feat.get_id() == fid:
if value is None:
return feat.get_enable()
return feat.set_enable(value)
logging.error('Unknown feature {}'.format(fid))
return False
available
Return True if the feature is available and/or set it.
Parameters
- fid: (str) Identifier of a feature
- value: (bool or None) Make the feature available or not.
View Source
def available(self, fid, value=None):
"""Return True if the feature is available and/or set it.
:param fid: (str) Identifier of a feature
:param value: (bool or None) Make the feature available or not.
"""
for feat in self.__features:
if feat.get_id() == fid:
if value is None:
return feat.get_available()
return feat.set_available(value)
logging.error('Unknown feature {}'.format(fid))
return False
brief
Return the brief description of the feature.
Parameters
- fid: (str) Identifier of a feature
View Source
def brief(self, fid):
"""Return the brief description of the feature.
:param fid: (str) Identifier of a feature
"""
for feat in self.__features:
if feat.get_id() == fid:
return feat.get_brief()
logging.error('Unknown feature {}'.format(fid))
return None
description
Return the description of the feature
Parameters
- fid: (str) Identifier of a feature
View Source
def description(self, fid):
"""Return the description of the feature
:param fid: (str) Identifier of a feature
"""
for feat in self.__features:
if feat.get_id() == fid:
return feat.get_desc()
logging.error('Unknown feature {}'.format(fid))
return None
packages
Return the dictionary of system dependencies of the feature.
Parameters
- fid: (str) Identifier of a feature
Returns
- (dict) key=package; value=version
View Source
def packages(self, fid):
"""Return the dictionary of system dependencies of the feature.
:param fid: (str) Identifier of a feature
:return: (dict) key=package; value=version
"""
for feat in self.__features:
if feat.get_id() == fid:
if isinstance(feat, DepsFeature) is True:
return feat.get_packages()
else:
logging.error('Feature {} is not a DepsFeature:No packages are defined.'.format(fid))
logging.error('Unknown feature {}'.format(fid))
return dict()
pypi
Return the dictionary of pip dependencies of the feature.
Parameters
- fid: (str) Identifier of a feature
Returns
- (dict) key=package; value=version
View Source
def pypi(self, fid):
"""Return the dictionary of pip dependencies of the feature.
:param fid: (str) Identifier of a feature
:return: (dict) key=package; value=version
"""
for feat in self.__features:
if feat.get_id() == fid:
if isinstance(feat, DepsFeature) is True:
pips = dict()
for key in feat.get_pypi_packages():
pips[key] = feat.get_pypi_package_version(key)
return pips
else:
logging.error('Feature {} is not a DepsFeature:No pypi is defined.'.format(fid))
logging.error('Unknown feature {}'.format(fid))
return dict()
pypi_alt
Return the dictionary of alternative pip dependencies of the feature.
Parameters
- fid: (str) Identifier of a feature
Returns
- (dict) key=package; value=version
View Source
def pypi_alt(self, fid):
"""Return the dictionary of alternative pip dependencies of the feature.
:param fid: (str) Identifier of a feature
:return: (dict) key=package; value=version
"""
for feat in self.__features:
if feat.get_id() == fid:
if isinstance(feat, DepsFeature) is True:
pips = dict()
for key in feat.get_pypi_alt_packages():
pips[key] = feat.get_pypi_alt_package_version(key)
return pips
else:
logging.error('Feature {} is not a DepsFeature:No alt pypi is defined.'.format(fid))
logging.error('Unknown feature {}'.format(fid))
return dict()
pypi_opt
Return the options of a pip dependency of the feature.
Parameters
- fid: (str) Identifier of a feature
Returns
- (str)
View Source
def pypi_opt(self, fid):
"""Return the options of a pip dependency of the feature.
:param fid: (str) Identifier of a feature
:return: (str)
"""
for feat in self.__features:
if feat.get_id() == fid:
if isinstance(feat, DepsFeature) is True:
return feat.get_pip_options()
return ''
cmd
Return the command to execute for the feature.
Parameters
- fid: (str) Identifier of a feature
Returns
- (str)
View Source
def cmd(self, fid):
"""Return the command to execute for the feature.
:param fid: (str) Identifier of a feature
:return: (str)
"""
for feat in self.__features:
if feat.get_id() == fid:
if isinstance(feat, DepsFeature) is True:
return feat.get_cmd()
else:
logging.error('Feature {} is not a DepsFeature:No cmd is defined.'.format(fid))
logging.error('Unknown feature {}'.format(fid))
return str()
lang
Return the lang code of the linguistic resource to download.
Parameters
- fid: (str) Identifier of a feature
Returns
- (str)
View Source
def lang(self, fid):
"""Return the lang code of the linguistic resource to download.
:param fid: (str) Identifier of a feature
:return: (str)
"""
for feat in self.__features:
if feat.get_id() == fid:
if isinstance(feat, LangFeature) is True:
return feat.get_lang()
else:
logging.error('Feature {} is not a LangFeature:No lang is defined.'.format(fid))
logging.error('Unknown feature {}'.format(fid))
return str()
annot
Return the name the annotation resource to download.
Parameters
- fid: (str) Identifier of a feature
Returns
- (str)
View Source
def annot(self, fid):
"""Return the name the annotation resource to download.
:param fid: (str) Identifier of a feature
:return: (str)
"""
for feat in self.__features:
if feat.get_id() == fid:
if isinstance(feat, AnnotFeature) is True:
return feat.get_annot()
else:
logging.error('Feature {} is not an AnnotFeature:No annot is defined.'.format(fid))
logging.error('Unknown feature {}'.format(fid))
return str()
set_features
Browses the features.ini file and instantiate a Feature().
Only unix-based systems can have package requirements. If they don't, the corresponding req_ attribute is missing or empty or with "nil".
A feature is not available for a system, if none of the corresponding "cmd" and "req" and the "pip" attributes are defined.
View Source
def set_features(self):
"""Browses the features.ini file and instantiate a Feature().
Only unix-based systems can have package requirements. If they don't,
the corresponding req_ attribute is missing or empty or with "nil".
A feature is not available for a system, if none of the corresponding "cmd_"
and "req_" and the "pip" attributes are defined.
"""
self.__features = list()
features_parser = self.__init_features()
for fid in features_parser.sections():
try:
feature = self.__set_feature(fid, features_parser)
except cp.NoOptionError:
logging.error('Missing or wrong feature type for feature {}'.format(fid))
continue
self.__features.append(feature)
try:
desc = features_parser.get(fid, 'brief')
feature.set_brief(desc)
except cp.NoOptionError:
pass
try:
desc = features_parser.get(fid, 'desc')
feature.set_desc(desc)
except cp.NoOptionError:
pass
try:
e = features_parser.getboolean(fid, 'enable')
feature.set_enable(e)
except cp.NoOptionError:
pass
ids = self.get_ids()
for fid in cfg.get_feature_ids():
if fid in ids:
self.enable(fid, not cfg.feature_installed(fid))
else:
logging.error('The config file contains an unknown feature identifier {}'.format(fid))
Protected functions
__set_feature
View Source
def __set_feature(self, fid, parser):
feature = None
try:
ft = parser.get(fid, 'type')
if ft == 'deps':
feature = DepsFeature(fid)
self.__fill_deps_feature(feature, parser)
if ft == 'lang':
feature = LangFeature(fid)
self.__fill_lang_feature(feature)
if ft == 'annot':
feature = AnnotFeature(fid)
self.__fill_annot_feature(feature)
except cp.NoOptionError:
pass
if feature is not None:
return feature
raise cp.NoOptionError
__fill_deps_feature
View Source
def __fill_deps_feature(self, feature, parser):
fid = feature.get_id()
try:
d = parser.get(fid, self.__req)
if len(d) > 0 and d.lower() != 'nil':
depend_packages = self.__parse_depend(d)
feature.set_packages(depend_packages)
except cp.NoOptionError:
pass
try:
d = parser.get(fid, 'pip')
if len(d) > 0 and d.lower() != 'nil':
depend_pypi = self.__parse_depend(d)
for key in depend_pypi:
feature.add_pypi(key, depend_pypi[key])
d = parser.get(fid, 'pip_alt')
if len(d) > 0 and d.lower() != 'nil':
depend_pypi = self.__parse_depend(d)
for key in depend_pypi:
feature.add_pypi_alt(key, depend_pypi[key])
opt = parser.get(fid, 'pip_opt')
if len(opt) > 0 and opt.lower() != 'nil':
feature.set_pip_options(opt)
except cp.NoOptionError:
pass
try:
cmd = parser.get(fid, self.__cmdos)
if len(cmd) > 0 and cmd != 'none' and (cmd != 'nil'):
feature.set_cmd(cmd)
except cp.NoOptionError:
pass
if len(feature.get_cmd()) > 0 or len(feature.get_pypi_packages()) > 0 or len(feature.get_packages()) > 0:
feature.set_available(True)
if fid not in cfg.get_feature_ids():
logging.debug(' -->> newly available feature: {:s}'.format(fid))
__fill_lang_feature
View Source
def __fill_lang_feature(self, feature):
fid = feature.get_id()
feature.set_lang(fid)
feature.set_available(True)
__fill_annot_feature
View Source
def __fill_annot_feature(self, feature):
fid = feature.get_id()
feature.set_annot(fid)
feature.set_available(True)
if fid not in cfg.get_feature_ids():
cfg.set_feature(fid, False)
logging.debug(' ----->>> new available feature: {:s}'.format(fid))
else:
logging.debug(' ----->>> already available feature: {:s}'.format(fid))
__init_features
Return a parsed version of the features.ini file.
View Source
def __init_features(self):
"""Return a parsed version of the features.ini file."""
cfg = self.get_features_filename()
if cfg is None:
raise IOError('Installation error: the file {filename} to configure the software is missing.'.format(filename=cfg))
features_parser = cp.ConfigParser()
try:
features_parser.read(self.get_features_filename())
except cp.MissingSectionHeaderError:
raise IOError('Malformed features configuration file {}: missing section header.'.format(cfg))
return features_parser
__parse_depend
Create a dictionary from the string given as an argument.
Parameters
- stringrequire: (*str*ing) The value of one of the req* key in one of the section of feature.ini.
Returns
- (dict)
View Source
@staticmethod
def __parse_depend(string_require):
"""Create a dictionary from the string given as an argument.
:param string_require: (string) The value of one of the req_*** key in one of the section of feature.ini.
:return: (dict)
"""
string_require = str(string_require)
dependencies = string_require.split(' ')
depend = dict()
for line in dependencies:
tab = line.split(':')
depend[tab[0]] = tab[1]
return depend
Overloads
__str__
Print each Feature of the list.
View Source
def __str__(self):
"""Print each Feature of the list. """
for f in self.__features:
print(f.__str__())
__format__
View Source
def __format__(self, fmt):
return str(self).__format__(fmt)
__len__
Return the number of features.
View Source
def __len__(self):
"""Return the number of features."""
return len(self.__features)
__contains__
Value can be either a Feature or its identifier.
Parameters
- value
View Source
def __contains__(self, value):
"""Value can be either a Feature or its identifier."""
if isinstance(value, Feature):
return value in self.__features
else:
for f in self.__features:
if f.get_id() == value:
return True
return False