We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Scope variables do not accept a value containing a ':'
Hi,
I modified the Boost package recipe so that I can specify an alternate url for downloading the source zip file. I used a scope variable for this purpose. However it seems that conan does not allow scope variables to contain a ':'.

When issuing this command:
conan install Boost/1.61.0@epr-eliaskousk/stable --build -s os=Windows -s arch=x86_64 -s compiler="Visual Studio" -s compiler.version=14 -s compiler.runtime=MDd -s build_type=Debug -sc ALL:source_url=http://sourceforge.net/projects/boost/files/boost

Here is the error message I get:
ERROR: Bad scope ALL:source_url=http://sourceforge.net/projects/boost/files/boost

I suppose there is an issue because the parsing treats the ':' as a special separator?...

Would it be possible to fix this or is it supposed to be like that?
(I can workaround the issue by replacing the character ':' in my string value by yet-another special character)

thanks


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `conans/model/scope.py`
Content:
```
1 from collections import defaultdict
2 from conans.errors import ConanException
3 
4 
5 class Scope(dict):
6     """ the set of possible scopes than a package can have, by name(string):
7     "dev", "test", "myscope"...
8     it is just a set, but with syntax to be queried as:
9        if self.scope.dev:
10     """
11 
12     def __getattr__(self, field):
13         return self.get(field)
14 
15     def __setattr__(self, field, value):
16         self[field] = value
17 
18     def __repr__(self):
19         return ", ".join("%s=%s" % (k, v) for k, v in sorted(self.items()))
20 
21 
22 # This is necessary, as None cannot be ordered in Py3
23 _root = "0CONAN_ROOT*"
24 _all = "ALL"
25 
26 
27 class Scopes(defaultdict):
28     """ all the scopes of a dependency graph, as a dict{package name(str): Scope
29     the root package of the graph might not have name, then its key is None.
30     It is loaded and saved to text as:
31         Package1:dev
32         Package1:test
33         Package2:dev
34         dev  # for the root package, without name
35         other # any name allowed
36     This will be stored in memory as {Package1: Scopes(set[dev, test]),
37                                       Package2: Scopes(...),
38                                       None: Scopes(set[dev, other])
39     """
40     def __init__(self):
41         super(Scopes, self).__init__(Scope)
42         self[_root].dev = True
43 
44     def package_scope(self, name=None):
45         """ return the scopes for the given package which are the scopes set
46         for ALL, updated (high priority) with the specific package scopes
47         if the package name is None, then it is the ROOT package/consumer
48         """
49         scope = Scope(self.get(_all, {}))
50         scope.update(self[name or _root])
51         return scope
52 
53     @staticmethod
54     def from_list(items):
55         result = Scopes()
56         for item in items:
57             chunks = item.split(":")
58             if len(chunks) == 2:
59                 root = chunks[0]
60                 scope = chunks[1]
61             elif len(chunks) == 1:
62                 root = _root
63                 scope = chunks[0]
64             else:
65                 raise ConanException("Bad scope %s" % item)
66             try:
67                 key, value = scope.split("=")
68             except:
69                 raise ConanException("Bad scope %s" % item)
70             v = value.upper()
71             if v == "TRUE":
72                 value = True
73             elif v == "FALSE":
74                 value = False
75             elif v == "NONE":
76                 value = None
77             result[root][key] = value
78         return result
79 
80     def update_scope(self, other):
81         for name, scopes in other.items():
82             self[name].update(scopes)
83 
84     @staticmethod
85     def loads(text):
86         return Scopes.from_list([s.strip() for s in text.splitlines()])
87 
88     def dumps(self):
89         result = []
90         for name, scopes in sorted(self.items()):
91             if name != _root:
92                 result.extend("%s:%s=%s" % (name, k, v) for (k, v) in sorted(scopes.items()))
93             else:
94                 result.extend("%s=%s" % (k, v) for (k, v) in sorted(scopes.items()))
95         return "\n".join(result)
96
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/conans/model/scope.py b/conans/model/scope.py
--- a/conans/model/scope.py
+++ b/conans/model/scope.py
@@ -54,17 +54,8 @@
     def from_list(items):
         result = Scopes()
         for item in items:
-            chunks = item.split(":")
-            if len(chunks) == 2:
-                root = chunks[0]
-                scope = chunks[1]
-            elif len(chunks) == 1:
-                root = _root
-                scope = chunks[0]
-            else:
-                raise ConanException("Bad scope %s" % item)
             try:
-                key, value = scope.split("=")
+                key, value = item.split("=")
             except:
                 raise ConanException("Bad scope %s" % item)
             v = value.upper()
@@ -74,7 +65,18 @@
                 value = False
             elif v == "NONE":
                 value = None
-            result[root][key] = value
+
+            chunks = key.split(":")
+            if len(chunks) == 2:
+                root = chunks[0]
+                scope = chunks[1]
+            elif len(chunks) == 1:
+                root = _root
+                scope = chunks[0]
+            else:
+                raise ConanException("Bad scope %s" % item)
+
+            result[root][scope] = value
         return result
 
     def update_scope(self, other):

{"golden_diff": "diff --git a/conans/model/scope.py b/conans/model/scope.py\n--- a/conans/model/scope.py\n+++ b/conans/model/scope.py\n@@ -54,17 +54,8 @@\n     def from_list(items):\n         result = Scopes()\n         for item in items:\n-            chunks = item.split(\":\")\n-            if len(chunks) == 2:\n-                root = chunks[0]\n-                scope = chunks[1]\n-            elif len(chunks) == 1:\n-                root = _root\n-                scope = chunks[0]\n-            else:\n-                raise ConanException(\"Bad scope %s\" % item)\n             try:\n-                key, value = scope.split(\"=\")\n+                key, value = item.split(\"=\")\n             except:\n                 raise ConanException(\"Bad scope %s\" % item)\n             v = value.upper()\n@@ -74,7 +65,18 @@\n                 value = False\n             elif v == \"NONE\":\n                 value = None\n-            result[root][key] = value\n+\n+            chunks = key.split(\":\")\n+            if len(chunks) == 2:\n+                root = chunks[0]\n+                scope = chunks[1]\n+            elif len(chunks) == 1:\n+                root = _root\n+                scope = chunks[0]\n+            else:\n+                raise ConanException(\"Bad scope %s\" % item)\n+\n+            result[root][scope] = value\n         return result\n \n     def update_scope(self, other):\n", "issue": "Scope variables do not accept a value containing a ':'\nHi,\nI modified the Boost package recipe so that I can specify an alternate url for downloading the source zip file. I used a scope variable for this purpose. However it seems that conan does not allow scope variables to contain a ':'.\n\nWhen issuing this command:\nconan install Boost/1.61.0@epr-eliaskousk/stable --build -s os=Windows -s arch=x86_64 -s compiler=\"Visual Studio\" -s compiler.version=14 -s compiler.runtime=MDd -s build_type=Debug -sc ALL:source_url=http://sourceforge.net/projects/boost/files/boost\n\nHere is the error message I get:\nERROR: Bad scope ALL:source_url=http://sourceforge.net/projects/boost/files/boost\n\nI suppose there is an issue because the parsing treats the ':' as a special separator?...\n\nWould it be possible to fix this or is it supposed to be like that?\n(I can workaround the issue by replacing the character ':' in my string value by yet-another special character)\n\nthanks\n\n", "before_files": [{"content": "from collections import defaultdict\nfrom conans.errors import ConanException\n\n\nclass Scope(dict):\n    \"\"\" the set of possible scopes than a package can have, by name(string):\n    \"dev\", \"test\", \"myscope\"...\n    it is just a set, but with syntax to be queried as:\n       if self.scope.dev:\n    \"\"\"\n\n    def __getattr__(self, field):\n        return self.get(field)\n\n    def __setattr__(self, field, value):\n        self[field] = value\n\n    def __repr__(self):\n        return \", \".join(\"%s=%s\" % (k, v) for k, v in sorted(self.items()))\n\n\n# This is necessary, as None cannot be ordered in Py3\n_root = \"0CONAN_ROOT*\"\n_all = \"ALL\"\n\n\nclass Scopes(defaultdict):\n    \"\"\" all the scopes of a dependency graph, as a dict{package name(str): Scope\n    the root package of the graph might not have name, then its key is None.\n    It is loaded and saved to text as:\n        Package1:dev\n        Package1:test\n        Package2:dev\n        dev  # for the root package, without name\n        other # any name allowed\n    This will be stored in memory as {Package1: Scopes(set[dev, test]),\n                                      Package2: Scopes(...),\n                                      None: Scopes(set[dev, other])\n    \"\"\"\n    def __init__(self):\n        super(Scopes, self).__init__(Scope)\n        self[_root].dev = True\n\n    def package_scope(self, name=None):\n        \"\"\" return the scopes for the given package which are the scopes set\n        for ALL, updated (high priority) with the specific package scopes\n        if the package name is None, then it is the ROOT package/consumer\n        \"\"\"\n        scope = Scope(self.get(_all, {}))\n        scope.update(self[name or _root])\n        return scope\n\n    @staticmethod\n    def from_list(items):\n        result = Scopes()\n        for item in items:\n            chunks = item.split(\":\")\n            if len(chunks) == 2:\n                root = chunks[0]\n                scope = chunks[1]\n            elif len(chunks) == 1:\n                root = _root\n                scope = chunks[0]\n            else:\n                raise ConanException(\"Bad scope %s\" % item)\n            try:\n                key, value = scope.split(\"=\")\n            except:\n                raise ConanException(\"Bad scope %s\" % item)\n            v = value.upper()\n            if v == \"TRUE\":\n                value = True\n            elif v == \"FALSE\":\n                value = False\n            elif v == \"NONE\":\n                value = None\n            result[root][key] = value\n        return result\n\n    def update_scope(self, other):\n        for name, scopes in other.items():\n            self[name].update(scopes)\n\n    @staticmethod\n    def loads(text):\n        return Scopes.from_list([s.strip() for s in text.splitlines()])\n\n    def dumps(self):\n        result = []\n        for name, scopes in sorted(self.items()):\n            if name != _root:\n                result.extend(\"%s:%s=%s\" % (name, k, v) for (k, v) in sorted(scopes.items()))\n            else:\n                result.extend(\"%s=%s\" % (k, v) for (k, v) in sorted(scopes.items()))\n        return \"\\n\".join(result)\n", "path": "conans/model/scope.py"}], "after_files": [{"content": "from collections import defaultdict\nfrom conans.errors import ConanException\n\n\nclass Scope(dict):\n    \"\"\" the set of possible scopes than a package can have, by name(string):\n    \"dev\", \"test\", \"myscope\"...\n    it is just a set, but with syntax to be queried as:\n       if self.scope.dev:\n    \"\"\"\n\n    def __getattr__(self, field):\n        return self.get(field)\n\n    def __setattr__(self, field, value):\n        self[field] = value\n\n    def __repr__(self):\n        return \", \".join(\"%s=%s\" % (k, v) for k, v in sorted(self.items()))\n\n\n# This is necessary, as None cannot be ordered in Py3\n_root = \"0CONAN_ROOT*\"\n_all = \"ALL\"\n\n\nclass Scopes(defaultdict):\n    \"\"\" all the scopes of a dependency graph, as a dict{package name(str): Scope\n    the root package of the graph might not have name, then its key is None.\n    It is loaded and saved to text as:\n        Package1:dev\n        Package1:test\n        Package2:dev\n        dev  # for the root package, without name\n        other # any name allowed\n    This will be stored in memory as {Package1: Scopes(set[dev, test]),\n                                      Package2: Scopes(...),\n                                      None: Scopes(set[dev, other])\n    \"\"\"\n    def __init__(self):\n        super(Scopes, self).__init__(Scope)\n        self[_root].dev = True\n\n    def package_scope(self, name=None):\n        \"\"\" return the scopes for the given package which are the scopes set\n        for ALL, updated (high priority) with the specific package scopes\n        if the package name is None, then it is the ROOT package/consumer\n        \"\"\"\n        scope = Scope(self.get(_all, {}))\n        scope.update(self[name or _root])\n        return scope\n\n    @staticmethod\n    def from_list(items):\n        result = Scopes()\n        for item in items:\n            try:\n                key, value = item.split(\"=\")\n            except:\n                raise ConanException(\"Bad scope %s\" % item)\n            v = value.upper()\n            if v == \"TRUE\":\n                value = True\n            elif v == \"FALSE\":\n                value = False\n            elif v == \"NONE\":\n                value = None\n\n            chunks = key.split(\":\")\n            if len(chunks) == 2:\n                root = chunks[0]\n                scope = chunks[1]\n            elif len(chunks) == 1:\n                root = _root\n                scope = chunks[0]\n            else:\n                raise ConanException(\"Bad scope %s\" % item)\n\n            result[root][scope] = value\n        return result\n\n    def update_scope(self, other):\n        for name, scopes in other.items():\n            self[name].update(scopes)\n\n    @staticmethod\n    def loads(text):\n        return Scopes.from_list([s.strip() for s in text.splitlines()])\n\n    def dumps(self):\n        result = []\n        for name, scopes in sorted(self.items()):\n            if name != _root:\n                result.extend(\"%s:%s=%s\" % (name, k, v) for (k, v) in sorted(scopes.items()))\n            else:\n                result.extend(\"%s=%s\" % (k, v) for (k, v) in sorted(scopes.items()))\n        return \"\\n\".join(result)\n", "path": "conans/model/scope.py"}]}