# Path: snakemakelib/rules.py
# def create_rule_from_existing(name, template, workflow, **kw):
#     """Create rule from a template.
#     
#     Create rule from existing rule and add it to the workflow. By
#     passing keyword arguments it is also possible to update/modify the
#     input, output and/or params.
# 
#     Args:
#         name (str): name of new rule
#         template (str): name of existing template rule
#         workflow (:class:`Workflow <snakemake.workflow.Workflow>`): snakemake workflow
#         kw (dict): keyword argument for updating input, output and/or params
#         
#     Returns:
#         None
#     """
#     assert type(workflow) is  Workflow, "workflow is not a Workflow: {}".format(workflow)
#     try:
#         rule = copy.copy(workflow.get_rule(template))
#         rule.name = name
#     except:
#         smllogger.warn("no such template rule '{}'; make sure you have included the template rule file".format(template))
#         raise
#     workflow.add_rule(name=rule.name)
#     workflow._rules[name] = rule
#     if kw.get('output'):
#         assert type(kw['output']) is tuple, "output argument must be a tuple of type (tuple, dict)"
#         rule._output = OutputFiles()
#         workflow._rules[name].set_output(*kw['output'][0], **kw['output'][1])
#     if kw.get('input'):
#         assert type(kw['input']) is tuple, "input argument must be a tuple of type (tuple, dict)"
#         workflow._rules[name].set_input(*kw['input'][0], **kw['input'][1])
#     if kw.get('params'):
#         assert type(kw['params']) is tuple, "params argument must be a tuple of type (tuple, dict)"
#         workflow._rules[name].set_params(*kw['params'][0], **kw['params'][1])


import os
import unittest
import logging
from nose.tools import raises
from snakemake.workflow import Workflow
from snakemake.exceptions import UnknownRuleException, NoRulesException
from snakemakelib.rules import create_rule_from_existing
class TestRules(unittest.TestCase):
    """Test rules"""
    def setUp(self):
        self.workflow = Workflow("foo")
        name = self.workflow.add_rule(name="bar")
        self.workflow._rules["bar"].set_output(*(), **{"foo":"bar"})
        self.workflow._rules["bar"].set_params(*(), **{"cmd":"foo", "options":["foo", "bar"]})
    
    def test_create_rule(self):
        self.assertListEqual(["bar"], [x.name for x in self.workflow.rules])
        create_rule_from_existing(name="foo", template="bar", workflow=self.workflow)
        self.assertListEqual(["bar", "foo"], [x.name for x in self.workflow.rules])

    @raises(NoRulesException)
    def test_create_rule_empty_workflow(self):
        create_rule_from_existing(name="foo", template="bar", workflow=Workflow("foo"))

    @raises(AssertionError)
    def test_create_rule_wrong_workflow(self):
        create_rule_from_existing(name="foo", template="bar", workflow=None)

    @raises(UnknownRuleException)
    def test_create_rule_wrong_template(self):
        create_rule_from_existing(name="bar", template="foo", workflow=self.workflow)

    def test_create_rule_add_output(self):
        create_rule_from_existing(name="foo", template="bar", workflow=self.workflow, **{'output':((), {'bar':'foo'})})
        self.assertDictEqual({'bar':'foo'}, dict(self.workflow.get_rule("foo").output))

    def test_create_rule_add_params(self):

# Path: snakemakelib/rules.py
# def create_rule_from_existing(name, template, workflow, **kw):
#     """Create rule from a template.
#     
#     Create rule from existing rule and add it to the workflow. By
#     passing keyword arguments it is also possible to update/modify the
#     input, output and/or params.
# 
#     Args:
#         name (str): name of new rule
#         template (str): name of existing template rule
#         workflow (:class:`Workflow <snakemake.workflow.Workflow>`): snakemake workflow
#         kw (dict): keyword argument for updating input, output and/or params
#         
#     Returns:
#         None
#     """
#     assert type(workflow) is  Workflow, "workflow is not a Workflow: {}".format(workflow)
#     try:
#         rule = copy.copy(workflow.get_rule(template))
#         rule.name = name
#     except:
#         smllogger.warn("no such template rule '{}'; make sure you have included the template rule file".format(template))
#         raise
#     workflow.add_rule(name=rule.name)
#     workflow._rules[name] = rule
#     if kw.get('output'):
#         assert type(kw['output']) is tuple, "output argument must be a tuple of type (tuple, dict)"
#         rule._output = OutputFiles()
#         workflow._rules[name].set_output(*kw['output'][0], **kw['output'][1])
#     if kw.get('input'):
#         assert type(kw['input']) is tuple, "input argument must be a tuple of type (tuple, dict)"
#         workflow._rules[name].set_input(*kw['input'][0], **kw['input'][1])
#     if kw.get('params'):
#         assert type(kw['params']) is tuple, "params argument must be a tuple of type (tuple, dict)"
#         workflow._rules[name].set_params(*kw['params'][0], **kw['params'][1])


# Path: snakemakelib/tests/test_rules.py
import os
import unittest
import logging
from nose.tools import raises
from snakemake.workflow import Workflow
from snakemake.exceptions import UnknownRuleException, NoRulesException
from snakemakelib.rules import create_rule_from_existing

class TestRules(unittest.TestCase):
    """Test rules"""
    def setUp(self):
        self.workflow = Workflow("foo")
        name = self.workflow.add_rule(name="bar")
        self.workflow._rules["bar"].set_output(*(), **{"foo":"bar"})
        self.workflow._rules["bar"].set_params(*(), **{"cmd":"foo", "options":["foo", "bar"]})
    
    def test_create_rule(self):
        self.assertListEqual(["bar"], [x.name for x in self.workflow.rules])
        create_rule_from_existing(name="foo", template="bar", workflow=self.workflow)
        self.assertListEqual(["bar", "foo"], [x.name for x in self.workflow.rules])

    @raises(NoRulesException)
    def test_create_rule_empty_workflow(self):
        create_rule_from_existing(name="foo", template="bar", workflow=Workflow("foo"))

    @raises(AssertionError)
    def test_create_rule_wrong_workflow(self):
        create_rule_from_existing(name="foo", template="bar", workflow=None)

    @raises(UnknownRuleException)
    def test_create_rule_wrong_template(self):
        create_rule_from_existing(name="bar", template="foo", workflow=self.workflow)

    def test_create_rule_add_output(self):
        create_rule_from_existing(name="foo", template="bar", workflow=self.workflow, **{'output':((), {'bar':'foo'})})
        self.assertDictEqual({'bar':'foo'}, dict(self.workflow.get_rule("foo").output))

    def test_create_rule_add_params(self):

        create_rule_from_existing(name="foo", template="bar", workflow=self.workflow, **{'params':((), {'cmd':'bar', 'options':['foo']})})