blob: 085e51def277ecd2227363c7114a1db15990d65d [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
82class NameComparableMixin(object):
83 """
84 A mixin that defines the object comparison and related functionality in terms
85 of a get_name(self) function.
86 """
87
88 def __lt__(self, other):
89 return self.get_name() < other.get_name()
90
91 def __gt__(self, other):
92 return self.get_name() > other.get_name()
93
94 def __eq__(self, other):
95 return self.get_name() == other.get_name()
96
97 def __le__(self, other):
98 return self.get_name() <= other.get_name()
99
100 def __ge__(self, other):
101 return self.get_name() >= other.get_name()
102
103 def __ne__(self, other):
104 return self.get_name() != other.get_name()
105
106 def __hash__(self):
107 return hash(self.get_name())
108
109Named.register(NameComparableMixin)
110collections.abc.Hashable.register(NameComparableMixin)
111
112class DumpMixin(metaclass=abc.ABCMeta):
113 """
114 A mixin to add support for dumping the string representation of an object to a
115 file. Requires the get_file_name(self) method be defined.
116 """
117
118 @abc.abstractmethod
119 def __str__(self):
120 """
121 Returns the data to be printed to a file by dump.
122 """
123 pass
124
125 def dump(self, directory):
126 """
127 Dump this object to a file in the given directory
128 """
129 out_file = directory / self.get_file_name()
130 if out_file.exists():
131 out_file.unlink()
132 with out_file.open('w') as out:
133 print(str(self), file=out)
134
135FileLike.register(DumpMixin)