Sisyphus repositório
Última atualização: 1 outubro 2023 | SRPMs: 18631 | Visitas: 37044611
en ru br
ALT Linux repositórios
S:78.11.0-alt2.1

Group :: Sistema/Bibliotecas
RPM: libmozjs78

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs e FR  Repocop 

Patch: mozjs-78.11.0-mozbuild-util.patch
Download


--- mozjs-78.11.0/python/mozbuild/mozbuild/util.py	2021-05-31 17:20:25.000000000 +0300
+++ mozjs-91.5.0/python/mozbuild/mozbuild/util.py	2022-01-07 17:21:02.000000000 +0300
@@ -9,6 +9,7 @@
 
 import argparse
 import collections
+import collections.abc
 import ctypes
 import difflib
 import errno
@@ -22,19 +23,21 @@
 import stat
 import sys
 import time
-from collections import (
-    OrderedDict,
-)
-from io import (BytesIO, StringIO)
+from collections import OrderedDict
+from io import BytesIO, StringIO
 
 import six
 
-if sys.platform == 'win32':
+MOZBUILD_METRICS_PATH = os.path.abspath(
+    os.path.join(__file__, "..", "..", "metrics.yaml")
+)
+
+if sys.platform == "win32":
     _kernel32 = ctypes.windll.kernel32
     _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000
-    system_encoding = 'mbcs'
+    system_encoding = "mbcs"
 else:
-    system_encoding = 'utf-8'
+    system_encoding = "utf-8"
 
 
 def exec_(object, globals=None, locals=None):
@@ -54,9 +57,9 @@
 
 
 def _open(path, mode):
-    if 'b' in mode:
+    if "b" in mode:
         return io.open(path, mode)
-    return io.open(path, mode, encoding='utf-8', newline='\n')
+    return io.open(path, mode, encoding="utf-8", newline="\n")
 
 
 def hash_file(path, hasher=None):
@@ -66,7 +69,7 @@
     # lots of cached data.  Don't change it lightly.
     h = hasher or hashlib.sha1()
 
-    with open(path, 'rb') as fh:
+    with open(path, "rb") as fh:
         while True:
             data = fh.read(8192)
 
@@ -98,20 +101,21 @@
             super(ReadOnlyNamespace, self).__setattr__(k, v)
 
     def __delattr__(self, key):
-        raise Exception('Object does not support deletion.')
+        raise Exception("Object does not support deletion.")
 
     def __setattr__(self, key, value):
-        raise Exception('Object does not support assignment.')
+        raise Exception("Object does not support assignment.")
 
     def __ne__(self, other):
         return not (self == other)
 
     def __eq__(self, other):
         return self is other or (
-            hasattr(other, '__dict__') and self.__dict__ == other.__dict__)
+            hasattr(other, "__dict__") and self.__dict__ == other.__dict__
+        )
 
     def __repr__(self):
-        return '<%s %r>' % (self.__class__.__name__, self.__dict__)
+        return "<%s %r>" % (self.__class__.__name__, self.__dict__)
 
 
 class ReadOnlyDict(dict):
@@ -121,13 +125,13 @@
         dict.__init__(self, *args, **kwargs)
 
     def __delitem__(self, key):
-        raise Exception('Object does not support deletion.')
+        raise Exception("Object does not support deletion.")
 
     def __setitem__(self, key, value):
-        raise Exception('Object does not support assignment.')
+        raise Exception("Object does not support assignment.")
 
     def update(self, *args, **kwargs):
-        raise Exception('Object does not support update.')
+        raise Exception("Object does not support update.")
 
 
 class undefined_default(object):
@@ -174,15 +178,15 @@
             raise
 
     if not_indexed:
