# pylint:disable-msg=E0222 # # Copyright (c) 2005 DoCoMo Euro-Labs GmbH (Munich, Germany). # Copyright (c) 2001-2005 LOGILAB S.A. (Paris, FRANCE). # # http://www.docomolab-euro.com/ -- mailto:tarlano@docomolab-euro.com # http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """interfaces and adapters for some base elements: :data handler: - url - file - event - command - category :data structure: - raw data - dictionary :communication: - protocol handler activator - email - IM message / presence - phone call :abstraction: - file-like openable - command initiator :version: $Revision:$ :author: Logilab :copyright: 2001-2005 LOGILAB S.A. (Paris, FRANCE) 2005 DoCoMo Euro-Labs GmbH (Munich, Germany) :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr http://www.docomolab-euro.com/ -- mailto:tarlano@docomolab-euro.com """ __revision__ = "$Id: lib.py,v 1.78 2002/10/14 14:24:11 syt Exp $" __docformat__ = "restructuredtext en" import urllib2 from narval.public import Interface, Adapter from narval.interfaces.core import IError # interfaces ################################################################## class IActivator(Interface): """a protocol handler activator""" def master_id(self, master_info): """ :type master_info: `narval.elements.base.MasterInformationsElement` :param master_info: element holding master's information :rtype: str :return: the master id for this protocol (if it applies) """ class IURL(Interface): """interface for url elements :ivar address: the URL string :ivar encoding: optional encoding of the file located at
""" def normalize(self): """return the expanded normalized url string""" def protocol(self): """return the normalized url string""" def path(self): """return the expanded normalized path string""" class IFile(IURL): """interface for file elements :ivar data: data contained in the file :ivar mode: mode used to open the file :ivar type: file type """ class IData(Interface): """interface for data container elements :ivar data: data contained in the file """ class ICommand(Interface): """interface for command elements :ivar command: the name of the command :ivar args: a list of arguments to give to the command """ class IDictionary(Interface): """interface for dictionary elements """ def __getitem__(self, item): """support access by subscription notation""" def __setitem__(self, item, value): """support modification by subscription notation""" class ICategory(Interface): """interface for a named category :ivar name: the name of the category """ class IEvent(Interface): """interface for a calendar event :ivar from_time: the start time of the event (mx.DateTime object) :ivar to_time: the end time of the event (optional mx.DateTime object, maybe None) :ivar subject: the event's subject (should be short and descriptive) :ivar description: a long description :ivar location: the location of the event :ivar attendees: people attendees to the event """ class IOpen(Interface): """open anything and return a file-like object """ def open(self): """return a readable file-like object""" class ICommandInitiator(Interface): """base interface for elements which may initiate a command those elements should provide the following method to allow narval to give feedback about the command execution """ def feedback(self, msg): """give feedback to the user who has triggered the command, whatever the used media :rtype: `IReplyable` :return: the element that will be used to give the feedback """ class IBaseIMessage(Interface): """interface for url elements :type type: str :ivar type: the type of the request, i.e. 'incoming' or 'outgoing' :type context: str :ivar context: the thread context identifier, according to the connection and to the sender (user or conference room.) :type activator_eid: int :ivar activator_eid: the eid of the jabber service activator """ def build_reply(self, answer): """create a reply to an incoming request :rtype: `IIMessage` :return: a new message ready to be sent """ def get_from(self): """return the the sender of the given message""" def get_to(self): """return the receiver of the given message""" def get_from_user(self): """return the user id of the sender of the given message, handling group chats """ def get_to_user(self): """return the user id of the receiver of the given message, handling group chats """ class IIMessage(IBaseIMessage): def get_body(self): """return the content of the message""" class IIPresence(IBaseIMessage): def get_status(self): """return the presence'status""" def set_status(self, status): """set the presence'status""" class IEmail(Interface): """interface for electronic mail :ivar message_id: a unique identifier for this message :ivar from_name: sender's name :ivar from_address: sender's email address :ivar to: main recipients :ivar cc: carbon copy recipients :ivar subject: email's subject line :ivar body: email's content :ivar date: :ivar type: incoming | outgoing :ivar content_type: """ def build_reply(self, msg, all=False): """create a reply to the sender of this email, include all recipients if all==True :type msg: unicode :var msg: the reply body :type all: bool :var all: flag indicating whether other recipients should be cced :rtype: `EmailElement` :return: an outgoing email """ def from_rfc822(cls, msg, path=None): """class method to create a EmailElement from a email message as defined by the mailbox module from the python standard library """ from_rfc822 = classmethod(from_rfc822) class IPhoneCall(Interface): """interface for a phone call definition :ivar sip_uri: the sip address of the callee :ivar sentence: the sentence to tell to the callee """ # adapters #################################################################### class AttrDelegatorAdapter(Adapter): """base adapter which proxies everything to a delegate, which is stored in a special attribute (other than 'original') """ __sources__ = () __implements__ = () _delegate = None def __getattr__(self, attr): return getattr(self._delegate, attr) def __setattr__(self, attr, value): if attr == 'original' or attr == '_delegate': self.__dict__[attr] = value else: setattr(self._delegate, attr, value) class IURLToIOpen(Adapter): """adapt IURL to IOpen""" __sources__ = (IURL,) __implements__ = (IOpen,) def open(self): """return a file-like object from an IURL object""" return urllib2.urlopen(self.original.normalize()) class ICommandToIIMessage(AttrDelegatorAdapter): """adapt elements with a 'from_msg' attribute to IIMessage""" __sources__ = (ICommand,) __implements__ = (IIMessage,) def __init__(self, original): # FIXME (syt): explain the lattest test... if not (original.from_msg and IIMessage in original.from_msg.__implements__): # FIXME: raise appropriate exception raise Exception() self._delegate = original.from_msg AttrDelegatorAdapter.__init__(self, original) class ICommandToIIPresence(AttrDelegatorAdapter): """adapt elements with a 'from_msg' attribute to IIPresence""" __sources__ = (ICommand,) __implements__ = (IIPresence,) def __init__(self, original): if not (original.from_msg and IIPresence in original.from_msg.__implements__): # FIXME: raise appropriate exception raise Exception() self._delegate = original.from_msg AttrDelegatorAdapter.__init__(self, original) class IErrorToIIMessage(ICommandToIIMessage): """adapt IError elements with a 'from_msg' attribute to outgoing IIMessage""" __sources__ = (IError,) __implements__ = (IIMessage,) def __init__(self, original): ICommandToIIMessage.__init__(self, original) self._delegate = original.from_msg.build_reply(original.msg) class ToICommandInitiator(Adapter): """IIMessage and IEmail elements are ICommandInitiator""" __sources__ = (IIMessage, IEmail) __implements__ = (ICommandInitiator,) def __init__(self, original): Adapter.__init__(self, original) if not original.type == 'incoming': # FIXME: raise appropriate exception raise Exception() def feedback(self, msg): return self.original.build_reply(msg) class ICommandToICommandInitiator(Adapter): """adapt ICommand elements to ICommandInitiator, through IIMessage""" __sources__ = (ICommand,) __implements__ = (ICommandInitiator,) def __init__(self, original): # If we can't adapt to IIMessage, don't go further self._msg = IIMessage(original) if not self._msg.type == 'incoming': # FIXME: raise appropriate exception raise Exception() Adapter.__init__(self, original) def feedback(self, msg): return self._msg.build_reply(msg) ## class IPhoneCallToICommand(AttrDelegatorAdapter): ## """adapt IError elements with a 'from_msg' attribute to outgoing IIMessage""" ## __sources__ = (IPhoneCall,) ## __implements__ = (ICommand,) ## def __init__(self, original): ## Adapter.__init__(self, original) ## if not getattr(original, 'from_cmd', None): ## # FIXME: raise appropriate exception ## raise Exception() ## self._delegate = original.from_cmd ## class IDictionaryToIData(Adapter): ## """adapt IDictionary to IData""" ## __sources__ = IDictionary, ## __implements__ = IData, ## def __init__(self, original): ## Adapter.__init__(self, original) ## data_dict = original.as_dict() ## self.data = '\n'.join([' - %r : %s' % kv for kv in data_dict.items()])