diff options
Diffstat (limited to 'Demo/newmetaclasses')
-rw-r--r-- | Demo/newmetaclasses/Eiffel.py | 141 | ||||
-rw-r--r-- | Demo/newmetaclasses/Enum.py | 177 |
2 files changed, 0 insertions, 318 deletions
diff --git a/Demo/newmetaclasses/Eiffel.py b/Demo/newmetaclasses/Eiffel.py deleted file mode 100644 index 15fa58a..0000000 --- a/Demo/newmetaclasses/Eiffel.py +++ /dev/null @@ -1,141 +0,0 @@ -"""Support Eiffel-style preconditions and postconditions.""" - -from types import FunctionType as function - -class EiffelBaseMetaClass(type): - - def __new__(meta, name, bases, dict): - meta.convert_methods(dict) - return super(EiffelBaseMetaClass, meta).__new__(meta, name, bases, - dict) - - @classmethod - def convert_methods(cls, dict): - """Replace functions in dict with EiffelMethod wrappers. - - The dict is modified in place. - - If a method ends in _pre or _post, it is removed from the dict - regardless of whether there is a corresponding method. - """ - # find methods with pre or post conditions - methods = [] - for k, v in dict.items(): - if k.endswith('_pre') or k.endswith('_post'): - assert isinstance(v, function) - elif isinstance(v, function): - methods.append(k) - for m in methods: - pre = dict.get("%s_pre" % m) - post = dict.get("%s_post" % m) - if pre or post: - dict[k] = cls.make_eiffel_method(dict[m], pre, post) - -class EiffelMetaClass1(EiffelBaseMetaClass): - # an implementation of the "eiffel" meta class that uses nested functions - - @staticmethod - def make_eiffel_method(func, pre, post): - def method(self, *args, **kwargs): - if pre: - pre(self, *args, **kwargs) - x = func(self, *args, **kwargs) - if post: - post(self, x, *args, **kwargs) - return x - - if func.__doc__: - method.__doc__ = func.__doc__ - - return method - -class EiffelMethodWrapper: - - def __init__(self, inst, descr): - self._inst = inst - self._descr = descr - - def __call__(self, *args, **kwargs): - return self._descr.callmethod(self._inst, args, kwargs) - -class EiffelDescriptor(object): - - def __init__(self, func, pre, post): - self._func = func - self._pre = pre - self._post = post - - self.__name__ = func.__name__ - self.__doc__ = func.__doc__ - - def __get__(self, obj, cls): - return EiffelMethodWrapper(obj, self) - - def callmethod(self, inst, args, kwargs): - if self._pre: - self._pre(inst, *args, **kwargs) - x = self._func(inst, *args, **kwargs) - if self._post: - self._post(inst, x, *args, **kwargs) - return x - -class EiffelMetaClass2(EiffelBaseMetaClass): - # an implementation of the "eiffel" meta class that uses descriptors - - make_eiffel_method = EiffelDescriptor - -def _test(metaclass): - class Eiffel(metaclass=metaclass): - pass - - class Test(Eiffel): - - def m(self, arg): - """Make it a little larger""" - return arg + 1 - - def m2(self, arg): - """Make it a little larger""" - return arg + 1 - - def m2_pre(self, arg): - assert arg > 0 - - def m2_post(self, result, arg): - assert result > arg - - class Sub(Test): - def m2(self, arg): - return arg**2 - def m2_post(self, Result, arg): - super(Sub, self).m2_post(Result, arg) - assert Result < 100 - - t = Test() - t.m(1) - t.m2(1) - try: - t.m2(0) - except AssertionError: - pass - else: - assert False - - s = Sub() - try: - s.m2(1) - except AssertionError: - pass # result == arg - else: - assert False - try: - s.m2(10) - except AssertionError: - pass # result == 100 - else: - assert False - s.m2(5) - -if __name__ == "__main__": - _test(EiffelMetaClass1) - _test(EiffelMetaClass2) diff --git a/Demo/newmetaclasses/Enum.py b/Demo/newmetaclasses/Enum.py deleted file mode 100644 index 3ff8ddd..0000000 --- a/Demo/newmetaclasses/Enum.py +++ /dev/null @@ -1,177 +0,0 @@ -"""Enumeration metaclass.""" - -class EnumMetaclass(type): - """Metaclass for enumeration. - - To define your own enumeration, do something like - - class Color(Enum): - red = 1 - green = 2 - blue = 3 - - Now, Color.red, Color.green and Color.blue behave totally - different: they are enumerated values, not integers. - - Enumerations cannot be instantiated; however they can be - subclassed. - """ - - def __init__(cls, name, bases, dict): - super(EnumMetaclass, cls).__init__(name, bases, dict) - cls._members = [] - for attr in dict.keys(): - if not (attr.startswith('__') and attr.endswith('__')): - enumval = EnumInstance(name, attr, dict[attr]) - setattr(cls, attr, enumval) - cls._members.append(attr) - - def __getattr__(cls, name): - if name == "__members__": - return cls._members - raise AttributeError(name) - - def __repr__(cls): - s1 = s2 = "" - enumbases = [base.__name__ for base in cls.__bases__ - if isinstance(base, EnumMetaclass) and not base is Enum] - if enumbases: - s1 = "(%s)" % ", ".join(enumbases) - enumvalues = ["%s: %d" % (val, getattr(cls, val)) - for val in cls._members] - if enumvalues: - s2 = ": {%s}" % ", ".join(enumvalues) - return "%s%s%s" % (cls.__name__, s1, s2) - -class FullEnumMetaclass(EnumMetaclass): - """Metaclass for full enumerations. - - A full enumeration displays all the values defined in base classes. - """ - - def __init__(cls, name, bases, dict): - super(FullEnumMetaclass, cls).__init__(name, bases, dict) - for obj in cls.__mro__: - if isinstance(obj, EnumMetaclass): - for attr in obj._members: - # XXX inefficient - if not attr in cls._members: - cls._members.append(attr) - -class EnumInstance(int): - """Class to represent an enumeration value. - - EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves - like the integer 12 when compared, but doesn't support arithmetic. - - XXX Should it record the actual enumeration rather than just its - name? - """ - - def __new__(cls, classname, enumname, value): - return int.__new__(cls, value) - - def __init__(self, classname, enumname, value): - self.__classname = classname - self.__enumname = enumname - - def __repr__(self): - return "EnumInstance(%s, %s, %d)" % (self.__classname, self.__enumname, - self) - - def __str__(self): - return "%s.%s" % (self.__classname, self.__enumname) - -class Enum(metaclass=EnumMetaclass): - pass - -class FullEnum(metaclass=FullEnumMetaclass): - pass - -def _test(): - - class Color(Enum): - red = 1 - green = 2 - blue = 3 - - print(Color.red) - - print(repr(Color.red)) - print(Color.red == Color.red) - print(Color.red == Color.blue) - print(Color.red == 1) - print(Color.red == 2) - - class ExtendedColor(Color): - white = 0 - orange = 4 - yellow = 5 - purple = 6 - black = 7 - - print(ExtendedColor.orange) - print(ExtendedColor.red) - - print(Color.red == ExtendedColor.red) - - class OtherColor(Enum): - white = 4 - blue = 5 - - class MergedColor(Color, OtherColor): - pass - - print(MergedColor.red) - print(MergedColor.white) - - print(Color) - print(ExtendedColor) - print(OtherColor) - print(MergedColor) - -def _test2(): - - class Color(FullEnum): - red = 1 - green = 2 - blue = 3 - - print(Color.red) - - print(repr(Color.red)) - print(Color.red == Color.red) - print(Color.red == Color.blue) - print(Color.red == 1) - print(Color.red == 2) - - class ExtendedColor(Color): - white = 0 - orange = 4 - yellow = 5 - purple = 6 - black = 7 - - print(ExtendedColor.orange) - print(ExtendedColor.red) - - print(Color.red == ExtendedColor.red) - - class OtherColor(FullEnum): - white = 4 - blue = 5 - - class MergedColor(Color, OtherColor): - pass - - print(MergedColor.red) - print(MergedColor.white) - - print(Color) - print(ExtendedColor) - print(OtherColor) - print(MergedColor) - -if __name__ == '__main__': - _test() - _test2() |