-        if sys.platform == 'win32':
+        if sys.platform == "win32":
             if isinstance(path, six.string_types):
                 fn = _kernel32.SetFileAttributesW
             else:
                 fn = _kernel32.SetFileAttributesA
 
             fn(path, _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
-        elif sys.platform == 'darwin':
-            with open(os.path.join(path, '.metadata_never_index'), 'a'):
+        elif sys.platform == "darwin":
+            with open(os.path.join(path, ".metadata_never_index"), "a"):
                 pass
 
 
@@ -196,11 +200,12 @@
     new_lines can be None, indicating a file deletion.
     """
 
-    old_name = '/dev/null' if old_lines is None else filename
-    new_name = '/dev/null' if new_lines is None else filename
+    old_name = "/dev/null" if old_lines is None else filename
+    new_name = "/dev/null" if new_lines is None else filename
 
-    return difflib.unified_diff(old_lines or [], new_lines or [],
-                                old_name, new_name, n=4, lineterm='')
+    return difflib.unified_diff(
+        old_lines or [], new_lines or [], old_name, new_name, n=4, lineterm=""
+    )
 
 
 class FileAvoidWrite(BytesIO):
@@ -220,17 +225,17 @@
     still occur, as well as diff capture if requested.
     """
 
-    def __init__(self, filename, capture_diff=False, dry_run=False, readmode='rU'):
+    def __init__(self, filename, capture_diff=False, dry_run=False, readmode="rU"):
         BytesIO.__init__(self)
         self.name = filename
         assert type(capture_diff) == bool
         assert type(dry_run) == bool
-        assert 'r' in readmode
+        assert "r" in readmode
         self._capture_diff = capture_diff
         self._write_to_file = not dry_run
         self.diff = None
         self.mode = readmode
-        self._binary_mode = 'b' in readmode
+        self._binary_mode = "b" in readmode
 
     def write(self, buf):
         BytesIO.write(self, six.ensure_binary(buf))
@@ -276,9 +281,9 @@
             ensureParentDir(self.name)
             # Maintain 'b' if specified.  'U' only applies to modes starting with
             # 'r', so it is dropped.
-            writemode = 'w'
+            writemode = "w"
             if self._binary_mode:
-                writemode += 'b'
+                writemode += "b"
                 buf = six.ensure_binary(buf)
             else:
                 buf = six.ensure_text(buf)
@@ -309,13 +314,13 @@
             else:
                 if self._binary_mode:
                     # difflib doesn't work with bytes.
-                    old_content = old_content.decode('utf-8')
+                    old_content = old_content.decode("utf-8")
 
                 old_lines = old_content.splitlines()
 
             if self._binary_mode:
                 # difflib doesn't work with bytes.
-                new_content = new_content.decode('utf-8')
+                new_content = new_content.decode("utf-8")
 
             new_lines = new_content.splitlines()
 
@@ -327,8 +332,7 @@
         # This can go away once FileAvoidWrite uses io.BytesIO and
         # io.StringIO. But that will require a lot of work.
         except (UnicodeDecodeError, UnicodeEncodeError):
-            self.diff = ['Binary or non-ascii file changed: %s' %
-                         self.name]
+            self.diff = ["Binary or non-ascii file changed: %s" % self.name]
 
     def __enter__(self):
         return self
@@ -339,7 +343,7 @@
 
 
 def resolve_target_to_make(topobjdir, target):
-    r'''
+    r"""
     Resolve `target` (a target, directory, or file) to a make target.
 
     `topobjdir` is the object directory; all make targets will be
@@ -359,9 +363,9 @@
     A Makefile resolves to the nearest parent strictly above the
     Makefile containing a different Makefile, and an appropriate
     target.
-    '''
+    """
 
-    target = target.replace(os.sep, '/').lstrip('/')
+    target = target.replace(os.sep, "/").lstrip("/")
     abs_target = os.path.join(topobjdir, target)
 
     # For directories, run |make -C dir|. If the directory does not
@@ -371,15 +375,15 @@
         current = abs_target
 
         while True:
-            make_path = os.path.join(current, 'Makefile')
+            make_path = os.path.join(current, "Makefile")
             if os.path.exists(make_path):
-                return (current[len(topobjdir) + 1:], None)
+                return (current[len(topobjdir) + 1 :], None)
 
             current = os.path.dirname(current)
 
     # If it's not in a directory, this is probably a top-level make
     # target. Treat it as such.
-    if '/' not in target:
+    if "/" not in target:
         return (None, target)
 
     # We have a relative path within the tree. We look for a Makefile
@@ -389,11 +393,11 @@
     target = os.path.basename(target)
 
     while True:
-        make_path = os.path.join(topobjdir, reldir, 'Makefile')
+        make_path = os.path.join(topobjdir, reldir, "Makefile")
 
         # We append to target every iteration, so the check below
         # happens exactly once.
-        if target != 'Makefile' and os.path.exists(make_path):
+        if target != "Makefile" and os.path.exists(make_path):
             return (reldir, target)
 
         target = os.path.join(os.path.basename(reldir), target)
@@ -412,29 +416,28 @@
         if iterable is None:
             iterable = []
         if not isinstance(iterable, list):
-            raise ValueError('List can only be created from other list instances.')
+            raise ValueError("List can only be created from other list instances.")
 
         self._kwargs = kwargs
         return super(List, self).__init__(iterable)
 
     def extend(self, l):
         if not isinstance(l, list):
-            raise ValueError('List can only be extended with other list instances.')
+            raise ValueError("List can only be extended with other list instances.")
 
         return super(List, self).extend(l)
 
     def __setitem__(self, key, val):
         if isinstance(key, slice):
             if not isinstance(val, list):
-                raise ValueError('List can only be sliced with other list '
-                                 'instances.')
+                raise ValueError(
+                    "List can only be sliced with other list " "instances."
+                )
             if key.step:
-                raise ValueError('List cannot be sliced with a nonzero step '
-                                 'value')
+                raise ValueError("List cannot be sliced with a nonzero step " "value")
             # Python 2 and Python 3 do this differently for some reason.
             if six.PY2:
-                return super(List, self).__setslice__(key.start, key.stop,
-                                                      val)
+                return super(List, self).__setslice__(key.start, key.stop, val)
             else:
                 return super(List, self).__setitem__(key, val)
         return super(List, self).__setitem__(key, val)
@@ -447,7 +450,7 @@
         # variable references in moz.build behave better.
         other = [] if isinstance(other, (type(None), EmptyValue)) else other
         if not isinstance(other, list):
-            raise ValueError('Only lists can be appended to lists.')
+            raise ValueError("Only lists can be appended to lists.")
 
         new_list = self.__class__(self, **self._kwargs)
         new_list.extend(other)
@@ -456,7 +459,7 @@
     def __iadd__(self, other):
         other = [] if isinstance(other, (type(None), EmptyValue)) else other
         if not isinstance(other, list):
-            raise ValueError('Only lists can be appended to lists.')
+            raise ValueError("Only lists can be appended to lists.")
 
         return super(List, self).__iadd__(other)
 
@@ -478,11 +481,12 @@
     def __str__(self):
         s = StringIO()
 
-        s.write('An attempt was made to add an unsorted sequence to a list. ')
-        s.write('The incoming list is unsorted starting at element %d. ' %
-                self.i)
-        s.write('We expected "%s" but got "%s"' % (
-            self.sorted[self.i], self.original[self.i]))
+        s.write("An attempt was made to add an unsorted sequence to a list. ")
+        s.write("The incoming list is unsorted starting at element %d. " % self.i)
+        s.write(
+            'We expected "%s" but got "%s"'
+            % (self.sorted[self.i], self.original[self.i])
+        )
 
         return s.getvalue()
 
@@ -503,6 +507,7 @@
             # If the list entry is a tuple, we sort based on the first element
             # in the tuple.
             return e[0] if isinstance(e, tuple) else e
+
         srtd = sorted(l, key=lambda x: _first_element(x).lower())
 
         if srtd != l:
@@ -538,8 +543,7 @@
 
 
 class ImmutableStrictOrderingOnAppendList(StrictOrderingOnAppendList):
-    """Like StrictOrderingOnAppendList, but not allowing mutations of the value.
-    """
+    """Like StrictOrderingOnAppendList, but not allowing mutations of the value."""
 
     def append(self, elt):
         raise Exception("cannot use append on this type")
@@ -567,23 +571,28 @@
 
     def __init__(self, iterable=(), action=None):
         if not callable(action):
-            raise ValueError('A callable action is required to construct '
-                             'a StrictOrderingOnAppendListWithAction')
+            raise ValueError(
+                "A callable action is required to construct "
+                "a StrictOrderingOnAppendListWithAction"
+            )
 
         self._action = action
         if not isinstance(iterable, (tuple, list)):
             raise ValueError(
-                'StrictOrderingOnAppendListWithAction can only be initialized '
-                'with another list')
+                "StrictOrderingOnAppendListWithAction can only be initialized "
+                "with another list"
+            )
         iterable = [self._action(i) for i in iterable]
         super(StrictOrderingOnAppendListWithAction, self).__init__(
-            iterable, action=action)
+            iterable, action=action
+        )
 
     def extend(self, l):
         if not isinstance(l, list):
             raise ValueError(
-                'StrictOrderingOnAppendListWithAction can only be extended '
-                'with another list')
+                "StrictOrderingOnAppendListWithAction can only be extended "
+                "with another list"
+            )
         l = [self._action(i) for i in l]
         return super(StrictOrderingOnAppendListWithAction, self).extend(l)
 
@@ -591,24 +600,26 @@
         if isinstance(key, slice):
             if not isinstance(val, list):
                 raise ValueError(
-                    'StrictOrderingOnAppendListWithAction can only be sliced '
-                    'with another list')
+                    "StrictOrderingOnAppendListWithAction can only be sliced "
+                    "with another list"
+                )
             val = [self._action(item) for item in val]
-        return super(StrictOrderingOnAppendListWithAction, self).__setitem__(
-            key, val)
+        return super(StrictOrderingOnAppendListWithAction, self).__setitem__(key, val)
 
     def __add__(self, other):
         if not isinstance(other, list):
             raise ValueError(
-                'StrictOrderingOnAppendListWithAction can only be added with '
-                'another list')
+                "StrictOrderingOnAppendListWithAction can only be added with "
+                "another list"
+            )
         return super(StrictOrderingOnAppendListWithAction, self).__add__(other)
 
     def __iadd__(self, other):
         if not isinstance(other, list):
             raise ValueError(
-                'StrictOrderingOnAppendListWithAction can only be added with '
-                'another list')
+                "StrictOrderingOnAppendListWithAction can only be added with "
+                "another list"
+            )
         other = [self._action(i) for i in other]
         return super(StrictOrderingOnAppendListWithAction, self).__iadd__(other)
 
@@ -639,8 +650,10 @@
 
         def __getattr__(self, name):
             if name not in self.__slots__:
-                raise AttributeError("'%s' object has no attribute '%s'" %
-                                     (self.__class__.__name__, name))
+                raise AttributeError(
+                    "'%s' object has no attribute '%s'"
+                    % (self.__class__.__name__, name)
+                )
             try:
                 return object.__getattr__(self, name)
             except AttributeError:
@@ -650,16 +663,19 @@
 
         def __setattr__(self, name, value):
             if name not in self.__slots__:
-                raise AttributeError("'%s' object has no attribute '%s'" %
-                                     (self.__class__.__name__, name))
+                raise AttributeError(
+                    "'%s' object has no attribute '%s'"
+                    % (self.__class__.__name__, name)
+                )
             if not isinstance(value, self._flags[name]):
-                raise TypeError("'%s' attribute of class '%s' must be '%s'" %
-                                (name, self.__class__.__name__,
-                                 self._flags[name].__name__))
+                raise TypeError(
+                    "'%s' attribute of class '%s' must be '%s'"
+                    % (name, self.__class__.__name__, self._flags[name].__name__)
+                )
             return object.__setattr__(self, name, value)
 
         def __delattr__(self, name):
-            raise MozbuildDeletionError('Unable to delete attributes for this object')
+            raise MozbuildDeletionError("Unable to delete attributes for this object")
 
     return Flags
 
@@ -687,7 +703,10 @@
         foo['a'].foo = True
         foo['b'].bar = 'bar'
     """
-    class StrictOrderingOnAppendListWithFlagsSpecialization(StrictOrderingOnAppendListWithFlags):
+
+    class StrictOrderingOnAppendListWithFlagsSpecialization(
+        StrictOrderingOnAppendListWithFlags
+    ):
         def __init__(self, iterable=None):
             if iterable is None:
                 iterable = []
@@ -704,10 +723,13 @@
 
         def __setitem__(self, name, value):
             if not isinstance(name, slice):
-                raise TypeError("'%s' object does not support item assignment" %
-                                self.__class__.__name__)
-            result = super(StrictOrderingOnAppendListWithFlagsSpecialization,
-                           self).__setitem__(name, value)
+                raise TypeError(
+                    "'%s' object does not support item assignment"
+                    % self.__class__.__name__
+                )
+            result = super(
+                StrictOrderingOnAppendListWithFlagsSpecialization, self
+            ).__setitem__(name, value)
             # We may have removed items.
             for k in set(self._flags.keys()) - set(self):
                 del self._flags[k]
@@ -717,26 +739,30 @@
 
         def _update_flags(self, other):
             if self._flags_type._flags != other._flags_type._flags:
-                raise ValueError('Expected a list of strings with flags like %s, not like %s' %
-                                 (self._flags_type._flags, other._flags_type._flags))
+                raise ValueError(
+                    "Expected a list of strings with flags like %s, not like %s"
+                    % (self._flags_type._flags, other._flags_type._flags)
+                )
             intersection = set(self._flags.keys()) & set(other._flags.keys())
             if intersection:
                 raise ValueError(
-                    'Cannot update flags: both lists of strings with flags configure %s' %
-                    intersection
-                    )
+                    "Cannot update flags: both lists of strings with flags configure %s"
+                    % intersection
+                )
             self._flags.update(other._flags)
 
         def extend(self, l):
