-
Notifications
You must be signed in to change notification settings - Fork 0
/
oop.py
107 lines (89 loc) · 2.99 KB
/
oop.py
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
# -*- coding: utf-8 -*-
# This file is part of the pymfony package.
#
# (c) Alexandre Quercia <[email protected]>
#
# For the full copyright and license information, please view the LICENSE
# file that was distributed with this source code.
from __future__ import absolute_import;
import abc;
import inspect;
"""
"""
__all__ = [
'abstract',
'interface',
'final',
];
class OOPMeta(abc.ABCMeta):
def __new__(cls, name, bases, namespace):
cls = abc.ABCMeta.__new__(cls, name, bases, namespace);
abstracts = set(cls.__abstractmethods__);
# Compute set of abstract method names
for name, value in namespace.items():
if getattr(value, "__isabstractmethod__", False):
abstracts.add(name);
for base in bases:
for name in getattr(base, "__interfacemethods__", set()):
value = getattr(cls, name, None);
if getattr(value, "__isabstractmethod__", False):
abstracts.add(name);
cls.__abstractmethods__ = frozenset(abstracts);
finals = set();
for name, value in namespace.items():
if getattr(value, "__isfinalmethod__", False):
finals.add(name);
for base in bases:
if getattr(base, "__isfinalclass__", False):
raise TypeError(
"Class {0} may not inherit from final class ({1})"
"".format(
cls.__module__+'.'+cls.__name__,
base.__module__+'.'+base.__name__
)
);
for name in getattr(base, "__finalmethods__", set()):
if name in namespace:
raise TypeError(
"Cannot override final method {0}.{1}()"
"".format(base.__module__+'.'+base.__name__, name)
);
cls.__finalmethods__ = frozenset(finals);
return cls
def abstractclass(obj):
"""Decorator"""
obj.__abstractclass__ = obj;
return obj;
def interface(obj):
"""Decorator"""
if not isinstance(obj, type(OOPMeta)):
return obj;
absMethods = set();
for name, method in obj.__dict__.items():
if inspect.isfunction(method):
absMethods.add(name);
setattr(obj, name, abc.abstractmethod(method));
obj.__interfacemethods__ = frozenset(absMethods);
return abstractclass(obj);
def abstract(obj):
"""Decorator"""
if inspect.isfunction(obj):
return abc.abstractmethod(obj);
elif isinstance(obj, type(OOPMeta)):
return abstractclass(obj);
return obj;
def finalclass(obj):
"""Decorator"""
obj.__isfinalclass__ = True;
return obj;
def finalmethod(obj):
"""Decorator"""
obj.__isfinalmethod__ = True;
return obj;
def final(obj):
"""Decorator"""
if inspect.isfunction(obj):
return finalmethod(obj);
elif isinstance(obj, type(OOPMeta)):
return finalclass(obj);
return obj;