예제 #1
0
def Rmarkdown(script=None,
              input=None,
              output=None,
              args='{input:r}, output_file={output:ar}',
              **kwargs):
    '''Convert input file to output using Rmarkdown

    The input can be specified in three ways:

    1. instant script, which is assumed to be in md format

    Rmarkdown:   output='report.html'
      script

    2. one or more input files. The format is determined by extension of input file

    Rmarkdown(input, output='report.html')

    3. input file specified by command line option `-r` .
    Rmarkdown(output='report.html')

    If no output is specified, it is assumed to be in html format
    and is written to standard output.

    You can specify more options using the args parameter of the action. The default value
    of args is `${input!r} --output ${output!ar}'
    '''
    if not R_library('rmarkdown').target_exists():
        raise RuntimeError('Library rmarkdown does not exist')

    input = sos_targets(collect_input(script, input))

    output = sos_targets(output)
    if len(output) == 0:
        write_to_stdout = True
        output = sos_targets(
            tempfile.NamedTemporaryFile(mode='w+t',
                                        suffix='.html',
                                        delete=False).name)
    else:
        write_to_stdout = False
    #
    ret = 1
    try:
        #   render(input, output_format = NULL, output_file = NULL, output_dir = NULL,
        #        output_options = NULL, intermediates_dir = NULL,
        #        runtime = c("auto", "static", "shiny"),
        #        clean = TRUE, params = NULL, knit_meta = NULL, envir = parent.frame(),
        #        run_Rmarkdown = TRUE, quiet = FALSE, encoding = getOption("encoding"))
        cmd = interpolate(f'Rscript -e "rmarkdown::render({args})"', {
            'input': input,
            'output': output
        })
        env.logger.trace(f'Running command "{cmd}"')
        if env.config['run_mode'] == 'interactive':
            # need to catch output and send to python output, which will in trun be hijacked by SoS notebook
            p = subprocess.Popen(cmd,
                                 shell=True,
                                 stderr=subprocess.PIPE,
                                 stdout=subprocess.PIPE)
            #pid = p.pid
            out, err = p.communicate()
            sys.stdout.write(out.decode())
            sys.stderr.write(err.decode())
            ret = p.returncode
        else:
            p = subprocess.Popen(cmd, shell=True)
            #pid = p.pid
            ret = p.wait()
    except Exception as e:
        env.logger.error(e)
    if ret != 0:
        temp_file = os.path.join('.sos', f'{"Rmarkdown"}_{os.getpid()}.md')
        shutil.copyfile(str(input), temp_file)
        cmd = interpolate(f'Rscript -e "rmarkdown::render({args})"', {
            'input': input,
            'output': sos_targets(temp_file)
        })
        raise RuntimeError(
            f'Failed to execute script. Please use command \n"{cmd}"\nunder {os.getcwd()} to test it.'
        )
    if write_to_stdout:
        with open(str(output[0])) as out:
            sys.stdout.write(out.read())
    else:
        env.logger.info(f'Report saved to {output}')
예제 #2
0
파일: actions.py 프로젝트: BoPeng/SOS
def Rmarkdown(script=None, input=None, output=None, args="${input!r}, output_file=${output!ar}", **kwargs):
    """Convert input file to output using Rmarkdown

    The input can be specified in three ways:
    
    1. instant script, which is assumed to be in md format

    Rmarkdown:   output='report.html'
      script

    2. one or more input files. The format is determined by extension of input file

    Rmarkdown(input, output='report.html')

    3. input file specified by command line option `-r` .
    Rmarkdown(output='report.html')

    If no output is specified, it is assumed to be in html format
    and is written to standard output.
    
    You can specify more options using the args parameter of the action. The default value
    of args is `${input!r} --output ${output!ar}'
    """
    if not R_library("rmarkdown").exists():
        raise UnknownTarget(R_library("rmarkdown"))

    input_file = collect_input(script, input)

    write_to_stdout = False
    if output is None:
        write_to_stdout = True
        output_file = tempfile.NamedTemporaryFile(mode="w+t", suffix=".html", delete=False).name
    elif isinstance(output, str):
        output_file = output
    else:
        raise RuntimeError("A filename is expected, {} provided".format(output))
    #
    ret = 1
    try:
        #   render(input, output_format = NULL, output_file = NULL, output_dir = NULL,
        #        output_options = NULL, intermediates_dir = NULL,
        #        runtime = c("auto", "static", "shiny"),
        #        clean = TRUE, params = NULL, knit_meta = NULL, envir = parent.frame(),
        #        run_Rmarkdown = TRUE, quiet = FALSE, encoding = getOption("encoding"))
        cmd = interpolate(
            'Rscript -e "rmarkdown::render({})"'.format(args), "${ }", {"input": input_file, "output": output_file}
        )
        env.logger.trace('Running command "{}"'.format(cmd))
        if env.run_mode == "interactive":
            # need to catch output and send to python output, which will in trun be hijacked by SoS notebook
            p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
            pid = p.pid
            env.register_process(p.pid, "Runing {}".format(input_file))
            out, err = p.communicate()
            sys.stdout.write(out.decode())
            sys.stderr.write(err.decode())
            ret = p.returncode
        else:
            p = subprocess.Popen(cmd, shell=True)
            pid = p.pid
            env.register_process(pid, "Runing {}".format(input_file))
            ret = p.wait()
    except Exception as e:
        env.logger.error(e)
    finally:
        env.deregister_process(p.pid)
    if ret != 0:
        temp_file = os.path.join(".sos", "{}_{}.md".format("Rmarkdown", os.getpid()))
        shutil.copyfile(input_file, temp_file)
        cmd = interpolate(
            'Rscript -e "rmarkdown::render({})"'.format(args), "${ }", {"input": input_file, "output": output_file}
        )
        raise RuntimeError(
            'Failed to execute script. Please use command \n"{}"\nunder {} to test it.'.format(cmd, os.getcwd())
        )
    if write_to_stdout:
        with open(output_file) as out:
            sys.stdout.write(out.read())
    else:
        env.logger.info("Report saved to {}".format(output_file))