<gh_stars>1-10
"""
Autogenerated Problem Facilitation
"""

import api

import shutil
import os
import spur

from os import path
from string import Template
from api.common import InternalException
from hashlib import sha1

log = api.logger.use(__name__)

_build_directories = []

def run_makefile(make_directory):
    """
    Runs a makefile in a given directory.

    Args:
        make_directory: directory where the Makefile is located.
    """

    make_path = path.join(make_directory, "Makefile")

    if not path.isfile(make_path):
        raise InternalException(make_path + " does not exist.")

    shell = spur.LocalShell()

    try:
        shell.run(["make", "-C", make_directory])
    except Exception as e:
        raise InternalException(str(e))

def get_directory(resource_path):
    """
    Returns the directory in which something exists. You can supply __file__ from
    a module/generator to get its directory.

    Args:
        resource_path: path to a resource
    Returns:
        The resource's directory of residence.
    """

    return path.dirname(path.abspath(resource_path))


def generate_resource_url(pid, resource_path, static=False):
    return '/api/autogen/serve/{}?static={}&pid={}'.format(resource_path, "true" if static else "false", pid)


def generate_resource_link(pid, resource_path, static=False, title=None):
    """
    Returns a valid html link to a public resource within an autogenerated instance.

    Args:
        pid: the problem id
        resource_path: the resource path
        static: boolean whether or not it is a static resource
        title: the displayed text. Defaults to the path
    Returns:
        The html link to the resource.
    """

    return '<a target=_blank href="/api/autogen/serve/{}?static={}&pid={}">{}</a>'.format(
        resource_path,
        "true" if static else "false",
        pid,
        resource_path if not title else title
    )

def generate_build_directory(base=os.getcwd()):
    """
    Generates a random writable directory for generators to build instances with.
    All directories generated will be removed in the call to clear_build_directories()

    Args:
        base: base path to create the directory. defaults to the current working directory.
    Returns:
        The path to the directory
    """

    build_path = path.join(base, api.common.token()[:6])

    try:
        os.makedirs(build_path)
    except Exception:
        raise InternalException("Unable to create build path: "+build_path)

    _build_directories.append(build_path)

    return build_path

def clear_build_directories():
    """
    Removes everything in the generated build directories.
    """

    problems = []

    for directory in _build_directories:
        if path.isdir(directory):
            try:
                shutil.rmtree(directory)
            except Exception:
                problems.append(directory)

    problem_string = ", ".join(problems)

    if len(problems) > 0:
        raise InternalException("Unable to delete these directories: "+problem_string)
    else:
        _build_directories.clear()

def replace_source_tokens(file_path, lookup, out_path):
    """
    Replace tokens in a file and write out the substitution.

    Args:
        file_path: the path of the file to be read.
        lookup: a dictionary containing the substitutions.
        out_path: file in which the substitutions will be written.
    """

    if not path.isfile(file_path):
        raise InternalException("File: {} does not exist.".format(file_path))

    try:
        source_file = open(file_path, "r")
        source = source_file.read()
    except Exception:
        raise InternalException("Unable to read from source file.")

    template = Template(source)

    output = template.safe_substitute(lookup)

    try:
        output_file = open(out_path, "w")
        output_file.write(output)
    except Exception:
        raise InternalException("Unable to write to output file.")

"""
Autogenerated Problem Facilitation
"""

import api

import shutil
import os
import spur

from os import path
from string import Template
from api.common import InternalException
from hashlib import sha1

log = api.logger.use(__name__)

_build_directories = []

def run_makefile(make_directory):
    """
    Runs a makefile in a given directory.

    Args:
        make_directory: directory where the Makefile is located.
    """

    make_path = path.join(make_directory, "Makefile")

    if not path.isfile(make_path):
        raise InternalException(make_path + " does not exist.")

    shell = spur.LocalShell()

    try:
        shell.run(["make", "-C", make_directory])
    except Exception as e:
        raise InternalException(str(e))

def get_directory(resource_path):
    """
    Returns the directory in which something exists. You can supply __file__ from
    a module/generator to get its directory.

    Args:
        resource_path: path to a resource
    Returns:
        The resource's directory of residence.
    """

    return path.dirname(path.abspath(resource_path))


def generate_resource_url(pid, resource_path, static=False):
    return '/api/autogen/serve/{}?static={}&pid={}'.format(resource_path, "true" if static else "false", pid)


def generate_resource_link(pid, resource_path, static=False, title=None):
    """
    Returns a valid html link to a public resource within an autogenerated instance.

    Args:
        pid: the problem id
        resource_path: the resource path
        static: boolean whether or not it is a static resource
        title: the displayed text. Defaults to the path
    Returns:
        The html link to the resource.
    """

    return '<a target=_blank href="/api/autogen/serve/{}?static={}&pid={}">{}</a>'.format(
        resource_path,
        "true" if static else "false",
        pid,
        resource_path if not title else title
    )

def generate_build_directory(base=os.getcwd()):
    """
    Generates a random writable directory for generators to build instances with.
    All directories generated will be removed in the call to clear_build_directories()

    Args:
        base: base path to create the directory. defaults to the current working directory.
    Returns:
        The path to the directory
    """

    build_path = path.join(base, api.common.token()[:6])

    try:
        os.makedirs(build_path)
    except Exception:
        raise InternalException("Unable to create build path: "+build_path)

    _build_directories.append(build_path)

    return build_path

def clear_build_directories():
    """
    Removes everything in the generated build directories.
    """

    problems = []

    for directory in _build_directories:
        if path.isdir(directory):
            try:
                shutil.rmtree(directory)
            except Exception:
                problems.append(directory)

    problem_string = ", ".join(problems)

    if len(problems) > 0:
        raise InternalException("Unable to delete these directories: "+problem_string)
    else:
        _build_directories.clear()

def replace_source_tokens(file_path, lookup, out_path):
    """
    Replace tokens in a file and write out the substitution.

    Args:
        file_path: the path of the file to be read.
        lookup: a dictionary containing the substitutions.
        out_path: file in which the substitutions will be written.
    """

    if not path.isfile(file_path):
        raise InternalException("File: {} does not exist.".format(file_path))

    try:
        source_file = open(file_path, "r")
        source = source_file.read()
    except Exception:
        raise InternalException("Unable to read from source file.")

    template = Template(source)

    output = template.safe_substitute(lookup)

    try:
        output_file = open(out_path, "w")
        output_file.write(output)
    except Exception:
        raise InternalException("Unable to write to output file.")
Autogenerated Problem Facilitation Runs a makefile in a given directory.      Args:         make_directory: directory where the Makefile is located. Returns the directory in which something exists. You can supply __file__ from     a module/generator to get its directory.      Args:         resource_path: path to a resource     Returns:         The resource's directory of residence. Returns a valid html link to a public resource within an autogenerated instance.      Args:         pid: the problem id         resource_path: the resource path         static: boolean whether or not it is a static resource         title: the displayed text. Defaults to the path     Returns:         The html link to the resource. Generates a random writable directory for generators to build instances with.     All directories generated will be removed in the call to clear_build_directories()      Args:         base: base path to create the directory. defaults to the current working directory.     Returns:         The path to the directory Removes everything in the generated build directories. Replace tokens in a file and write out the substitution.      Args:         file_path: the path of the file to be read.         lookup: a dictionary containing the substitutions.         out_path: file in which the substitutions will be written.