__init__.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright 2011 Yesudeep Mangalapilly <yesudeep@gmail.com>
  5. # Copyright 2012 Google, Inc.
  6. #
  7. # Licensed under the Apache License, Version 2.0 (the "License");
  8. # you may not use this file except in compliance with the License.
  9. # You may obtain a copy of the License at
  10. #
  11. # http://www.apache.org/licenses/LICENSE-2.0
  12. #
  13. # Unless required by applicable law or agreed to in writing, software
  14. # distributed under the License is distributed on an "AS IS" BASIS,
  15. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. # See the License for the specific language governing permissions and
  17. # limitations under the License.
  18. """
  19. :module: watchdog.utils
  20. :synopsis: Utility classes and functions.
  21. :author: yesudeep@google.com (Yesudeep Mangalapilly)
  22. Classes
  23. -------
  24. .. autoclass:: BaseThread
  25. :members:
  26. :show-inheritance:
  27. :inherited-members:
  28. """
  29. import os
  30. import sys
  31. import threading
  32. from watchdog.utils import platform
  33. from watchdog.utils.compat import Event
  34. if sys.version_info[0] == 2 and platform.is_windows():
  35. # st_ino is not implemented in os.stat on this platform
  36. import win32stat
  37. stat = win32stat.stat
  38. else:
  39. stat = os.stat
  40. def has_attribute(ob, attribute):
  41. """
  42. :func:`hasattr` swallows exceptions. :func:`has_attribute` tests a Python object for the
  43. presence of an attribute.
  44. :param ob:
  45. object to inspect
  46. :param attribute:
  47. ``str`` for the name of the attribute.
  48. """
  49. return getattr(ob, attribute, None) is not None
  50. class UnsupportedLibc(Exception):
  51. pass
  52. class BaseThread(threading.Thread):
  53. """ Convenience class for creating stoppable threads. """
  54. def __init__(self):
  55. threading.Thread.__init__(self)
  56. if has_attribute(self, 'daemon'):
  57. self.daemon = True
  58. else:
  59. self.setDaemon(True)
  60. self._stopped_event = Event()
  61. if not has_attribute(self._stopped_event, 'is_set'):
  62. self._stopped_event.is_set = self._stopped_event.isSet
  63. @property
  64. def stopped_event(self):
  65. return self._stopped_event
  66. def should_keep_running(self):
  67. """Determines whether the thread should continue running."""
  68. return not self._stopped_event.is_set()
  69. def on_thread_stop(self):
  70. """Override this method instead of :meth:`stop()`.
  71. :meth:`stop()` calls this method.
  72. This method is called immediately after the thread is signaled to stop.
  73. """
  74. pass
  75. def stop(self):
  76. """Signals the thread to stop."""
  77. self._stopped_event.set()
  78. self.on_thread_stop()
  79. def on_thread_start(self):
  80. """Override this method instead of :meth:`start()`. :meth:`start()`
  81. calls this method.
  82. This method is called right before this thread is started and this
  83. object’s run() method is invoked.
  84. """
  85. pass
  86. def start(self):
  87. self.on_thread_start()
  88. threading.Thread.start(self)
  89. def load_module(module_name):
  90. """Imports a module given its name and returns a handle to it."""
  91. try:
  92. __import__(module_name)
  93. except ImportError:
  94. raise ImportError('No module named %s' % module_name)
  95. return sys.modules[module_name]
  96. def load_class(dotted_path):
  97. """Loads and returns a class definition provided a dotted path
  98. specification the last part of the dotted path is the class name
  99. and there is at least one module name preceding the class name.
  100. Notes:
  101. You will need to ensure that the module you are trying to load
  102. exists in the Python path.
  103. Examples:
  104. - module.name.ClassName # Provided module.name is in the Python path.
  105. - module.ClassName # Provided module is in the Python path.
  106. What won't work:
  107. - ClassName
  108. - modle.name.ClassName # Typo in module name.
  109. - module.name.ClasNam # Typo in classname.
  110. """
  111. dotted_path_split = dotted_path.split('.')
  112. if len(dotted_path_split) > 1:
  113. klass_name = dotted_path_split[-1]
  114. module_name = '.'.join(dotted_path_split[:-1])
  115. module = load_module(module_name)
  116. if has_attribute(module, klass_name):
  117. klass = getattr(module, klass_name)
  118. return klass
  119. # Finally create and return an instance of the class
  120. # return klass(*args, **kwargs)
  121. else:
  122. raise AttributeError('Module %s does not have class attribute %s' % (
  123. module_name, klass_name))
  124. else:
  125. raise ValueError(
  126. 'Dotted module path %s must contain a module name and a classname' % dotted_path)