Repository: conan-io/conan
Pull request: fixing version ranges with spaces
Changelog: Bugfix: Fix version ranges containing spaces and not separated by commas.
Docs: Omit

Close #4270


I think it doesn't make sense to replace whitespace in the middle of a <ref>. That should be an error, not "magically" fixed.

Problem statement:
conan install unexpectedly reports invalid version range
i have this requirement in my `conanfile.py`:
`foo/[>16.5.0 <17.0.0]@bar/stable`

`conan install` aborts with this error:
`ERROR: version range expression '>16.5.0<17.0.0' is not valid`

note: using the deprecated comma-based syntax works fine

* Python 3.6 on CentOS 7.5
* Conan 1.11.2
* node-semver 0.6.1

Hints from issue discussion:
Reproduced, indeed an undesired bug. Thanks for reporting @mistafunk !

Commit message: simplified testing

Patch to review:
diff --git a/conans/model/ref.py b/conans/model/ref.py
index 560534eade0..984bb0e3d98 100644
--- a/conans/model/ref.py
+++ b/conans/model/ref.py
@@ -78,7 +78,6 @@ class ConanFileReference(namedtuple("ConanFileReference", "name version user cha
     """ Full reference of a package recipes, e.g.:
     opencv/2.4.10@lasote/testing
     """
-    whitespace_pattern = re.compile(r"\s+")
     sep_pattern = re.compile(r"([^/]+)/([^/]+)@([^/]+)/([^/#]+)#?(.+)?")
 
     def __new__(cls, name, version, user, channel, revision=None, validate=True):
@@ -107,7 +106,6 @@ def _validate(self):
     def loads(text, validate=True):
         """ Parses a text string to generate a ConanFileReference object
         """
-        text = ConanFileReference.whitespace_pattern.sub("", text)
         try:
             # Split returns empty start and end groups
             _, name, version, user, channel, revision, _ = ConanFileReference.sep_pattern.split(text)
diff --git a/conans/test/functional/old/paths_test.py b/conans/test/functional/old/paths_test.py
index 6fe72b0e7ee..5c79530e7f7 100644
--- a/conans/test/functional/old/paths_test.py
+++ b/conans/test/functional/old/paths_test.py
@@ -32,7 +32,7 @@ def basic_test(self):
         folder = temp_folder()
         paths = SimplePaths(folder)
         self.assertEqual(paths._store_folder, folder)
-        conan_ref = ConanFileReference.loads("opencv/2.4.10 @ lasote /testing")
+        conan_ref = ConanFileReference.loads("opencv/2.4.10@lasote/testing")
         package_ref = PackageReference(conan_ref, "456fa678eae68")
         expected_base = os.path.join(folder, os.path.sep.join(["opencv", "2.4.10",
                                                                "lasote", "testing"]))
@@ -84,4 +84,3 @@ def test_with_env_variable(self, _, short_paths):
 
             self.assertEqual(self.home_short in r, short_paths)
             self.assertEqual(self.home in r, not short_paths)
-
diff --git a/conans/test/unittests/model/ref_test.py b/conans/test/unittests/model/ref_test.py
index 0497334ec87..929e55d796b 100644
--- a/conans/test/unittests/model/ref_test.py
+++ b/conans/test/unittests/model/ref_test.py
@@ -7,7 +7,7 @@
 
 class RefTest(unittest.TestCase):
     def basic_test(self):
-        ref = ConanFileReference.loads("opencv/2.4.10 @ lasote/testing")
+        ref = ConanFileReference.loads("opencv/2.4.10@lasote/testing")
         self.assertEqual(ref.name, "opencv")
         self.assertEqual(ref.version, "2.4.10")
         self.assertEqual(ref.user, "lasote")
@@ -37,7 +37,7 @@ def basic_test(self):
     def errors_test(self):
         self.assertRaises(ConanException, ConanFileReference.loads, "")
         self.assertRaises(ConanException, ConanFileReference.loads, "opencv/2.4.10")
-        self.assertRaises(ConanException, ConanFileReference.loads, "opencv/2.4.10 @ lasote")
+        self.assertRaises(ConanException, ConanFileReference.loads, "opencv/2.4.10@lasote")
         self.assertRaises(ConanException, ConanFileReference.loads, "opencv??/2.4.10@laso/testing")
         self.assertRaises(ConanException, ConanFileReference.loads, ".opencv/2.4.10@lasote/testing")
         self.assertRaises(ConanException, ConanFileReference.loads, "o/2.4.10 @ lasote/testing")
diff --git a/conans/test/unittests/model/version_ranges_test.py b/conans/test/unittests/model/version_ranges_test.py
index 6790896b78f..9917d68a3e7 100644
--- a/conans/test/unittests/model/version_ranges_test.py
+++ b/conans/test/unittests/model/version_ranges_test.py
@@ -287,8 +287,10 @@ class HelloConan(ConanFile):
                            # ranges
                            ('"Say/[<=1.2]@myuser/testing"', "1.2.1", False, False),
                            ('"Say/[>=0.2,<=1.0]@myuser/testing"', "0.3", False, True),
+                           ('"Say/[>=0.2 <=1.0]@myuser/testing"', "0.3", False, True),
                            ('("Say/[<=1.2]@myuser/testing", "override")', "1.2.1", True, False),
                            ('("Say/[>=0.2,<=1.0]@myuser/testing", "override")', "0.3", True, True),
+                           ('("Say/[>=0.2 <=1.0]@myuser/testing", "override")', "0.3", True, True),
                            ])
     def transitive_test(self, version_range, solution, override, valid):
         hello_text = hello_content % ">0.1, <1"


Code review comments:
diff_hunk: @@ -37,7 +37,7 @@ def basic_test(self):
     def errors_test(self):
         self.assertRaises(ConanException, ConanFileReference.loads, "")
         self.assertRaises(ConanException, ConanFileReference.loads, "opencv/2.4.10")
-        self.assertRaises(ConanException, ConanFileReference.loads, "opencv/2.4.10 @ lasote")
+        self.assertRaises(ConanException, ConanFileReference.loads, "opencv/2.4.10@lasote")
         self.assertRaises(ConanException, ConanFileReference.loads, "opencv??/2.4.10@laso/testing")
         self.assertRaises(ConanException, ConanFileReference.loads, ".opencv/2.4.10@lasote/testing")
         self.assertRaises(ConanException, ConanFileReference.loads, "o/2.4.10 @ lasote/testing")
path: conans/test/unittests/model/ref_test.py
text: @user2:
Change this test to:

```
"o/2.4.10@user1/testing"
```

it should fail because the `name` is too short, not because of the spaces