Repository: nf-core/tools

Issue:
json-schema: No such thing as a range type
Thanks to @jfy133, I read through the [json-schema specs for ranges](https://json-schema.org/understanding-json-schema/reference/numeric.html#range) again  and it turns out what we treat as `range` types are just `number` types with a `minimum/maximum` property... 🤯 

So we have to fix that in the following files:
- tools repo:
  - [x] `launch.py`
  - [x] `test_launch.py`
- nf-co.re repo:
  - [x] `launch.php`
  - [x] `pipeline_schema_builder.php`
  - [x] `nf-core-schema-builder.js`


Discussion:

Resolving patch:
diff --git a/nf_core/launch.py b/nf_core/launch.py
--- a/nf_core/launch.py
+++ b/nf_core/launch.py
@@ -531,7 +531,11 @@ def validate_number(val):
                 try:
                     if val.strip() == "":
                         return True
-                    float(val)
+                    fval = float(val)
+                    if "minimum" in param_obj and fval < float(param_obj["minimum"]):
+                        return "Must be greater than or equal to {}".format(param_obj["minimum"])
+                    if "maximum" in param_obj and fval > float(param_obj["maximum"]):
+                        return "Must be less than or equal to {}".format(param_obj["maximum"])
                 except ValueError:
                     return "Must be a number"
                 else:
@@ -569,31 +573,6 @@ def filter_integer(val):
 
             question["filter"] = filter_integer
 
-        if param_obj.get("type") == "range":
-            # Validate range type
-            def validate_range(val):
-                try:
-                    if val.strip() == "":
-                        return True
-                    fval = float(val)
-                    if "minimum" in param_obj and fval < float(param_obj["minimum"]):
-                        return "Must be greater than or equal to {}".format(param_obj["minimum"])
-                    if "maximum" in param_obj and fval > float(param_obj["maximum"]):
-                        return "Must be less than or equal to {}".format(param_obj["maximum"])
-                    return True
-                except ValueError:
-                    return "Must be a number"
-
-            question["validate"] = validate_range
-
-            # Filter returned value
-            def filter_range(val):
-                if val.strip() == "":
-                    return ""
-                return float(val)
-
-            question["filter"] = filter_range
-
         if "enum" in param_obj:
             # Use a selection list instead of free text input
             question["type"] = "list"
diff --git a/nf_core/schema.py b/nf_core/schema.py
--- a/nf_core/schema.py
+++ b/nf_core/schema.py
@@ -424,7 +424,7 @@ def prompt_remove_schema_notfound_config(self, p_key):
             if self.no_prompts or self.schema_from_scratch:
                 return True
             if Confirm.ask(
-                ":question: Unrecognised [white bold]'params.{}'[/] found in schema but not pipeline! [yellow]Remove it?".format(
+                ":question: Unrecognised [white bold]'params.{}'[/] found in the schema but not in the pipeline config! [yellow]Remove it?".format(
                     p_key
                 )
             ):
@@ -443,7 +443,7 @@ def add_schema_found_configs(self):
                     self.no_prompts
                     or self.schema_from_scratch
                     or Confirm.ask(
-                        ":sparkles: Found [white bold]'params.{}'[/] in pipeline but not in schema. [blue]Add to pipeline schema?".format(
+                        ":sparkles: Found [white bold]'params.{}'[/] in the pipeline config, but not in the schema. [blue]Add to pipeline schema?".format(
                             p_key
                         )
                     )


Test patch:
diff --git a/tests/test_launch.py b/tests/test_launch.py
--- a/tests/test_launch.py
+++ b/tests/test_launch.py
@@ -248,7 +248,7 @@ def test_ob_to_questionary_integer(self):
 
     def test_ob_to_questionary_range(self):
         """ Check converting a python dict to a pyenquirer format - with enum """
-        sc_obj = {"type": "range", "minimum": "10", "maximum": "20", "default": 15}
+        sc_obj = {"type": "number", "minimum": "10", "maximum": "20", "default": 15}
         result = self.launcher.single_param_to_questionary("broad_cutoff", sc_obj)
         assert result["type"] == "input"
         assert result["default"] == "15"