From: Frank Brehm Date: Mon, 13 Mar 2017 14:25:29 +0000 (+0100) Subject: Adding pp_lib/obj.py X-Git-Tag: 0.1.2~274 X-Git-Url: https://git.uhu-banane.net/?a=commitdiff_plain;h=a2a664e4708fc499c6bc836796557de7ac99f900;p=pixelpark%2Fadmin-tools.git Adding pp_lib/obj.py --- diff --git a/pp_lib/obj.py b/pp_lib/obj.py new file mode 100644 index 0000000..7da42a9 --- /dev/null +++ b/pp_lib/obj.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +@author: Frank Brehm +@contact: frank.brehm@pixelpark.com +@copyright: © 2010 - 2017 by Frank Brehm, Publicies Pixelpark GmbH, Berlin +""" + +# Standard modules +import sys +import os +import logging +import datetime +import traceback + +# Third party modules +import six + +# Own modules +from pp_tools import pp + +from pp_tools.errors import PpError + + +__version__ = '0.1.1' + +LOG = logging.getLogger(__name__) + + +# ============================================================================= +class PpBaseObjectError(PpError): + """ + Base error class useable by all descendand objects. + """ + + pass + + +# ============================================================================= +class PpBaseObject(object): + """ + Base class for all objects. + """ + + # ------------------------------------------------------------------------- + def __init__( + self, appname=None, verbose=0, version=__version__, base_dir=None, + initialized=False): + """ + Initialisation of the base object. + + Raises an exception on a uncoverable error. + """ + + self._appname = None + """ + @ivar: name of the current running application + @type: str + """ + if appname: + v = str(appname).strip() + if v: + self._appname = v + if not self._appname: + self._appname = os.path.basename(sys.argv[0]) + + self._version = version + """ + @ivar: version string of the current object or application + @type: str + """ + + self._verbose = int(verbose) + """ + @ivar: verbosity level (0 - 9) + @type: int + """ + if self._verbose < 0: + msg = _("Wrong verbose level %r, must be >= 0") % (verbose) + raise ValueError(msg) + + self._initialized = False + """ + @ivar: initialisation of this object is complete + after __init__() of this object + @type: bool + """ + + self._base_dir = base_dir + """ + @ivar: base directory used for different purposes, must be an existent + directory. Defaults to directory of current script daemon.py. + @type: str + """ + if base_dir: + if not os.path.exists(base_dir): + msg = _("Base directory %r does not exists.") % (base_dir) + self.handle_error(msg) + self._base_dir = None + elif not os.path.isdir(base_dir): + msg = _("Base directory %r is not a directory.") % (base_dir) + self.handle_error(msg) + self._base_dir = None + if not self._base_dir: + self._base_dir = os.path.dirname(os.path.abspath(sys.argv[0])) + + self._initialized = bool(initialized) + + # ----------------------------------------------------------- + @property + def appname(self): + """The name of the current running application.""" + return self._appname + + @appname.setter + def appname(self, value): + if value: + v = str(value).strip() + if v: + self._appname = v + + # ----------------------------------------------------------- + @property + def version(self): + """The version string of the current object or application.""" + return self._version + + # ----------------------------------------------------------- + @property + def verbose(self): + """The verbosity level.""" + return getattr(self, '_verbose', 0) + + @verbose.setter + def verbose(self, value): + v = int(value) + if v >= 0: + self._verbose = v + else: + log.warn(_("Wrong verbose level %r, must be >= 0"), value) + + # ----------------------------------------------------------- + @property + def initialized(self): + """The initialisation of this object is complete.""" + return getattr(self, '_initialized', False) + + @initialized.setter + def initialized(self, value): + self._initialized = bool(value) + + # ----------------------------------------------------------- + @property + def base_dir(self): + """The base directory used for different purposes.""" + return self._base_dir + + @base_dir.setter + def base_dir(self, value): + if value.startswith('~'): + value = os.path.expanduser(value) + if not os.path.exists(value): + msg = _("Base directory %r does not exists.") % (value) + log.error(msg) + elif not os.path.isdir(value): + msg = _("Base directory %r is not a directory.") % (value) + log.error(msg) + else: + self._base_dir = value + + # ------------------------------------------------------------------------- + def __str__(self): + """ + Typecasting function for translating object structure + into a string + + @return: structure as string + @rtype: str + """ + + return pp(self.as_dict(short=True)) + + # ------------------------------------------------------------------------- + def __repr__(self): + """Typecasting into a string for reproduction.""" + + out = "<%s(" % (self.__class__.__name__) + + fields = [] + fields.append("appname=%r" % (self.appname)) + fields.append("verbose=%r" % (self.verbose)) + fields.append("version=%r" % (self.version)) + fields.append("base_dir=%r" % (self.base_dir)) + fields.append("initialized=%r" % (self.initialized)) + + out += ", ".join(fields) + ")>" + return out + + # ------------------------------------------------------------------------- + def as_dict(self, short=False): + """ + Transforms the elements of the object into a dict + + @param short: don't include local properties in resulting dict. + @type short: bool + + @return: structure as dict + @rtype: dict + """ + + res = self.__dict__ + res = {} + for key in self.__dict__: + if short and key.startswith('_') and not key.startswith('__'): + continue + val = self.__dict__[key] + if isinstance(val, PbBaseObject): + res[key] = val.as_dict(short=short) + else: + res[key] = val + res['__class_name__'] = self.__class__.__name__ + res['appname'] = self.appname + res['version'] = self.version + res['verbose'] = self.verbose + res['initialized'] = self.initialized + res['base_dir'] = self.base_dir + + return res + + # ------------------------------------------------------------------------- + def handle_error( + self, error_message=None, exception_name=None, do_traceback=False): + """ + Handle an error gracefully. + + Print a traceback and continue. + + @param error_message: the error message to display + @type error_message: str + @param exception_name: name of the exception class + @type exception_name: str + @param do_traceback: allways show a traceback + @type do_traceback: bool + + """ + + msg = 'Exception happened: ' + if exception_name is not None: + exception_name = exception_name.strip() + if exception_name: + msg = exception_name + ': ' + else: + msg = '' + if error_message: + msg += str(error_message) + else: + msg += _('undefined error.') + + root_log = logging.getLogger() + has_handlers = False + if root_log.handlers: + has_handlers = True + + if has_handlers: + log.error(msg) + if do_traceback: + log.error(traceback.format_exc()) + + if not has_handlers: + curdate = datetime.datetime.now() + curdate_str = "[" + curdate.isoformat(' ') + "]: " + msg = curdate_str + msg + "\n" + if hasattr(sys.stderr, 'buffer'): + sys.stderr.buffer.write(msg) + else: + sys.stderr.write(msg) + if do_traceback: + traceback.print_exc() + + return + + # ------------------------------------------------------------------------- + def handle_info(self, message, info_name=None): + """ + Shows an information. This happens both to STDERR and to all + initialized log handlers. + + @param message: the info message to display + @type message: str + @param info_name: Title of information + @type info_name: str + + """ + + msg = '' + if info_name is not None: + info_name = info_name.strip() + if info_name: + msg = info_name + ': ' + msg += str(message).strip() + + root_log = logging.getLogger() + has_handlers = False + if root_log.handlers: + has_handlers = True + + if has_handlers: + log.info(msg) + + if not has_handlers: + curdate = datetime.datetime.now() + curdate_str = "[" + curdate.isoformat(' ') + "]: " + msg = curdate_str + msg + "\n" + if hasattr(sys.stderr, 'buffer'): + sys.stderr.buffer.write(msg) + else: + sys.stderr.write(msg) + + return + +# ============================================================================= + +if __name__ == "__main__": + + pass + +# ============================================================================= + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + + +