示例#1
0
文件: util.py 项目: darwinz/coconut
def get_target_info_smart(target, mode="lowest"):
    """Converts target into a length 2 Python version tuple.

    Modes:
    - "lowest" (default): Gets the lowest version supported by the target.
    - "highest": Gets the highest version supported by the target.
    - "nearest": Gets the supported version that is nearest to the current one.
    - "mypy": Gets the version to use for --mypy."""
    supported_vers = get_vers_for_target(target)
    if mode == "lowest":
        return supported_vers[0]
    elif mode == "highest":
        return supported_vers[-1]
    elif mode == "nearest":
        sys_ver = sys.version_info[:2]
        if sys_ver in supported_vers:
            return sys_ver
        elif sys_ver > supported_vers[-1]:
            return supported_vers[-1]
        elif sys_ver < supported_vers[0]:
            return supported_vers[0]
        else:
            raise CoconutInternalException("invalid sys version", sys_ver)
    elif mode == "mypy":
        if any(v[0] == 2 for v in supported_vers):
            return supported_py2_vers[-1]
        else:
            return supported_vers[-1]
    else:
        raise CoconutInternalException("unknown get_target_info_smart mode", mode)
示例#2
0
def transform(grammar, text):
    """Transform text by replacing matches to grammar."""
    results = []
    intervals = []
    for result, start, stop in all_matches(grammar, text):
        if result is not ignore_transform:
            internal_assert(isinstance(result, str), "got non-string transform result", result)
            if start == 0 and stop == len(text):
                return result
            results.append(result)
            intervals.append((start, stop))

    if not results:
        return None

    split_indices = [0]
    split_indices.extend(start for start, _ in intervals)
    split_indices.extend(stop for _, stop in intervals)
    split_indices.sort()
    split_indices.append(None)

    out = []
    for i in range(len(split_indices) - 1):
        if i % 2 == 0:
            start, stop = split_indices[i], split_indices[i + 1]
            out.append(text[start:stop])
        else:
            out.append(results[i // 2])
    if i // 2 < len(results) - 1:
        raise CoconutInternalException("unused transform results", results[i // 2 + 1:])
    if stop is not None:
        raise CoconutInternalException("failed to properly split text to be transformed")
    return "".join(out)
示例#3
0
文件: util.py 项目: pyzh/coconut
def transform(grammar, text):
    """Transforms text by replacing matches to grammar."""
    results = []
    intervals = []
    for tokens, start, stop in grammar.parseWithTabs().scanString(text):
        if len(tokens) != 1:
            raise CoconutInternalException("invalid transform result tokens", tokens)
        results.append(tokens[0])
        intervals.append((start, stop))

    if not results:
        return None

    split_indices = [0]
    split_indices.extend(start for start, _ in intervals)
    split_indices.extend(stop for _, stop in intervals)
    split_indices.sort()
    split_indices.append(None)

    out = []
    for i in range(len(split_indices) - 1):
        if i % 2 == 0:
            start, stop = split_indices[i], split_indices[i + 1]
            out.append(text[start:stop])
        else:
            out.append(results[i // 2])
    if i // 2 < len(results) - 1:
        raise CoconutInternalException("unused transform results", results[i // 2 + 1:])
    if stop is not None:
        raise CoconutInternalException("failed to properly split text to be transformed")
    return "".join(out)
示例#4
0
文件: util.py 项目: pyzh/coconut
def addskip(skips, skip):
    """Adds a line skip to the skips."""
    if skip < 1:
        complain(CoconutInternalException("invalid skip of line " + str(skip)))
    elif skip in skips:
        complain(CoconutInternalException("duplicate skip of line " + str(skip)))
    else:
        skips.add(skip)
    return skips
示例#5
0
 def show_tabulated(self, begin, middle, end):
     """Shows a tabulated message."""
     if len(begin) < info_tabulation:
         self.show(begin + " " * (info_tabulation - len(begin)) + middle +
                   " " + end)
     else:
         raise CoconutInternalException("info message too long", begin)
示例#6
0
def find_new_value(value, toklist, new_toklist):
    """Find the value in new_toklist that corresponds to the given value in toklist."""
    # find ParseResults by looking up their tokens
    if isinstance(value, ParseResults):
        if value._ParseResults__toklist == toklist:
            new_value_toklist = new_toklist
        else:
            new_value_toklist = []
            for inner_value in value._ParseResults__toklist:
                new_value_toklist.append(find_new_value(inner_value, toklist, new_toklist))
        return ParseResults(new_value_toklist)

    # find other objects by looking them up directly
    try:
        return new_toklist[toklist.index(value)]
    except ValueError:
        complain(
            lambda: CoconutInternalException(
                "inefficient reevaluation of tokens: {} not in {}".format(
                    value,
                    toklist,
                ),
            ),
        )
        return evaluate_tokens(value)
示例#7
0
 def match_sequence(self, tokens, item):
     """Matches a sequence."""
     tail = None
     if len(tokens) == 2:
         series_type, matches = tokens
     else:
         series_type, matches, tail = tokens
     self.add_check("_coconut.isinstance(" + item +
                    ", _coconut.abc.Sequence)")
     if tail is None:
         self.add_check("_coconut.len(" + item + ") == " +
                        str(len(matches)))
     else:
         self.add_check("_coconut.len(" + item + ") >= " +
                        str(len(matches)))
         if len(matches):
             splice = "[" + str(len(matches)) + ":]"
         else:
             splice = ""
         if series_type == "(":
             self.add_def(tail + " = _coconut.tuple(" + item + splice + ")")
         elif series_type == "[":
             self.add_def(tail + " = _coconut.list(" + item + splice + ")")
         else:
             raise CoconutInternalException("invalid series match type",
                                            series_type)
     self.match_all_in(matches, item)
示例#8
0
 def match_msequence(self, tokens, item):
     """Matches a middle sequence."""
     series_type, head_matches, middle, _, last_matches = tokens
     self.add_check("_coconut.isinstance(" + item +
                    ", _coconut.abc.Sequence)")
     self.add_check("_coconut.len(" + item + ") >= " +
                    str(len(head_matches) + len(last_matches)))
     if len(head_matches) and len(last_matches):
         splice = "[" + str(
             len(head_matches)) + ":" + str(-len(last_matches)) + "]"
     elif len(head_matches):
         splice = "[" + str(len(head_matches)) + ":]"
     elif len(last_matches):
         splice = "[:" + str(-len(last_matches)) + "]"
     else:
         splice = ""
     if series_type == "(":
         self.add_def(middle + " = _coconut.tuple(" + item + splice + ")")
     elif series_type == "[":
         self.add_def(middle + " = _coconut.list(" + item + splice + ")")
     else:
         raise CoconutInternalException("invalid series match type",
                                        series_type)
     self.match_all_in(head_matches, item)
     for x in range(len(last_matches)):
         self.match(last_matches[x],
                    item + "[" + str(x - len(last_matches)) + "]")
示例#9
0
文件: matching.py 项目: yggdr/coconut
 def match(self, tokens, item):
     """Performs pattern-matching processing."""
     for flag, get_handler in self.matchers.items():
         if flag in tokens.keys():
             return get_handler(self)(tokens, item)
     raise CoconutInternalException("invalid pattern-matching tokens",
                                    tokens)
示例#10
0
    def split_data_or_class_match(self, tokens):
        """Split data/class match tokens into cls_name, pos_matches, name_matches, star_match."""
        cls_name, matches = tokens

        pos_matches = []
        name_matches = {}
        star_match = None
        for match_arg in matches:
            if len(match_arg) == 1:
                match, = match_arg
                if star_match is not None:
                    raise CoconutDeferredSyntaxError("positional arg after starred arg in data/class match", self.loc)
                if name_matches:
                    raise CoconutDeferredSyntaxError("positional arg after named arg in data/class match", self.loc)
                pos_matches.append(match)
            elif len(match_arg) == 2:
                internal_assert(match_arg[0] == "*", "invalid starred data/class match arg tokens", match_arg)
                _, match = match_arg
                if star_match is not None:
                    raise CoconutDeferredSyntaxError("duplicate starred arg in data/class match", self.loc)
                if name_matches:
                    raise CoconutDeferredSyntaxError("both starred arg and named arg in data/class match", self.loc)
                star_match = match
            elif len(match_arg) == 3:
                internal_assert(match_arg[1] == "=", "invalid named data/class match arg tokens", match_arg)
                name, _, match = match_arg
                if star_match is not None:
                    raise CoconutDeferredSyntaxError("both named arg and starred arg in data/class match", self.loc)
                if name in name_matches:
                    raise CoconutDeferredSyntaxError("duplicate named arg {name!r} in data/class match".format(name=name), self.loc)
                name_matches[name] = match
            else:
                raise CoconutInternalException("invalid data/class match arg", match_arg)

        return cls_name, pos_matches, name_matches, star_match
示例#11
0
def evaluate_tokens(tokens):
    """Evaluate the given tokens in the computation graph."""
    if isinstance(tokens, str):
        return tokens

    elif isinstance(tokens, ParseResults):

        # evaluate the list portion of the ParseResults
        toklist, name, asList, modal = tokens.__getnewargs__()
        new_toklist = [evaluate_tokens(toks) for toks in toklist]
        new_tokens = ParseResults(new_toklist, name, asList, modal)

        # evaluate the dictionary portion of the ParseResults
        new_tokdict = {}
        for name, occurrences in tokens._ParseResults__tokdict.items():
            new_occurences = []
            for value, position in occurrences:
                new_value = find_new_value(value, toklist, new_toklist)
                new_occurences.append(_ParseResultsWithOffset(new_value, position))
            new_tokdict[name] = occurrences
        new_tokens._ParseResults__accumNames.update(tokens._ParseResults__accumNames)
        new_tokens._ParseResults__tokdict.update(new_tokdict)
        return new_tokens

    elif isinstance(tokens, ComputationNode):
        return tokens.evaluate()

    elif isinstance(tokens, (list, tuple)):
        return [evaluate_tokens(inner_toks) for inner_toks in tokens]

    else:
        raise CoconutInternalException("invalid computation graph tokens", tokens)
示例#12
0
 def assign_to_series(self, name, series_type, item):
     """Assign name to item converted to the given series_type."""
     if self.using_python_rules or series_type == "[":
         self.add_def(name + " = _coconut.list(" + item + ")")
     elif series_type == "(":
         self.add_def(name + " = _coconut.tuple(" + item + ")")
     else:
         raise CoconutInternalException("invalid series match type", series_type)
示例#13
0
    def compile(self,
                codepath,
                destpath=None,
                package=False,
                run=False,
                force=False,
                show_unchanged=True):
        """Compile a source Coconut file to a destination Python file."""
        with openfile(codepath, "r") as opened:
            code = readfile(opened)

        if destpath is not None:
            destdir = os.path.dirname(destpath)
            if not os.path.exists(destdir):
                os.makedirs(destdir)
            if package is True:
                self.create_package(destdir)

        foundhash = None if force else self.has_hash_of(
            destpath, code, package)
        if foundhash:
            if show_unchanged:
                logger.show_tabulated("Left unchanged", showpath(destpath),
                                      "(pass --force to override).")
            if self.show:
                print(foundhash)
            if run:
                self.execute_file(destpath)

        else:
            logger.show_tabulated("Compiling", showpath(codepath), "...")

            if package is True:
                compile_method = "parse_package"
            elif package is False:
                compile_method = "parse_file"
            else:
                raise CoconutInternalException("invalid value for package",
                                               package)

            def callback(compiled):
                if destpath is None:
                    logger.show_tabulated("Compiled", showpath(codepath),
                                          "without writing to file.")
                else:
                    with openfile(destpath, "w") as opened:
                        writefile(opened, compiled)
                    logger.show_tabulated("Compiled to", showpath(destpath),
                                          ".")
                if self.show:
                    print(compiled)
                if run:
                    if destpath is None:
                        self.execute(compiled, path=codepath, allow_show=False)
                    else:
                        self.execute_file(destpath)

            self.submit_comp_job(codepath, callback, compile_method, code)
示例#14
0
文件: util.py 项目: darwinz/coconut
def get_vers_for_target(target):
    """Gets a list of the versions supported by the given target."""
    target_info = get_target_info(target)
    if not target_info:
        return supported_py2_vers + supported_py3_vers
    elif len(target_info) == 1:
        if target_info == (2,):
            return supported_py2_vers
        elif target_info == (3,):
            return supported_py3_vers
        else:
            raise CoconutInternalException("invalid target info", target_info)
    elif target_info[0] == 2:
        return tuple(ver for ver in supported_py2_vers if ver >= target_info)
    elif target_info[0] == 3:
        return tuple(ver for ver in supported_py3_vers if ver >= target_info)
    else:
        raise CoconutInternalException("invalid target info", target_info)
示例#15
0
文件: util.py 项目: pyzh/coconut
def longest(*args):
    """Match the longest of the given grammar elements."""
    if len(args) < 2:
        raise CoconutInternalException("longest expected at least two args")
    else:
        matcher = args[0] + skip_whitespace
        for elem in args[1:]:
            matcher ^= elem + skip_whitespace
        return matcher
示例#16
0
 def match_trailer(self, tokens, item):
     """Matches typedefs and as patterns."""
     if len(tokens) <= 1 or len(tokens) % 2 != 1:
         raise CoconutInternalException("invalid trailer match tokens", tokens)
     else:
         match, trailers = tokens[0], tokens[1:]
         for i in range(0, len(trailers), 2):
             op, arg = trailers[i], trailers[i + 1]
             if op == "is":
                 self.add_check("_coconut.isinstance(" + item + ", " + arg + ")")
             elif op == "as":
                 if arg in self.names:
                     self.add_check(self.names[arg] + " == " + item)
                 elif arg != wildcard:
                     self.add_def(arg + " = " + item)
                     self.names[arg] = item
             else:
                 raise CoconutInternalException("invalid trailer match operation", op)
         self.match(match, item)
示例#17
0
 def match_set(self, tokens, item):
     """Matches a set."""
     if len(tokens) == 1:
         match = tokens[0]
     else:
         raise CoconutInternalException("invalid set match tokens", tokens)
     self.add_check("_coconut.isinstance(" + item + ", _coconut.abc.Set)")
     self.add_check("_coconut.len(" + item + ") == " + str(len(match)))
     for const in match:
         self.add_check(const + " in " + item)
示例#18
0
 def wrapped_handler(s, l, t):
     self.log_trace(handler.__name__, s, l, t)
     try:
         return _trim_arity(handler)(s, l, t)
     except CoconutException:
         raise
     except Exception:
         raise CoconutInternalException(
             "error calling handler " + handler.__name__ +
             " with tokens", t)
示例#19
0
def evaluate_tokens(tokens):
    """Evaluate the given tokens in the computation graph."""
    if isinstance(tokens, str):
        return tokens
    elif isinstance(tokens, ParseResults):
        # evaluate the list portion of the ParseResults
        toklist, name, asList, modal = tokens.__getnewargs__()
        new_toklist = [evaluate_tokens(toks) for toks in toklist]
        new_tokens = ParseResults(new_toklist, name, asList, modal)
        # evaluate the dictionary portion of the ParseResults
        new_tokdict = {}
        for name, occurrences in tokens._ParseResults__tokdict.items():
            new_occurences = []
            for value, position in occurrences:
                if isinstance(value, ParseResults
                              ) and value._ParseResults__toklist == toklist:
                    new_value = new_tokens
                else:
                    try:
                        new_value = new_toklist[toklist.index(value)]
                    except ValueError:
                        complain(lambda: CoconutInternalException(
                            "inefficient reevaluation of tokens: {} not in {}".
                            format(
                                value,
                                toklist,
                            )))
                        new_value = evaluate_tokens(value)
                new_occurences.append(
                    _ParseResultsWithOffset(new_value, position))
            new_tokdict[name] = occurrences
        new_tokens._ParseResults__accumNames.update(
            tokens._ParseResults__accumNames)
        new_tokens._ParseResults__tokdict.update(new_tokdict)
        return new_tokens
    elif isinstance(tokens, ComputationNode):
        return tokens.evaluate()
    elif isinstance(tokens, (list, tuple)):
        return [evaluate_tokens(inner_toks) for inner_toks in tokens]
    else:
        raise CoconutInternalException("invalid computation graph tokens",
                                       tokens)
示例#20
0
 def input(self, more=False):
     """Prompts for code input."""
     if more:
         msg = more_prompt
     else:
         msg = main_prompt
     if self.style is None:
         return input(msg)
     elif prompt_toolkit is None:
         raise CoconutInternalException("cannot highlight style without prompt_toolkit", self.style)
     else:
         return prompt_toolkit.prompt(msg, **self.prompt_kwargs())
示例#21
0
 def match_trailer(self, tokens, item):
     """Matches typedefs and as patterns."""
     internal_assert(len(tokens) > 1 and len(tokens) % 2 == 1, "invalid trailer match tokens", tokens)
     match, trailers = tokens[0], tokens[1:]
     for i in range(0, len(trailers), 2):
         op, arg = trailers[i], trailers[i + 1]
         if op == "as":
             self.match_var([arg], item, bind_wildcard=True)
         elif op == "is":
             self.add_check("_coconut.isinstance(" + item + ", " + arg + ")")
         else:
             raise CoconutInternalException("invalid trailer match operation", op)
     self.match(match, item)
示例#22
0
文件: root.py 项目: darwinz/coconut
        def do_complete(self, code, cursor_pos):
            # first try with Jedi completions
            self.use_experimental_completions = True
            try:
                return super(CoconutKernel, self).do_complete(code, cursor_pos)
            except Exception:
                logger.print_exc()
                logger.warn_err(CoconutInternalException("experimental IPython completion failed, defaulting to shell completion"), force=True)

            # then if that fails default to shell completions
            self.use_experimental_completions = False
            try:
                return super(CoconutKernel, self).do_complete(code, cursor_pos)
            finally:
                self.use_experimental_completions = True
示例#23
0
def get_vers_for_target(target):
    """Gets a list of the versions supported by the given target."""
    target_info = get_target_info(target)
    if not target_info:
        return py2_vers + py3_vers
    elif len(target_info) == 1:
        if target_info == (2, ):
            return py2_vers
        elif target_info == (3, ):
            return py3_vers
        else:
            raise CoconutInternalException("invalid target info", target_info)
    elif target_info == (3, 3):
        return [(3, 3), (3, 4)]
    else:
        return [target_info[:2]]
示例#24
0
 def match_rsequence(self, tokens, item):
     """Matches a reverse sequence."""
     front, series_type, matches = tokens
     self.add_check("_coconut.isinstance(" + item + ", _coconut.abc.Sequence)")
     self.add_check("_coconut.len(" + item + ") >= " + str(len(matches)))
     if len(matches):
         splice = "[:" + str(-len(matches)) + "]"
     else:
         splice = ""
     if series_type == "(":
         self.add_def(front + " = _coconut.tuple(" + item + splice + ")")
     elif series_type == "[":
         self.add_def(front + " = _coconut.list(" + item + splice + ")")
     else:
         raise CoconutInternalException("invalid series match type", series_type)
     for x in range(len(matches)):
         self.match(matches[x], item + "[" + str(x - len(matches)) + "]")
示例#25
0
def get_target_info_len2(target, lowest=False):
    """By default, gets the highest version supported by the target before the next target.
    If lowest is passed, instead gets the lowest version supported by the target."""
    target_info = get_target_info(target)
    if not target_info:
        return (2, 6) if lowest else (2, 7)
    elif len(target_info) == 1:
        if target_info == (2, ):
            return (2, 6) if lowest else (2, 7)
        elif target_info == (3, ):
            return (3, 2) if lowest else (3, 4)
        else:
            raise CoconutInternalException("invalid target info", target_info)
    elif len(target_info) == 2:
        return target_info
    else:
        return target_info[:2]
示例#26
0
 def match_data(self, tokens, item):
     """Matches a data type."""
     if len(tokens) == 2:
         data_type, matches = tokens
         star_match = None
     elif len(tokens) == 3:
         data_type, matches, star_match = tokens
     else:
         raise CoconutInternalException("invalid data match tokens", tokens)
     self.add_check("_coconut.isinstance(" + item + ", " + data_type + ")")
     if star_match is None:
         self.add_check("_coconut.len(" + item + ") == " + str(len(matches)))
     elif len(matches):
         self.add_check("_coconut.len(" + item + ") >= " + str(len(matches)))
     self.match_all_in(matches, item)
     if star_match is not None:
         self.match(star_match, item + "[" + str(len(matches)) + ":]")
示例#27
0
def run_cmd(cmd, show_output=True, raise_errs=True):
    """Runs a console command."""
    if not isinstance(cmd, list):
        raise CoconutInternalException("console commands must be passed as lists")
    else:
        if sys.version_info >= (3, 3):
            import shutil
            cmd[0] = shutil.which(cmd[0]) or cmd[0]
        logger.log_cmd(cmd)
        if show_output and raise_errs:
            return subprocess.check_call(cmd)
        elif raise_errs:
            return subprocess.check_output(cmd, stderr=subprocess.STDOUT)
        elif show_output:
            return subprocess.call(cmd)
        else:
            return "".join(call_output(cmd))
示例#28
0
文件: header.py 项目: x10an14/coconut
def minify(compiled):
    """Performs basic minifications (fails with strings or non-tabideal indentation)."""
    compiled = compiled.strip()
    if compiled:
        out = []
        for line in compiled.splitlines():
            line = line.split("#", 1)[0].rstrip()
            if line:
                ind = 0
                while line.startswith(" "):
                    line = line[1:]
                    ind += 1
                if ind % tabideal != 0:
                    raise CoconutInternalException("invalid indentation in",
                                                   line)
                out.append(" " * (ind // tabideal) + line)
        compiled = "\n".join(out) + "\n"
    return compiled
示例#29
0
 def evaluate(self):
     """Get the result of evaluating the computation graph at this node."""
     if DEVELOP:
         internal_assert(not self.been_called, "inefficient reevaluation of action " + self.name + " with tokens", self.tokens)
         self.been_called = True
     evaluated_toks = evaluate_tokens(self.tokens)
     if logger.tracing:  # avoid the overhead of the call if not tracing
         logger.log_trace(self.name, self.original, self.loc, evaluated_toks, self.tokens)
     try:
         return _trim_arity(self.action)(
             self.original,
             self.loc,
             evaluated_toks,
         )
     except CoconutException:
         raise
     except (Exception, AssertionError):
         traceback.print_exc()
         raise CoconutInternalException("error computing action " + self.name + " of evaluated tokens", evaluated_toks)
示例#30
0
def get_target_info_len2(target, mode="lowest"):
    """Converts target into a length 2 Python version tuple.

    Modes:
    - "lowest" (default): Gets the lowest version supported by the target.
    - "highest": Gets the highest version supported by the target.
    - "nearest": If the current version is supported, returns that, otherwise gets the highest."""
    supported_vers = get_vers_for_target(target)
    if mode == "lowest":
        return supported_vers[0]
    elif mode == "highest":
        return supported_vers[-1]
    elif mode == "nearest":
        if sys.version_info[:2] in supported_vers:
            return sys.version_info[:2]
        else:
            return supported_vers[-1]
    else:
        raise CoconutInternalException("unknown get_target_info_len2 mode", mode)