class Interface(object):
    def __init__(self): def get_config():
    return RatatoskConfigParser.instance() def get_custom_config():
    """Get separate parser for custom config; else custom config
    parent_task setting will override config file settings"""
    return RatatoskCustomConfigParser.instance() class MergeSamFiles(PicardJobTask):
    executable = "MergeSamFiles.jar"
    label = luigi.Parameter(default=".merge")
    read1_suffix = luigi.Parameter(default="_R1_001")
    target_generator_handler = luigi.Parameter(default=None)
    # FIXME: TMP_DIR should not be hard-coded
    options = luigi.Parameter(default=("SO=coordinate TMP_DIR=./tmp", ), is_list=True)

    def args(self):
        return ["OUTPUT=", self.output()] + [item for sublist in [["INPUT=", x] for x in self.input()] for item in sublist]

    def requires(self):
        cls = self.parent()[0]
        sources = []
        cnf = get_config()
        if self.target_generator_handler and "target_generator_handler" not in self._handlers.keys():
            tgf = RatatoskHandler(label="target_generator_handler", mod=self.target_generator_handler)
            register_task_handler(self, tgf)
        if not "target_generator_handler" in self._handlers.keys():
            logging.warn("MergeSamFiles requires a target generator handler; no defaults are as of yet implemented")
            return []
        sources = list(set(self._handlers["target_generator_handler"](self)))
        return [cls(target=src) for src in sources]     def fullclassname(o):
    return o.__module__ + "." + o.__name__ def rreplace(s, old, new, occurrence):
    li = s.rsplit(old, occurrence)
    return new.join(li) def register(handler_obj, default_handler=None):
    """Register a module function represented as string in
    to a backend handler.
    
    :param handler_obj: the handler object to register
    :param default_handler: the default handler to fall back on

    :return: None
    """
    if not handler_obj:
        logging.warn("No handler object provided; skipping")
        return
    if not isinstance(handler_obj, IHandler):
        raise ValueError, "handler object must implement the IHandler interface"
    hdl = _load(handler_obj)
    if not hdl:
        return
    if handler_obj.label() in backend.__handlers__:
        old_hdl = backend.__handlers__[handler_obj.label()]
        if fullclassname(old_hdl) == fullclassname(hdl):
            logging.info("Handler object '{}' already registered; skipping".format(fullclassname(hdl)))
            return
        else:
            logging.warn("Trying to reset already registered '{}' which is not supported".format(handler_obj.label()))
            return
    else:
        backend.__handlers__[handler_obj.label()] = hdl def register_task_handler(obj, handler_obj, default_handler=None):
    """Register a module function represented as string in
    to a task handler.
    
    :param obj: the object to which the handler is registered
    :param handler_obj: the handler object to register
    :param default_handler: the default handler to fall back on

    :return: None
    """
    if not handler_obj:
        logging.warn("No handler object provided; skipping")
        return
    if not isinstance(handler_obj, IHandler):
        raise ValueError, "handler object must implement the IHandler interface"
    hdl = _load(handler_obj)
    if not hdl:
        return
    if handler_obj.label() in obj._handlers:
        old_hdl = obj._handlers[handler_obj.label()]
        if fullclassname(old_hdl) == fullclassname(hdl):
            logging.info("Handler object '{}' already registered in {}; skipping".format(fullclassname(hdl), obj))
            return
        else:
            logging.warn("Trying to reset already registered '{}' which is not supported".format(handler_obj.label()))
            return
    else:
        obj._handlers[handler_obj.label()] = hdl class RatatoskHandler(IHandler):
    """Ratatosk handler class. Ensures we have at least label and mod
    functions that uses register to place mod in
    backend.__handlers__[label].
    """
    _label = None
    _mod = None
    _load_type = None
    
    def __init__(self, label, mod, load_type="function"):
        """Initialize handler with label (key in backend.__handlers__)
        and mod (string representation of class/function). Load_type
        deterimines what load function to use.
        """
        setattr(self, "_label", label)
        setattr(self, "_mod", mod)
        setattr(self, "_load_type", load_type)

    def label(self):
        """Handler identifier label"""
        return self._label

    def mod(self):
        """String representation of class/function"""
        return self._mod

    def load_type(self):
        """Load type (class or function)"""
        return self._load_type
import os
import glob
import shutil
import sys
import unittest
import luigi
import yaml
import logging
from ratatosk import interface, backend
from ratatosk.config import get_config, get_custom_config
from ratatosk.lib.tools.picard import MergeSamFiles
from ratatosk.utils import fullclassname, rreplace
from types import GeneratorType
from ratatosk.handler import register, register_task_handler, RatatoskHandler

logging.basicConfig(level=logging.DEBUG)

def local_target_generator(task):
    return None

def setUpModule():
    global cnf, conf
    cnf = get_custom_config()
    cnf.clear()
    conf = get_config()
    conf.clear()

def tearDownModule():
    cnf.clear()
    conf.clear()

class TestHandler(unittest.TestCase):
    def test_register_handler(self):
        backend.__handlers__ = {}

        target_handler = RatatoskHandler(label="target_generator_handler", mod="test.test_handler.local_target_generator")