def make_output(rule, prefix="s1"): """Generate output file for rule. Assume target is based on prefix 's1'; else, use rules2targets dictionary""" rn = os.path.basename(rule).replace(".rule", "") app = os.path.basename(os.path.dirname(rule)) target = rules2targets.get(app, {}).get(rn, None) if target: return target code, linemake, rulecount = parse(rule) m = re.search("@workflow.output\(\s+(?P<output>.*)", code) if m is None: # return input case m = re.search("@workflow.input\(\s+(?P<input>.*)", code) output = m.group("input") else: output = m.group("output") m = re.search( "\"[ ]*(?P<prefix>\{[a-zA-Z_0-9]+\})+(?P<ext>[_\/\.a-zA-Z0-9 ]+)\"", output) # Regular extension; use first one if m: return "{prefix}{ext}".format(prefix=prefix, ext=m.group("ext")) # expand case; skip for now m = re.search("expand", output) if m: return None # Config case m = re.search("[a-zA-Z =]*(?P<config>config[^\)]+)", output) if m: return "config" return None
def get_rule_names(snakefile_name): """ Run snakemake.parser.parse and use regexp to get the rule names This is incredibly inefficient, but a little more stable than trying to parse rules myself. """ for line in parse(snakefile_name)[0].split("\n"): m = rule_rexp.match(line) if m: yield m.group(1)
def include( self, snakefile, overwrite_first_rule=False, print_compilation=False, overwrite_shellcmd=None, ): """ Include a snakefile. """ # check if snakefile is a path to the filesystem if not urllib.parse.urlparse(snakefile).scheme: if not os.path.isabs(snakefile) and self.included_stack: snakefile = os.path.join(self.current_basedir, snakefile) # Could still be an url if relative import was used if not urllib.parse.urlparse(snakefile).scheme: snakefile = os.path.abspath(snakefile) # else it could be an url. # at least we don't want to modify the path for clarity. if snakefile in self.included: logger.info("Multiple include of {} ignored".format(snakefile)) return self.included.append(snakefile) self.included_stack.append(snakefile) global workflow workflow = self first_rule = self.first_rule code, linemap, rulecount = parse( snakefile, overwrite_shellcmd=self.overwrite_shellcmd, rulecount=self._rulecount, ) self._rulecount = rulecount if print_compilation: print(code) # insert the current directory into sys.path # this allows to import modules from the workflow directory sys.path.insert(0, os.path.dirname(snakefile)) self.linemaps[snakefile] = linemap exec(compile(code, snakefile, "exec"), self.globals) if not overwrite_first_rule: self.first_rule = first_rule self.included_stack.pop()
def include(self, snakefile, overwrite_first_rule=False, print_compilation=False, overwrite_shellcmd=None): """ Include a snakefile. """ # check if snakefile is a path to the filesystem if not urllib.parse.urlparse(snakefile).scheme: if not os.path.isabs(snakefile) and self.included_stack: current_path = os.path.dirname(self.included_stack[-1]) snakefile = os.path.join(current_path, snakefile) # Could still be an url if relative import was used if not urllib.parse.urlparse(snakefile).scheme: snakefile = os.path.abspath(snakefile) # else it could be an url. # at least we don't want to modify the path for clarity. if snakefile in self.included: logger.info("Multiple include of {} ignored".format(snakefile)) return self.included.append(snakefile) self.included_stack.append(snakefile) global workflow workflow = self first_rule = self.first_rule code, linemap, rulecount = parse(snakefile, overwrite_shellcmd=self.overwrite_shellcmd, rulecount=self._rulecount) self._rulecount = rulecount if print_compilation: print(code) # insert the current directory into sys.path # this allows to import modules from the workflow directory sys.path.insert(0, os.path.dirname(snakefile)) self.linemaps[snakefile] = linemap exec(compile(code, snakefile, "exec"), self.globals) if not overwrite_first_rule: self.first_rule = first_rule self.included_stack.pop()
def include(self, snakefile, workdir=None, overwrite_first_rule=False, print_compilation=False): """ Include a snakefile. """ global workflow workflow = self first_rule = self.first_rule if workdir: os.chdir(workdir) code, linemap = parse(snakefile) if print_compilation: print(code) self.linemaps[snakefile] = linemap exec(compile(code, snakefile, "exec"), self.globals) if not overwrite_first_rule: self.first_rule = first_rule
def make_output(rule, prefix="s1"): rn = os.path.basename(rule).replace(".rule", "") app = os.path.basename(os.path.dirname(rule)) target = rules2targets.get(app, {}).get(rn, None) if target: return target code, linemake, rulecount = parse(rule) m = re.search("@workflow.output\(\s+(?P<output>.*)", code) output = m.group("output") m = re.search("\"[ ]*(?P<prefix>\{[a-zA-Z_0-9]+\})+(?P<ext>[_\/\.a-zA-Z0-9 ]+)\"", output) # Regular extension; use first one if m: return "{prefix}{ext}".format(prefix=prefix, ext=m.group("ext")) # expand case; skip for now m = re.search("expand", output) if m: return None # Config case m = re.search("[a-zA-Z =]*(?P<config>config[^\)]+)", output) if m: return "config" return None
def parse_rule(rule, prefix=None): """Generate information for rule stored in a dictionary. Params: rule (str): file containing a snakemake rule Results: input (list): list of input files output (list): list of output targets """ d = {} codemap = { 'rule': "", 'input': "", 'output': "", 'wildcard_constraints': "" } rn = os.path.basename(rule).replace(".rule", "") app = os.path.basename(os.path.dirname(rule)) code, linemake, rulecount = parse(rule) l = regex_workflow.findall(code) for k, v in l: codemap[k] = re.sub("[\t\n ]", "", v) m_name = regex_name.search(codemap['rule']) d['name'] = m_name.group("name") d['output'] = get_targets(codemap["output"]) d['input'] = get_targets(codemap["input"]) d['wildcard_constraints'] = { k: v for k, v in regex_wildcard_constraints.findall( codemap["wildcard_constraints"]) } if d['wildcard_constraints'] == '': d['wildcard_constraints'] = {} # Output missing; return input case if possible return d
def _cli(): ######################################################################## # First install snakemake module parser = argparse.ArgumentParser( description="Converts *.smk file to *.py using snakemake parser", formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument("input", metavar="INPUT", help="Snakemake file (or *.smk file)") parser.add_argument("output", metavar="OUTPUT", help="Result python file") args = parser.parse_args() input_path = args.input output_path = args.output ######################################################################## compilation, _linemap, rc = smp.parse(input_path) with open(output_path, mode="w") as out: print(compilation, file=out) print("Done, rules:", str(rc)) print("Saved to :", output_path)