# Buggy code
def compound_match(self, tgt):
    """
    Runs the compound target check
    """
    if not isinstance(tgt, string_types):
        log.debug("Compound target received that is not a string")
        return False
    ref = {
        "G": "grain",
        "P": "grain_pcre",
        "X": "exsel",
        "I": "pillar",
        "L": "list",
        "S": "ipcidr",
        "E": "pcre",
        "D": "data",
    }
    if HAS_RANGE:
        ref["R"] = "range"
    results = []
    opers = ["and", "or", "not", "(", ")"]
    tokens = tgt.split()
    for match in tokens:
        # Try to match tokens from the compound target, first by using
        # the 'G, X, I, L, S, E' matcher types, then by hostname glob.
        if "@" in match and match[1] == "@":
            comps = match.split("@")
            matcher = ref.get(comps[0])
            if not matcher:
                # If an unknown matcher is called at any time, fail out
                return False
            results.append(
                str(getattr(self, "{0}_match".format(matcher))("@".join(comps[1:])))
            )
        elif match in opers:
            # We didn't match a target, so append a boolean operator or
            # subexpression
            if results:
                if match == "not":
                    if results[-1] == "and":
                        pass
                    elif results[-1] == "or":
                        pass
                    else:
                        results.append("and")
                results.append(match)
        else:
            # The match is not explicitly defined, evaluate it as a glob
            results.append(str(self.glob_match(match)))
    try:
        return eval(" ".join(results))
    except Exception:
        log.error("Invalid compound target: {0}".format(tgt))
        return False
    return False


# Traceback (SyntaxError)
[INFO    ] Fetching file 'salt://top.sls'
[DEBUG   ] Jinja search path: '['/var/cache/salt/minion/files/base']'
Traceback (most recent call last):
File "/usr/bin/salt-call", line 11, in <module>
salt_call()
File "/usr/lib/pymodules/python2.7/salt/scripts.py", line 76, in salt_call
client.run()
File "/usr/lib/pymodules/python2.7/salt/cli/__init__.py", line 251, in run
caller.run()
File "/usr/lib/pymodules/python2.7/salt/cli/caller.py", line 128, in run
ret = self.call()
File "/usr/lib/pymodules/python2.7/salt/cli/caller.py", line 70, in call
ret['return'] = self.minion.functions[fun](*args, **kwargs)
File "/usr/lib/pymodules/python2.7/salt/modules/state.py", line 155, in highstate
ret = st_.call_highstate(exclude=kwargs.get('exclude', []))
File "/usr/lib/pymodules/python2.7/salt/state.py", line 2019, in call_highstate
matches = self.top_matches(top)
File "/usr/lib/pymodules/python2.7/salt/state.py", line 1728, in top_matches
self.opts['nodegroups']
File "/usr/lib/pymodules/python2.7/salt/minion.py", line 941, in confirm_top
return getattr(self, funcname)(match)
File "/usr/lib/pymodules/python2.7/salt/minion.py", line 1151, in compound_match
return eval(' '.join(results))
File "<string>", line 1
True ( False ) False or False
^
SyntaxError: invalid syntax

# Fixed code
def compound_match(self, tgt):
    """
    Runs the compound target check
    """
    if not isinstance(tgt, string_types):
        log.debug("Compound target received that is not a string")
        return False
    ref = {
        "G": "grain",
        "P": "grain_pcre",
        "X": "exsel",
        "I": "pillar",
        "L": "list",
        "S": "ipcidr",
        "E": "pcre",
        "D": "data",
    }
    if HAS_RANGE:
        ref["R"] = "range"
    results = []
    opers = ["and", "or", "not", "(", ")"]
    tokens = tgt.split()
    for match in tokens:
        # Try to match tokens from the compound target, first by using
        # the 'G, X, I, L, S, E' matcher types, then by hostname glob.
        if "@" in match and match[1] == "@":
            comps = match.split("@")
            matcher = ref.get(comps[0])
            if not matcher:
                # If an unknown matcher is called at any time, fail out
                return False
            results.append(
                str(getattr(self, "{0}_match".format(matcher))("@".join(comps[1:])))
            )
        elif match in opers:
            # We didn't match a target, so append a boolean operator or
            # subexpression
            if results:
                if match == "not":
                    if results[-1] == "and":
                        pass
                    elif results[-1] == "or":
                        pass
                    else:
                        results.append("and")
                results.append(match)
            else:
                # seq start with oper, fail
                if match not in ["(", ")"]:
                    return False
        else:
            # The match is not explicitly defined, evaluate it as a glob
            results.append(str(self.glob_match(match)))
    results = " ".join(results)
    try:
        return eval(results)
    except Exception:
        log.error("Invalid compound target: {0}".format(tgt))
        return False
    return False