[Twisted-Python] Configuration, Final Spec

Moshe Zadka moshez at zadka.site.co.il
Sat May 12 03:32:25 EDT 2001

Rewritten, standalone, spec

OK, let me first state some axioms:

1. Everything should be configurable the same way, from within twisted.

Glyph has mentioned that he's not familiar with what's in bin/ anymore:
he just mktelnetserver, and configures from within the telnet server
everything. This is what should happen, except not limited to the telnet

2. The configuration interface must not be ui specific.

This is obvious, right? Command line and web based aren't the only option.
No reason why we can't implement a special purpose client/server for configurin

3. It should be easy to optimize the configuration for a ui

This is like the last one -- since we might deal with very good UIs, we
need to give them enough information for using all their abilities to
help us.

4. It should be very easy to make an object configurable.

This is very important -- the harder it is, the less it will be easy
to add *good* code to twisted. This is what may be the single most idiotic
thing in Zope (and DC is aware of it! and thinking of how to fix it!). Let's
learn from their mistakes: the less methods, the better. The more the
learning curve is gradual (not needing to learn a class/method/interface
before you need the functionality), the better.

OK, so what do we need to do about it?
Here's a rough proposition:

the configurable *interface*, which will be a class, but not a class
people should inherit from, will contain the following methods:

.getParameters() --> return a dictionary: name of parameter, Parameter object
.setParameter(name, answer) --> notify the application that an answer has been
                             given to a particular question
                             It can throw an InvalidParameter exception with
                             a string for a reason. This is for
                             application-level verification. Note that 
                             application-level verification is discouraged.
.endParameters() --> the "application" promises that no methods of the object
                 will be called between a series of .setParameter()s and
                 .endParameters(). So, this means that if the UI got a bunch
                 of answers, it will call .setParameter() several times, and
                 then .endParameters(). The UI will *check* for this method's
                 existance, and will not call it if it doesn't exist.
.setParent(parent) --> if the object is created inside an InterfaceProperty
                       of some other object, module nested ArrayParameters
                       and DictParameters, .setParent will be called with
                       that object, *if it exists*.

Parameter objects are meant to be open ended.
They can contain a default.

Here is the general interface of the Question, that all objects conform

.hasValue() --> boolean, whether the Parameter already contains an
.getValue() --> will only work if .hasValue() is true, returns the answer
.setValue(val) --> make .hasValue() true
.title --> A string, the human-readable description of the property.

Objects which can be created by the UI should have an initParameters
attribute which should be a sequence of Parameters, which correspond
to the mandatory arguments of the __init__ method.

Well, my proposal would not be complete if I didn't say what parameters are
available. Keep in mind, though, that the set of parameters is *open ended*.
That does not violate the light-and-lean guidelines, since a specific
Parameter class will only be used if the functionality is needed.

Without further ado:

class BooleanParameter:
class IntParameter: (can have .min and .max)
class FloatParameter:
class StringParameter: (can have .maxlength)
class LongStringParameter: (same as above -- it's a hint to the ui)
class InterfaceParameter: (specify interface, valid answers are objects)
class ArrayParameter: (an array of the same kind of question)
class DictParameter: (a dictionary mapping strings -> same kind of question)

The constructor will always take a title as a first argument, and possibly
some more parameters if appropriate. I'm thinking of adding some generic 
methods, the most interesting one is traverse, which either returns
a Parameter or throws a ValueError("node parameter").

A class will be said to implement an interface if the interface class
is a member of the __implements__ attribute. We can refine it to saying
that the interface is a superclass of some member of __implements__:

def implements(klass, interface):
    for member in klass.__implements__:
        if issubclass(member, interface):
            return 1
    return 0

This leaves open the question of how classes register with the UI at all.
A possibly radical solution will be to have the UI scan through sys.modules,
and each class will be checked for the __implements__ attribute. A less
radical option is to have a register(klass) function which registers
it with the UI. register() can be used from within the module, if it is
an active participant, or from within an importing module.


class Server: # note -- not inheriting from anything

    initParameters = (StringParameter("Server Name"), IntParameter("Port"))
    def __init__(self, name, port):
        self.name, self.port = name, port

    def getParameters(self):
        name = StringQuestion("Server Name")
        port = IntQuestion("Port")
        return {'port': port, 'name': name}

    def setParameter(self, name, answer):
        # note: no need to use int(answer)
        # for port: an IntQuestion has an integer as a .getValue()
        setattr(self, name, answer)

"I'll be ex-DPL soon anyway so I'm        |LUKE: Is Perl better than Python?
looking for someplace else to grab power."|YODA: No...no... no. Quicker,
   -- Wichert Akkerman (on debian-private)|      easier, more seductive.
For public key, finger moshez at debian.org  |http://www.{python,debian,gnu}.org

"I'll be ex-DPL soon anyway so I'm        |LUKE: Is Perl better than Python?
looking for someplace else to grab power."|YODA: No...no... no. Quicker,
   -- Wichert Akkerman (on debian-private)|      easier, more seductive.
For public key, finger moshez at debian.org  |http://www.{python,debian,gnu}.org

More information about the Twisted-Python mailing list