[Subversion] / PEAK / src / peak / storage / DDE.py  

View of /PEAK/src/peak/storage/DDE.py

Parent Directory | Revision Log
Revision: 1086 - (download) (as text)
Tue May 6 23:33:16 2003 UTC (21 years ago) by pje
File size: 5298 byte(s)
Began work on replacing 'naming.ParsedURL' with a structure type using
'peak.model'.  See 'CHANGES.txt' for a summary of how your ParsedURL
subclasses must be changed.  There is a further refactoring coming,
however, to support simpler parsing mechanisms for complex URL syntaxes,
and to support URLs generating a "canonical form" body part.  This will
be important for robust comparison of URLs, path manipulation, etc.
from peak.api import *

import os, sys, weakref
from time import sleep


class DDEConnectionError(Exception):
    """Problem connecting to a DDE Server"""


class ServerManager(object):

    """This ensures that 'Shutdown()' gets called when the server is GC'd"""

    def __init__(self,name,logger=logs.AbstractLogger(level=logs.EMERG)):
        import win32ui, dde
        server = self.server = dde.CreateServer()
        self.name = name
        self.logger = logger
        server.Create(name)

    def __call__(self, serviceName, topicName):
        import dde
        conn = dde.CreateConversation(self.server)

        self.logger.debug("%s: attempting DDE connection to (%s,%s)",
            self.name, serviceName, topicName
        )

        conn.ConnectTo(serviceName, topicName)
        return conn

    def __del__(self):
        if self.server is not None:
            self.logger.debug("%s: shutting down DDE server", self.name)
            self.server.Shutdown()
            self.server = None

    close = __del__


class ddeURL(naming.ParsedURL):

    """PEAK Win32 DDE URL

    Example::

        "win32.dde:service::topic;file=c:\\foo;retries=5;sleep=5"

    Syntax is 'service::topic' followed by semicolon-separated
    parameters, which may be 'file' to designate a file to be launched
    if the initial connection attempt is unsuccessful, 'retries' to
    indicate how many retries should occur if the initial attempt is
    unsuccessful, and 'sleep' to set the number of seconds to wait between
    retry attempts.

    These parameters are all available as attributes of the same names,
    including 'service' and 'topic'."""

    supportedSchemes = 'win32.dde',

    class service(model.structField):
        referencedType = model.String

    class topic(model.structField):
        referencedType = model.String

    class file(model.structField):
        referencedType = model.String
        defaultValue = None

    class retries(model.structField):
        referencedType = model.Integer
        defaultValue = 10

    class sleep(model.structField):
        referencedType = model.Integer
        defaultValue = 1




    def retrieve(self, refInfo, name, context, attrs=None):
        return DDEConnection(
            context.creationParent, context.creationName,
            serviceName=self.service,
            topicName=self.topic,
            launchFile=self.file,
            retries=self.retries,
            sleepFor=self.sleep,
        )


    def parse(self, scheme, body):

        _l = body.split(';')
        _svct = _l[0].split('::',1)

        if len(_svct)<2:
            raise exceptions.InvalidName("Must contain 'service::topic'", body)

        service, topic = _svct

        _other = dict( [tuple(_x.split('=', 1)) for _x in _l[1:]] )

        for _x in 'retries', 'sleep':
            if _x in _other:
                _other[_x] = int(_other[_x])

        for _x in _other:
            if _x not in ('file','retries','sleep'):
                raise exceptions.InvalidName(
                    "Unrecognized parameter %s=%s" % (_x,_other[_x])
                )

        _other['service'] = service
        _other['topic'] = topic
        return _other





class DDEConnection(storage.ManagedConnection):

    """Managed DDE connection"""

    serviceName = binding.requireBinding("Service name for DDE conversation")
    topicName   = binding.requireBinding("Topic name for DDE conversation")
    launchFile  = None

    retries  = 10
    sleepFor = 1

    logger = binding.bindToProperty('peak.logs.dde')

    def ddeServer(self,d,a):
        return ServerManager(
            str(binding.getComponentPath(self)),
            # weakref to the logger so that the ServerManager isn't part of
            # a cycle with us (if our logger refers to us)
            logger=weakref.proxy(self.logger)
        )

    ddeServer = binding.Once(ddeServer)


    def __call__(self, requestStr):
        """Issue a DDE request (requestStr -> responseStr)"""
        return self.connection.Request(requestStr)

    def execute(self, commandStr):
        """Execute a DDE command"""
        return self.connection.Exec(commandStr)

    def poke(self, commandStr, data=None):
        """DDE Poke of command string and optional data buffer"""
        return self.connection.Poke(commandStr, data)






    def _open(self):

        attemptedLaunch = False

        for i in range(self.retries+1):

            try:
                conn = self.ddeServer(self.serviceName, self.topicName)
            except:
                t,v,tb = sys.exc_info()
                if (t,v) != ('error','ConnectTo failed'):
                    del t,v,tb,conn
                    raise
            else:
                return conn

            if attemptedLaunch:
                sleep(self.sleepFor)
            else:
                if self.launchFile:
                    self.logger.debug("%s: launching %s",self,self.launchFile)
                    os.startfile(self.launchFile)

                attemptedLaunch = True


        else:
            raise DDEConnectionError(
                "ConnectTo failed", self.serviceName, self.topicName
            )

    def _close(self):
        self.ddeServer.close()
        del self.ddeServer  # force shutdown








cvs-admin@eby-sarna.com

Powered by ViewCVS 1.0-dev

ViewCVS and CVS Help