Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
a0033163
Commit
a0033163
authored
Jul 11, 2002
by
Jeremy Hylton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Enum and Eiffel examples using new-style classes.
parent
20e5abc8
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
323 additions
and
0 deletions
+323
-0
Demo/newmetaclasses/Eiffel.py
Demo/newmetaclasses/Eiffel.py
+145
-0
Demo/newmetaclasses/Enum.py
Demo/newmetaclasses/Enum.py
+178
-0
No files found.
Demo/newmetaclasses/Eiffel.py
0 → 100644
View file @
a0033163
"""Support Eiffel-style preconditions and postconditions."""
from
new
import
function
class
EiffelBaseMetaClass
(
type
):
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
=
[]
prenpost
=
[]
for
k
,
v
in
dict
.
iteritems
():
if
k
.
endswith
(
'_pre'
)
or
k
.
endswith
(
'_post'
):
assert
isinstance
(
v
,
function
)
prenpost
.
append
(
k
)
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
)
convert_methods
=
classmethod
(
convert_methods
)
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
make_eiffel_method
=
staticmethod
(
make_eiffel_method
)
class
EiffelMetaClass1
(
EiffelBaseMetaClass
):
# an implementation of the "eiffel" meta class that uses nested functions
def
__new__
(
meta
,
name
,
bases
,
dict
):
meta
.
convert_methods
(
dict
)
return
super
(
EiffelMetaClass1
,
meta
).
__new__
(
meta
,
name
,
bases
,
dict
)
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
(
EiffelMetaClass1
):
# an implementation of the "eiffel" meta class that uses descriptors
make_eiffel_method
=
EiffelDescriptor
def
_test
(
metaclass
):
class
Eiffel
:
__metaclass__
=
metaclass
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
if
__name__
==
"__main__"
:
_test
(
EiffelMetaClass1
)
_test
(
EiffelMetaClass2
)
Demo/newmetaclasses/Enum.py
0 → 100644
View file @
a0033163
"""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
class
FullEnum
:
__metaclass__
=
FullEnumMetaclass
def
_test
():
class
Color
(
Enum
):
red
=
1
green
=
2
blue
=
3
print
Color
.
red
print
`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
`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
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment