from functools import cmp_to_key
# Third party modules
-
+import six
from six import reraise
# Own modules
-from fb_tools.common import to_bool, to_bytes
+from fb_tools.common import to_bool, to_bytes, pp
from fb_tools.obj import FbBaseObject
from .mod_info import ForgeModuleInfo
from ..xlate import XLATOR
-__version__ = '0.2.2'
+__version__ = '0.3.0'
LOG = logging.getLogger(__name__)
pass
+# =============================================================================
+class DatafileNotExistingError(ForgeModuleDictError, IOError):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, data_file):
+
+ msg = _("Data file of forge modules cache is not existing")
+ super(DatafileNotExistingError, self).__init__(
+ errno.ENOENT, msg, str(data_file))
+
+
+# =============================================================================
+class DatafileIsDirError(ForgeModuleDictError, IOError):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, data_file):
+
+ msg = _("Data file of forge modules cache is a directory")
+ super(DatafileIsDirError, self).__init__(
+ errno.EISDIR, msg, str(data_file))
+
+
+# =============================================================================
+class DatafileAccessError(ForgeModuleDictError, IOError):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, data_file):
+
+ msg = _("Data file of forge modules cache is not readable")
+ super(DatafileAccessError, self).__init__(
+ errno.EACCES, msg, str(data_file))
+
+
# =============================================================================
class ParentNotExistingError(ForgeModuleDictError, IOError):
default_data_dir = root_path / 'var' / 'lib' / 'webhooks'
default_data_file = Path('forge-modules.js')
default_json_indent = 4
+ default_charset = 'utf-8'
+
+ open_args = {}
+ if six.PY3:
+ open_args = {
+ 'encoding': default_charset,
+ 'errors': 'surrogateescape',
+ }
# -------------------------------------------------------------------------
# __init__() method required to create instance from class.
res['json_indent'] = self.json_indent
res['simulate'] = self.simulate
res['sort_by_name'] = self.sort_by_name
+ res['default_charset'] = self.default_charset
+ res['open_args'] = self.open_args
res['items'] = {}
res['keys'] = []
for full_name in self.keys():
res[full_name] = self._map[full_name].to_data()
return res
+ # -------------------------------------------------------------------------
+ def from_data(self, data):
+ """Converting the given dict (read from a cache file) and re-instantiate
+ the appropriate module infos."""
+
+ if self.verbose > 1:
+ LOG.debug(_("Converting Python objects into a dict of {} objects.").format(
+ 'ForgeModuleInfo'))
+
+ self.clear()
+ for full_name in data.keys():
+ mdata = data[full_name]
+ mod = ForgeModuleInfo.from_data(
+ mdata, appname=self.appname, verbose=self.verbose, base_dir=self.base_dir)
+ self.append(mod)
+
+ if self.verbose > 3:
+ LOG.debug("Re-instantiated forge module infos:\n" + pp(self.as_dict()))
+
# -------------------------------------------------------------------------
def write_file(self, output_file=None):
src=str(tmp_file), tgt=str(output_file)))
tmp_file.rename(output_file)
+ # -------------------------------------------------------------------------
+ def read_file(self, data_file=None):
+
+ if data_file is None:
+ data_file = self.data_file
+ if not data_file.is_absolute():
+ data_file = self.data_dir / self.data_file
+ data_file = Path(os.path.abspath(str(data_file)))
+ fd = None
+
+ if not data_file.exists():
+ raise DatafileNotExistingError(data_file)
+ if data_file.is_dir():
+ raise DatafileIsDirError(data_file)
+ if not os.access(str(data_file), os.R_OK):
+ raise DatafileAccessError(data_file)
+
+ LOG.info(_("Trying to read {!r} ...").format(str(data_file)))
+
+ file_content = None
+ if six.PY3:
+ with open(str(data_file), 'r', **self.open_args) as fh:
+ file_content = fh.read()
+ else:
+ with open(str(data_file), 'r') as fh:
+ file_content = fh.read()
+
+ if self.verbose > 1:
+ LOG.debug(_("Deserialize file content to Python objects."))
+ data = json.loads(file_content)
+ if self.verbose > 3:
+ LOG.debug(_("File content as Python objects:") + '\n' + pp(data))
+
+ self.from_data(data)
# =============================================================================
if __name__ == "__main__":
from .errors import BaseHookError, UncriticalHookError
from .base_app import BaseHookApp
+from .forge.mod_dict import ForgeModuleDictError
from .xlate import XLATOR
LOG = logging.getLogger(__name__)
self.print_out("#" * len_title)
self.print_out('')
+ self.init_puppet_environments()
+ self.collect_local_modules()
+
+ if not self.read_forge_cache():
+ self.exit(7)
+ return
+ return
+
module_infos = []
try:
module_infos = self.read_cache_file()
else:
self.output_modules(module_infos)
+ # -------------------------------------------------------------------------
+ def read_forge_cache(self):
+
+ self.init_forge_module_dict()
+ try:
+ self.forge_modules.read_file()
+ except ForgeModuleDictError as e:
+ LOG.error(_("Got a {cn} reading input data as JSON: {e}").format(
+ cn=e.__class__.__name__, e=e))
+ return False
+ return True
+
# -------------------------------------------------------------------------
def output_modules(self, module_infos):