-            result = super(StrictOrderingOnAppendListWithFlagsSpecialization,
-                           self).extend(l)
+            result = super(
+                StrictOrderingOnAppendListWithFlagsSpecialization, self
+            ).extend(l)
             if isinstance(l, StrictOrderingOnAppendListWithFlags):
                 self._update_flags(l)
             return result
 
         def __add__(self, other):
-            result = super(StrictOrderingOnAppendListWithFlagsSpecialization,
-                           self).__add__(other)
+            result = super(
+                StrictOrderingOnAppendListWithFlagsSpecialization, self
+            ).__add__(other)
             if isinstance(other, StrictOrderingOnAppendListWithFlags):
                 # Result has flags from other but not from self, since
                 # internally we duplicate self and then extend with other, and
@@ -748,8 +774,9 @@
             return result
 
         def __iadd__(self, other):
-            result = super(StrictOrderingOnAppendListWithFlagsSpecialization,
-                           self).__iadd__(other)
+            result = super(
+                StrictOrderingOnAppendListWithFlagsSpecialization, self
+            ).__iadd__(other)
             if isinstance(other, StrictOrderingOnAppendListWithFlags):
                 self._update_flags(other)
             return result
@@ -774,7 +801,8 @@
     EXPORTS.mozilla.dom), and the first and last each have one element in their
     list.
     """
-    __slots__ = ('_strings', '_children')
+
+    __slots__ = ("_strings", "_children")
 
     def __init__(self):
         # Please change ContextDerivedTypedHierarchicalStringList in context.py
@@ -782,7 +810,7 @@
         self._strings = StrictOrderingOnAppendList()
         self._children = {}
 
-    class StringListAdaptor(collections.Sequence):
+    class StringListAdaptor(collections.abc.Sequence):
         def __init__(self, hsl):
             self._hsl = hsl
 
@@ -803,13 +831,13 @@
         """
 
         if self._strings:
-            path_to_here = ''
+            path_to_here = ""
             yield path_to_here, self.StringListAdaptor(self)
 
         for k, l in sorted(self._children.items()):
             for p, v in l.walk():
-                path_to_there = '%s/%s' % (k, p)
-                yield path_to_there.strip('/'), v
+                path_to_there = "%s/%s" % (k, p)
+                yield path_to_there.strip("/"), v
 
     def __setattr__(self, name, value):
         if name in self.__slots__:
@@ -829,12 +857,12 @@
         self._set_exportvariable(name, value)
 
     def __getattr__(self, name):
-        if name.startswith('__'):
+        if name.startswith("__"):
             return object.__getattr__(self, name)
         return self._get_exportvariable(name)
 
     def __delattr__(self, name):
-        raise MozbuildDeletionError('Unable to delete attributes for this object')
+        raise MozbuildDeletionError("Unable to delete attributes for this object")
 
     def __iadd__(self, other):
         if isinstance(other, HierarchicalStringList):
@@ -864,8 +892,7 @@
         if name in self._children:
             if value is self._get_exportvariable(name):
                 return
-            raise KeyError('global_ns', 'reassign',
-                           '<some variable>.%s' % name)
+            raise KeyError("global_ns", "reassign", "<some variable>.%s" % name)
 
         exports = self._get_exportvariable(name)
         exports._check_list(value)
@@ -873,11 +900,12 @@
 
     def _check_list(self, value):
         if not isinstance(value, list):
-            raise ValueError('Expected a list of strings, not %s' % type(value))
+            raise ValueError("Expected a list of strings, not %s" % type(value))
         for v in value:
             if not isinstance(v, six.string_types):
                 raise ValueError(
-                    'Expected a list of strings, not an element of %s' % type(v))
+                    "Expected a list of strings, not an element of %s" % type(v)
+                )
 
 
 class LockFile(object):
@@ -921,8 +949,9 @@
             # We created the lockfile, so we're the owner
             break
         except OSError as e:
-            if (e.errno == errno.EEXIST or
-                (sys.platform == "win32" and e.errno == errno.EACCES)):
+            if e.errno == errno.EEXIST or (
+                sys.platform == "win32" and e.errno == errno.EACCES
+            ):
                 pass
             else:
                 # Should not occur
@@ -931,7 +960,7 @@
         try:
             # The lock file exists, try to stat it to get its age
             # and read its contents to report the owner PID
-            f = open(lockfile, 'r')
+            f = open(lockfile, "r")
             s = os.stat(lockfile)
         except EnvironmentError as e:
             if e.errno == errno.ENOENT or e.errno == errno.EACCES:
@@ -939,16 +968,19 @@
                 # gone now. Just try again
                 continue
 
-            raise Exception('{0} exists but stat() failed: {1}'.format(
-                lockfile, e.strerror))
+            raise Exception(
+                "{0} exists but stat() failed: {1}".format(lockfile, e.strerror)
+            )
 
         # We didn't create the lockfile and it's still there, check
         # its age
         now = int(time.time())
         if now - s[stat.ST_MTIME] > max_wait:
             pid = f.readline().rstrip()
-            raise Exception('{0} has been locked for more than '
-                            '{1} seconds (PID {2})'.format(lockfile, max_wait, pid))
+            raise Exception(
+                "{0} has been locked for more than "
+                "{1} seconds (PID {2})".format(lockfile, max_wait, pid)
+            )
 
         # It's not been locked too long, wait a while and retry
         f.close()
@@ -956,15 +988,15 @@
 
     # if we get here. we have the lockfile. Convert the os.open file
     # descriptor into a Python file object and record our PID in it
-    f = os.fdopen(fd, 'w')
-    f.write('{0}\n'.format(os.getpid()))
+    f = os.fdopen(fd, "w")
+    f.write("{0}\n".format(os.getpid()))
     f.close()
 
     return LockFile(lockfile)
 
 
 class OrderedDefaultDict(OrderedDict):
