• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/opal/ZSI/build/lib/ZSI/generate/pyclass.py

00001 ############################################################################
00002 # Joshua R. Boverhof, LBNL
00003 # See LBNLCopyright for copyright notice!
00004 ###########################################################################
00005 
00006 import pydoc, sys, warnings
00007 from ZSI import TC
00008 
00009 # If function.__name__ is read-only, fail
00010 def _x(): return
00011 try: 
00012     _x.func_name = '_y'
00013 except:
00014     raise RuntimeError,\
00015         'use python-2.4 or later, cannot set function names in python "%s"'\
00016         %sys.version
00017 del _x
00018 
00019 
00020 #def GetNil(typecode=None):
00021 #    """returns the nilled element, use to set an element 
00022 #    as nilled for immutable instance.
00023 #    """
00024 # 
00025 #    nil = TC.Nilled()
00026 #    if typecode is not None: nil.typecode = typecode
00027 #    return nil
00028 #
00029 #
00030 #def GetNilAsSelf(cls, typecode=None):
00031 #    """returns the nilled element with typecode specified, 
00032 #    use returned instance to set this element as nilled.
00033 #    
00034 #    Key Word Parameters:
00035 #        typecode -- use to specify a derived type or wildcard as nilled.
00036 #    """
00037 #    if typecode is not None and not isinstance(typecode, TC.TypeCode):
00038 #        raise TypeError, "Expecting a TypeCode instance"
00039 #    
00040 #    nil = TC.Nilled()
00041 #    nil.typecode = typecode or cls.typecode
00042 #    return nil
00043 
00044     
00045 class pyclass_type(type):
00046     """Stability: Unstable
00047 
00048     type for pyclasses used with typecodes.  expects the typecode to
00049     be available in the classdict.  creates python properties for accessing
00050     and setting the elements specified in the ofwhat list, and factory methods
00051     for constructing the elements.
00052     
00053     Known Limitations:
00054         1)Uses XML Schema element names directly to create method names, 
00055            using characters in this set will cause Syntax Errors:
00056         
00057               (NCNAME)-(letter U digit U "_")
00058     
00059     """
00060     def __new__(cls, classname, bases, classdict):
00061         """
00062         """
00063         #import new
00064         typecode = classdict.get('typecode')
00065         assert typecode is not None, 'MUST HAVE A TYPECODE.'
00066 
00067         # Assume this means immutable type. ie. str
00068         if len(bases) > 0:
00069             #classdict['new_Nill'] = classmethod(GetNilAsSelf)
00070             pass
00071         # Assume this means mutable type. ie. ofwhat.
00072         else:
00073             assert hasattr(typecode, 'ofwhat'), 'typecode has no ofwhat list??'
00074             assert hasattr(typecode, 'attribute_typecode_dict'),\
00075                 'typecode has no attribute_typecode_dict??'
00076                 
00077             #classdict['new_Nill'] = staticmethod(GetNil)
00078             
00079             if typecode.mixed:
00080                 get,set = cls.__create_text_functions_from_what(typecode)
00081                 
00082                 if classdict.has_key(get.__name__):
00083                     raise AttributeError,\
00084                         'attribute %s previously defined.' %get.__name__
00085                         
00086                 if classdict.has_key(set.__name__):
00087                     raise AttributeError,\
00088                         'attribute %s previously defined.' %set.__name__
00089                 
00090                 classdict[get.__name__] = get
00091                 classdict[set.__name__] = set
00092                 
00093             for what in typecode.ofwhat:
00094                 get,set,new_func = cls.__create_functions_from_what(what)
00095 
00096                 if classdict.has_key(get.__name__):
00097                     raise AttributeError,\
00098                         'attribute %s previously defined.' %get.__name__
00099                         
00100                 classdict[get.__name__] = get
00101                 if classdict.has_key(set.__name__):
00102                     raise AttributeError,\
00103                         'attribute %s previously defined.' %set.__name__
00104                         
00105                 classdict[set.__name__] = set
00106                 if new_func is not None:
00107                     if classdict.has_key(new_func.__name__):
00108                         raise AttributeError,\
00109                             'attribute %s previously defined.' %new_func.__name__
00110                             
00111                     classdict[new_func.__name__] = new_func
00112 
00113                 assert not classdict.has_key(what.pname),\
00114                     'collision with pname="%s", bail..' %what.pname
00115                     
00116                 pname = what.pname
00117                 if pname is None and isinstance(what, TC.AnyElement): pname = 'any'
00118                 assert pname is not None, 'Element with no name: %s' %what
00119 
00120                 # TODO: for pname if keyword just uppercase first letter.
00121                 #if pydoc.Helper.keywords.has_key(pname):
00122                 pname = pname[0].upper() + pname[1:]
00123                 assert not pydoc.Helper.keywords.has_key(pname), 'unexpected keyword: %s' %pname
00124 
00125                 classdict[pname] =\
00126                     property(get, set, None, 
00127                         'property for element (%s,%s), minOccurs="%s" maxOccurs="%s" nillable="%s"'\
00128                         %(what.nspname,what.pname,what.minOccurs,what.maxOccurs,what.nillable)
00129                         )
00130 
00131         # 
00132         # mutable type <complexType> complexContent | modelGroup
00133         # or immutable type <complexType> simpleContent (float, str, etc)
00134         # 
00135         if hasattr(typecode, 'attribute_typecode_dict'):
00136             attribute_typecode_dict = typecode.attribute_typecode_dict or {}
00137             for key,what in attribute_typecode_dict.items():
00138                 get,set = cls.__create_attr_functions_from_what(key, what)
00139                 if classdict.has_key(get.__name__):
00140                     raise AttributeError,\
00141                         'attribute %s previously defined.' %get.__name__
00142                         
00143                 if classdict.has_key(set.__name__):
00144                     raise AttributeError,\
00145                         'attribute %s previously defined.' %set.__name__
00146                 
00147                 classdict[get.__name__] = get
00148                 classdict[set.__name__] = set
00149 
00150         return type.__new__(cls,classname,bases,classdict)
00151 
00152     def __create_functions_from_what(what):
00153         if not callable(what):
00154             def get(self):
00155                 return getattr(self, what.aname)
00156     
00157             if what.maxOccurs > 1:
00158                 def set(self, value):
00159                     if not (value is None or hasattr(value, '__iter__')):
00160                         raise TypeError, 'expecting an iterable instance'
00161                     setattr(self, what.aname, value)
00162             else:
00163                 def set(self, value):
00164                     setattr(self, what.aname, value)
00165         else:
00166             def get(self):
00167                 return getattr(self, what().aname)
00168     
00169             if what.maxOccurs > 1:
00170                 def set(self, value):
00171                     if not (value is None or hasattr(value, '__iter__')):
00172                         raise TypeError, 'expecting an iterable instance'
00173                     setattr(self, what().aname, value)
00174             else:
00175                 def set(self, value):
00176                     setattr(self, what().aname, value)
00177 
00178         # 
00179         # new factory function
00180         # if pyclass is None, skip
00181         # 
00182         if not callable(what) and getattr(what, 'pyclass', None) is None: 
00183             new_func = None
00184         elif (isinstance(what, TC.ComplexType) or 
00185             isinstance(what, TC.Array)):
00186             
00187             def new_func(self):
00188                 '''returns a mutable type
00189                 '''
00190                 return what.pyclass()
00191             
00192         elif not callable(what):
00193             
00194             def new_func(self, value):
00195                 '''value -- initialize value
00196                 returns an immutable type
00197                 '''
00198                 return what.pyclass(value)
00199             
00200         elif (issubclass(what.klass, TC.ComplexType) or 
00201               issubclass(what.klass, TC.Array)):
00202             
00203             def new_func(self):
00204                 '''returns a mutable type or None (if no pyclass).
00205                 '''
00206                 p = what().pyclass
00207                 if p is None: return
00208                 return p()
00209                 
00210         else:
00211             
00212             def new_func(self, value=None):
00213                 '''if simpleType provide initialization value, else
00214                 if complexType value should be left as None.
00215                 Parameters:
00216                     value -- initialize value or None
00217                     
00218                 returns a mutable instance (value is None) 
00219                     or an immutable instance or None (if no pyclass)
00220                 '''
00221                 p = what().pyclass
00222                 if p is None: return
00223                 if value is None: return p()
00224                 return p(value)
00225             
00226         #TODO: sub all illegal characters in set
00227         #    (NCNAME)-(letter U digit U "_")
00228         if new_func is not None:
00229             new_func.__name__ = 'new_%s' %what.pname
00230         get.func_name = 'get_element_%s' %what.pname
00231         set.func_name = 'set_element_%s' %what.pname
00232         return get,set,new_func
00233     __create_functions_from_what = staticmethod(__create_functions_from_what)
00234     
00235     def __create_attr_functions_from_what(key, what):
00236         
00237         def get(self):
00238             '''returns attribute value for attribute %s, else None.
00239             ''' %str(key)
00240             return getattr(self, what.attrs_aname, {}).get(key, None)
00241 
00242         def set(self, value):
00243             '''set value for attribute %s.
00244             value -- initialize value, immutable type
00245             ''' %str(key)
00246             if not hasattr(self, what.attrs_aname):
00247                 setattr(self, what.attrs_aname, {})
00248             getattr(self, what.attrs_aname)[key] = value
00249         
00250         #TODO: sub all illegal characters in set
00251         #    (NCNAME)-(letter U digit U "_")
00252         if type(key) in (tuple, list):
00253             get.__name__ = 'get_attribute_%s' %key[1]
00254             set.__name__ = 'set_attribute_%s' %key[1]
00255         else:
00256             get.__name__ = 'get_attribute_%s' %key
00257             set.__name__ = 'set_attribute_%s' %key
00258 
00259         return get,set
00260     __create_attr_functions_from_what = \
00261         staticmethod(__create_attr_functions_from_what)
00262 
00263     def __create_text_functions_from_what(what):
00264         
00265         def get(self):
00266             '''returns text content, else None.
00267             '''
00268             return getattr(self, what.mixed_aname, None)
00269                 
00270         get.im_func = 'get_text'
00271 
00272         def set(self, value):
00273             '''set text content.
00274             value -- initialize value, immutable type
00275             '''
00276             setattr(self, what.mixed_aname, value)
00277             
00278         get.im_func = 'set_text'
00279         
00280         return get,set
00281     __create_text_functions_from_what = \
00282         staticmethod(__create_text_functions_from_what)
00283         
00284         
00285         

Generated on Wed Oct 20 2010 11:12:15 for APBS by  doxygen 1.7.2