home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Shareware / Comunicatii / jyte / jyte.exe / util.py < prev    next >
Encoding:
Python Source  |  2004-01-26  |  5.6 KB  |  191 lines

  1. """ General Server side utilities 
  2. """
  3. import pythoncom
  4. import policy
  5. import winerror
  6. from exception import COMException
  7.  
  8. def wrap(ob, iid=None, usePolicy=None, useDispatcher=None):
  9.   """Wraps an object in a PyGDispatch gateway.
  10.  
  11.      Returns a client side PyI{iid} interface.
  12.  
  13.      Interface and gateway support must exist for the specified IID, as
  14.      the QueryInterface() method is used.
  15.  
  16.   """
  17.   if usePolicy is None:
  18.     usePolicy = policy.DefaultPolicy
  19.   if useDispatcher == 1: # True will also work here.
  20.     import win32com.server.dispatcher
  21.     useDispatcher = win32com.server.dispatcher.DefaultDebugDispatcher
  22.   if useDispatcher is None or useDispatcher==0:
  23.     ob = usePolicy(ob)
  24.   else:
  25.     ob = useDispatcher(usePolicy, ob)
  26.  
  27.   # get a PyIDispatch, which interfaces to PyGDispatch
  28.   ob = pythoncom.WrapObject(ob)
  29.   if iid is not None:
  30.     ob = ob.QueryInterface(iid)       # Ask the PyIDispatch if it supports it?
  31.   return ob
  32.  
  33. def unwrap(ob):
  34.   """Unwraps an interface.
  35.  
  36.   Given an interface which wraps up a Gateway, return the object behind
  37.   the gateway.
  38.   """
  39.   ob = pythoncom.UnwrapObject(ob)
  40.   # see if the object is a dispatcher
  41.   if hasattr(ob, 'policy'):
  42.     ob = ob.policy
  43.   return ob._obj_
  44.  
  45.  
  46. class ListEnumerator:
  47.   """A class to expose a Python sequence as an EnumVARIANT.
  48.  
  49.      Create an instance of this class passing a sequence (list, tuple, or
  50.      any sequence protocol supporting object) and it will automatically
  51.      support the EnumVARIANT interface for the object.
  52.  
  53.      See also the @NewEnum@ function, which can be used to turn the
  54.      instance into an actual COM server.
  55.   """
  56.   _public_methods_ = [ 'Next', 'Skip', 'Reset', 'Clone' ]
  57.  
  58.   def __init__(self, data, index=0, iid = pythoncom.IID_IEnumVARIANT):
  59.     self._list_ = data
  60.     self.index = index
  61.     self._iid_ = iid
  62.  
  63.   def _query_interface_(self, iid):
  64.       if iid == self._iid_:
  65.           return 1
  66.   def Next(self, count):
  67.     result = self._list_[self.index:self.index+count]
  68.     self.Skip(count)
  69.     return result
  70.  
  71.   def Skip(self, count):
  72.     end = self.index + count
  73.     if end > len(self._list_):
  74.       end = len(self._list_)
  75.     self.index = end
  76.  
  77.   def Reset(self):
  78.     self.index = 0
  79.  
  80.   def Clone(self):
  81.     return self._wrap(self.__class__(self._list_, self.index))
  82.  
  83.   def _wrap(self, ob):
  84.     return wrap(ob)
  85.  
  86.  
  87. class ListEnumeratorGateway(ListEnumerator):
  88.   """A List Enumerator which wraps a sequence's items in gateways.
  89.  
  90.   If a sequence contains items (objects) that have not been wrapped for
  91.   return through the COM layers, then a ListEnumeratorGateway can be
  92.   used to wrap those items before returning them (from the Next() method).
  93.  
  94.   See also the @ListEnumerator@ class and the @NewEnum@ function.
  95.   """
  96.  
  97.   def Next(self, count):
  98.     result = self._list_[self.index:self.index+count]
  99.     self.Skip(count)
  100.     return map(self._wrap, result) 
  101.  
  102.  
  103. def NewEnum(seq,
  104.             cls=ListEnumerator,
  105.             iid=pythoncom.IID_IEnumVARIANT,
  106.             usePolicy=None,
  107.             useDispatcher=None):
  108.   """Creates a new enumerator COM server.
  109.  
  110.   This function creates a new COM Server that implements the 
  111.   IID_IEnumVARIANT interface.
  112.  
  113.   A COM server that can enumerate the passed in sequence will be
  114.   created, then wrapped up for return through the COM framework.
  115.   Optionally, a custom COM server for enumeration can be passed
  116.   (the default is @ListEnumerator@), and the specific IEnum
  117.   interface can be specified.
  118.   """
  119.   ob = cls(seq, iid=iid)
  120.   return wrap(ob, iid, usePolicy=usePolicy, useDispatcher=useDispatcher)
  121.  
  122.  
  123. class Collection:
  124.   "A collection of VARIANT values."
  125.  
  126.   _public_methods_ = [ 'Item', 'Count', 'Add', 'Remove', 'Insert' ]
  127.  
  128.   def __init__(self, data=None, readOnly=0):
  129.     if data is None:
  130.       data = [ ]
  131.     self.data = data
  132.  
  133.     # disable Add/Remove if read-only. note that we adjust _public_methods_
  134.     # on this instance only.
  135.     if readOnly:
  136.       self._public_methods_ = [ 'Item', 'Count' ]
  137.  
  138.   # This method is also used as the "default" method.
  139.   # Thus "print ob" will cause this to be called with zero
  140.   # params.  Handle this slightly more elegantly here.
  141.   # Ideally the  policy should handle this.
  142.   def Item(self, *args):
  143.     if len(args) != 1:
  144.       raise COMException(scode=winerror.DISP_E_BADPARAMCOUNT)
  145.  
  146.     try:
  147.       return self.data[args[0]]
  148.     except IndexError, desc:
  149.       raise COMException(scode=winerror.DISP_E_BADINDEX, desc=str(desc))
  150.  
  151.     
  152.   _value_ = Item
  153.   
  154.   def Count(self):
  155.     return len(self.data)
  156.  
  157.   def Add(self, value):
  158.     self.data.append(value)
  159.  
  160.   def Remove(self, index):
  161.     try:
  162.       del self.data[index]
  163.     except IndexError, desc:
  164.       raise COMException(scode=winerror.DISP_E_BADINDEX, desc=str(desc))
  165.  
  166.   def Insert(self, index, value):
  167.     try:
  168.       index = int(index)
  169.     except (ValueError, TypeError):
  170.       raise COMException(scode=winerror.DISP_E_TYPEMISMATCH)
  171.     self.data.insert(index, value)
  172.  
  173.   def _NewEnum(self):
  174.     return NewEnum(self.data)
  175.  
  176. def NewCollection(seq, cls=Collection):
  177.   """Creates a new COM collection object
  178.  
  179.   This function creates a new COM Server that implements the 
  180.   common collection protocols, including enumeration. (_NewEnum)
  181.  
  182.   A COM server that can enumerate the passed in sequence will be
  183.   created, then wrapped up for return through the COM framework.
  184.   Optionally, a custom COM server for enumeration can be passed
  185.   (the default is @Collection@).
  186.   """
  187.   return pythoncom.WrapObject(policy.DefaultPolicy(cls(seq)),
  188.                               pythoncom.IID_IDispatch,
  189.                               pythoncom.IID_IDispatch)
  190.  
  191.