-    '''A combination of OrderedDict and defaultdict.'''
+    """A combination of OrderedDict and defaultdict."""
 
     def __init__(self, default_factory, *args, **kwargs):
         OrderedDict.__init__(self, *args, **kwargs)
@@ -976,8 +1008,8 @@
 
 
 class KeyedDefaultDict(dict):
-    '''Like a defaultdict, but the default_factory function takes the key as
-    argument'''
+    """Like a defaultdict, but the default_factory function takes the key as
+    argument"""
 
     def __init__(self, default_factory, *args, **kwargs):
         dict.__init__(self, *args, **kwargs)
@@ -990,15 +1022,15 @@
 
 
 class ReadOnlyKeyedDefaultDict(KeyedDefaultDict, ReadOnlyDict):
-    '''Like KeyedDefaultDict, but read-only.'''
+    """Like KeyedDefaultDict, but read-only."""
 
 
 class memoize(dict):
-    '''A decorator to memoize the results of function calls depending
+    """A decorator to memoize the results of function calls depending
     on its arguments.
     Both functions and instance methods are handled, although in the
     instance method case, the results are cache in the instance itself.
-    '''
+    """
 
     def __init__(self, func):
         self.func = func
@@ -1010,7 +1042,7 @@
         return self[args]
 
     def method_call(self, instance, *args):
-        name = '_%s' % self.func.__name__
+        name = "_%s" % self.func.__name__
         if not hasattr(instance, name):
             setattr(instance, name, {})
         cache = getattr(instance, name)
@@ -1020,19 +1052,20 @@
 
     def __get__(self, instance, cls):
         return functools.update_wrapper(
-            functools.partial(self.method_call, instance), self.func)
+            functools.partial(self.method_call, instance), self.func
+        )
 
 
 class memoized_property(object):
-    '''A specialized version of the memoize decorator that works for
+    """A specialized version of the memoize decorator that works for
     class instance properties.
-    '''
+    """
 
     def __init__(self, func):
         self.func = func
 
     def __get__(self, instance, cls):
-        name = '_%s' % self.func.__name__
+        name = "_%s" % self.func.__name__
         if not hasattr(instance, name):
             setattr(instance, name, self.func(instance))
         return getattr(instance, name)
@@ -1077,9 +1110,10 @@
                 value = self[i]
 
                 if not isinstance(value, ftype):
-                    raise TypeError('field in tuple not of proper type: %s; '
-                                    'got %s, expected %s' % (fname,
-                                                             type(value), ftype))
+                    raise TypeError(
+                        "field in tuple not of proper type: %s; "
+                        "got %s, expected %s" % (fname, type(value), ftype)
+                    )
 
     TypedTuple._fields = fields
 
@@ -1088,7 +1122,7 @@
 
 @memoize
 def TypedList(type, base_class=List):
-    '''A list with type coercion.
+    """A list with type coercion.
 
     The given ``type`` is what list elements are being coerced to. It may do
     strict validation, throwing ValueError exceptions.
@@ -1097,7 +1131,8 @@
     example, a Typed StrictOrderingOnAppendList can be created with:
 
        TypedList(unicode, StrictOrderingOnAppendList)
-    '''
+    """
+
     class _TypedList(base_class):
         @staticmethod
         def normalize(e):
@@ -1144,8 +1179,7 @@
     return _TypedList
 
 
-def group_unified_files(files, unified_prefix, unified_suffix,
-                        files_per_unified_file):
+def group_unified_files(files, unified_prefix, unified_suffix, files_per_unified_file):
     """Return an iterator of (unified_filename, source_filenames) tuples.
 
     We compile most C and C++ files in "unified mode"; instead of compiling
@@ -1169,8 +1203,7 @@
     dummy_fill_value = ("dummy",)
 
     def filter_out_dummy(iterable):
-        return six.moves.filter(lambda x: x != dummy_fill_value,
-                                iterable)
+        return six.moves.filter(lambda x: x != dummy_fill_value, iterable)
 
     # From the itertools documentation, slightly modified:
     def grouper(n, iterable):
@@ -1178,67 +1211,66 @@
         args = [iter(iterable)] * n
         return six.moves.zip_longest(fillvalue=dummy_fill_value, *args)
 
-    for i, unified_group in enumerate(grouper(files_per_unified_file,
-                                              files)):
+    for i, unified_group in enumerate(grouper(files_per_unified_file, files)):
         just_the_filenames = list(filter_out_dummy(unified_group))
-        yield '%s%d.%s' % (unified_prefix, i, unified_suffix), just_the_filenames
+        yield "%s%d.%s" % (unified_prefix, i, unified_suffix), just_the_filenames
 
 
 def pair(iterable):
-    '''Given an iterable, returns an iterable pairing its items.
+    """Given an iterable, returns an iterable pairing its items.
 
     For example,
         list(pair([1,2,3,4,5,6]))
     returns
         [(1,2), (3,4), (5,6)]
-    '''
+    """
     i = iter(iterable)
     return six.moves.zip_longest(i, i)
 
 
 def pairwise(iterable):
-    '''Given an iterable, returns an iterable of overlapped pairs of
+    """Given an iterable, returns an iterable of overlapped pairs of
     its items. Based on the Python itertools documentation.
 
     For example,
         list(pairwise([1,2,3,4,5,6]))
     returns
         [(1,2), (2,3), (3,4), (4,5), (5,6)]
-    '''
+    """
     a, b = itertools.tee(iterable)
     next(b, None)
     return zip(a, b)
 
 
-VARIABLES_RE = re.compile('\$\((\w+)\)')
+VARIABLES_RE = re.compile("\$\((\w+)\)")
 
 
 def expand_variables(s, variables):
-    '''Given a string with $(var) variable references, replace those references
+    """Given a string with $(var) variable references, replace those references
     with the corresponding entries from the given `variables` dict.
 
     If a variable value is not a string, it is iterated and its items are
-    joined with a whitespace.'''
-    result = ''
+    joined with a whitespace."""
+    result = ""
     for s, name in pair(VARIABLES_RE.split(s)):
         result += s
         value = variables.get(name)
         if not value:
             continue
         if not isinstance(value, six.string_types):
-            value = ' '.join(value)
+            value = " ".join(value)
         result += value
     return result
 
 
 class DefinesAction(argparse.Action):
-    '''An ArgumentParser action to handle -Dvar[=value] type of arguments.'''
+    """An ArgumentParser action to handle -Dvar[=value] type of arguments."""
 
     def __call__(self, parser, namespace, values, option_string):
         defines = getattr(namespace, self.dest)
         if defines is None:
             defines = {}
-        values = values.split('=', 1)
+        values = values.split("=", 1)
         if len(values) == 1:
             name, value = values[0], 1
         else:
@@ -1254,25 +1286,28 @@
 
 
 class EnumString(six.text_type):
-    '''A string type that only can have a limited set of values, similarly to
+    """A string type that only can have a limited set of values, similarly to
     an Enum, and can only be compared against that set of values.
 
     The class is meant to be subclassed, where the subclass defines
     POSSIBLE_VALUES. The `subclass` method is a helper to create such
     subclasses.
-    '''
+    """
+
     POSSIBLE_VALUES = ()
 
     def __init__(self, value):
         if value not in self.POSSIBLE_VALUES:
-            raise ValueError("'%s' is not a valid value for %s"
-                             % (value, self.__class__.__name__))
+            raise ValueError(
+                "'%s' is not a valid value for %s" % (value, self.__class__.__name__)
+            )
 
     def __eq__(self, other):
         if other not in self.POSSIBLE_VALUES:
             raise EnumStringComparisonError(
-                'Can only compare with %s'
-                % ', '.join("'%s'" % v for v in self.POSSIBLE_VALUES))
+                "Can only compare with %s"
+                % ", ".join("'%s'" % v for v in self.POSSIBLE_VALUES)
+            )
         return super(EnumString, self).__eq__(other)
 
     def __ne__(self, other):
@@ -1285,6 +1320,7 @@
     def subclass(*possible_values):
         class EnumStringSubclass(EnumString):
             POSSIBLE_VALUES = possible_values
+
         return EnumStringSubclass
 
 
@@ -1293,7 +1329,7 @@
     # quoting could be done with either ' or ".
     if c == "'":
         return "\\'"
-    return six.text_type(c.encode('unicode_escape'))
+    return six.text_type(c.encode("unicode_escape"))
 
 
 if six.PY2:  # Delete when we get rid of Python 2.
@@ -1301,43 +1337,43 @@
     # counterpart, when they differ
     _INDENTED_REPR_TABLE = {
         c: e
-        for c, e in map(lambda x: (x, _escape_char(x)),
-                        map(unichr, range(128)))
+        for c, e in map(lambda x: (x, _escape_char(x)), map(unichr, range(128)))
         if c != e
     }
     # Regexp matching all characters to escape.
     _INDENTED_REPR_RE = re.compile(
-        '([' + ''.join(_INDENTED_REPR_TABLE.values()) + ']+)')
+        "([" + "".join(_INDENTED_REPR_TABLE.values()) + "]+)"
+    )
 
 
 def write_indented_repr(f, o, indent=4):
-    '''Write an indented representation (similar to repr()) of the object to the
+    """Write an indented representation (similar to repr()) of the object to the
     given file `f`.
 
     One notable difference with repr is that the returned representation
     assumes `from __future__ import unicode_literals`.
-    '''
+    """
     if six.PY3:
         pprint.pprint(o, stream=f, indent=indent)
         return
     # Delete everything below when we get rid of Python 2.
-    one_indent = ' ' * indent
+    one_indent = " " * indent
 
     def recurse_indented_repr(o, level):
         if isinstance(o, dict):
-            yield '{\n'
+            yield "{\n"
             for k, v in sorted(o.items()):
                 yield one_indent * (level + 1)
                 for d in recurse_indented_repr(k, level + 1):
                     yield d
-                yield ': '
+                yield ": "
                 for d in recurse_indented_repr(v, level + 1):
                     yield d
-                yield ',\n'
+                yield ",\n"
             yield one_indent * level
-            yield '}'
+            yield "}"
         elif isinstance(o, bytes):
-            yield 'b'
+            yield "b"
             yield repr(o)
         elif isinstance(o, six.text_type):
             yield "'"
@@ -1350,23 +1386,24 @@
                 else:
                     yield s
             yield "'"
-        elif hasattr(o, '__iter__'):
-            yield '[\n'
+        elif hasattr(o, "__iter__"):
+            yield "[\n"
             for i in o:
                 yield one_indent * (level + 1)
                 for d in recurse_indented_repr(i, level + 1):
                     yield d
-                yield ',\n'
+                yield ",\n"
             yield one_indent * level
-            yield ']'
+            yield "]"
         else:
             yield repr(o)
-    result = ''.join(recurse_indented_repr(o, 0)) + '\n'
+
+    result = "".join(recurse_indented_repr(o, 0)) + "\n"
     f.write(result)
 
 
 def patch_main():
-    '''This is a hack to work around the fact that Windows multiprocessing needs
+    """This is a hack to work around the fact that Windows multiprocessing needs
     to import the original main module, and assumes that it corresponds to a file
     ending in .py.
 
@@ -1383,92 +1420,66 @@
 
     See also: http://bugs.python.org/issue19946
     And: https://bugzilla.mozilla.org/show_bug.cgi?id=914563
-    '''
+    """
     # XXX In Python 3.4 the multiprocessing module was re-written and the below
     # code is no longer valid. The Python issue19946 also claims to be fixed in
     # this version. It's not clear whether this hack is still needed in 3.4+ or
     # not, but at least some basic mach commands appear to work without it. So
     # skip it in 3.4+ until we determine it's still needed.
-    if sys.platform == 'win32' and sys.version_info < (3, 4):
-        import inspect
+    if sys.platform == "win32" and sys.version_info < (3, 4):
         import os
         from multiprocessing import forking
+
         global orig_command_line
 
         # Figure out what multiprocessing will assume our main module
         # is called (see python/Lib/multiprocessing/forking.py).
-        main_path = getattr(sys.modules['__main__'], '__file__', None)
+        main_path = getattr(sys.modules["__main__"], "__file__", None)
         if main_path is None:
             # If someone deleted or modified __main__, there's nothing left for
             # us to do.
             return
         main_file_name = os.path.basename(main_path)
         main_module_name, ext = os.path.splitext(main_file_name)
-        if ext == '.py':
+        if ext == ".py":
             # If main is a .py file, everything ought to work as expected.
             return
 
-        def fork_interpose():
-            import imp
-            import os
-            import sys
-            orig_find_module = imp.find_module
-
-            def my_find_module(name, dirs):
-                if name == main_module_name:
-                    path = os.path.join(dirs[0], main_file_name)
-                    f = open(path)
-                    return (f, path, ('', 'r', imp.PY_SOURCE))
-                return orig_find_module(name, dirs)
-
-            # Don't allow writing bytecode file for the main module.
-            orig_load_module = imp.load_module
-
-            def my_load_module(name, file, path, description):
-                # multiprocess.forking invokes imp.load_module manually and
-                # hard-codes the name __parents_main__ as the module name.
-                if name == '__parents_main__':
-                    old_bytecode = sys.dont_write_bytecode
-                    sys.dont_write_bytecode = True
-                    try:
-                        return orig_load_module(name, file, path, description)
-                    finally:
-                        sys.dont_write_bytecode = old_bytecode
-
-                return orig_load_module(name, file, path, description)
-
-            imp.find_module = my_find_module
-            imp.load_module = my_load_module
-            from multiprocessing.forking import main
-            main()
-
         def my_get_command_line():
-            fork_code, lineno = inspect.getsourcelines(fork_interpose)
-            # Remove the first line (for 'def fork_interpose():') and the three
-            # levels of indentation (12 spaces), add our relevant globals.
-            fork_string = ("main_file_name = '%s'\n" % main_file_name +
-                           "main_module_name = '%s'\n" % main_module_name +
-                           ''.join(x[12:] for x in fork_code[1:]))
+            with open(
+                os.path.join(os.path.dirname(__file__), "fork_interpose.py"), "rU"
+            ) as fork_file:
+                fork_code = fork_file.read()
+            # Add our relevant globals.
+            fork_string = (
+                "main_file_name = '%s'\n" % main_file_name
+                + "main_module_name = '%s'\n" % main_module_name
+                + fork_code
+            )
             cmdline = orig_command_line()
-            cmdline[2] = fork_string
+            # We don't catch errors if "-c" is not found because it's not clear
+            # what we should do if the original command line is not of the form
+            # "python ... -c 'script'".
+            cmdline[cmdline.index("-c") + 1] = fork_string
             return cmdline
+
         orig_command_line = forking.get_command_line
         forking.get_command_line = my_get_command_line
 
 
-def ensure_bytes(value, encoding='utf-8'):
+def ensure_bytes(value, encoding="utf-8"):
     if isinstance(value, six.text_type):
         return value.encode(encoding)
     return value
 
 
-def ensure_unicode(value, encoding='utf-8'):
+def ensure_unicode(value, encoding="utf-8"):
     if isinstance(value, six.binary_type):
         return value.decode(encoding)
     return value
 
 
-def ensure_subprocess_env(env, encoding='utf-8'):
+def ensure_subprocess_env(env, encoding="utf-8"):
     """Ensure the environment is in the correct format for the `subprocess`
     module.
 
@@ -1489,3 +1500,34 @@
         return time.clock()
     else:
         return time.process_time()
