#!/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)