PageRenderTime 50ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/yppy/config.py

https://bitbucket.org/leycec/yppy
Python | 230 lines | 228 code | 0 blank | 2 comment | 0 complexity | 2dc3b6e0b1bb954eee4c9626d548bc5a MD5 | raw file
Possible License(s): BSD-3-Clause
  1. '''Yppy configuration facilities.
  2. This module exposes a global variable, "Config", encapsulating the set of all
  3. global settings for the current Yppy process. Other modules are encouraged to
  4. import and access this variable as needed and at any time.
  5. '''
  6. # ....................{ IMPORTS }....................
  7. from yppy import core
  8. from yppy.classmap import ClassMaps
  9. from yppy.exception import YppyException
  10. from yppy.util.file import filesystem
  11. import os
  12. # ....................{ CLASSES }....................
  13. class YppyConfig(object):
  14. '''Yppy configuration.
  15. This class encapsulates the set of all globally accessible "settings" for
  16. this Yppy process.
  17. Attributes
  18. ----------
  19. _graph_library_name : string
  20. Name of the graph library to be used.
  21. is_overwriting_output_paths : boolean
  22. True if overwriting existing output files and directories.
  23. '''
  24. # ..................{ CLASS ATTRIBUTES }..................
  25. # Frozen set of all graph library names (i.e., the set of all external graph
  26. # libraries installed on the current system).
  27. GRAPH_LIBRARY_NAMES = ClassMaps.GRAPH_LIBRARY_NAME_TO_FACTORY_CLASS.keys()
  28. # Default graph library name (i.e., the "factory"-recommended external graph
  29. # library to be used on the current system).
  30. GRAPH_LIBRARY_NAME_DEFAULT =\
  31. ClassMaps.GRAPH_LIBRARY_NAME_TO_FACTORY_CLASS.default_key
  32. # ..................{ INITIALIZATION }..................
  33. # Do not use "@core.assign_parameters_to_self()" here, as that confuses
  34. # common IDE editors. (Eclipse, I'm squinting at you.)
  35. def __init__(self,
  36. graph_library_name=None,
  37. is_overwriting_output_paths=False):
  38. '''Initialize this configuration.
  39. Arguments
  40. ----------
  41. _graph_library_name : string, optional
  42. Name of the graph library to be used. This must necessarily be a key
  43. in the "ClassMaps.GRAPH_LIBRARY_NAME_TO_FACTORY_CLASS" classmap.
  44. Defaults to None, in which case the optimally efficient graph
  45. library available on the current system is used.
  46. _is_overwriting_output_paths : boolean, optional
  47. True if overwriting existing output files and directories. If False,
  48. then classes elsewhere raise exceptions when attempting to overwrite
  49. such files. Defaults to False for safety.
  50. '''
  51. # Technically, this should be:
  52. #
  53. # if not graph_library_name:
  54. # graph_library_name =\
  55. # ClassMaps.GRAPH_LIBRARY_NAME_TO_FACTORY_CLASS.default_key
  56. #
  57. # However, that induces a circular dependency issue. So, just do this!
  58. if graph_library_name:
  59. self.graph_library_name = graph_library_name
  60. else:
  61. self._graph_library_name = None
  62. # Copy the passed parameters to object attributes.
  63. self.is_overwriting_output_paths = is_overwriting_output_paths
  64. # Make user-specific Yppy directories, if not already.
  65. filesystem.make_dir_if_not_found(self.dot_dirname)
  66. filesystem.make_dir_if_not_found(self.temporary_dirname)
  67. # Set this object as the new singleton configuration.
  68. global Config
  69. Config = self
  70. # ..................{ PROPERTIES ~ immutable }..................
  71. #FIXME: This technically works under Windows, but may refer to an unexpected
  72. #location. Sadly, although there has been some recent discusson on Python
  73. #forums concerning a standardization of the dot directory concept under
  74. #Windows, there appears to be no broad consensus as of yet.
  75. @property
  76. def dot_dirname(self):
  77. '''Get the absolute path to the user-specific Yppy dot directory.
  78. This is the platform-dependent directory to which Yppy records user-
  79. specific logs, history, et al., as follows:
  80. * Under *nix (e.g., Linux), "~/.yppy".
  81. * Under Windows, ...?
  82. '''
  83. return os.path.join(
  84. filesystem.get_user_home_dir(),
  85. '.' + core.get_program_executable_name())
  86. @property
  87. def temporary_dirname(self):
  88. '''Get the absolute path to the user-specific Yppy temporary directory.
  89. '''
  90. return os.path.join(self.dot_dirname, 'tmp')
  91. @property
  92. def log_filename(self):
  93. '''Get the absolute path to the user-specific Yppy log filename.
  94. '''
  95. return os.path.join(self.dot_dirname, 'log')
  96. # ..................{ PROPERTIES ~ mutable }..................
  97. @property
  98. def graph_library_name(self):
  99. '''Get the currently configured graph library name.
  100. '''
  101. return self._graph_library_name
  102. @graph_library_name.setter
  103. def graph_library_name(self, graph_library_name):
  104. '''Set the currently configured graph library name.
  105. Parameters
  106. ----------
  107. graph_library_name : string
  108. Key in the "GRAPH_LIBRARY_NAME_TO_FACTORY_CLASS" classmap.
  109. '''
  110. if graph_library_name not in self.GRAPH_LIBRARY_NAMES:
  111. raise YppyException(graph_library_name,
  112. 'not available on this system; expected one of: ' +\
  113. core.to_human_readable_string(self.GRAPH_LIBRARY_NAMES))
  114. self._graph_library_name = graph_library_name
  115. # ..................{ FILENAMES }..................
  116. def get_temporary_filename(self, *args, **kwargs):
  117. '''Get the absolute path to a unique temporary file.
  118. Caveats
  119. ----------
  120. This function guarantees that at the time of return this file does not
  121. exist, but no guarantees past that time. Inevitably, this *COULD* lead
  122. to subtle race conditions; as in Latin, "Caveat emptor."
  123. Parameters
  124. ----------
  125. This method passes all passed parameters to the
  126. filesystem.get_temporary_filename() function.
  127. '''
  128. return filesystem.get_temporary_filename(
  129. dirname=self.temporary_dirname, *args, **kwargs)
  130. # ....................{ GLOBALS }....................
  131. # Singleton configuration for the current Yppy process.
  132. #
  133. # Technically, this should be None. Instead, set this to the above base class to
  134. # reduce IDE errors (e.g., as from Eclipse).
  135. Config = YppyConfig()
  136. #FIXME: Obsolete.
  137. # # ..................{ PUBLIC }..................
  138. # def make_graph(self, *args, **kwargs):
  139. # '''Make a new graph object for the currently configured graph library.
  140. #
  141. # Parameters
  142. # ----------
  143. # This method delegates to the YppyGraphObjectFactory.make() method; see
  144. # that method for parameter details.
  145. #
  146. # Returns
  147. # ----------
  148. # object
  149. # Empty graph object.
  150. # '''
  151. # return ClassMaps.GRAPH_LIBRARY_NAME_TO_FACTORY_CLASS[
  152. # self._graph_library_name].make(*args, **kwargs)
  153. #Defaults to None,
  154. # requiring callers to call the init() function before accessing this global.
  155. # ....................{ FUNCTIONS }....................
  156. #def init(*args, **kwargs):
  157. # '''Initialize the singleton configuration for the current Yppy process.
  158. #
  159. # This function should be called once and only once, per Yppy process:
  160. # typically by the instance of the "YppyConfigBase" base class itself.
  161. # '''
  162. # # Initialize a new configuration given the passed parameters.
  163. # new_config = YppyConfig(*args, **kwargs)
  164. #
  165. # # If a singleton Config has already been set, raise an exception.
  166. # global Config
  167. # if Config:
  168. # raise YppyException(Config, 'already initialized, so cannot overwrite '\
  169. # 'with new configuration "%s"' % new_config)
  170. #
  171. # # Set us up the config bomb.
  172. # Config = new_config
  173. # --------------------( COPYRIGHT AND LICENSE )--------------------
  174. # The information below applies to everything in this distribution,
  175. # except where noted.
  176. #
  177. # Copyright 2010-2011, Cecil Curry <leycec@gmail.com {*} http://raiazome.com>.
  178. # All rights reserved.
  179. #
  180. # Redistribution and use in source and binary forms, with or without
  181. # modification, are permitted provided that the following conditions are met:
  182. #
  183. # 1. Redistributions of source code must retain the above copyright notice,
  184. # this list of conditions and the following disclaimer.
  185. # 2. Redistributions in binary form must reproduce the above copyright
  186. # notice, this list of conditions and the following disclaimer in the
  187. # documentation and/or other materials provided with the distribution.
  188. # 3. Neither the name of the <ORGANIZATION> nor the names of its
  189. # contributors may be used to endorse or promote products derived from
  190. # this software without specific prior written permission.
  191. #
  192. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  193. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  194. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  195. # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  196. #
  197. # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  198. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  199. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  200. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  201. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  202. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  203. # POSSIBILITY OF SUCH DAMAGE.