# Path: dput/profile.py
# def parse_overrides(overrides):
#     """
#     Translate a complex string structure into a JSON like object. For example
#     this function would translate foo.bar=baz like strings into objects
#     overriding the JSON profile.
# 
#     Basically this function function will take any object separated by a dot on
#     the left side as a dict object, whereas the terminal value on the right
#     side is taken literally.
#     """
#     # This function involves lots of black magic.
#     # Generally we expect a foo.bar=value format, with foo.bar being a profile
#     # key and value being $anything.
#     # However, people might provide that in weird combinations such as
#     # 'foo.bar      =     "value value"'
#     override_obj = {}
#     for override in overrides:
#         parent_obj = override_obj
#         if override.find("=") > 0 or override.startswith("-") > 0:
#             (profile_key, profile_value) = (None, None)
#             if override.startswith("-"):
#                 profile_key = override[1:]
#                 profile_value = None
#             else:
#                 (profile_key, profile_value) = override.split("=", 1)
#                 profile_value = shlex.split(profile_value)
#             profile_key = re.sub(r'\s', '', profile_key)
#             profile_key = profile_key.split(".")
#             last_item = profile_key.pop()
# 
#             for key in profile_key:
#                 if not key in parent_obj:
#                     parent_obj[key] = {}
#                 parent_obj = parent_obj[key]
# 
#             if isinstance(parent_obj, list):
#                 raise DputConfigurationError("Ambiguous override: object %s "
#                     "can either be a composite type or a terminal, not both" %
#                     (last_item))
# 
#             if not last_item in parent_obj:
#                 parent_obj[last_item] = []
#             if last_item in parent_obj and not (
#                                     isinstance(parent_obj[last_item], list)):
#                 raise DputConfigurationError("Ambiguous override: object %s "
#                     "can either be a composite type or a terminal, not both" %
#                     (last_item))
#             parent_obj[last_item].append(profile_value)
#         else:
#             raise DputConfigurationError(
#                            "Profile override %s does not seem to match the "
#                            "expected format" % override)
#     return override_obj
# 
# Path: dput/exceptions.py
# class DputConfigurationError(DputError):
#     """
#     Errors in the parsing or retrieving of configuration files should raise
#     an instance of this, or a subclass thereof.
#     """
#     pass


from dput.profile import parse_overrides
from dput.exceptions import DputConfigurationError


def test_parse_overrides():
    test_cases = [
        ({'foo': [['bar']]},
            ['foo=bar']),
        ({'foo': [None]},
            ['-foo']),
        ({'+foo': [['bar']]},
            ['+foo=bar']),
        ({'foo': [None, ['1']]},
            ['-foo', 'foo=1']),
        ({'foo': {'bar': {'baz': [['paultag.is.a.god']]}}},
            ['foo.bar.baz=paultag.is.a.god']),
        ({'foo': {'bar': [['1'], ['2'], ['3']]}, 'foo2': [['4']]},
            ['foo.bar=1', 'foo.bar=2', 'foo.bar=3', 'foo2=4']),
        ({'foo': {'bar': [['True=True'], ['foo=False', 'obj2']]},
          'foo2': [['bar']]},
            ['foo.bar      =     "True=True"', "foo.bar='foo'=False 'obj2'",
             'foo2=bar'])
     ]

    bad_test_cases = [
                      (None, ['invalid']),
                      (None, ['foo=bar', 'foo=bar', 'foo.bar=bar']),
                      (None, ['foo.bar=1', 'foo.bar.baz=1'])
    ]

    for (expectation, case) in test_cases:
        print(parse_overrides(case))

# Path: dput/profile.py
# def parse_overrides(overrides):
#     """
#     Translate a complex string structure into a JSON like object. For example
#     this function would translate foo.bar=baz like strings into objects
#     overriding the JSON profile.
# 
#     Basically this function function will take any object separated by a dot on
#     the left side as a dict object, whereas the terminal value on the right
#     side is taken literally.
#     """
#     # This function involves lots of black magic.
#     # Generally we expect a foo.bar=value format, with foo.bar being a profile
#     # key and value being $anything.
#     # However, people might provide that in weird combinations such as
#     # 'foo.bar      =     "value value"'
#     override_obj = {}
#     for override in overrides:
#         parent_obj = override_obj
#         if override.find("=") > 0 or override.startswith("-") > 0:
#             (profile_key, profile_value) = (None, None)
#             if override.startswith("-"):
#                 profile_key = override[1:]
#                 profile_value = None
#             else:
#                 (profile_key, profile_value) = override.split("=", 1)
#                 profile_value = shlex.split(profile_value)
#             profile_key = re.sub(r'\s', '', profile_key)
#             profile_key = profile_key.split(".")
#             last_item = profile_key.pop()
# 
#             for key in profile_key:
#                 if not key in parent_obj:
#                     parent_obj[key] = {}
#                 parent_obj = parent_obj[key]
# 
#             if isinstance(parent_obj, list):
#                 raise DputConfigurationError("Ambiguous override: object %s "
#                     "can either be a composite type or a terminal, not both" %
#                     (last_item))
# 
#             if not last_item in parent_obj:
#                 parent_obj[last_item] = []
#             if last_item in parent_obj and not (
#                                     isinstance(parent_obj[last_item], list)):
#                 raise DputConfigurationError("Ambiguous override: object %s "
#                     "can either be a composite type or a terminal, not both" %
#                     (last_item))
#             parent_obj[last_item].append(profile_value)
#         else:
#             raise DputConfigurationError(
#                            "Profile override %s does not seem to match the "
#                            "expected format" % override)
#     return override_obj
# 
# Path: dput/exceptions.py
# class DputConfigurationError(DputError):
#     """
#     Errors in the parsing or retrieving of configuration files should raise
#     an instance of this, or a subclass thereof.
#     """
#     pass


# Path: tests/test_overrides.py
from dput.profile import parse_overrides
from dput.exceptions import DputConfigurationError



def test_parse_overrides():
    test_cases = [
        ({'foo': [['bar']]},
            ['foo=bar']),
        ({'foo': [None]},
            ['-foo']),
        ({'+foo': [['bar']]},
            ['+foo=bar']),
        ({'foo': [None, ['1']]},
            ['-foo', 'foo=1']),
        ({'foo': {'bar': {'baz': [['paultag.is.a.god']]}}},
            ['foo.bar.baz=paultag.is.a.god']),
        ({'foo': {'bar': [['1'], ['2'], ['3']]}, 'foo2': [['4']]},
            ['foo.bar=1', 'foo.bar=2', 'foo.bar=3', 'foo2=4']),
        ({'foo': {'bar': [['True=True'], ['foo=False', 'obj2']]},
          'foo2': [['bar']]},
            ['foo.bar      =     "True=True"', "foo.bar='foo'=False 'obj2'",
             'foo2=bar'])
     ]

    bad_test_cases = [
                      (None, ['invalid']),
                      (None, ['foo=bar', 'foo=bar', 'foo.bar=bar']),
                      (None, ['foo.bar=1', 'foo.bar.baz=1'])
    ]

    for (expectation, case) in test_cases:
        print(parse_overrides(case))

        assert(expectation == parse_overrides(case))