暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

settings.py 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #-*- coding: utf-8 -*-
  2. import types
  3. import warnings
  4. from . import settings_format
  5. ## @package Lodel.settings
  6. #
  7. # @brief Defines stuff to handles Lodel2 configuration (see @ref lodel_settings )
  8. #
  9. # To access the confs use the Lodel.settings.Settings SettingsHandler instance
  10. ## @brief A class designed to handles Lodel2 settings
  11. #
  12. # When instanciating a SettingsHandler, the new instance is filled with the content of settings.py (in the root directory of lodel2
  13. #
  14. # @warning You don't have to instanciate this class, you can access to the global instance with the Settings variable in this module
  15. # @todo Forbid module assignement in settings ! and disable tests about this
  16. # @todo Implements a type checking of config value
  17. # @todo Implements default values for config keys
  18. class SettingsHandler(object):
  19. ## @brief Shortcut
  20. _allowed = settings_format.ALLOWED + settings_format.MANDATORY
  21. ## @brief Shortcut
  22. _mandatory = settings_format.MANDATORY
  23. def __init__(self):
  24. try:
  25. import settings as default_settings
  26. self._load_module(default_settings)
  27. except ImportError:
  28. warnings.warn("Unable to find global default settings")
  29. ## @brief A flag set to True when the instance is fully loaded
  30. self._set_loaded(False if len(self._missings()) > 0 else True)
  31. ## @brief Compat wrapper for getattr
  32. def get(self, name):
  33. return getattr(self, name)
  34. ## @brief Compat wrapper for setattr
  35. def set(self, name, value):
  36. return setattr(self, name, value)
  37. ## @brief Load every module properties in the settings instance
  38. #
  39. # Load a module content into a SettingsHandler instance and checks that no mandatory settings are missing
  40. # @note Example : <pre> import my_cool_settings;
  41. # Settings._load_module(my_cool_settings);</pre>
  42. # @param module module|None: a loaded module (if None just check for missing settings)
  43. # @throw LookupError if invalid settings found or if mandatory settings are missing
  44. def load_module(self, module = None):
  45. if not(module is None):
  46. self._load_module(module)
  47. missings = self._missings()
  48. if len(missings) > 0:
  49. self._loaded = False
  50. raise LookupError("Mandatory settings are missing : %s"%missings)
  51. self._set_loaded(True)
  52. ## @brief supersede of default __setattr__ method
  53. def __setattr__(self, name, value):
  54. if not hasattr(self, name):
  55. if name not in self._allowed:
  56. raise LookupError("Invalid setting : %s"%name)
  57. super().__setattr__(name, value)
  58. ## @brief This method do the job for SettingsHandler.load_module()
  59. #
  60. # @note The difference with SettingsHandler.load_module() is that it didn't check if some settings are missing
  61. # @throw LokkupError if an invalid settings is given
  62. # @param module : a loaded module
  63. def _load_module(self, module):
  64. errors = []
  65. fatal_errors = []
  66. conf_dict = {
  67. name: getattr(module, name)
  68. for name in dir(module)
  69. if not name.startswith('__') and not isinstance(getattr(module, name), types.ModuleType)
  70. }
  71. for name, value in conf_dict.items():
  72. try:
  73. setattr(self, name, value)
  74. except LookupError:
  75. errors.append(name)
  76. if len(errors) > 0:
  77. err_msg = "Found invalid settings in %s : %s"%(module.__name__, errors)
  78. raise LookupError(err_msg)
  79. ## @brief Refresh the allowed and mandatory settings list
  80. @classmethod
  81. def _refresh_format(cls):
  82. ## @brief Shortcut
  83. cls._allowed = settings_format.ALLOWED + settings_format.MANDATORY
  84. ## @brief Shortcut
  85. cls._mandatory = settings_format.MANDATORY
  86. ## @brief If some settings are missings return their names
  87. # @return an array of string
  88. def _missings(self):
  89. return [ confname for confname in self._mandatory if not hasattr(self, confname) ]
  90. def _set_loaded(self, value):
  91. super().__setattr__('_loaded', bool(value))
  92. Settings = SettingsHandler()
  93. ## @page lodel_settings Lodel SettingsHandler
  94. #
  95. # This page describe the way settings are handled in Lodel2.
  96. #
  97. # @section lodel_settings_files Lodel settings files
  98. #
  99. # - Lodel/settings.py defines the Lodel.settings package, the SettingsHandler class and the Lodel.settings.Settings instance
  100. # - Lodel/settings_format.py defines the mandatory and allowed configurations keys lists
  101. # - install/instance_settings.py is a model of the file that will be deployed in Lodel2 instances directories
  102. #
  103. # @section Using Lodel.settings.Settings SettingsHandler instance
  104. #
  105. # @subsection lodel_settings_without_loader Without loader
  106. #
  107. # Without any loader you can import Lodel.settings.Settings and acces its property with getattr (or . ) or with SettingsHandler.get() method.
  108. # In the same way you can set a settings by standart affectation of a propery or with SettingsHandler.set() method.
  109. #
  110. # @subsection lodel_settings_loader With a loader in a lodel2 instance
  111. #
  112. # The loader will import Lodel.settings.Settings and then calls the SettingsHandler.load_module() method to load the content of the instance_settings.py file into the SettingsHandler instance
  113. #
  114. # @subsection lodel_settings_example Examples
  115. #
  116. # <pre>
  117. # #!/usr/bin/python
  118. # from Lodel.settings import Settings
  119. # if Settings.debug:
  120. # print("DEBUG")
  121. # # or
  122. # if Settings.get('debug'):
  123. # print("DEBUG")
  124. # Settings.debug = False
  125. # # or
  126. # Settings.set('debug', False)
  127. # </pre>
  128. #