Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
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
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
0318a786
Commit
0318a786
authored
Dec 01, 1998
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
more work on first cut
parent
58b45b84
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
490 additions
and
33 deletions
+490
-33
lib/python/Interface/Attr.py
lib/python/Interface/Attr.py
+10
-0
lib/python/Interface/Basic.py
lib/python/Interface/Basic.py
+1
-1
lib/python/Interface/Exceptions.py
lib/python/Interface/Exceptions.py
+16
-0
lib/python/Interface/Mapping.py
lib/python/Interface/Mapping.py
+1
-1
lib/python/Interface/Method.py
lib/python/Interface/Method.py
+50
-0
lib/python/Interface/README.txt
lib/python/Interface/README.txt
+303
-0
lib/python/Interface/Standard.py
lib/python/Interface/Standard.py
+5
-7
lib/python/Interface/Util.py
lib/python/Interface/Util.py
+19
-10
lib/python/Interface/__init__.py
lib/python/Interface/__init__.py
+9
-1
lib/python/Interface/iclass.py
lib/python/Interface/iclass.py
+76
-13
No files found.
lib/python/Interface/Attr.py
0 → 100644
View file @
0318a786
class
Attribute
:
"""Attribute descriptions
"""
def
__init__
(
self
,
__name__
=
None
,
__doc__
=
None
):
"""Create an 'attribute' description
"""
self
.
__name__
=
__name__
self
.
__doc__
=
__doc__
or
__name__
lib/python/Interface/Basic.py
View file @
0318a786
...
...
@@ -15,7 +15,7 @@ class Orderable(Comparable):
class
Hashable
(
Base
):
"""Objects that support hash"""
class
Key
(
Comparable
,
Hashable
):
class
Hash
Key
(
Comparable
,
Hashable
):
"""Objects that are immutable with respect to state that
influences comparisons or hash values"""
...
...
lib/python/Interface/Exceptions.py
0 → 100644
View file @
0318a786
class
BrokenImplementation
(
Exception
):
"""An attribute is not completely implemented.
"""
def
__init__
(
self
,
interface
,
name
):
self
.
interface
=
interface
self
.
name
=
name
def
__str__
(
self
):
return
"""An object has failed to implement interface %(interface)s
The %(name)s attribute was not provided.
"""
%
self
.
__dict__
class
InvalidInterface
(
Exception
):
pass
lib/python/Interface/Mapping.py
View file @
0318a786
...
...
@@ -16,7 +16,7 @@ class Sequence(Mapping):
class
Sequential
(
Sequence
):
"Keys must be used in order"
Util
.
assertTypeImplements
(
type
(()),
(
Sequence
,
Sized
,
Basic
.
Key
))
Util
.
assertTypeImplements
(
type
(()),
(
Sequence
,
Sized
,
Basic
.
Hash
Key
))
Util
.
assertTypeImplements
(
type
([]),
(
Sequence
,
Sized
,
MutableMapping
))
Util
.
assertTypeImplements
(
type
({}),
(
Mapping
,
Sized
,
MutableMapping
))
lib/python/Interface/Method.py
0 → 100644
View file @
0318a786
"""Method interfaces
"""
import
Exceptions
from
Attr
import
Attribute
class
MethodClass
:
def
fromFunction
(
self
,
func
,
interface
=
''
):
m
=
Method
(
func
.
__name__
,
func
.
__doc__
)
defaults
=
func
.
func_defaults
or
()
c
=
func
.
func_code
na
=
c
.
co_argcount
names
=
c
.
co_varnames
d
=
{}
nr
=
na
-
len
(
defaults
)
if
nr
==
0
:
defaults
=
defaults
[
1
:]
nr
=
1
for
i
in
range
(
len
(
defaults
)):
d
[
names
[
i
+
nr
]]
=
defaults
[
i
]
m
.
positional
=
names
[
1
:
na
]
m
.
required
=
names
[
1
:
nr
]
m
.
optional
=
d
m
.
varargs
=
not
not
(
c
.
co_flags
&
4
)
m
.
kwargs
=
not
not
(
c
.
co_flags
&
8
)
m
.
interface
=
interface
return
m
class
Method
(
Attribute
):
"""Method interfaces
The idea here is that you have objects that describe methods.
This provides an opportunity for rich meta-data.
"""
fromFunction
=
MethodClass
().
fromFunction
interface
=
''
def
__init__
(
self
,
__name__
=
None
,
__doc__
=
None
):
"""Create a 'method' description
"""
self
.
__name__
=
__name__
self
.
__doc__
=
__doc__
or
__name__
def
__call__
(
self
,
*
args
,
**
kw
):
raise
Exception
.
BrokenImplementation
(
self
.
interface
,
self
.
name
)
lib/python/Interface/README.txt
0 → 100644
View file @
0318a786
Python Interfaces - The Scarecrow Implementation
This document describes my implementation of the Python interfaces
scarecrow proposal.
Status
This is a first-cut implementation of the proposal. My primary goal
is to shed light on some ideas and to provide a framework for
concrete discussion.
This implementation has had minimal testing. I expect many aspects
of the implementation to evolve over time.
Basic assumptions:
Interfaces are *not* classes:
o Interfaces have their own "hierarchy" (DAG really)
o Interfaces are objects that provide a protocol for
querying attributes (including methods) defined by an
an interface:
names() -- return a sequence of defined names
getDescriptionFor(name, [default]) --
Get a description of a name.
o You cannot mix interfaces and classes in base-class lists.
There are utilities and methods for computing implied interfaces
from classes and for computing "defered" classes from interfaces.
Why aren't interface classes? Interfaces perform a different
function that classes. Classes are for sharing implementation.
Interfaces are for denoting, defining, and documenting abstract
behavior.
Details
Software layout
There is an 'Interface' package that exports a variety of useful
facilities. These are described below.
Creating Interfaces
Interfaces can be created in several ways. The class statement
can be used with one or more interfaces provided as base classes.
This approach is convenient, syntactically, although it is a
little missleading, since interfaces are *not* classes. A minimal
interface that can be used as a base is Interface.Base.
You can also call Interface.new:
new(name, [bases, attrs, __doc__]) --
Create a new interface. The arguments are:
name -- the interface name
bases -- a sequence of "base" interfaces. Base interfaces
are "extended" by the new interface.
attrs -- an object that conforms to
'Interfaces.Standard.Dictionary' that provides attributes
defined by an interface. The attributes should be
'Interface.Attribute objects'.
Finally you can compute an implied interface from a class by calling
'Interface.impliedInterface':
impliedInterface(klass, [__name__, __doc__])
klass -- a class from which to create an interface.
__name__ -- The name of the interface. The default name is the
class name with the suffix "Interface".
__doc__ -- a doc string for the interface. The default doc
string is the class doc string.
The generated interface has attributes for each public method
defined in or inherited by the interface. A method is considered
public if it has a non-empty doc string and if it's name does
not begin with '_' or does begin and end with '__' and is
greater than 4 characters in length.
Note that computing an interface from a class does not automatically
assert that the class implements an interface.
Here's an example:
class X:
def foo(self, a, b):
...
XInterface=Interface.impliedInterface(X)
X.__implements__=XInterface
Interface assertions
Objects can assert that they implement one or more interfaces.
They do this by by defining an '__interfaces__' attribute that is
bound to an interface assertion.
An *interface assertion* is either:
- an Interface or
- a sequence of interface assertions.
Here are some examples of interface assertions:
I1
I1, I2
I1, (I2, I3)
where I1, I2, and I3 are interfaces.
Classes may provide (default) assertions for their instances
(and subclass instances). The usual inheritence rules apply.
Note that the definition of interface assertions makes composition
of interfaces straightforword. For example:
class A:
__implements__ = I1, I2
...
class B
__implements__ = I3, I4
class C(A. B):
...
class D:
__implements__ = I5
class E:
__implements__ = I5, A.__implements__
Special-case handling of classes
Special handling is required for Python classes to make assertions
about the interfaces a class implements, as opposed to the
interfaces that the instances of the class implement. You cannot
simply define an '__implements__' attribute for the class because
class "attributes" apply to instances.
By default, classes are assumed to implement the Interface.Standard.Class
interface. A class may override the default by providing a
'__class_implements__' attribute which will be treated as if it were
the '__implements__' attribute of the class.
Testing assertions
You can test whether an object implements an interface by calling
the 'implementedBy' method of the interface and passing the
object::
I1.implementedBy(x)
Similarly, you can test whether, by default, instances of a class
implement an interface by calling the 'implementedByInstancesOf'
method on the interface and passing the class::
I1.implementedByInstancesOf(A)
Testing interfaces
You can test whether one interface extends another by calling the
extends method on an interface:
I1.extends(I2)
Note that an interface does not extend itself.
Interface attributes
The purpose of an interface is to describe behavior, not to
provide implementation. In a similar fashion the attributes of
an interface describe and document the attributes provided by an
object that implements the interface.
There are currently two kinds of supported attributes:
Interface.Attribute -- The objects describe interface
attributes. They define at least names and doc strings and
may define other information as well.
Interface.Method -- These are interface attributes that
describe methods. They *may* define information about method
signatures. (Note Methods are kinds of Attributes.)
When a class statement is used to define an interface, method
definitions may be provided. These get converted to Method
objects during interface creation. For examle:
class I1(Interface.Base):
__name__=Attribute("The object's name")
def foo(self, a, b):
"blah blah"
defines an interface, 'I1' that has two attributes, '__name__' and
'foo'. The attribute 'foo' is a Method instance. It is *not* a
Python method.
It is my expectation that Attribute objects will eventually be
able to provide all sorts of interesting meta-data.
Defered classes
You cannot use interfaces as base classes. You can, however,
create "defered" classes from an interface:
class StackInterface(Interface.Base):
def push(self, v):
"Add a value to the top of a stack"
def pop(self):
"Remove and return an object from the top of the stack"
class Stack(StackInterface.defered()):
"This is supposed to implement a stack"
__implements__=StackInterface
Attempts to call methods inherited from a defered class will
raise Interface.BrokenImplementation exceptions.
Trial baloon: abstract implementations
Tim Peter's has expressed the desire to provide abstract
implementations in an interface definitions, where, presumably, an
abstract implementation uses only features defined by the
interface. For example:
class ListInterface(Interface.Standard.MutableSequence):
def append(self, v):
"add a value to the end of the object"
def push(self, v):
"add a value to the end of the object"
self.append(v)
Perhaps if a method definition has a body (other than a doc
string) then the corresponding method in the defered class
will not be defered. This would not be hard to do in CPython
if I cheat and sniff at method bytecodes.
Standard interfaces
The module Interface.Standard defines interfaces for standard
python obnjects.
This module, and the modules it uses need a lot more work!
Handling existing built-in types
A hack is provided to allow implementation assertions to be made
for builtin types. Interfaces.assertTypeImplements can be called
to assert that instances of a built-in type implement one or more
interfaces::
Util.assertTypeImplements(
type(1L),
(AbritraryPrecision, BitNumber, Signed))
Issues
o What should the objects that define attributes look like?
They shouldn't *be* the attributes, but should describe the
the attributes.
Note that we've made a first cut with 'Attribute' and
'Method' objects.
o There are places in the current implementation that use
'isinstance' that should be changed to use interface
checks.
o When the interface interfaces are finalized, C implementations
will be highly desirable for performance reasons.
o Alot more work is needed on the standard interface hierarchy.
...
lib/python/Interface/Standard.py
View file @
0318a786
...
...
@@ -7,16 +7,14 @@ Interface=Util.impliedInterface(
"""
)
iclass
.
Interface
.
__implements__
=
Interface
from
Basic
import
*
from
iclass
import
Named
,
Class
class
Class
(
Base
):
"""Implement shared instance behavior and create instances
Classes can be called to create an instance. This interface does
not specify what if any arguments are required.
"""
from
Basic
import
*
Util
.
assertTypeImplements
(
iclass
.
ClassType
,
Class
)
from
Number
import
*
from
Mapping
import
*
del
iclass
# cruft
del
Util
# cruft
lib/python/Interface/Util.py
View file @
0318a786
from
iclass
import
Interface
,
ClassType
,
Base
,
assertTypeImplements
from
iclass
import
Interface
,
Class
,
ClassType
,
Base
,
assertTypeImplements
from
types
import
FunctionType
def
impliedInterface
(
klass
,
__name__
=
None
,
__doc__
=
None
):
"""Create an interface object from a class
...
...
@@ -6,11 +7,13 @@ def impliedInterface(klass, __name__=None, __doc__=None):
The interface will contain only objects with doc strings and with names
that begin and end with '__' or names that don't begin with '_'.
"""
if
__name__
is
None
:
name
=
"%sInterface"
%
klass
.
__name__
if
__name__
is
None
:
__name__
=
"%sInterface"
%
klass
.
__name__
return
Interface
(
__name__
,
(),
_ii
(
klass
,
{}),
__doc__
)
def
_ii
(
klass
,
items
):
for
k
,
v
in
klass
.
__dict__
.
items
():
if
type
(
v
)
is
not
FunctionType
or
not
v
.
__doc__
:
continue
if
k
[:
1
]
==
'_'
and
not
(
len
(
k
)
>
4
and
k
[:
2
]
==
'__'
and
k
[
-
2
:]
==
'__'
):
continue
items
[
k
]
=
v
...
...
@@ -22,19 +25,25 @@ def implementedBy(object):
"""
r
=
[]
implements
=
tiget
(
type
(
object
),
None
)
if
implements
is
None
:
if
hasattr
(
object
,
'__implements__'
):
implements
=
object
.
__implements__
else
:
return
r
t
=
type
(
object
)
if
t
is
ClassType
:
if
hasattr
(
object
,
'__class_implements__'
):
implements
=
object
.
__class_implements__
else
:
implements
=
Class
elif
hasattr
(
object
,
'__implements__'
):
implements
=
object
.
__implements__
else
:
implements
=
tiget
(
t
,
None
)
if
implements
is
None
:
return
r
if
isinstance
(
implements
,
Interface
):
r
.
append
(
i
)
if
isinstance
(
implements
,
Interface
):
r
.
append
(
i
mplements
)
else
:
_wi
(
implements
,
r
.
append
)
return
r
def
implementedByInstances
(
object
):
def
implementedByInstances
Of
(
klass
):
"""Return the interfaces that instanced implement (by default)
"""
r
=
[]
...
...
@@ -50,7 +59,7 @@ def implementedByInstances(object):
implements
=
tiget
(
klass
,
None
)
if
implements
is
not
None
:
if
isinstance
(
implements
,
Interface
):
r
.
append
(
i
)
if
isinstance
(
implements
,
Interface
):
r
.
append
(
i
mplements
)
else
:
_wi
(
implements
,
r
.
append
)
return
r
...
...
lib/python/Interface/__init__.py
View file @
0318a786
from
Standard
import
Base
import
iclass
new
=
iclass
.
Interface
del
iclass
from
Util
import
impliedInterface
from
Util
import
assertTypeImplements
,
implementedBy
,
implementedByInstances
from
Util
import
assertTypeImplements
,
implementedBy
,
implementedByInstancesOf
from
Attr
import
Attribute
from
Method
import
Method
from
Exceptions
import
BrokenImplementation
lib/python/Interface/iclass.py
View file @
0318a786
...
...
@@ -3,12 +3,17 @@
Scarecrow version:
Classes or objects can implement an __implements__ attribute that
names a
sequence
of interface objects.
names a
n interface object or a collection
of interface objects.
An interface is defined using the class statement and one or more base
interfaces.
"""
from
Method
import
Method
from
Attr
import
Attribute
from
types
import
FunctionType
,
ClassType
import
Exceptions
_typeImplements
=
{}
class
Interface
:
...
...
@@ -31,7 +36,40 @@ class Interface:
self
.
__attrs
=
attrs
if
__doc__
is
not
None
:
self
.
__doc__
=
__doc__
for
k
,
v
in
attrs
.
items
():
if
isinstance
(
v
,
Method
):
v
.
interface
=
name
v
.
__name__
=
k
elif
isinstance
(
v
,
FunctionType
):
attrs
[
k
]
=
Method
.
fromFunction
(
v
,
name
)
elif
not
isinstance
(
v
,
Attribute
):
raise
Exceptions
.
InvalidInterface
(
"Concrete attribute, %s"
%
k
)
def
defered
(
self
):
"""Return a defered class corresponding to the interface
"""
if
hasattr
(
self
,
"_defered"
):
return
self
.
_defered
klass
=
{}
exec
"class %s: pass"
%
self
.
__name__
in
klass
klass
=
klass
[
self
.
__name__
]
self
.
__d
(
klass
.
__dict__
)
self
.
_defered
=
klass
return
klass
def
__d
(
self
,
dict
):
for
k
,
v
in
self
.
__dict__
.
items
():
if
isinstance
(
v
,
Method
)
and
not
dict
.
has_key
(
k
):
dict
[
k
]
=
v
for
b
in
self
.
__bases__
:
b
.
__d
(
dict
)
def
extends
(
self
,
other
):
"""Does an interface extend another?
...
...
@@ -45,11 +83,16 @@ class Interface:
tiget
=
_typeImplements
.
get
):
"""Does the given object implement the interface?
"""
implements
=
tiget
(
type
(
object
),
None
)
if
implements
is
None
:
if
hasattr
(
object
,
'__implements__'
):
implements
=
object
.
__implements__
else
:
return
0
t
=
type
(
object
)
if
t
is
ClassType
:
if
hasattr
(
object
,
'__class_implements__'
):
implements
=
object
.
__class_implements__
else
:
implements
=
Class
elif
hasattr
(
object
,
'__implements__'
):
implements
=
object
.
__implements__
else
:
implements
=
tiget
(
t
,
None
)
if
implements
is
None
:
return
0
if
isinstance
(
implements
,
Interface
):
return
implements
is
self
or
implements
.
extends
(
self
)
...
...
@@ -64,9 +107,9 @@ class Interface:
if
hasattr
(
klass
,
'__implements__'
):
implements
=
klass
.
__implements__
else
:
return
0
elif
hasattr
(
klass
,
'instancesImplement
s
'
):
elif
hasattr
(
klass
,
'instancesImplement'
):
# Hook for ExtensionClass. :)
implements
=
klass
.
instancesImplement
s
()
implements
=
klass
.
instancesImplement
()
else
:
implements
=
tiget
(
klass
,
None
)
...
...
@@ -95,16 +138,36 @@ class Interface:
def
__any
(
self
,
interfaces
):
for
i
in
interfaces
:
if
isinstance
(
i
,
Interface
):
return
i
is
self
or
i
.
extends
(
self
)
if
i
is
self
or
i
.
extends
(
self
):
return
1
else
:
return
self
.
__any
(
i
)
if
self
.
__any
(
i
):
return
1
return
0
ClassType
=
type
(
Interface
)
def
__repr__
(
self
):
return
"<Interface %s at %x>"
%
(
self
.
__name__
,
id
(
self
))
Base
=
Interface
(
"Interface"
)
class
Named
(
Base
):
"Objects that have a name."
__name__
=
Attribute
(
"The name of the object"
)
class
Class
(
Named
):
"""Implement shared instance behavior and create instances
Classes can be called to create an instance. This interface does
not specify what if any arguments are required.
"""
# Note that we don't use a function definition here, because
# we don't want to specify a signature!
__call__
=
Method
(
"Instantiate instances of the class"
)
__bases__
=
Attribute
(
"A sequence of base classes"
)
def
assertTypeImplements
(
type
,
interfaces
):
"""Return the interfaces implemented by objects of the given type
"""
_typeImplements
[
type
]
=
interfaces
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