+
+
+def hexdump(buf):
+    """
+    Returns a list of hexdump-like lines corresponding to the given input buffer.
+    """
+    assert six.PY3
+    off_format = "%0{}x ".format(len(str(len(buf))))
+    lines = []
+    for off in range(0, len(buf), 16):
+        line = off_format % off
+        chunk = buf[off : min(off + 16, len(buf))]
+        for n, byte in enumerate(chunk):
+            line += " %02x" % byte
+            if n == 7:
+                line += " "
+        for n in range(len(chunk), 16):
+            line += "   "
+            if n == 7:
+                line += " "
+        line += "  |"
+        for byte in chunk:
+            if byte < 127 and byte >= 32:
+                line += chr(byte)
+            else:
+                line += "."
+        for n in range(len(chunk), 16):
+            line += " "
+        line += "|\n"
+        lines.append(line)
+    return lines
--- mozjs-78.11.0/python/mozbuild/mozbuild/backend/configenvironment.py	2021-05-31 17:20:25.000000000 +0300
+++ mozjs-91.5.0/python/mozbuild/mozbuild/backend/configenvironment.py	2022-01-07 17:21:02.000000000 +0300
@@ -9,7 +9,8 @@
 import sys
 import json
 
-from collections import Iterable, OrderedDict
+from collections.abc import Iterable
+from collections import OrderedDict
 from types import ModuleType
 
 import mozpack.path as mozpath
@@ -52,21 +52,18 @@
         if path not in code_cache or code_cache[path][0] != mtime:
             # Add config.status manually to sys.modules so it gets picked up by
             # iter_modules_in_path() for automatic dependencies.
-            mod = ModuleType('config.status')
+            mod = ModuleType("config.status")
             mod.__file__ = path
-            sys.modules['config.status'] = mod
+            sys.modules["config.status"] = mod
 
-            with open(path, 'rt') as fh:
+            with open(path, "rt") as fh:
                 source = fh.read()
                 code_cache[path] = (
                     mtime,
-                    compile(source, path, 'exec', dont_inherit=1)
+                    compile(source, path, "exec", dont_inherit=1),
                 )
 
-        g = {
-            '__builtins__': __builtins__,
-            '__file__': path,
-        }
+        g = {"__builtins__": __builtins__, "__file__": path}
         l = {}
         try:
             exec(code_cache[path][1], g, l)
@@ -75,7 +72,7 @@
 
         config = BuildConfig()
 
-        for name in l['__all__']:
+        for name in l["__all__"]:
             setattr(config, name, l[name])
 
         return config
@@ -221,7 +207,7 @@
     def __init__(self, config_statusd, typ, environ_override=False):
         self._dict = {}
         self._datadir = mozpath.join(config_statusd, typ)
-        self._config_track = mozpath.join(self._datadir, 'config.track')
+        self._config_track = mozpath.join(self._datadir, "config.track")
         self._files = set()
         self._environ_override = environ_override
 
@@ -265,11 +251,11 @@
 
         with FileAvoidWrite(self._config_track) as fh:
             for f in sorted(new_files):
-                fh.write('%s\n' % f)
+                fh.write("%s\n" % f)
 
     def __getitem__(self, key):
         if self._environ_override:
-            if (key not in ('CPP', 'CXXCPP', 'SHELL')) and (key in os.environ):
+            if (key not in ("CPP", "CXXCPP", "SHELL")) and (key in os.environ):
                 return os.environ[key]
 
         if key not in self._dict:
--- mozjs-78.11.0/testing/mozbase/manifestparser/manifestparser/filters.py	2021-05-31 17:20:25.000000000 +0300
+++ mozjs-91.5.0/testing/mozbase/manifestparser/manifestparser/filters.py	2022-01-07 17:21:02.000000000 +0300
@@ -8,11 +8,16 @@
 possible to define custom filters if the built-in ones are not enough.
 """
 
-from __future__ import absolute_import
+from __future__ import absolute_import, division
 
 import itertools
 import os
-from collections import defaultdict, MutableSequence
+from collections import defaultdict
+
+try:
+    from collections.abc import MutableSequence
+except ImportError:
+    from collections import MutableSequence
 
 import six
 from six import string_types
@@ -26,26 +31,34 @@
 logger = None
 
 
-def log(msg, level='info'):
+def log(msg, level="info"):
     from mozlog import get_default_logger
+
     global logger
     if not logger:
-        logger = get_default_logger(component='manifestparser')
+        logger = get_default_logger(component="manifestparser")
     if logger:
         getattr(logger, level)(msg)
 
 
 # built-in filters
 
+
+def _match(exprs, **values):
+    if any(parse(e, **values) for e in exprs.splitlines() if e):
+        return True
+    return False
+
+
 def skip_if(tests, values):
     """
     Sets disabled on all tests containing the `skip-if` tag and whose condition
     is True. This filter is added by default.
     """
-    tag = 'skip-if'
+    tag = "skip-if"
     for test in tests:
-        if tag in test and parse(test[tag], **values):
-            test.setdefault('disabled', '{}: {}'.format(tag, test[tag]))
+        if tag in test and _match(test[tag], **values):
+            test.setdefault("disabled", "{}: {}".format(tag, test[tag]))
         yield test
 
 
@@ -54,10 +67,10 @@
     Sets disabled on all tests containing the `run-if` tag and whose condition
     is False. This filter is added by default.
     """
-    tag = 'run-if'
+    tag = "run-if"
     for test in tests:
-        if tag in test and not parse(test[tag], **values):
-            test.setdefault('disabled', '{}: {}'.format(tag, test[tag]))
+        if tag in test and not _match(test[tag], **values):
+            test.setdefault("disabled", "{}: {}".format(tag, test[tag]))
         yield test
 
 
@@ -66,10 +79,10 @@
     Sets expected to 'fail' on all tests containing the `fail-if` tag and whose
     condition is True. This filter is added by default.
     """
-    tag = 'fail-if'
+    tag = "fail-if"
     for test in tests:
-        if tag in test and parse(test[tag], **values):
-            test['expected'] = 'fail'
+        if tag in test and _match(test[tag], **values):
+            test["expected"] = "fail"
         yield test
 
 
@@ -79,7 +92,7 @@
     added by passing `disabled=False` into `active_tests`.
     """
     for test in tests:
-        if 'disabled' not in test:
+        if "disabled" not in test:
             yield test
 
 
@@ -90,12 +103,13 @@
     `active_tests`.
     """
     for test in tests:
-        if os.path.exists(test['path']):
+        if os.path.exists(test["path"]):
             yield test
 
 
 # built-in instance filters
 
+
 class InstanceFilter(object):
     """
     Generally only one instance of a class filter should be applied at a time.
