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