Repository: mesonbuild/meson

Issue:
New OrderedSet does not work with python 3.4
Here's a simple unit test:

```
diff --git a/run_unittests.py b/run_unittests.py
index 1d80aac..1251517 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -24,7 +24,7 @@ from pathlib import PurePath
 import mesonbuild.compilers
 import mesonbuild.environment
 import mesonbuild.mesonlib
-from mesonbuild.mesonlib import is_windows, is_osx, is_cygwin
+from mesonbuild.mesonlib import is_windows, is_osx, is_cygwin, OrderedSet
 from mesonbuild.environment import Environment
 from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram
 
@@ -316,6 +316,10 @@ class InternalTests(unittest.TestCase):
         cmd = ['@OUTPUT@.out', 'ordinary', 'strings']
         self.assertRaises(ME, substfunc, cmd, d)
 
+    def test_ordered_set(self):
+        oset = OrderedSet()
+        oset.update(['foo'])
+
 
 class BasePlatformTests(unittest.TestCase):
     def setUp(self):
```

This fails with:

```
======================================================================
ERROR: test_ordered_set (__main__.InternalTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./run_unittests.py", line 321, in test_ordered_set
    oset.update(['foo'])
  File "/home/meh/devel/sandbox/meson/mesonbuild/mesonlib.py", line 703, in update
    self[item] = True
  File "/usr/lib64/python3.4/collections/__init__.py", line 68, in __setitem__
    self.__map[key] = link = Link()
AttributeError: 'OrderedSet' object has no attribute '_OrderedDict__map'
```

My python version is 3.4.3.

I'm a bit surprised at this OrderedSet implementation, I would suggest using something like:

https://github.com/hotdoc/hotdoc/blob/master/hotdoc/utils/utils.py#L188


Discussion:

Resolving patch:
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -687,17 +687,37 @@ def get_filenames_templates_dict(inputs, outputs):
             values['@OUTDIR@'] = '.'
     return values
 
-class OrderedSet(collections.OrderedDict):
-    '''
-    A 'set' equivalent that preserves the order in which items are added.
-
-    This is a hack implementation that wraps OrderedDict. It may not be the
-    most efficient solution and might need fixing to override more methods.
-    '''
+class OrderedSet(collections.MutableSet):
+    """A set that preserves the order in which items are added, by first
+    insertion.
+    """
     def __init__(self, iterable=None):
+        self.__container = collections.OrderedDict()
         if iterable:
             self.update(iterable)
 
+    def __contains__(self, value):
+        return value in self.__container
+
+    def __iter__(self):
+        return iter(self.__container.keys())
+
+    def __len__(self):
+        return len(self.__container)
+
+    def __repr__(self):
+        # Don't print 'OrderedSet("")' for an empty set.
+        if self.__container:
+            return 'OrderedSet("{}")'.format('", "'.join(self.__container.keys()))
+        return 'OrderedSet()'
+
+    def add(self, value):
+        self.__container[value] = None
+
+    def discard(self, value):
+        if value in self.__container:
+            del self.__container[value]
+
     def update(self, iterable):
         for item in iterable:
-            self[item] = True
+            self.__container[item] = None


Test patch: