def load_bytecode_processors(): """ Loading BytecodeProcessor from modipyd.BYTECODE_PROCESSORS settings. Return ChainedBytecodeProcessor instance holds all loaded processors. """ if (BYTECODE_PROCESSORS and (len(BYTECODE_PROCESSORS_CACHE) != len(BYTECODE_PROCESSORS))): del BYTECODE_PROCESSORS_CACHE[:] for i, name in enumerate(BYTECODE_PROCESSORS[:]): LOGGER.info("Loading BytecodeProcesser '%s'" % name) try: klass = utils.import_component(name) except (ImportError, AttributeError): LOGGER.warn( "Loading BytecodeProcesser '%s' failed. " "This setting is removed" % name, exc_info=True) del BYTECODE_PROCESSORS[i] else: BYTECODE_PROCESSORS_CACHE.append(klass) processors = [] for klass in BYTECODE_PROCESSORS_CACHE: processors.append(klass()) return bc.ChainedBytecodeProcessor(processors)
def collect_unittest(paths): suite = unittest.TestSuite() loader = unittest.defaultTestLoader resolver = resolve.ModuleNameResolver() paths = utils.sequence(paths) for filepath in paths: try: name, package = resolver.resolve(filepath) except ImportError: # .py file not in the search path name = filepath_to_identifier(filepath) package = None try: if package: module = utils.import_module(name) else: module = imp.load_source(name, filepath) except ImportError: LOGGER.warn("ImportError occurred while loading module", exc_info=True) else: tests = loader.loadTestsFromModule(module) if tests.countTestCases(): suite.addTest(tests) LOGGER.info("Found %d test(s) in module '%s'" % (tests.countTestCases(), module.__name__)) else: LOGGER.warn("No tests found in module '%s'" % module.__name__) return suite
def install_plugin(self, plugin): """ Install a plugin specified by *plugin*. The *plugin* argument must be callable object (e.g. function, class) or a qualified name of the plugin itself. Read the ``modipyd.application.plugins`` module documentation for the plugin architecture details. """ if isinstance(plugin, basestring): try: plugin = import_component(plugin) except (ImportError, AttributeError): LOGGER.error("Loading plugin '%s' failed" % plugin) raise if not callable(plugin): raise TypeError("The plugin must be callable object") if hasattr(plugin, 'func_code'): LOGGER.info("Loading plugin: %s" % plugin.func_code.co_name) else: LOGGER.info("Loading plugin: %s" % plugin) self.plugins.append(plugin)
def reload(self, descriptors, co=None): """ Reload module code, update dependency graph """ LOGGER.info("Reload module descriptor '%s' at %s" % (self.name, relativepath(self.filename))) try: self.module_code.reload(co) except SyntaxError: # SyntaxError is OK LOGGER.warn("SyntaxError found in %s" % self.filename, exc_info=True) else: self.update_dependencies(descriptors)
def start(self, interval=1.0, refresh_factor=5): if refresh_factor < 1: raise RuntimeError("refresh_factor must be greater or eqaul to 1") if interval <= 0: raise RuntimeError("interval must not be negative or 0") descriptors = self.descriptors if LOGGER.isEnabledFor(logging.INFO): desc = "\n".join([ desc.describe(indent=4) for desc in descriptors.itervalues()]) LOGGER.info("Monitoring:\n%s" % desc) # Prior to Python 2.5, the ``yield`` statement is not # allowed in the ``try`` clause of a ``try ... finally`` # construct. try: self.monitoring = True times = 0 while descriptors and self.monitoring: time.sleep(interval) times += 1 if times % refresh_factor == 0: monitor = self.refresh() else: monitor = self.monitor() for modified in monitor: if not self.monitoring: break yield modified else: LOGGER.info("Terminating monitor %s" % str(self)) except: self.monitoring = False raise
def make_application(options, filepath): # options handling if options.verbosity > 0: LOGGER.setLevel(logging.INFO) if options.verbosity > 1: LOGGER.setLevel(logging.DEBUG) # So many projects contain its modules and packages at # the top level directory, modipyd inserts current directory # in ``sys.path`` module search path variable for convenience. sys.path.insert(0, os.getcwd()) # Create Application instance, Install plugins application = Application(filepath) for plugin in options.plugins: application.install_plugin(plugin) # Predefine variables variables = {} for var in options.defines: i = var.find('=') if i == -1: variables[var] = '' else: variables[var[:i]] = var[i+1:] if variables: import pprint application.update_variables(variables) LOGGER.info( "Predefined variables: %s" % pprint.pformat(variables)) # Load configuration (startup) file for rcfile in find_startup_files(os.environ, options.rcfile): LOGGER.info("Loading startup file from %s" % rcfile) execfile(rcfile, globals(), {'application': application}) return application
def __call__(self): # Walking dependency graph in imported module to # module imports order. testables = [] for desc in self.descriptor.walk_dependency_graph(reverse=True): LOGGER.info("-> Affected: %s" % desc.name) if has_subclass(desc, unittest.TestCase): LOGGER.debug("-> unittest.TestCase detected: %s" % desc.name) testables.append(desc) # Runntine tests if testables: # We can reload affected modules manually and run # all TestCase in same process. Running another process, # however, is simple and perfect solution. if LOGGER.isEnabledFor(logging.INFO): desc = ', '.join([x.name for x in testables]) LOGGER.info("Running UnitTests: %s" % desc) # Propagates the level of modipyd.LOGGER to # the unittest runner subprocess. extra = ['--loglevel', LOGGER.getEffectiveLevel()] self.spawn_unittest_runner(testables, extra)
def run(self): monitor = Monitor(self.paths) for event in monitor.start(): LOGGER.info("%s: %s" % (TYPE_STRINGS[event.type], event.descriptor.describe(indent=4))) self.invoke_plugins(event, monitor)