def test_mro_merge(self): self.assertEqual([], mro.MROMerge([[], []])) self.assertEqual([1], mro.MROMerge([[], [1]])) self.assertEqual([1], mro.MROMerge([[1], []])) self.assertEqual([1, 2], mro.MROMerge([[1], [2]])) self.assertEqual([1, 2], mro.MROMerge([[1, 2], [2]])) self.assertEqual([1, 2, 3, 4], mro.MROMerge([[1, 2, 3], [2, 4]])) self.assertEqual([1, 2, 3], mro.MROMerge([[1, 2], [1, 2, 3]])) self.assertEqual([1, 2], mro.MROMerge([[1, 1], [2, 2]])) self.assertEqual([1, 2, 3, 4, 5, 6], mro.MROMerge([[1, 3, 5], [2, 3, 4], [4, 5, 6]])) self.assertEqual([1, 2, 3], mro.MROMerge([[1, 2, 1], [2, 3, 2]]))
def compute_mro(self): """Compute the class precedence list (mro) according to C3.""" bases = abstract_utils.get_mro_bases(self.bases(), self.vm) bases = [[self]] + [list(base.mro) for base in bases] + [list(bases)] # If base classes are `ParameterizedClass`, we will use their `base_cls` to # calculate the MRO. Bacause of type parameter renaming, we can not compare # the `ParameterizedClass`s which contain the same `base_cls`. See example: # class A(Iterator[T]): ... # class B(Iterator[U], A[V]): ... # The inheritance: [B], [Iterator, ...], [A, Iterator, ...], [Iterator, A] # So this has MRO order issue, but because the template names of # `ParameterizedClass` of `Iterator` are different, they will be treated as # different base classes and it will infer the MRO order is correct. # TODO(b/159044968): fix this by solving the template rename problem base2cls = {} newbases = [] for row in bases: baselist = [] for base in row: if base.isinstance_ParameterizedClass(): base2cls[base.base_cls] = base baselist.append(base.base_cls) else: base2cls[base] = base baselist.append(base) newbases.append(baselist) # calc MRO and replace them with original base classes return tuple(base2cls[base] for base in mro.MROMerge(newbases))
def compute_mro(self): """Compute the class precedence list (mro) according to C3.""" bases = abstract_utils.get_mro_bases(self.bases(), self.vm) bases = [[self]] + [list(base.mro) for base in bases] + [list(bases)] base2cls = {} newbases = [] for row in bases: baselist = [] for base in row: if base.isinstance_ParameterizedClass(): base2cls[base.base_cls] = base baselist.append(base.base_cls) else: base2cls[base] = base baselist.append(base) newbases.append(baselist) # calc MRO and replace them with original base classes return tuple(base2cls[base] for base in mro.MROMerge(newbases))