# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3.9.4 64-bit
#     name: python38564bit1ada39ffdf0c4119935a34ccde4922f3
# ---

# +
#default_exp IOUtils

# +
#export
#hide
from typing import List, Iterable, Optional
import re
import subprocess

import sys
sys.path.append("..")

from hephaestus.AbstractMethod import *
from hephaestus.EditOperations import *


# -

# # IOUtils
#
# > Defines utility functions for input/output.

#export
def readAbstractMethodsFromFile(file: str) -> List[AbstractMethod]:
    """
    Returns a list of `AbstractMethods` read from the given `file`. The file should have one `AbstractMethod`
    per line with tokens separated by spaces.
    """
    
    abstractMethods = []

    with open(file, "r") as f:
        for line in f:
            abstractMethods.append(AbstractMethod(line.strip()))
    
    return abstractMethods


#export
def writeAbstractMethodsToFile(file: str, abstractMethods: List[AbstractMethod]) -> None:
    """
    Writes the given `abstractMethods` to the given `file` such that one `AbstractMethod` is written per line.
    """

    with open(file, "w") as f:

        for i in range(len(abstractMethods)):

            f.write(str(abstractMethods[i]))
            
            if i < len(abstractMethods) - 1:
                f.write("\n")


#export
def readCompoundOperationsFromFile(file: str) -> List[Optional[List[CompoundOperation]]]:
    """
    Returns a list of lists of CompoundOperations read from the given `file`. Each line in the file represents a
    list of CompoundOperations in machine string format, as in the file written by `writeCompoundOperationsToFile`.
    If a line is unable to be parsed into a list of CompoundOperations, then that list is instead represented by
    `None`. This is different from an empty list, which represents a line with no CompoundOperations.
    """

    operations = []

    with open(file, "r") as f:

        for line in f:

            lineOps = []

            # continue as long as there is stuff left in the line and there hasn't been a parse failure
            while line != "" and lineOps is not None:

                # match the beginning of the line to the machine string pattern
                line = line.strip()
                match = re.search(r"^<.+?>.*?</.+?>", line)

                # if the match succeeded, then attempt to remove the operation from the line and add it to lineOps
                if match:
                    try:
                        lineOps.append(CompoundOperation.FromMachineString(match.group(0)))
                        line = line[len(match.group(0)):]
                    except ValueError:
                        lineOps = None
                
                # if the match didn't succeed and there is stuff left on the line, then this line is invalid
                elif line != "":
                    lineOps = None
            
            operations.append(lineOps)

    return operations


#export
def writeCompoundOperationsToFile(file: str, operations: List[List[CompoundOperation]], form: str = "general") -> None:
    """
    Writes the given list of lists of CompoundOperations to the given `file` in the machine string form given by `form`
    (defaults to `"general"`). Each list of operations occupies one line.
    """

    with open(file, "w") as f:

        for i in range(len(operations)):
            
            for j in range(len(operations[i])):

                f.write(operations[i][j].getMachineString(form))

                if j < len(operations[i]) - 1:
                    f.write(" ")
            
            if i < len(operations) - 1:
                f.write("\n")


#export
#hide
def getYamlParameter(yamlFile: str, key: str) -> str:
    """
    Returns the value of the given `key` in the given `yamlFile`. If the parameter was not found,
    Returns None.
    """

    with open(yamlFile, "r") as file:
        for line in file:
            match = re.search(r"^\s*" + key + r"\s*:\s*(.+?)(?:\s+#|$)", line)
            if (match):
                return match.group(1).strip()
    
    return None


#export
#hide
def runCommand(command: Iterable[str]) -> str:
    """
    Runs the given command in the shell and continuously prints its output. If the command failed, raises
    a ProcessException. Returns the command output.
    """

    # run the command
    process = subprocess.Popen(command, shell = True, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
    output = ""

    while True:

        line = process.stdout.readline()

        # break out if the process has finished and there is no more output to print
        if process.poll() is not None and line == b"":
            break
    
        sys.stdout.write(line)
        sys.stdout.flush()
        output += line.decode()
    
    exitCode = process.returncode

    if exitCode == 0:
        return output
    
    raise subprocess.CalledProcessError(exitCode, command, output)

StarcoderdataJupyterScriptsDedupFiltered