1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
#!/usr/bin/python3
#
# Copyright (C) 2015 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Common mixins and abstract base classes (ABCs) useful for writing test generators in python
"""
import abc
import collections.abc
import functools
class Named(metaclass=abc.ABCMeta):
"""
An abc that defines a get_name method.
"""
@abc.abstractmethod
def get_name(self):
"""
Returns a unique name to use as the identity for implementing comparisons.
"""
pass
class FileLike(metaclass=abc.ABCMeta):
"""
An abc that defines get_file_name and get_file_extension methods.
"""
@abc.abstractmethod
def get_file_name(self):
"""Returns the filename this object represents"""
pass
@abc.abstractmethod
def get_file_extension(self):
"""Returns the file extension of the file this object represents"""
pass
@functools.lru_cache(maxsize=None)
def get_file_extension_mixin(ext):
"""
Gets a mixin that defines get_file_name(self) in terms of get_name(self) with the
given file extension.
"""
class FExt(object):
"""
A mixin defining get_file_name(self) in terms of get_name(self)
"""
def get_file_name(self):
return self.get_name() + ext
def get_file_extension(self):
return ext
# Register the ABCs
Named.register(FExt)
FileLike.register(FExt)
return FExt
class SmaliFileMixin(get_file_extension_mixin(".smali")):
"""
A mixin that defines that the file this class belongs to is get_name() + ".smali".
"""
pass
class JavaFileMixin(get_file_extension_mixin(".java")):
"""
A mixin that defines that the file this class belongs to is get_name() + ".java".
"""
pass
class NameComparableMixin(object):
"""
A mixin that defines the object comparison and related functionality in terms
of a get_name(self) function.
"""
def __lt__(self, other):
return self.get_name() < other.get_name()
def __gt__(self, other):
return self.get_name() > other.get_name()
def __eq__(self, other):
return self.get_name() == other.get_name()
def __le__(self, other):
return self.get_name() <= other.get_name()
def __ge__(self, other):
return self.get_name() >= other.get_name()
def __ne__(self, other):
return self.get_name() != other.get_name()
def __hash__(self):
return hash(self.get_name())
Named.register(NameComparableMixin)
collections.abc.Hashable.register(NameComparableMixin)
class DumpMixin(metaclass=abc.ABCMeta):
"""
A mixin to add support for dumping the string representation of an object to a
file. Requires the get_file_name(self) method be defined.
"""
@abc.abstractmethod
def __str__(self):
"""
Returns the data to be printed to a file by dump.
"""
pass
def dump(self, directory):
"""
Dump this object to a file in the given directory
"""
out_file = directory / self.get_file_name()
if out_file.exists():
out_file.unlink()
with out_file.open('w') as out:
print(str(self), file=out)
FileLike.register(DumpMixin)
|