@@ -104,14 +118,18 @@
     `filterlist`. This class also formats filters' __str__ method for easier
     debugging.
     """
+
     unique = True
 
     __hash__ = super.__hash__
 
     def __init__(self, *args, **kwargs):
-        self.fmt_args = ', '.join(itertools.chain(
-            [str(a) for a in args],
-            ['{}={}'.format(k, v) for k, v in six.iteritems(kwargs)]))
+        self.fmt_args = ", ".join(
+            itertools.chain(
+                [str(a) for a in args],
+                ["{}={}".format(k, v) for k, v in six.iteritems(kwargs)],
+            )
+        )
 
     def __eq__(self, other):
         if self.unique:
@@ -145,24 +163,24 @@
         # Look for conditional subsuites, and replace them with the subsuite
         # itself (if the condition is true), or nothing.
         for test in tests:
-            subsuite = test.get('subsuite', '')
-            if ',' in subsuite:
+            subsuite = test.get("subsuite", "")
+            if "," in subsuite:
                 try:
-                    subsuite, cond = subsuite.split(',')
+                    subsuite, cond = subsuite.split(",")
                 except ValueError:
                     raise ParseError("subsuite condition can't contain commas")
                 matched = parse(cond, **values)
                 if matched:
-                    test['subsuite'] = subsuite
+                    test["subsuite"] = subsuite
                 else:
-                    test['subsuite'] = ''
+                    test["subsuite"] = ""
 
             # Filter on current subsuite
             if self.name is None:
-                if not test.get('subsuite'):
+                if not test.get("subsuite"):
                     yield test
             else:
-                if test.get('subsuite', '') == self.name:
+                if test.get("subsuite", "") == self.name:
                     yield test
 
 
@@ -180,8 +198,7 @@
 
     def __init__(self, this_chunk, total_chunks, disabled=False):
         assert 1 <= this_chunk <= total_chunks
-        InstanceFilter.__init__(self, this_chunk, total_chunks,
-                                disabled=disabled)
+        InstanceFilter.__init__(self, this_chunk, total_chunks, disabled=disabled)
         self.this_chunk = this_chunk
         self.total_chunks = total_chunks
         self.disabled = disabled
@@ -191,9 +208,10 @@
         if self.disabled:
             chunk_tests = tests[:]
         else:
-            chunk_tests = [t for t in tests if 'disabled' not in t]
+            chunk_tests = [t for t in tests if "disabled" not in t]
 
         tests_per_chunk = float(len(chunk_tests)) / self.total_chunks
+        # pylint: disable=W1633
         start = int(round((self.this_chunk - 1) * tests_per_chunk))
         end = int(round(self.this_chunk * tests_per_chunk))
 
@@ -241,21 +259,22 @@
         tests_by_dir = defaultdict(list)
         ordered_dirs = []
         for test in tests:
-            path = test['relpath']
+            path = test["relpath"]
 
             if path.startswith(os.sep):
                 path = path[1:]
 
             dirs = path.split(os.sep)
-            dirs = dirs[:min(self.depth, len(dirs) - 1)]
+            dirs = dirs[: min(self.depth, len(dirs) - 1)]
             path = os.sep.join(dirs)
 
             # don't count directories that only have disabled tests in them,
             # but still yield disabled tests that are alongside enabled tests
-            if path not in ordered_dirs and 'disabled' not in test:
+            if path not in ordered_dirs and "disabled" not in test:
                 ordered_dirs.append(path)
             tests_by_dir[path].append(test)
 
+        # pylint: disable=W1633
         tests_per_chunk = float(len(ordered_dirs)) / self.total_chunks
         start = int(round((self.this_chunk - 1) * tests_per_chunk))
         end = int(round(self.this_chunk * tests_per_chunk))
@@ -268,8 +287,9 @@
         # be yielded for reporting purposes. Put them all in chunk 1 for
         # simplicity.
         if self.this_chunk == 1:
-            disabled_dirs = [v for k, v in six.iteritems(tests_by_dir)
-                             if k not in ordered_dirs]
+            disabled_dirs = [
+                v for k, v in six.iteritems(tests_by_dir) if k not in ordered_dirs
+            ]
             for disabled_test in itertools.chain(*disabled_dirs):
                 yield disabled_test
 
@@ -282,6 +302,7 @@
     :param this_chunk: the current chunk, 1 <= this_chunk <= total_chunks
     :param total_chunks: the total number of chunks
     """
+
     def __init__(self, this_chunk, total_chunks, *args, **kwargs):
         InstanceFilter.__init__(self, this_chunk, total_chunks, *args, **kwargs)
         self.this_chunk = this_chunk
@@ -289,19 +310,24 @@
 
     def __call__(self, tests, values):
         tests = list(tests)
-        manifests = set(t['manifest'] for t in tests)
+        manifests = set(t["manifest"] for t in tests)
 
         tests_by_manifest = []
         for manifest in manifests:
-            mtests = [t for t in tests if t['manifest'] == manifest]
+            mtests = [t for t in tests if t["manifest"] == manifest]
             tests_by_manifest.append(mtests)
-        tests_by_manifest.sort(reverse=True, key=lambda x: (len(x), x))
+        # Sort tests_by_manifest from largest manifest to shortest; include
+        # manifest name as secondary key to ensure consistent order across
+        # multiple runs.
+        tests_by_manifest.sort(reverse=True, key=lambda x: (len(x), x[0]["manifest"]))
 
         tests_by_chunk = [[] for i in range(self.total_chunks)]
         for batch in tests_by_manifest:
             # Sort to guarantee the chunk with the lowest score will always
             # get the next batch of tests.
-            tests_by_chunk.sort(key=lambda x: (len(x), x))
+            tests_by_chunk.sort(
+                key=lambda x: (len(x), x[0]["manifest"] if len(x) else "")
+            )
             tests_by_chunk[0].extend(batch)
 
         return (t for t in tests_by_chunk[self.this_chunk - 1])
@@ -327,14 +353,14 @@
 
     @classmethod
     def get_manifest(cls, test):
-        manifest = normsep(test.get('ancestor_manifest', ''))
+        manifest = normsep(test.get("ancestor_manifest", ""))
 
         # Ignore ancestor_manifests that live at the root (e.g, don't have a
         # path separator). The only time this should happen is when they are
         # generated by the build system and we shouldn't count generated
         # manifests for chunking purposes.
-        if not manifest or '/' not in manifest:
-            manifest = normsep(test['manifest_relpath'])
+        if not manifest or "/" not in manifest:
+            manifest = normsep(test["manifest_relpath"])
         return manifest
 
     def get_chunked_manifests(self, manifests):
@@ -343,10 +369,15 @@
 
         # Compute the average to use as a default for manifests that don't exist.
         times = [r[0] for r in runtimes]
+        # pylint --py3k W1619
+        # pylint: disable=W1633
         avg = round(sum(times) / len(times), 2) if times else 0
         missing = sorted([m for m in manifests if m not in self.runtimes])
-        log("Applying average runtime of {}s to the following missing manifests:\n{}".format(
-            avg, '  ' + '\n  '.join(missing)))
+        log(
+            "Applying average runtime of {}s to the following missing manifests:\n{}".format(
+                avg, "  " + "\n  ".join(missing)
+            )
+        )
         runtimes.extend([(avg, m) for m in missing])
 
         # Each chunk is of the form [<runtime>, <manifests>].
@@ -370,8 +401,14 @@
         manifests = set(self.get_manifest(t) for t in tests)
         chunks = self.get_chunked_manifests(manifests)
         runtime, this_manifests = chunks[self.this_chunk - 1]
-        log("Cumulative test runtime is around {} minutes (average is {} minutes)".format(
-            round(runtime / 60), round(sum([c[0] for c in chunks]) / (60 * len(chunks)))))
+        # pylint --py3k W1619
+        # pylint: disable=W1633
+        log(
+            "Cumulative test runtime is around {} minutes (average is {} minutes)".format(
+                round(runtime / 60),
+                round(sum([c[0] for c in chunks]) / (60 * len(chunks))),
+            )
+        )
         return (t for t in tests if self.get_manifest(t) in this_manifests)
 
 
@@ -420,19 +487,21 @@
         if isinstance(paths, string_types):
             paths = [paths]
         self.paths = paths
+        self.missing = set()
 
     def __call__(self, tests, values):
+        seen = set()
         for test in tests:
             for tp in self.paths:
                 tp = os.path.normpath(tp)
 
-                if tp.endswith('.ini'):
-                    mpaths = [test['manifest_relpath']]
-                    if 'ancestor_manifest' in test:
-                        mpaths.append(test['ancestor_manifest'])
+                if tp.endswith(".ini"):
+                    mpaths = [test["manifest_relpath"]]
+                    if "ancestor_manifest" in test:
+                        mpaths.append(test["ancestor_manifest"])
 
                     if os.path.isabs(tp):
-                        root = test['manifest'][:-len(test['manifest_relpath'])-1]
+                        root = test["manifest"][: -len(test["manifest_relpath"]) - 1]
                         mpaths = [os.path.join(root, m) for m in mpaths]
 
                     # only return tests that are in this manifest
