We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
SpecList has instances of mutable types as default __init__ arguments
While debugging #18338 I stepped on this definition:

https://github.com/spack/spack/blob/3701633937a80c56ce212cd77c82c082f705e7ad/lib/spack/spack/spec_list.py#L26-L30

that might cause unwanted interactions between different instances of `SpecList` if they use defaults for `reference` (and is difficult to read if default for `yaml_list` is used). This issue is a reminder to refactor this part of the code.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/spack/spack/spec_list.py`
Content:
```
1 # Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
2 # Spack Project Developers. See the top-level COPYRIGHT file for details.
3 #
4 # SPDX-License-Identifier: (Apache-2.0 OR MIT)
5 import itertools
6 from six import string_types
7 
8 import spack.variant
9 from spack.spec import Spec
10 from spack.error import SpackError
11 
12 
13 def spec_ordering_key(s):
14     if s.startswith('^'):
15         return 5
16     elif s.startswith('/'):
17         return 4
18     elif s.startswith('%'):
19         return 3
20     elif any(s.startswith(c) for c in '~-+@') or '=' in s:
21         return 2
22     else:
23         return 1
24 
25 
26 class SpecList(object):
27 
28     def __init__(self, name='specs', yaml_list=[], reference={}):
29         self.name = name
30         self._reference = reference  # TODO: Do we need defensive copy here?
31 
32         # Validate yaml_list before assigning
33         if not all(isinstance(s, string_types) or isinstance(s, (list, dict))
34                    for s in yaml_list):
35             raise ValueError(
36                 "yaml_list can contain only valid YAML types!  Found:\n  %s"
37                 % [type(s) for s in yaml_list])
38         self.yaml_list = yaml_list[:]
39 
40         # Expansions can be expensive to compute and difficult to keep updated
41         # We cache results and invalidate when self.yaml_list changes
42         self._expanded_list = None
43         self._constraints = None
44         self._specs = None
45 
46     @property
47     def specs_as_yaml_list(self):
48         if self._expanded_list is None:
49             self._expanded_list = self._expand_references(self.yaml_list)
50         return self._expanded_list
51 
52     @property
53     def specs_as_constraints(self):
54         if self._constraints is None:
55             constraints = []
56             for item in self.specs_as_yaml_list:
57                 if isinstance(item, dict):  # matrix of specs
58                     constraints.extend(_expand_matrix_constraints(item))
59                 else:  # individual spec
60                     constraints.append([Spec(item)])
61             self._constraints = constraints
62 
63         return self._constraints
64 
65     @property
66     def specs(self):
67         if self._specs is None:
68             specs = []
69             # This could be slightly faster done directly from yaml_list,
70             # but this way is easier to maintain.
71             for constraint_list in self.specs_as_constraints:
72                 spec = constraint_list[0].copy()
73                 for const in constraint_list[1:]:
74                     spec.constrain(const)
75                 specs.append(spec)
76             self._specs = specs
77 
78         return self._specs
79 
80     def add(self, spec):
81         self.yaml_list.append(str(spec))
82 
83         # expanded list can be updated without invalidation
84         if self._expanded_list is not None:
85             self._expanded_list.append(str(spec))
86 
87         # Invalidate cache variables when we change the list
88         self._constraints = None
89         self._specs = None
90 
91     def remove(self, spec):
92         # Get spec to remove from list
93         remove = [s for s in self.yaml_list
94                   if (isinstance(s, string_types) and not s.startswith('$'))
95                   and Spec(s) == Spec(spec)]
96         if not remove:
97             msg = 'Cannot remove %s from SpecList %s\n' % (spec, self.name)
98             msg += 'Either %s is not in %s or %s is ' % (spec, self.name, spec)
99             msg += 'expanded from a matrix and cannot be removed directly.'
100             raise SpecListError(msg)
101         assert len(remove) == 1
102         self.yaml_list.remove(remove[0])
103 
104         # invalidate cache variables when we change the list
105         self._expanded_list = None
106         self._constraints = None
107         self._specs = None
108 
109     def extend(self, other, copy_reference=True):
110         self.yaml_list.extend(other.yaml_list)
111         self._expanded_list = None
112         self._constraints = None
113         self._specs = None
114 
115         if copy_reference:
116             self._reference = other._reference
117 
118     def update_reference(self, reference):
119         self._reference = reference
120         self._expanded_list = None
121         self._constraints = None
122         self._specs = None
123 
124     def _parse_reference(self, name):
125         sigil = ''
126         name = name[1:]
127 
128         # Parse specs as constraints
129         if name.startswith('^') or name.startswith('%'):
130             sigil = name[0]
131             name = name[1:]
132 
133         # Make sure the reference is valid
134         if name not in self._reference:
135             msg = 'SpecList %s refers to ' % self.name
136             msg += 'named list %s ' % name
137             msg += 'which does not appear in its reference dict'
138             raise UndefinedReferenceError(msg)
139 
140         return (name, sigil)
141 
142     def _expand_references(self, yaml):
143         if isinstance(yaml, list):
144             ret = []
145 
146             for item in yaml:
147                 # if it's a reference, expand it
148                 if isinstance(item, string_types) and item.startswith('$'):
149                     # replace the reference and apply the sigil if needed
150                     name, sigil = self._parse_reference(item)
151                     referent = [
152                         _sigilify(item, sigil)
153                         for item in self._reference[name].specs_as_yaml_list
154                     ]
155                     ret.extend(referent)
156                 else:
157                     # else just recurse
158                     ret.append(self._expand_references(item))
159             return ret
160         elif isinstance(yaml, dict):
161             # There can't be expansions in dicts
162             return dict((name, self._expand_references(val))
163                         for (name, val) in yaml.items())
164         else:
165             # Strings are just returned
166             return yaml
167 
168     def __len__(self):
169         return len(self.specs)
170 
171     def __getitem__(self, key):
172         return self.specs[key]
173 
174 
175 def _expand_matrix_constraints(object, specify=True):
176     # recurse so we can handle nexted matrices
177     expanded_rows = []
178     for row in object['matrix']:
179         new_row = []
180         for r in row:
181             if isinstance(r, dict):
182                 new_row.extend(
183                     [[' '.join(c)]
184                      for c in _expand_matrix_constraints(r, specify=False)])
185             else:
186                 new_row.append([r])
187         expanded_rows.append(new_row)
188 
189     excludes = object.get('exclude', [])  # only compute once
190     sigil = object.get('sigil', '')
191 
192     results = []
193     for combo in itertools.product(*expanded_rows):
194         # Construct a combined spec to test against excludes
195         flat_combo = [constraint for list in combo for constraint in list]
196         ordered_combo = sorted(flat_combo, key=spec_ordering_key)
197 
198         test_spec = Spec(' '.join(ordered_combo))
199         # Abstract variants don't have normal satisfaction semantics
200         # Convert all variants to concrete types.
201         # This method is best effort, so all existing variants will be
202         # converted before any error is raised.
203         # Catch exceptions because we want to be able to operate on
204         # abstract specs without needing package information
205         try:
206             spack.variant.substitute_abstract_variants(test_spec)
207         except spack.variant.UnknownVariantError:
208             pass
209         if any(test_spec.satisfies(x) for x in excludes):
210             continue
211 
212         if sigil:  # add sigil if necessary
213             ordered_combo[0] = sigil + ordered_combo[0]
214 
215         # Add to list of constraints
216         if specify:
217             results.append([Spec(x) for x in ordered_combo])
218         else:
219             results.append(ordered_combo)
220     return results
221 
222 
223 def _sigilify(item, sigil):
224     if isinstance(item, dict):
225         if sigil:
226             item['sigil'] = sigil
227         return item
228     else:
229         return sigil + item
230 
231 
232 class SpecListError(SpackError):
233     """Error class for all errors related to SpecList objects."""
234 
235 
236 class UndefinedReferenceError(SpecListError):
237     """Error class for undefined references in Spack stacks."""
238 
239 
240 class InvalidSpecConstraintError(SpecListError):
241     """Error class for invalid spec constraints at concretize time."""
242
```
--- 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/lib/spack/spack/spec_list.py b/lib/spack/spack/spec_list.py
--- a/lib/spack/spack/spec_list.py
+++ b/lib/spack/spack/spec_list.py
@@ -25,7 +25,11 @@
 
 class SpecList(object):
 
-    def __init__(self, name='specs', yaml_list=[], reference={}):
+    def __init__(self, name='specs', yaml_list=None, reference=None):
+        # Normalize input arguments
+        yaml_list = yaml_list or []
+        reference = reference or {}
+
         self.name = name
         self._reference = reference  # TODO: Do we need defensive copy here?

{"golden_diff": "diff --git a/lib/spack/spack/spec_list.py b/lib/spack/spack/spec_list.py\n--- a/lib/spack/spack/spec_list.py\n+++ b/lib/spack/spack/spec_list.py\n@@ -25,7 +25,11 @@\n \n class SpecList(object):\n \n-    def __init__(self, name='specs', yaml_list=[], reference={}):\n+    def __init__(self, name='specs', yaml_list=None, reference=None):\n+        # Normalize input arguments\n+        yaml_list = yaml_list or []\n+        reference = reference or {}\n+\n         self.name = name\n         self._reference = reference  # TODO: Do we need defensive copy here?\n", "issue": "SpecList has instances of mutable types as default __init__ arguments\nWhile debugging #18338 I stepped on this definition:\r\n\r\nhttps://github.com/spack/spack/blob/3701633937a80c56ce212cd77c82c082f705e7ad/lib/spack/spack/spec_list.py#L26-L30\r\n\r\nthat might cause unwanted interactions between different instances of `SpecList` if they use defaults for `reference` (and is difficult to read if default for `yaml_list` is used). This issue is a reminder to refactor this part of the code.\n", "before_files": [{"content": "# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other\n# Spack Project Developers. See the top-level COPYRIGHT file for details.\n#\n# SPDX-License-Identifier: (Apache-2.0 OR MIT)\nimport itertools\nfrom six import string_types\n\nimport spack.variant\nfrom spack.spec import Spec\nfrom spack.error import SpackError\n\n\ndef spec_ordering_key(s):\n    if s.startswith('^'):\n        return 5\n    elif s.startswith('/'):\n        return 4\n    elif s.startswith('%'):\n        return 3\n    elif any(s.startswith(c) for c in '~-+@') or '=' in s:\n        return 2\n    else:\n        return 1\n\n\nclass SpecList(object):\n\n    def __init__(self, name='specs', yaml_list=[], reference={}):\n        self.name = name\n        self._reference = reference  # TODO: Do we need defensive copy here?\n\n        # Validate yaml_list before assigning\n        if not all(isinstance(s, string_types) or isinstance(s, (list, dict))\n                   for s in yaml_list):\n            raise ValueError(\n                \"yaml_list can contain only valid YAML types!  Found:\\n  %s\"\n                % [type(s) for s in yaml_list])\n        self.yaml_list = yaml_list[:]\n\n        # Expansions can be expensive to compute and difficult to keep updated\n        # We cache results and invalidate when self.yaml_list changes\n        self._expanded_list = None\n        self._constraints = None\n        self._specs = None\n\n    @property\n    def specs_as_yaml_list(self):\n        if self._expanded_list is None:\n            self._expanded_list = self._expand_references(self.yaml_list)\n        return self._expanded_list\n\n    @property\n    def specs_as_constraints(self):\n        if self._constraints is None:\n            constraints = []\n            for item in self.specs_as_yaml_list:\n                if isinstance(item, dict):  # matrix of specs\n                    constraints.extend(_expand_matrix_constraints(item))\n                else:  # individual spec\n                    constraints.append([Spec(item)])\n            self._constraints = constraints\n\n        return self._constraints\n\n    @property\n    def specs(self):\n        if self._specs is None:\n            specs = []\n            # This could be slightly faster done directly from yaml_list,\n            # but this way is easier to maintain.\n            for constraint_list in self.specs_as_constraints:\n                spec = constraint_list[0].copy()\n                for const in constraint_list[1:]:\n                    spec.constrain(const)\n                specs.append(spec)\n            self._specs = specs\n\n        return self._specs\n\n    def add(self, spec):\n        self.yaml_list.append(str(spec))\n\n        # expanded list can be updated without invalidation\n        if self._expanded_list is not None:\n            self._expanded_list.append(str(spec))\n\n        # Invalidate cache variables when we change the list\n        self._constraints = None\n        self._specs = None\n\n    def remove(self, spec):\n        # Get spec to remove from list\n        remove = [s for s in self.yaml_list\n                  if (isinstance(s, string_types) and not s.startswith('$'))\n                  and Spec(s) == Spec(spec)]\n        if not remove:\n            msg = 'Cannot remove %s from SpecList %s\\n' % (spec, self.name)\n            msg += 'Either %s is not in %s or %s is ' % (spec, self.name, spec)\n            msg += 'expanded from a matrix and cannot be removed directly.'\n            raise SpecListError(msg)\n        assert len(remove) == 1\n        self.yaml_list.remove(remove[0])\n\n        # invalidate cache variables when we change the list\n        self._expanded_list = None\n        self._constraints = None\n        self._specs = None\n\n    def extend(self, other, copy_reference=True):\n        self.yaml_list.extend(other.yaml_list)\n        self._expanded_list = None\n        self._constraints = None\n        self._specs = None\n\n        if copy_reference:\n            self._reference = other._reference\n\n    def update_reference(self, reference):\n        self._reference = reference\n        self._expanded_list = None\n        self._constraints = None\n        self._specs = None\n\n    def _parse_reference(self, name):\n        sigil = ''\n        name = name[1:]\n\n        # Parse specs as constraints\n        if name.startswith('^') or name.startswith('%'):\n            sigil = name[0]\n            name = name[1:]\n\n        # Make sure the reference is valid\n        if name not in self._reference:\n            msg = 'SpecList %s refers to ' % self.name\n            msg += 'named list %s ' % name\n            msg += 'which does not appear in its reference dict'\n            raise UndefinedReferenceError(msg)\n\n        return (name, sigil)\n\n    def _expand_references(self, yaml):\n        if isinstance(yaml, list):\n            ret = []\n\n            for item in yaml:\n                # if it's a reference, expand it\n                if isinstance(item, string_types) and item.startswith('$'):\n                    # replace the reference and apply the sigil if needed\n                    name, sigil = self._parse_reference(item)\n                    referent = [\n                        _sigilify(item, sigil)\n                        for item in self._reference[name].specs_as_yaml_list\n                    ]\n                    ret.extend(referent)\n                else:\n                    # else just recurse\n                    ret.append(self._expand_references(item))\n            return ret\n        elif isinstance(yaml, dict):\n            # There can't be expansions in dicts\n            return dict((name, self._expand_references(val))\n                        for (name, val) in yaml.items())\n        else:\n            # Strings are just returned\n            return yaml\n\n    def __len__(self):\n        return len(self.specs)\n\n    def __getitem__(self, key):\n        return self.specs[key]\n\n\ndef _expand_matrix_constraints(object, specify=True):\n    # recurse so we can handle nexted matrices\n    expanded_rows = []\n    for row in object['matrix']:\n        new_row = []\n        for r in row:\n            if isinstance(r, dict):\n                new_row.extend(\n                    [[' '.join(c)]\n                     for c in _expand_matrix_constraints(r, specify=False)])\n            else:\n                new_row.append([r])\n        expanded_rows.append(new_row)\n\n    excludes = object.get('exclude', [])  # only compute once\n    sigil = object.get('sigil', '')\n\n    results = []\n    for combo in itertools.product(*expanded_rows):\n        # Construct a combined spec to test against excludes\n        flat_combo = [constraint for list in combo for constraint in list]\n        ordered_combo = sorted(flat_combo, key=spec_ordering_key)\n\n        test_spec = Spec(' '.join(ordered_combo))\n        # Abstract variants don't have normal satisfaction semantics\n        # Convert all variants to concrete types.\n        # This method is best effort, so all existing variants will be\n        # converted before any error is raised.\n        # Catch exceptions because we want to be able to operate on\n        # abstract specs without needing package information\n        try:\n            spack.variant.substitute_abstract_variants(test_spec)\n        except spack.variant.UnknownVariantError:\n            pass\n        if any(test_spec.satisfies(x) for x in excludes):\n            continue\n\n        if sigil:  # add sigil if necessary\n            ordered_combo[0] = sigil + ordered_combo[0]\n\n        # Add to list of constraints\n        if specify:\n            results.append([Spec(x) for x in ordered_combo])\n        else:\n            results.append(ordered_combo)\n    return results\n\n\ndef _sigilify(item, sigil):\n    if isinstance(item, dict):\n        if sigil:\n            item['sigil'] = sigil\n        return item\n    else:\n        return sigil + item\n\n\nclass SpecListError(SpackError):\n    \"\"\"Error class for all errors related to SpecList objects.\"\"\"\n\n\nclass UndefinedReferenceError(SpecListError):\n    \"\"\"Error class for undefined references in Spack stacks.\"\"\"\n\n\nclass InvalidSpecConstraintError(SpecListError):\n    \"\"\"Error class for invalid spec constraints at concretize time.\"\"\"\n", "path": "lib/spack/spack/spec_list.py"}], "after_files": [{"content": "# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other\n# Spack Project Developers. See the top-level COPYRIGHT file for details.\n#\n# SPDX-License-Identifier: (Apache-2.0 OR MIT)\nimport itertools\nfrom six import string_types\n\nimport spack.variant\nfrom spack.spec import Spec\nfrom spack.error import SpackError\n\n\ndef spec_ordering_key(s):\n    if s.startswith('^'):\n        return 5\n    elif s.startswith('/'):\n        return 4\n    elif s.startswith('%'):\n        return 3\n    elif any(s.startswith(c) for c in '~-+@') or '=' in s:\n        return 2\n    else:\n        return 1\n\n\nclass SpecList(object):\n\n    def __init__(self, name='specs', yaml_list=None, reference=None):\n        # Normalize input arguments\n        yaml_list = yaml_list or []\n        reference = reference or {}\n\n        self.name = name\n        self._reference = reference  # TODO: Do we need defensive copy here?\n\n        # Validate yaml_list before assigning\n        if not all(isinstance(s, string_types) or isinstance(s, (list, dict))\n                   for s in yaml_list):\n            raise ValueError(\n                \"yaml_list can contain only valid YAML types!  Found:\\n  %s\"\n                % [type(s) for s in yaml_list])\n        self.yaml_list = yaml_list[:]\n\n        # Expansions can be expensive to compute and difficult to keep updated\n        # We cache results and invalidate when self.yaml_list changes\n        self._expanded_list = None\n        self._constraints = None\n        self._specs = None\n\n    @property\n    def specs_as_yaml_list(self):\n        if self._expanded_list is None:\n            self._expanded_list = self._expand_references(self.yaml_list)\n        return self._expanded_list\n\n    @property\n    def specs_as_constraints(self):\n        if self._constraints is None:\n            constraints = []\n            for item in self.specs_as_yaml_list:\n                if isinstance(item, dict):  # matrix of specs\n                    constraints.extend(_expand_matrix_constraints(item))\n                else:  # individual spec\n                    constraints.append([Spec(item)])\n            self._constraints = constraints\n\n        return self._constraints\n\n    @property\n    def specs(self):\n        if self._specs is None:\n            specs = []\n            # This could be slightly faster done directly from yaml_list,\n            # but this way is easier to maintain.\n            for constraint_list in self.specs_as_constraints:\n                spec = constraint_list[0].copy()\n                for const in constraint_list[1:]:\n                    spec.constrain(const)\n                specs.append(spec)\n            self._specs = specs\n\n        return self._specs\n\n    def add(self, spec):\n        self.yaml_list.append(str(spec))\n\n        # expanded list can be updated without invalidation\n        if self._expanded_list is not None:\n            self._expanded_list.append(str(spec))\n\n        # Invalidate cache variables when we change the list\n        self._constraints = None\n        self._specs = None\n\n    def remove(self, spec):\n        # Get spec to remove from list\n        remove = [s for s in self.yaml_list\n                  if (isinstance(s, string_types) and not s.startswith('$'))\n                  and Spec(s) == Spec(spec)]\n        if not remove:\n            msg = 'Cannot remove %s from SpecList %s\\n' % (spec, self.name)\n            msg += 'Either %s is not in %s or %s is ' % (spec, self.name, spec)\n            msg += 'expanded from a matrix and cannot be removed directly.'\n            raise SpecListError(msg)\n        assert len(remove) == 1\n        self.yaml_list.remove(remove[0])\n\n        # invalidate cache variables when we change the list\n        self._expanded_list = None\n        self._constraints = None\n        self._specs = None\n\n    def extend(self, other, copy_reference=True):\n        self.yaml_list.extend(other.yaml_list)\n        self._expanded_list = None\n        self._constraints = None\n        self._specs = None\n\n        if copy_reference:\n            self._reference = other._reference\n\n    def update_reference(self, reference):\n        self._reference = reference\n        self._expanded_list = None\n        self._constraints = None\n        self._specs = None\n\n    def _parse_reference(self, name):\n        sigil = ''\n        name = name[1:]\n\n        # Parse specs as constraints\n        if name.startswith('^') or name.startswith('%'):\n            sigil = name[0]\n            name = name[1:]\n\n        # Make sure the reference is valid\n        if name not in self._reference:\n            msg = 'SpecList %s refers to ' % self.name\n            msg += 'named list %s ' % name\n            msg += 'which does not appear in its reference dict'\n            raise UndefinedReferenceError(msg)\n\n        return (name, sigil)\n\n    def _expand_references(self, yaml):\n        if isinstance(yaml, list):\n            ret = []\n\n            for item in yaml:\n                # if it's a reference, expand it\n                if isinstance(item, string_types) and item.startswith('$'):\n                    # replace the reference and apply the sigil if needed\n                    name, sigil = self._parse_reference(item)\n                    referent = [\n                        _sigilify(item, sigil)\n                        for item in self._reference[name].specs_as_yaml_list\n                    ]\n                    ret.extend(referent)\n                else:\n                    # else just recurse\n                    ret.append(self._expand_references(item))\n            return ret\n        elif isinstance(yaml, dict):\n            # There can't be expansions in dicts\n            return dict((name, self._expand_references(val))\n                        for (name, val) in yaml.items())\n        else:\n            # Strings are just returned\n            return yaml\n\n    def __len__(self):\n        return len(self.specs)\n\n    def __getitem__(self, key):\n        return self.specs[key]\n\n\ndef _expand_matrix_constraints(object, specify=True):\n    # recurse so we can handle nexted matrices\n    expanded_rows = []\n    for row in object['matrix']:\n        new_row = []\n        for r in row:\n            if isinstance(r, dict):\n                new_row.extend(\n                    [[' '.join(c)]\n                     for c in _expand_matrix_constraints(r, specify=False)])\n            else:\n                new_row.append([r])\n        expanded_rows.append(new_row)\n\n    excludes = object.get('exclude', [])  # only compute once\n    sigil = object.get('sigil', '')\n\n    results = []\n    for combo in itertools.product(*expanded_rows):\n        # Construct a combined spec to test against excludes\n        flat_combo = [constraint for list in combo for constraint in list]\n        ordered_combo = sorted(flat_combo, key=spec_ordering_key)\n\n        test_spec = Spec(' '.join(ordered_combo))\n        # Abstract variants don't have normal satisfaction semantics\n        # Convert all variants to concrete types.\n        # This method is best effort, so all existing variants will be\n        # converted before any error is raised.\n        # Catch exceptions because we want to be able to operate on\n        # abstract specs without needing package information\n        try:\n            spack.variant.substitute_abstract_variants(test_spec)\n        except spack.variant.UnknownVariantError:\n            pass\n        if any(test_spec.satisfies(x) for x in excludes):\n            continue\n\n        if sigil:  # add sigil if necessary\n            ordered_combo[0] = sigil + ordered_combo[0]\n\n        # Add to list of constraints\n        if specify:\n            results.append([Spec(x) for x in ordered_combo])\n        else:\n            results.append(ordered_combo)\n    return results\n\n\ndef _sigilify(item, sigil):\n    if isinstance(item, dict):\n        if sigil:\n            item['sigil'] = sigil\n        return item\n    else:\n        return sigil + item\n\n\nclass SpecListError(SpackError):\n    \"\"\"Error class for all errors related to SpecList objects.\"\"\"\n\n\nclass UndefinedReferenceError(SpecListError):\n    \"\"\"Error class for undefined references in Spack stacks.\"\"\"\n\n\nclass InvalidSpecConstraintError(SpecListError):\n    \"\"\"Error class for invalid spec constraints at concretize time.\"\"\"\n", "path": "lib/spack/spack/spec_list.py"}]}