python-peps/pep-0245.txt

1061 lines
37 KiB
Plaintext
Raw Normal View History

PEP: 245
Title: Python Interfaces
Version: $Revision$
Author: michel@digicool.com (Michel Pelletier)
Discussions-To: http://www.zope.org/Wikis/Interfaces
Status: Draft
Type: Standards Track
Created: 11-Jan-2001
Python-Version: 2.2
2001-03-21 16:50:48 -05:00
Post-History: 21-Mar-2001
Introduction
This PEP describes a Python interface model and a proposed syntax
for creating interface objects in Python.
Background
In addition to thinking about adding a static type system to
Python, the Types-SIG was also charged to devise an interface
system for Python. In December of 1998, Jim Fulton released a
prototype interfaces system based on discussions from the SIG.
Many of the issues and background information on this discussion
and prototype can be found in the SIG archives[1].
Around the end of 2000, Digital Creations began thinking about
better component model designs for Zope[2]. Zope's future
component model relies heavily on interface objects. This led to
further development of Jim's "Scarecrow" interfaces prototype.
Starting with version 2.3, Zope comes with an Interface package as
standard software. Zope's Interface package is used as the
reference implementation for this PEP.
Overview
This PEP proposes two additions to the Python language:
- An interface model
- A syntax for creating interfaces
The extended syntax proposed by this PEP relies on syntax
enhancements describe in PEP 232 [3] and describes an underlying
framework which PEP 233 [4] could be based upon. There is some
work being done with regard to interface objects and Proxy
objects, so for those optional parts of this PEP you may want to
see[5].
2001-03-21 18:21:49 -05:00
The Problem
Interfaces are important because they solve a number of problems
that arise while developing large systems with lots of developers:
- Developers waste a lot of time looking at the source code of
your system to figure out how objects work.
- Developers who are new to your system may misunderstand how
your objects work, causing, and possibly propagating, usage
errors.
- Because a lack of interfaces means usage is inferred from
the source, developers may end up using methods and
attributes that are meant for "internal use only".
- Code inspection can be hard, and very discouraging to novice
programmers trying to properly understand code written by
gurus.
- A lot of time is wasted when many people try very hard to
understand obscurity (like undocumented software). Effort
spend up front documenting interfaces will save much of this
time in the end.
Interfaces try to solve these problems by providing a way for you
to describe how to use an object, a built-in mechanism for
discovering that description, and a framework for defining well
known Python interfaces.
Python has very useful introspection features. It is well known
that this makes exploring concepts in the interactive interpreter
easier, because Python gives you the ability to look at all kinds
of information about the objects: the type, doc strings, instance
dictionaries, base classes, unbound methods and more.
Many of these features are oriented toward using and changing
implementations of software, and one of them ("doc strings") is
oriented toward providing documentation. This proposal describes
an extension to this natural introspection framework that
describes an object's interface.
Backward Compatibility
The proposed interface model does not introduce any backward
compatibility issues in Python. The proposed syntax, however,
does.
Any existing code that uses `interface' as an identifier will
break. There may be other kinds of backwards incompatibility that
defining `interface' as a new keyword will introduce. This
extension to Python's syntax does not change any existing syntax
in any backward incompatible way.
The new `from __future__' Python syntax[6], and the new warning
framework [7] is ideal for resolving this backward
incompatibility. To use interface syntax now, a developer could
use the statement:
from __future__ import interfaces
In addition, any code that uses the keyword `interface' as an
identifier will be issued a warning from Python. After the
appropriate period of time, the interface syntax would become
standard, the above import assertion would do nothing, and any
identifiers named `interface' would raise an exception. This
period of time is proposed to be 24 months.
Overview of the Interface Model
Python Interfaces are objects that denote, describe, and document
the behavior of an object, and can be associated with that object.
An object that is associated with an interface is said to
"implement" that interface.
Since there is no real way, short of a unit test (and then some),
to prove that an implementation is absolutely correct, the object
is trusted to not be lying about what interfaces it implements.
This trust, or contract, between the object and the developer is
the interface. Whether or not an interface enforcement mechanism
is in effect is discussed below.
Interface objects describe the behavior of an object by containing
useful information about the object. This information includes:
- Prose documentation about the object. In Python terms, this
is called the "doc string" of the interface.
- Descriptions of attributes including the name of the
attribute and prose documentation describing the attributes
usage.
- Descriptions of methods, including a name and prose
documentation. They also include a description of the
methods parameters.
- Descriptions of parameters including the name and prose
documentation. They can also describe properties about the
parameter like its position, name, and default value (if
any).
- Optional tagged data.
The four type of objects proposed in the interface model,
Interface, Attribute, Method and Parameter, are referred to as
"interface elements".
Overview of the Interface Syntax
This PEP proposes just one possible syntax for spelling interfaces
in the Python language. This syntax will be used throughout the
PEP to describe examples of using interfaces. For the most part,
the syntax of interfaces is very much like the syntax of classes,
but future needs, or needs brought up in discussion, may define
new possibilities for interface syntax. The syntax proposed does
not effect the proposed model.
Here is an example of two different interfaces created with the
proposed syntax:
interface CountFishInterface:
"Fish counting methods"
def oneFish():
"Increments the fish count by one"
def twoFish():
"Increments the fish count by two"
def getFishCount():
"Returns the fish count"
interface ColorFishInterface:
"Fish coloring methods"
def redFish():
"Sets the current fish color to red"
def blueFish():
"Sets the current fish color to blue"
def getFishColor():
"This returns the current fish color"
This code, when evaluated, will create two interfaces called
`CountFishInterface' and `ColorFishInterface'. These interfaces
are defined by the `interface' statement.
The prose documentation for the interfaces and their methods come
from doc strings. The method signature information comes from the
signatures of the `def' statements. Notice how there is no body
for the def statements. The interface does not implement a
service to anything; it merely describes one.
You can also create interfaces that "extend" other interfaces.
Here, you can see a new type of Interface that extends the
CountFishInterface and ColorFishInterface:
interface FishMarketInterface(CountFishInterface, ColorFishInterface):
"This is the documentation for the FishMarketInterface"
def getFishMonger():
"Returns the fish monger you can interact with"
def hireNewFishMonger(name):
"Hire a new fish monger"
def buySomeFish(quantity=1):
"Buy some fish at the market"
The FishMarketInteface extends upon the CountFishInterface and
ColorfishInterface.
The Interface Model
The interface for Interface objects can be expressed as an
interface. For example, all Interface objects implement the
`InterfaceBaseInterface':
interface InterfaceBaseInterface:
"""
A base interface that defines a common Interface interface.
"""
def getName():
"""
Returns the name of the current interface object.
"""
def getDoc():
"""
Returns the documentation for the current interface object.
"""
def setTaggedValue(tag, value):
"""
Associates `value' to the object with `tag'.
"""
def getTaggedValue(tag):
"""
Returns the value associated with `tag'.
"""
def getTaggedValueTags():
"""
Returns a list of all tags associated with this object.
"""
With this interface, you can ask an interface for its name or
documentation and a way to tag the interface with special data
(see the section Tagging Attributes for descriptions on using the
Tag methods):
>>> FishMarketInterface.getName()
'FishMarketInterface'
>>> FishMarketInterface.getDoc()
'This is the documentation for the FishMarketInterface'
>>>
Note that Methods, Attributes and Parameters also implement the
InterfaceBaseInterface, and their interfaces are described in a
later section of this PEP.
Interfaces can be asked about the interfaces they extend and what
Methods and Attributes they define by using the
`InterfaceInterface':
interface InterfaceInterface(InterfaceBaseInterface):
"""
This is the interface to interface objects that
are described in this document.
"""
def getBases():
"""
Returns a sequence of base interfaces
this interface extends.
"""
def extends(other):
"""
Does this interface extend the `other' interface?
"""
def isImplementedBy(object):
"""
Does the given object implement the interface?
"""
def isImplementedByInstancesOf(klass):
"""
Do instances of the given class implement
this interface?
"""
def names():
"""
Return the attribute names defined by the interface
"""
def namesAndDescriptions():
"""
Return the attribute names and description
objects defined by the interface
"""
def getDescriptionFor(name, default=None):
"""
Return the attribute description
object for the given name
"""
def deferred():
"""
Return a deferred class corresponding to the interface.
A deferred class is a class built like the interface that
can be subclassed by other classes. Calling any methods on
a deferred class will raise a `NotImplemented' error.
Sub-classes of deferred classes are therefor obliged to
override deferred class methods.
"""
The InterfaceInterface provides a way for discovering methods.
Here is an example of inspecting the methods of
ColorFishInterface:
>>> ColorFishInteface.names()
['redFish', 'blueFish', 'getFishColor']
>>> ColorFishInterface.namesAndDescriptions()
[('redFish', <Interface.Method.Method instance at 810f420>),
('blueFish', <Interface.Method.Method instance at 810a604>),
('getFishColor', <Interface.Method.Method instance at 810b060>)]
>>> ColorFishInteface.getDescriptionFor('getFishColor')
<Interface.Method.Method instance at 810b060>
>>> print ColorFishInterface.getDescriptionFor('getFishColor').getDoc()
This returns the current fish color
>>>
Other method provide ways to determine base interfaces:
>>> FishMarketInterface.getBases()
(<Interface CountFishInterface at 81006f0>,
<Interface ColorFishInterface at 810ab78>)
>>> FishMarketInterface.extends(ColorFishInterface)
1
>>> FishMarketInterface.extends(CountFishInterface)
1
It's important to point out that interface definitions may look a
lot like class definitions, but their semantics have a couple
different behaviors. For example, when a class definition uses
the following code:
class Foo:
def bar(self):
pass
"Foo.bar" returns you an unbound Python method. However, the
similar looking interface construct:
interface FooInterface:
def bar():
pass
FooInterface does not have the method attribute `bar'. Instead,
bar is described by using the interface interface to find out the
various attributes of the interface, like::
>>> FooInterface.names()
['bar']
>>>
This is an intentional feature of the design. Sharing names with
inheritance is sharing implementation. Interfaces can extend
other interfaces, but they do not share the contractual
responsibility of the interfaces they extend.
Classes and Interfaces
The example interfaces above do not describe any kind of behavior
for their methods, they just describe an interface that a typical
FishMarket object would realize.
You may notice a similarity between interfaces extending from
other interfaces and classes sub-classing from other classes.
This is a similar concept. However it is important to note that
interfaces extend interfaces and classes subclass classes. You
cannot extend a class or subclass an interface. Classes and
interfaces are separate.
The purpose of a class is to share the implementation of how an
object works. The purpose of an interface is to document how to
work with an object, not how the object is implemented. It is
possible to have several different classes with very different
implementations realize the same interface.
It's also possible to implement one interface with many classes
that mix in pieces the functionality of the interface or,
conversely, it's possible to have one class implement many
interfaces. Because of this, interfaces and classes should not be
confused or intermingled.
Interface Assertion
The next step is to put classes and interfaces together by
creating a concrete Python class that asserts that it implements
an interface. Here is an example FishMarket component that might
do this:
class FishError(Error):
pass
class FishMarket implements FishMarketInterface:
number = 0
color = None
monger_name = 'Crusty Barnacles'
def __init__(self, number, color):
self.number = number
self.color = color
def oneFish(self):
self.number += 1
def twoFish(self):
self.number += 2
def redFish(self):
self.color = 'red'
def blueFish(self):
self.color = 'blue'
def getFishCount(self):
return self.number
def getFishColor(self):
return self.color
def getFishMonger(self):
return self.monger_name
def hireNewFishMonger(self, name):
self.monger_name = name
def buySomeFish(self, quantity=1):
if quantity > self.count:
raise FishError("There's not enough fish")
self.count -= quantity
return quantity
This new class, FishMarket defines a concrete class which
implements the FishMarketInterface. The object following the
`implements' statement is called an "interface assertion". An
interface assertion can be either an interface object, or tuple of
interface assertions.
The interface assertion provided in a `class' statement like this
is stored in the class's `__implements__' class attribute. After
interpreting the above example, you would have a class statement
that can be examined like this:
>>> FishMarket
<class FishMarket at 8140f50>
>>> FishMarket.__implements__
(<Interface FishMarketInterface at 81006f0>,)
>>> f = FishMarket(6, 'red')
>>> implements(f, FishMarketInterface)
1
>>>
A class can realize more than one interface. For example, say you
had an interface called `ItemInterface' that described how an
object worked as an item in a container object. If you wanted to
assert that FishMarket instances realized the ItemInterface
interface as well as the FishMarketInterface, you can provide an
interface assertion that contained a tuple of interface objects to
the FishMarket class:
class FishMarket implements FishMarketInterface, ItemInterface:
# ...
Interface assertions can also be used if you want to assert that
one class implements an interface, and all of the interfaces that
another class implements:
class MyFishMarket implements FishMarketInterface, ItemInterface:
# ...
class YourFishMarket implements FooInterface, MyFishMarket.__implements__:
# ...
This new class YourFishMarket, asserts that it implements the
FooInterface, as well as the interfaces implemented by the
MyFishMarket class.
It's worth going into a little bit more detail about interface
assertions. An interface assertion is either an interface object,
or a tuple of interface assertions. For example:
FooInterface
FooInterface, (BarInteface, BobInterface)
FooInterface, (BarInterface, (BobInterface, MyClass.__implements__))
Are all valid interface assertions. When two interfaces define
the same attributes, the order in which information is preferred
in the assertion is from top-to-bottom, left-to-right.
There are other interface proposals that, in the need for
simplicity, have combined the notion of class and interface to
provide simple interface enforcement. Interface objects have a
`deferred' method that returns a deferred class that implements
this behavior::
>>> FM = FishMarketInterface.deferred()
>>> class MyFM(FM): pass
>>> f = MyFM()
>>> f.getFishMonger()
Traceback (innermost last):
File "<stdin>", line 1, in ?
Interface.Exceptions.BrokenImplementation:
An object has failed to implement interface FishMarketInterface
The getFishMonger attribute was not provided.
>>>
This provides for a bit of passive interface enforcement by
telling you what you forgot to do to implement that interface.
Tagging Interface Elements
Interface elements can be tagged with optional data for
application specific reasons. For example, in Zope an interface
defines not only documentation and descriptions for methods, it
also provides security assertions that associate methods with
Zope's permission based security model. In Zope, you could define
permissions on an interface by using the new syntax proposed by
PEP-232 (Function Attributes [3]) and implemented in Python 2.1:
from Zope.Security.Permissions import View
interface MyZopeInterface:
def foo():
""" This is the foo method """
foo.permission = View
This is a Zope specific example, but it shows off the syntax. For
your application, you many find other kinds of information to
associate with interface attributes. Some possible use cases we
came up with for tagged data are:
- type
- pre/post-conditions
- unit tests
- security assertions
- examples
- exception descriptions
These are some suggestions; this proposal does not specify what
tagged data can be used for.
Interface-aware built-ins
A useful extension to Python's list of built-in functions in the
light of interface objects would be `implements()'. This builtin
would expect two arguments, an object and an interface, and return
a true value if the object implements the interface, false
otherwise. For example:
>>> interface FooInterface: pass
>>> class Foo implements FooInterface: pass
>>> f = Foo()
>>> implements(f, FooInterface)
1
Currently, this functionality exists in the reference
implementation as functions in the `Interface' package, requiring
an "import Interface" to use it. Its existence as a built-in
would be purely for a convenience, and not necessary for using
interfaces, and analogous to `isinstance()' for classes.
Interface Enforcement and Type Checking
Interface enforcement could be useful for many different purposes.
For example, during the building/testing phase of software
development, enforcement could be turned on during unit testing to
ensure that interfaces are being used properly. When the software
is ready to ship in "production", this enforcement could be turned
off. We have implemented a simple interface enforcement system
with mxProxy [5] that can be turned on and off to debug
implementations.
Itamar Shtull-Trauring has also implemented a
precondition/postcondition enforcer based on Zope's ExtensionClass
and Interfaces. This package can be found along with the
reference implementation. This package allows you to turn on
debugging assertions when methods on an object are called. Here's
is an example from Itamar's implementation:
from Interface import Base, EnforcedInterface
class IDummy(Base):
""" Dummy interface """
def foo(self, n, s):
""" Return n * s, where n is an integer, and s is a string """
def bar(self, x):
""" Return 1 """
EnforcedInterface.setPrecondition(
"foo", IDummy,
"n > 0 and type(s) == type('string')")
EnforcedInterface.setPostcondition(
"foo", IDummy,
"type(result) == type('string')")
EnforcedInterface.setPostcondition("bar", IDummy, "result == 1")
This is Itamar's prototype implementation based on Zope's
ExtentionClass and Interface package. This code illustrates how
it is easy to associate a type qualifying assertion as a
precondition or post condition on an interface object. Using the
new 2.1 function attribute syntax, this same concept can be
expressed as an interface::
interface IDummy:
""" Dummy interface """
def foo(n, s):
""" Return n * s, where n is an integer, and s is a string
"""
foo.precondition = "n > 0 and type(s) == type('string')"
foo.postcondition = "type(result) == type('string')"
def bar(x):
""" Return 1
"""
bar.postcondition = "result == 1"
Now, this interface is tagged with data that a class wrapper based
on Extension Class might want to play with, like Itamar's
implementation.
Standard Python Protocols
There is another possible use for interfaces with type checking:
often, a programmer does not want to specify that a parameter must
be of a certain type, but that the parameter must implement a
specific interface. There are a number of standard, but informal,
interfaces in Python, often referred to as protocols. For example,
it is possible to think of "sequence" and "mapping" protocols as
interfaces, and do type checking with them::
interface MappingInterface:
"""Anything supporting __getitem__."""
def __getitem__(key):
"""Return an item from the mapping."""
interface SequenceInterface(MappingInterface):
"""Keys must be integers in a sequence starting at 0."""
This gives the programmer similar flexibility in defining expected
types as that which is proposed by other type checking proposals.
The current reference implementation defines the following Python
protocol definitions as interfaces:
interface MappingInterface:
def __getitem__(key):
""" Get the item that maps to the key """
interface SequentialInterface:
""" Keys must be used in order """
interface SizedInterface:
def __len__(self):
""" Returns the length of the object """
interface MutableInterface:
""" Object can be changed in place """
interface ComparableInterface:
""" Objects that can be tested for equality """
interface HashableInterface:
""" Objects that support hash """
interface SequenceInterface(MappingInterface, SequentialInterface):
"""Keys must be integers in a sequence starting at 0."""
interface OrderableInterface(ComparableInterface):
"""Objects that can be compared with < > == <= >= !="""
interface HashKeyInterface(ComparableInterface, HashableInterface):
"""Objects that are immutable with respect to state that
influences comparisons or hash values"""
There are many Python protocols to define in Python; this is by no
means an exhaustive list. The effort of defining protocol
interfaces for the entire Python language is not too extensive.
But the work load to define and provide interface assertions for
the entire standard library distribution would be a fairly
enormous task.
Type Assertion
This PEP so far only explains how to associate interfaces with
classes and their instances, but not with Python types. Since
types cannot be assigned attributes, the Interface package
maintains a registry of types and the interfaces they assert to
implement. This is done with a type assertion:
from Interface import Attribute, assertTypeImplements
import types
interface FunctionInterface:
__doc__ = Attribute("documentation string")
__name__ = Attribute("name with which this function was defined")
func_code = Attribute("Code object containing compiled function bytecode")
func_defaults = Attribute("tuple of any default values for arguments")
func_doc = Attribute("same as __doc__")
func_globals = Attribute("global namespace in which this function was defined")
func_name = Attribute("same as __name__")
assertTypeImplements(types.FunctionType, FunctionInterface)
The Interface package makes a number of assertions like this,
based on the properties of Python types defined in Ka-Ping Yee's
`inspect.py' module. The Interface package defines and asserts
the following type interfaces (for complete descriptions,
including Attribute definitions, see the reference
implementation):
- DocumentedInterface (Abstract interface that provides __doc__)
- NamedInterface (Abstract interface that provides __name___
- FunctionInterface
- TracebackInterface
- FrameInterface
- LambdaInterface
- CodeInterface
- ModuleInterface(DocumentedInterface)
- ClassInterface(DocumentedInterface)
- MethodInterface(DocumentedInterface, NamedInterface)
- BuiltinInterface(DocumentedInterface, NamedInterface)
- RoutineInterface(FunctionInterface, LambdaInterface,
MethodInterface, BuiltinInterface)
The Interface package maintains a registry of common Python types
and the above interfaces that they "assert". The framework also
provides an API function for registering new types called
`assertTypeImplements'. There are other Python types that come
with Python that are not defined yet, like file and other C
written file like types.
Creating Interfaces
Using the `interface' and `implements' syntax allows you to create
complex interface objects. The `Interface' module provides you
with some features that the Python syntax does not let you create,
and provides some standard interface tools to make using
interfaces more convenient.
Interfaces can be created by calling Interface.new(). New
supports the following interface:
def __init__(name, bases=(), attrs=None, doc=None):
"""
Create a new interface object. `Name' is the name of
the interface and the only required attribute. `bases' is
either an interface or a tuple. A sequence of pre-built
attribute objects can be passed to `attrs'. This could be
useful for building interface objects from modeling tools
or other generation tools. Last, documentation the
interface in general can be passed to `doc'. A `__doc__'
object can also be provided in the `attrs' sequence.
"""
Creating Attributes
Attributes can be created with Interface.Attribute(). The
Attribute constructor implements the following interface:
interface AttributeInterface(InterfaceBaseInterface):
def __init__(name=None, doc=None):
"""
Create a new attribute object. The object can be
named and described with name and doc.
"""
Creating Methods
Interface Methods can be created by calling Interface.Method().
Method objects have the same constructor arguments as Attribute
objects. In addition, they provide methods for return parameter
descriptions and other information:
interface MethodInterface(InterfaceBaseInterface, AttributeInterface):
def fromConcreteMethod(m):
"""
Introspects the python method `m' and creates a Method
object based on it. It can be either a bound method, an
unbound method, or a function
"""
def getParameters():
"""
Returns a sequence of parameter objects that describe
the individual parameters to a method call
"""
def getSignatureString():
"""
Returns a valid signature string that describes, in
python, the parameter interface to a method
"""
Parameter Objects
Parameter objects can be created with Interface.Parameter():
interface ParameterInterface(InterfaceBaseInterface):
def __init__(name, type=None, default=None, __doc__=None):
"""
Build a Parameter object with `name'. A `type' can be
provided and must be an interface, an interface tuple, a
python type, a python class, or None. If `default' is
provided, the default value is remembered and the method is
flagged as optional. Documentation can be provided with
`__doc__'.
"""
def default():
"""
Default value.
"""
def isOptional():
"""
a flag indicating if it is optional
"""
Reference Implementation
Zope's prototype system is distributed with Zope versions 2.3a1
and higher. The project Wiki also contains a stand-alone
distribution at[8].
At the object level, there are very few differences between this
PEP and the software distributed with Zope. With the current
model, Interfaces are declared with the following syntax:
import Interface
class CountFishInterface(Interface.Base):
"Fish counting methods"
def oneFish(self):
"Increments the fish count by one"
def twoFish(self):
"Increments the fish count by two"
def getFishCount(self):
"Returns the fish count"
This creates an Interface object called `CountFishInteface' by
overloading the Python `class' statement. This PEP proposes
adding a new keyword `interface' which allows the following,
equivalent declaration in Python::
interface CountFishInterface:
"Fish counting methods"
def oneFish():
"Increments the fish count by one"
def twoFish():
"Increments the fish count by two"
def getFishCount():
"Returns the fish count"
This syntax is cleaner and the intent is more clear. This syntax
has the added benefit of not overloading the concepts behind
`class'. Notice that interface methods do not define a `self'
parameter.
This proposal also suggests a way to associate Python classes with
the interfaces they implement by adding the `implements' keyword,
like this:
class Foo implements CountFishInterface:
""" The foo interface """
In the current model, this is done by assigning a class attribute
`__implements__':
class Foo:
""" The foo interface """
__implements__ = CountFishInterface
Because this is done with a class attribute, inheritance rules can
end up asserting interfaces for classes that may not want to be
signed up for those contracts.
Use Cases
A complete set of use cases is collected in the Wiki[9].
Additional use cases should be suggested to the author or entered
into the Wiki.
Other Uses
Component Model
The next generation of Zope will use interfaces heavily in its
component model. Zope's definition of a component is, in
fact, "an object with an interface". The Zope Component model
defines a base set of interfaces (including a component
interface). These base interfaces define how you work with
Zope components, how Zope components are accessed by other
components, and how components are access from the web and
other mediums.
Online Help System
Zope's online help system uses interface objects to derive the
API and prose online help information from objects. Other
Python applications, like text editors (think IDLE) could be
extended to introspect interfaces and provide easy context
sensitive help.
Summary of Proposed Changes to Python
Adding new `interface' keyword and extending class syntax with
`implements'.
Turning existing Interfaces Python package into a standard Python
type that provides objects that implement the InterfaceInterface,
described in this PEP.
Extending class interface to include __implements__.
Risks
This PEP proposes adding one new keyword to the Python language,
`interface'. This will break code.
2001-03-21 18:21:49 -05:00
Open Issues
Goals
Syntax
Architecture
Dissenting Opinion
This PEP has not yet been discussed on python-dev.
References
[1] http://mail.python.org/pipermail/types-sig/1998-December/date.html
[2] http://www.zope.org
[3] PEP 232, Function Attributes, Warsaw
http://python.sourceforge.net/peps/pep-0232.html
[4] PEP 233, Python Online Help, Prescod
http://python.sourceforge.net/peps/pep-0233.html
[5] http://www.lemburg.com/files/python/mxProxy.html
[6] PEP 236, Back to the __future__, Peters
http://python.sourceforge.net/peps/pep-0236.html
[7] PEP 230, Warning Framework, van Rossum
http://python.sourceforge.net/peps/pep-0236.html
[8] http://www.zope.org/Wikis/Interfaces
[9] http://www.zope.org/Wikis/Interfaces/InterfacesUseCases
Copyright
This document has been placed in the public domain.
Local Variables:
mode: indented-text
indent-tabs-mode: nil
End: