Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 'infinite' value cannot pass to R script #2476

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- series-7
pull_request:
branches_ignore: []
jobs:
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,23 @@
# Changelog


## [7.32.4](https://github.com/snakemake/snakemake/compare/v7.32.3...v7.32.4) (2023-08-18)


### Bug Fixes

* always sort report (sub-)categories in lexicographical order
* also inherit rule proxies if there is no rulename modifier specified in a use rule statement
* ensure that targetjob is always forced. This fixes a bug causing run-directive rules to not being executed even when enforced via e.g. -R.


## [7.32.3](https://github.com/snakemake/snakemake/compare/v7.32.2...v7.32.3) (2023-08-07)


### Bug Fixes

* fix bug occuring when using multiple `use rule` statements in combination with the rules object for referring to output of already defined rules.

## [7.32.2](https://github.com/snakemake/snakemake/compare/v7.32.1...v7.32.2) (2023-08-07)


Expand Down
5 changes: 4 additions & 1 deletion snakemake/common/__init__.py
Expand Up @@ -264,7 +264,10 @@ def __getattr__(self, name):
try:
return self._rules[name]
except KeyError:
raise WorkflowError(f"Rule {name} is not defined in this workflow.")
raise WorkflowError(
f"Rule {name} is not defined in this workflow. "
f"Available rules: {', '.join(self._rules)}"
)


class Scatter:
Expand Down
1 change: 1 addition & 0 deletions snakemake/dag.py
Expand Up @@ -236,6 +236,7 @@ def init(self, progress=False):
create_inventory=True,
)
self.targetjobs.add(job)
self.forcefiles.update(job.output)

self.cleanup()

Expand Down
17 changes: 10 additions & 7 deletions snakemake/modules.py
Expand Up @@ -52,6 +52,7 @@ def __init__(
self.config = config
self.skip_validation = skip_validation
self.parent_modifier = self.workflow.modifier
self.rule_proxies = Rules()

if prefix is not None:
if isinstance(prefix, Path):
Expand Down Expand Up @@ -97,6 +98,7 @@ def use_rules(
replace_prefix=self.replace_prefix,
prefix=self.prefix,
replace_wrapper_tag=self.get_wrapper_tag(),
rule_proxies=self.rule_proxies,
)
with modifier:
self.workflow.include(snakefile, overwrite_default_target=True)
Expand Down Expand Up @@ -155,6 +157,7 @@ def __init__(
prefix=None,
replace_wrapper_tag=None,
namespace=None,
rule_proxies=None,
):
if parent_modifier is not None:
# init with values from parent modifier
Expand All @@ -174,21 +177,22 @@ def __init__(
self.namespace = parent_modifier.namespace
self.wildcard_constraints = parent_modifier.wildcard_constraints
self.rules = parent_modifier.rules
self.rule_proxies = parent_modifier.rule_proxies
else:
# default settings for globals if not inheriting from parent
self.globals = (
globals if globals is not None else dict(workflow.vanilla_globals)
)
self.wildcard_constraints = dict()
self.rules = set()
self.rule_proxies = rule_proxies or Rules()
self.globals["rules"] = self.rule_proxies

self.workflow = workflow
self.base_snakefile = base_snakefile
self.rule_proxies = Rules()

if config is not None:
self.globals["config"] = config
self.globals["rules"] = self.rule_proxies

self.skip_configfile = skip_configfile
self.resolved_rulename_modifier = resolved_rulename_modifier
Expand All @@ -204,11 +208,10 @@ def __init__(
self.namespace = namespace

def inherit_rule_proxies(self, child_modifier):
if child_modifier.local_rulename_modifier is not None:
for name, rule in child_modifier.rule_proxies._rules.items():
self.rule_proxies._register_rule(
child_modifier.local_rulename_modifier(name), rule
)
for name, rule in child_modifier.rule_proxies._rules.items():
if child_modifier.local_rulename_modifier is not None:
name = child_modifier.local_rulename_modifier(name)
self.rule_proxies._register_rule(name, rule)

def skip_rule(self, rulename):
return (
Expand Down
1 change: 0 additions & 1 deletion snakemake/report/template/components/abstract_menu.js
Expand Up @@ -9,7 +9,6 @@ class AbstractMenu extends React.Component {
}

getMenuItem(label, iconName, onClick) {
console.log(label, onClick);
return e(
"li",
{ key: label },
Expand Down
3 changes: 0 additions & 3 deletions snakemake/report/template/components/abstract_results.js
Expand Up @@ -40,9 +40,7 @@ class AbstractResults extends React.Component {

getLabels() {
let first_index = {};
console.log(this.getResults());
this.getResults().map(function ([path, result]) {
console.log(path, result);
let i = 0;
for (let key in result.labels) {
if (!(key in first_index)) {
Expand All @@ -56,7 +54,6 @@ class AbstractResults extends React.Component {
return labels.sort(function (a, b) {
return first_index[a] - first_index[b];
});
//return Array.from(new Set(this.getResults().map(function ([path, result]) { return Object.keys(result.labels) }).flat())).sort();
}

isLabelled() {
Expand Down
3 changes: 2 additions & 1 deletion snakemake/report/template/components/category.js
Expand Up @@ -15,8 +15,9 @@ class Category extends AbstractMenu {

getSubcategoryMenuitems() {
let _this = this
return Object.keys(categories[this.props.category]).map(function (subcategory) {
let items = Object.keys(categories[this.props.category]).sort().map(function (subcategory) {
return _this.getMenuItem(subcategory, "folder", () => _this.showSubcategory(subcategory));
});
return items;
}
}
1 change: 0 additions & 1 deletion snakemake/report/template/components/common.js
Expand Up @@ -13,6 +13,5 @@ function isSingleDefaultCategory() {
}

function isSingleSubcategory(category) {
console.log(categories, category);
return Object.keys(categories[category]).length == 1;
}
2 changes: 1 addition & 1 deletion snakemake/report/template/components/menu.js
Expand Up @@ -52,7 +52,7 @@ class Menu extends AbstractMenu {
{ key: "Results", text: "Result" }
)];

items.push(...Object.keys(categories).map(function (category) {
items.push(...Object.keys(categories).sort().map(function (category) {
return _this.getMenuItem(category, "folder", () => app.showCategory(category));
}));

Expand Down
4 changes: 4 additions & 0 deletions snakemake/script.py
Expand Up @@ -181,6 +181,10 @@ def encode_numeric(cls, value):
def encode_value(cls, value):
if value is None:
return "NULL"
elif value == float("inf"):
return "Inf"
elif value == - float("inf"):
return "-Inf"
elif isinstance(value, str):
return repr(value)
elif isinstance(value, Path):
Expand Down
7 changes: 7 additions & 0 deletions tests/test_inf_to_R_script_issue2475/Snakefile
@@ -0,0 +1,7 @@
configfile: "config.yaml"

rule all:
output: "final.rst"
params:
threshold = [-float("inf"), float("inf")]
script: "test.R"
3 changes: 3 additions & 0 deletions tests/test_inf_to_R_script_issue2475/config.yaml
@@ -0,0 +1,3 @@
threshold:
- -.inf
- .inf
@@ -0,0 +1,2 @@
The type: numeric.
The value: -Inf, Inf.
16 changes: 16 additions & 0 deletions tests/test_inf_to_R_script_issue2475/test.R
@@ -0,0 +1,16 @@
#! /opt/conda/envs/dev/bin/R

run <- function (output, threshold){
log <- c(
paste("The type: ", class(threshold[1]), ".", sep = ""),
paste("The value: ", paste(threshold, collapse = ', '), ".", sep = "")
)
conn <- file(output, "w")
writeLines(log, conn)
close(conn)
}

run(
snakemake@output[[1]],
snakemake@params[["threshold"]]
)