@@ -440,20 +509,24 @@
                         continue
                 else:
                     # only return tests that start with this path
-                    path = test['relpath']
+                    path = test["relpath"]
                     if os.path.isabs(tp):
-                        path = test['path']
+                        path = test["path"]
 
                     if not os.path.normpath(path).startswith(tp):
                         continue
 
                 # any test path that points to a single file will be run no
                 # matter what, even if it's disabled
-                if 'disabled' in test and os.path.normpath(test['relpath']) == tp:
-                    del test['disabled']
+                if "disabled" in test and os.path.normpath(test["relpath"]) == tp:
+                    del test["disabled"]
+
+                seen.add(tp)
                 yield test
                 break
 
+        self.missing = set(self.paths) - seen
+
 
 # filter container
 
--- mozjs-78.11.0/python/mozbuild/mozbuild/makeutil.py	2021-05-31 17:20:25.000000000 +0300
+++ mozjs-91.5.0/python/mozbuild/mozbuild/makeutil.py	2022-01-07 17:21:02.000000000 +0300
@@ -7,24 +7,24 @@
 import os
 import re
 import six
-from collections import Iterable
+from collections.abc import Iterable
 
 
 class Makefile(object):
-    '''Provides an interface for writing simple makefiles
+    """Provides an interface for writing simple makefiles
 
     Instances of this class are created, populated with rules, then
     written.
-    '''
+    """
 
     def __init__(self):
         self._statements = []
 
     def create_rule(self, targets=()):
-        '''
+        """
         Create a new rule in the makefile for the given targets.
         Returns the corresponding Rule instance.
-        '''
+        """
         targets = list(targets)
         for target in targets:
             assert isinstance(target, six.text_type)
@@ -33,19 +33,19 @@
         return rule
 
     def add_statement(self, statement):
-        '''
+        """
         Add a raw statement in the makefile. Meant to be used for
         simple variable assignments.
-        '''
+        """
         assert isinstance(statement, six.text_type)
         self._statements.append(statement)
 
     def dump(self, fh, removal_guard=True):
-        '''
+        """
         Dump all the rules to the given file handle. Optionally (and by
         default), add guard rules for file removals (empty rules for other
         rules' dependencies)
-        '''
+        """
         all_deps = set()
         all_targets = set()
         for statement in self._statements:
@@ -54,18 +54,18 @@
                 all_deps.update(statement.dependencies())
                 all_targets.update(statement.targets())
             else:
-                fh.write('%s\n' % statement)
+                fh.write("%s\n" % statement)
         if removal_guard:
             guard = Rule(sorted(all_deps - all_targets))
             guard.dump(fh)
 
 
 class _SimpleOrderedSet(object):
-    '''
+    """
     Simple ordered set, specialized for used in Rule below only.
     It doesn't expose a complete API, and normalizes path separators
     at insertion.
-    '''
+    """
 
     def __init__(self):
         self._list = []
@@ -87,22 +87,23 @@
         def _add(iterable):
             emitted = set()
             for i in iterable:
-                i = i.replace(os.sep, '/')
+                i = i.replace(os.sep, "/")
                 if i not in self._set and i not in emitted:
                     yield i
                     emitted.add(i)
+
         added = list(_add(iterable))
         self._set.update(added)
         self._list.extend(added)
 
 
 class Rule(object):
-    '''Class handling simple rules in the form:
-           target1 target2 ... : dep1 dep2 ...
-                   command1
-                   command2
-                   ...
-    '''
+    """Class handling simple rules in the form:
+    target1 target2 ... : dep1 dep2 ...
+            command1
+            command2
+            ...
+    """
 
     def __init__(self, targets=()):
         self._targets = _SimpleOrderedSet()
@@ -111,9 +112,10 @@
         self.add_targets(targets)
 
     def add_targets(self, targets):
-        '''Add additional targets to the rule.'''
+        """Add additional targets to the rule."""
         assert isinstance(targets, Iterable) and not isinstance(
-            targets, six.string_types)
+            targets, six.string_types
+        )
         targets = list(targets)
         for target in targets:
             assert isinstance(target, six.text_type)
@@ -121,9 +123,8 @@
         return self
 
     def add_dependencies(self, deps):
-        '''Add dependencies to the rule.'''
-        assert isinstance(deps, Iterable) and not isinstance(
-            deps, six.string_types)
+        """Add dependencies to the rule."""
+        assert isinstance(deps, Iterable) and not isinstance(deps, six.string_types)
         deps = list(deps)
         for dep in deps:
             assert isinstance(dep, six.text_type)
@@ -131,9 +132,10 @@
         return self
 
     def add_commands(self, commands):
-        '''Add commands to the rule.'''
+        """Add commands to the rule."""
         assert isinstance(commands, Iterable) and not isinstance(
-            commands, six.string_types)
+            commands, six.string_types
+        )
         commands = list(commands)
         for command in commands:
             assert isinstance(command, six.text_type)
@@ -141,35 +143,35 @@
         return self
 
     def targets(self):
-        '''Return an iterator on the rule targets.'''
+        """Return an iterator on the rule targets."""
         # Ensure the returned iterator is actually just that, an iterator.
         # Avoids caller fiddling with the set itself.
         return iter(self._targets)
 
     def dependencies(self):
-        '''Return an iterator on the rule dependencies.'''
+        """Return an iterator on the rule dependencies."""
         return iter(d for d in self._dependencies if d not in self._targets)
 
     def commands(self):
-        '''Return an iterator on the rule commands.'''
+        """Return an iterator on the rule commands."""
         return iter(self._commands)
 
     def dump(self, fh):
-        '''
+        """
         Dump the rule to the given file handle.
-        '''
+        """
         if not self._targets:
             return
-        fh.write('%s:' % ' '.join(self._targets))
+        fh.write("%s:" % " ".join(self._targets))
         if self._dependencies:
-            fh.write(' %s' % ' '.join(self.dependencies()))
-        fh.write('\n')
+            fh.write(" %s" % " ".join(self.dependencies()))
+        fh.write("\n")
         for cmd in self._commands:
-            fh.write('\t%s\n' % cmd)
+            fh.write("\t%s\n" % cmd)
 
 
 # colon followed by anything except a slash (Windows path detection)
-_depfilesplitter = re.compile(r':(?![\\/])')
+_depfilesplitter = re.compile(r":(?![\\/])")
 
 
 def read_dep_makefile(fh):
@@ -179,30 +181,31 @@
     it contains. Ignores removal guard rules.
     """
 
-    rule = ''
+    rule = ""
     for line in fh.readlines():
         line = six.ensure_text(line)
-        assert not line.startswith('\t')
+        assert not line.startswith("\t")
         line = line.strip()
-        if line.endswith('\\'):
+        if line.endswith("\\"):
             rule += line[:-1]
         else:
             rule += line
             split_rule = _depfilesplitter.split(rule, 1)
             if len(split_rule) > 1 and split_rule[1].strip():
-                yield Rule(split_rule[0].strip().split()) \
-                      .add_dependencies(split_rule[1].strip().split())
-            rule = ''
+                yield Rule(split_rule[0].strip().split()).add_dependencies(
+                    split_rule[1].strip().split()
+                )
+            rule = ""
 
     if rule:
-        raise Exception('Makefile finishes with a backslash. Expected more input.')
+        raise Exception("Makefile finishes with a backslash. Expected more input.")
 
 
 def write_dep_makefile(fh, target, deps):
-    '''
+    """
     Write a Makefile containing only target's dependencies to the file handle
     specified.
-    '''
+    """
     mk = Makefile()
     rule = mk.create_rule(targets=[target])
     rule.add_dependencies(deps)
 
projeto & código: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
mantenedor atual: Michael Shigorin
mantenedor da tradução: Fernando Martini aka fmartini © 2009