removed unnecessary things
This commit is contained in:
		
							parent
							
								
									120586dd5d
								
							
						
					
					
						commit
						65565c7b16
					
				
					 255 changed files with 0 additions and 35978 deletions
				
			
		|  | @ -1,337 +0,0 @@ | |||
| # ------------------------------------------------------------------------------ | ||||
| import os, os.path, subprocess, md5, shutil | ||||
| from appy.shared.utils import getOsTempFolder, FolderDeleter, cleanFolder | ||||
| 
 | ||||
| # ------------------------------------------------------------------------------ | ||||
| debianInfo = '''Package: python-appy%s | ||||
| Version: %s | ||||
| Architecture: all | ||||
| Maintainer: Gaetan Delannay <gaetan.delannay@geezteem.com> | ||||
| Installed-Size: %d | ||||
| Depends: python (>= %s)%s | ||||
| Section: python | ||||
| Priority: optional | ||||
| Homepage: http://appyframework.org | ||||
| Description: Appy builds simple but complex web Python apps. | ||||
| ''' | ||||
| appCtl = '''#! /usr/lib/zope2.12/bin/python | ||||
| import sys | ||||
| from appy.bin.zopectl import ZopeRunner | ||||
| args = ' '.join(sys.argv[1:]) | ||||
| sys.argv = [sys.argv[0], '-C', '/etc/%s.conf', args] | ||||
| ZopeRunner().run() | ||||
| ''' | ||||
| appRun = '''#! /bin/sh | ||||
| exec "/usr/lib/zope2.12/bin/runzope" -C "/etc/%s.conf" "$@" | ||||
| ''' | ||||
| ooStart = '#! /bin/sh\nsoffice -invisible -headless -nofirststartwizard ' \ | ||||
|           '"-accept=socket,host=localhost,port=2002;urp;"' | ||||
| zopeConf = '''# Zope configuration. | ||||
| %%define INSTANCE %s | ||||
| %%define DATA %s | ||||
| %%define LOG %s | ||||
| %%define HTTPPORT %s | ||||
| %%define ZOPE_USER zope | ||||
| 
 | ||||
| instancehome $INSTANCE | ||||
| effective-user $ZOPE_USER | ||||
| %s | ||||
| <eventlog> | ||||
|   level info | ||||
|   <logfile> | ||||
|     path $LOG/event.log | ||||
|     level info | ||||
|   </logfile> | ||||
| </eventlog> | ||||
| <logger access> | ||||
|   level WARN | ||||
|   <logfile> | ||||
|     path $LOG/Z2.log | ||||
|     format %%(message)s | ||||
|   </logfile> | ||||
| </logger> | ||||
| <http-server> | ||||
|   address $HTTPPORT | ||||
| </http-server> | ||||
| <zodb_db main> | ||||
|   <filestorage> | ||||
|     path $DATA/Data.fs | ||||
|   </filestorage> | ||||
|   mount-point / | ||||
| </zodb_db> | ||||
| <zodb_db temporary> | ||||
|   <temporarystorage> | ||||
|    name temporary storage for sessioning | ||||
|   </temporarystorage> | ||||
|   mount-point /temp_folder | ||||
|   container-class Products.TemporaryFolder.TemporaryContainer | ||||
| </zodb_db> | ||||
| ''' | ||||
| # initScript below will be used to define the scripts that will run the | ||||
| # app-powered Zope instance and OpenOffice in server mode at boot time. | ||||
| initScript = '''#! /bin/sh | ||||
| ### BEGIN INIT INFO | ||||
| # Provides:          %s | ||||
| # Required-Start:    $syslog $remote_fs | ||||
| # Required-Stop:     $syslog $remote_fs | ||||
| # Should-Start:      $remote_fs | ||||
| # Should-Stop:       $remote_fs | ||||
| # Default-Start:     2 3 4 5 | ||||
| # Default-Stop:      0 1 6 | ||||
| # Short-Description: Start %s | ||||
| # Description:       %s | ||||
| ### END INIT INFO | ||||
| 
 | ||||
| case "$1" in | ||||
|   start) | ||||
|     %s | ||||
|     ;; | ||||
|   restart|reload|force-reload) | ||||
|     %s | ||||
|     ;; | ||||
|   stop) | ||||
|     %s | ||||
|     ;; | ||||
|   *) | ||||
|     echo "Usage: $0 start|restart|stop" >&2 | ||||
|     exit 3 | ||||
|     ;; | ||||
| esac | ||||
| exit 0 | ||||
| ''' | ||||
| 
 | ||||
| class Debianizer: | ||||
|     '''This class allows to produce a Debian package from a Python (Appy) | ||||
|        package.''' | ||||
| 
 | ||||
|     def __init__(self, app, out, appVersion='0.1.0', | ||||
|                  pythonVersions=('2.6',), zopePort=8080, | ||||
|                  depends=('zope2.12', 'openoffice.org', 'imagemagick'), | ||||
|                  sign=False): | ||||
|         # app is the path to the Python package to Debianize. | ||||
|         self.app = app | ||||
|         self.appName = os.path.basename(app) | ||||
|         self.appNameLower = self.appName.lower() | ||||
|         # Must we sign the Debian package? If yes, we make the assumption that | ||||
|         # the currently logged user has a public/private key pair in ~/.gnupg, | ||||
|         # generated with command "gpg --gen-key". | ||||
|         self.sign = sign | ||||
|         # out is the folder where the Debian package will be generated. | ||||
|         self.out = out | ||||
|         # What is the version number for this app ? | ||||
|         self.appVersion = appVersion | ||||
|         # On which Python versions will the Debian package depend? | ||||
|         self.pythonVersions = pythonVersions | ||||
|         # Port for Zope | ||||
|         self.zopePort = zopePort | ||||
|         # Debian package dependencies | ||||
|         self.depends = depends | ||||
|         # Zope 2.12 requires Python 2.6 | ||||
|         if 'zope2.12' in depends: self.pythonVersions = ('2.6',) | ||||
| 
 | ||||
|     def run(self): | ||||
|         '''Generates the Debian package.''' | ||||
|         curdir = os.getcwd() | ||||
|         j = os.path.join | ||||
|         tempFolder = getOsTempFolder() | ||||
|         # Create, in the temp folder, the required sub-structure for the Debian | ||||
|         # package. | ||||
|         debFolder = j(tempFolder, 'debian') | ||||
|         if os.path.exists(debFolder): | ||||
|             FolderDeleter.delete(debFolder) | ||||
|         # Copy the Python package into it | ||||
|         srcFolder = j(debFolder, 'usr', 'lib') | ||||
|         for version in self.pythonVersions: | ||||
|             libFolder = j(srcFolder, 'python%s' % version) | ||||
|             os.makedirs(libFolder) | ||||
|             destFolder = j(libFolder, self.appName) | ||||
|             shutil.copytree(self.app, destFolder) | ||||
|             # Clean dest folder (.svn/.bzr files) | ||||
|             cleanFolder(destFolder, folders=('.svn', '.bzr')) | ||||
|         # When packaging Appy itself, everything is in /usr/lib/pythonX. When | ||||
|         # packaging an Appy app, we will generate more files for creating a | ||||
|         # running instance. | ||||
|         if self.appName != 'appy': | ||||
|             # Create the folders that will collectively represent the deployed | ||||
|             # Zope instance. | ||||
|             binFolder = j(debFolder, 'usr', 'bin') | ||||
|             os.makedirs(binFolder) | ||||
|             # <app>ctl | ||||
|             name = '%s/%sctl' % (binFolder, self.appNameLower) | ||||
|             f = file(name, 'w') | ||||
|             f.write(appCtl % self.appNameLower) | ||||
|             os.chmod(name, 0o744) # Make it executable by owner. | ||||
|             f.close() | ||||
|             # <app>run | ||||
|             name = '%s/%srun' % (binFolder, self.appNameLower) | ||||
|             f = file(name, 'w') | ||||
|             f.write(appRun % self.appNameLower) | ||||
|             os.chmod(name, 0o744) # Make it executable by owner. | ||||
|             f.close() | ||||
|             # startoo | ||||
|             name = '%s/startoo' % binFolder | ||||
|             f = file(name, 'w') | ||||
|             f.write(ooStart) | ||||
|             f.close() | ||||
|             os.chmod(name, 0o744) # Make it executable by owner. | ||||
|             # /var/lib/<app> (will store Data.fs, lock files, etc) | ||||
|             varLibFolder = j(debFolder, 'var', 'lib', self.appNameLower) | ||||
|             os.makedirs(varLibFolder) | ||||
|             f = file('%s/README' % varLibFolder, 'w') | ||||
|             f.write('This folder stores the %s database.\n' % self.appName) | ||||
|             f.close() | ||||
|             # /var/log/<app> (will store event.log and Z2.log) | ||||
|             varLogFolder = j(debFolder, 'var', 'log', self.appNameLower) | ||||
|             os.makedirs(varLogFolder) | ||||
|             f = file('%s/README' % varLogFolder, 'w') | ||||
|             f.write('This folder stores the log files for %s.\n' % self.appName) | ||||
|             f.close() | ||||
|             # /etc/<app>.conf (Zope configuration file) | ||||
|             etcFolder = j(debFolder, 'etc') | ||||
|             os.makedirs(etcFolder) | ||||
|             name = '%s/%s.conf' % (etcFolder, self.appNameLower) | ||||
|             n = self.appNameLower | ||||
|             f = file(name, 'w') | ||||
|             productsFolder = '/usr/lib/python%s/%s/zope' % \ | ||||
|                              (self.pythonVersions[0], self.appName) | ||||
|             f.write(zopeConf % ('/var/lib/%s' % n, '/var/lib/%s' % n, | ||||
|                                 '/var/log/%s' % n, str(self.zopePort), | ||||
|                                 'products %s\n' % productsFolder)) | ||||
|             f.close() | ||||
|             # /etc/init.d/<app> (start the app at boot time) | ||||
|             initdFolder = j(etcFolder, 'init.d') | ||||
|             os.makedirs(initdFolder) | ||||
|             name = '%s/%s' % (initdFolder, self.appNameLower) | ||||
|             f = file(name, 'w') | ||||
|             n = self.appNameLower | ||||
|             f.write(initScript % (n, n, 'Start Zope with the Appy-based %s ' \ | ||||
|                                   'application.' % n, '%sctl start' % n, | ||||
|                                   '%sctl restart' % n, '%sctl stop' % n)) | ||||
|             f.close() | ||||
|             os.chmod(name, 0o744) # Make it executable by owner. | ||||
|             # /etc/init.d/oo (start OpenOffice at boot time) | ||||
|             name = '%s/oo' % initdFolder | ||||
|             f = file(name, 'w') | ||||
|             f.write(initScript % ('oo', 'oo', 'Start OpenOffice in server mode', | ||||
|                                   'startoo', 'startoo', "#Can't stop OO.")) | ||||
|             f.write('\n') | ||||
|             f.close() | ||||
|             os.chmod(name, 0o744) # Make it executable by owner. | ||||
|         # Get the size of the app, in Kb. | ||||
|         os.chdir(tempFolder) | ||||
|         cmd = subprocess.Popen(['du', '-b', '-s', 'debian'], | ||||
|                                stdout=subprocess.PIPE) | ||||
|         size = int(int(cmd.stdout.read().split()[0])/1024.0) | ||||
|         os.chdir(debFolder) | ||||
|         # Create data.tar.gz based on it. | ||||
|         os.system('tar czvf data.tar.gz *') | ||||
|         # Create the control file | ||||
|         f = file('control', 'w') | ||||
|         nameSuffix = '' | ||||
|         dependencies = [] | ||||
|         if self.appName != 'appy': | ||||
|             nameSuffix = '-%s' % self.appNameLower | ||||
|             dependencies.append('python-appy') | ||||
|         if self.depends: | ||||
|             for d in self.depends: dependencies.append(d) | ||||
|         depends = '' | ||||
|         if dependencies: | ||||
|             depends = ', ' + ', '.join(dependencies) | ||||
|         f.write(debianInfo % (nameSuffix, self.appVersion, size, | ||||
|                               self.pythonVersions[0], depends)) | ||||
|         f.close() | ||||
|         # Create md5sum file | ||||
|         f = file('md5sums', 'w') | ||||
|         toWalk = ['usr'] | ||||
|         if self.appName != 'appy': | ||||
|             toWalk += ['etc', 'var'] | ||||
|         for folderToWalk in toWalk: | ||||
|             for dir, dirnames, filenames in os.walk(folderToWalk): | ||||
|                 for name in filenames: | ||||
|                     m = md5.new() | ||||
|                     pathName = j(dir, name) | ||||
|                     currentFile = file(pathName, 'rb') | ||||
|                     while True: | ||||
|                         data = currentFile.read(8096) | ||||
|                         if not data: | ||||
|                             break | ||||
|                         m.update(data) | ||||
|                     currentFile.close() | ||||
|                     # Add the md5 sum to the file | ||||
|                     f.write('%s  %s\n' % (m.hexdigest(), pathName)) | ||||
|         f.close() | ||||
|         # Create postinst, a script that will: | ||||
|         # - bytecompile Python files after the Debian install | ||||
|         # - change ownership of some files if required | ||||
|         # - [in the case of an app-package] call update-rc.d for starting it at | ||||
|         #   boot time. | ||||
|         f = file('postinst', 'w') | ||||
|         content = '#!/bin/sh\nset -e\n' | ||||
|         for version in self.pythonVersions: | ||||
|             bin = '/usr/bin/python%s' % version | ||||
|             lib = '/usr/lib/python%s' % version | ||||
|             cmds = ' %s -m compileall -q %s/%s 2> /dev/null\n' % (bin, lib, | ||||
|                                                                   self.appName) | ||||
|             content += 'if [ -e %s ]\nthen\n%sfi\n' % (bin, cmds) | ||||
|         if self.appName != 'appy': | ||||
|             # Allow user "zope", that runs the Zope instance, to write the | ||||
|             # database and log files. | ||||
|             content += 'chown -R zope:root /var/lib/%s\n' % self.appNameLower | ||||
|             content += 'chown -R zope:root /var/log/%s\n' % self.appNameLower | ||||
|             # Call update-rc.d for starting the app at boot time | ||||
|             content += 'update-rc.d %s defaults\n' % self.appNameLower | ||||
|             content += 'update-rc.d oo defaults\n' | ||||
|             # (re-)start the app | ||||
|             content += '%sctl restart\n' % self.appNameLower | ||||
|             # (re-)start oo | ||||
|             content += 'startoo\n' | ||||
|         f.write(content) | ||||
|         f.close() | ||||
|         # Create prerm, a script that will remove all pyc files before removing | ||||
|         # the Debian package. | ||||
|         f = file('prerm', 'w') | ||||
|         content = '#!/bin/sh\nset -e\n' | ||||
|         for version in self.pythonVersions: | ||||
|             content += 'find /usr/lib/python%s/%s -name "*.pyc" -delete\n' % \ | ||||
|                        (version, self.appName) | ||||
|         f.write(content) | ||||
|         f.close() | ||||
|         # Create control.tar.gz | ||||
|         os.system('tar czvf control.tar.gz ./control ./md5sums ./postinst ' \ | ||||
|                   './prerm') | ||||
|         # Create debian-binary | ||||
|         f = file('debian-binary', 'w') | ||||
|         f.write('2.0\n') | ||||
|         f.close() | ||||
|         # Create the signature if required | ||||
|         if self.sign: | ||||
|             # Create the concatenated version of all files within the deb | ||||
|             os.system('cat debian-binary control.tar.gz data.tar.gz > ' \ | ||||
|                       '/tmp/combined-contents') | ||||
|             os.system('gpg -abs -o _gpgorigin /tmp/combined-contents') | ||||
|             signFile = '_gpgorigin ' | ||||
|             os.remove('/tmp/combined-contents') | ||||
|             # Export the public key and name it according to its ID as found by | ||||
|             # analyzing the result of command "gpg --fingerprint". | ||||
|             cmd = subprocess.Popen(['gpg', '--fingerprint'], | ||||
|                                    stdout=subprocess.PIPE) | ||||
|             fingerprint = cmd.stdout.read().split('\n') | ||||
|             id = 'pubkey' | ||||
|             for line in fingerprint: | ||||
|                 if '=' not in line: continue | ||||
|                 id = line.split('=')[1].strip() | ||||
|                 id = ''.join(id.split()[-4:]) | ||||
|                 break | ||||
|             os.system('gpg --export -a > %s/%s.asc' % (self.out, id)) | ||||
|         else: | ||||
|             signFile = '' | ||||
|         # Create the .deb package | ||||
|         debName = 'python-appy%s-%s.deb' % (nameSuffix, self.appVersion) | ||||
|         os.system('ar -r %s %sdebian-binary control.tar.gz data.tar.gz' % \ | ||||
|                   (debName, signFile)) | ||||
|         # Move it to self.out | ||||
|         os.rename(j(debFolder, debName), j(self.out, debName)) | ||||
|         # Clean temp files | ||||
|         FolderDeleter.delete(debFolder) | ||||
|         os.chdir(curdir) | ||||
| # ------------------------------------------------------------------------------ | ||||
|  | @ -1,234 +0,0 @@ | |||
| '''This module allows to call RFC functions exposed by a distant SAP system. | ||||
|    It requires the "pysap" module available at http://pysaprfc.sourceforge.net | ||||
|    and the library librfccm.so that one can download from the "SAP MarketPlace", | ||||
|    a website by SAP requiring a login/password.''' | ||||
| 
 | ||||
| # ------------------------------------------------------------------------------ | ||||
| from appy.shared.utils import sequenceTypes | ||||
| 
 | ||||
| class SapError(Exception): pass | ||||
| SAP_MODULE_ERROR = 'Module pysap was not found (you can get it at ' \ | ||||
|     'http://pysaprfc.sourceforge.net)' | ||||
| SAP_CONNECT_ERROR = 'Error while connecting to SAP (conn_string: %s). %s' | ||||
| SAP_FUNCTION_ERROR = 'Error while calling function "%s". %s' | ||||
| SAP_DISCONNECT_ERROR = 'Error while disconnecting from SAP. %s' | ||||
| SAP_TABLE_PARAM_ERROR = 'Param "%s" does not correspond to a valid table ' \ | ||||
|     'parameter for function "%s".' | ||||
| SAP_STRUCT_ELEM_NOT_FOUND = 'Structure used by parameter "%s" does not define '\ | ||||
|     'an attribute named "%s."' | ||||
| SAP_STRING_REQUIRED = 'Type mismatch for attribute "%s" used in parameter ' \ | ||||
|     '"%s": a string value is expected (SAP type is %s).' | ||||
| SAP_STRING_OVERFLOW = 'A string value for attribute "%s" used in parameter ' \ | ||||
|     '"%s" is too long (SAP type is %s).' | ||||
| SAP_FUNCTION_NOT_FOUND = 'Function "%s" does not exist.' | ||||
| SAP_FUNCTION_INFO_ERROR = 'Error while asking information about function ' \ | ||||
|     '"%s". %s' | ||||
| SAP_GROUP_NOT_FOUND = 'Group of functions "%s" does not exist or is empty.' | ||||
| 
 | ||||
| # Is the pysap module present or not ? | ||||
| hasSap = True | ||||
| try: | ||||
|     import pysap | ||||
| except ImportError: | ||||
|     hasSap = False | ||||
| 
 | ||||
| # ------------------------------------------------------------------------------ | ||||
| class SapResult: | ||||
|     '''Represents a result as returned by SAP. It defines a __getattr__ method | ||||
|        that allows to retrieve SAP "output" parameters (export, tables) by their | ||||
|        name (as if they were attributes of this class), in a Python format | ||||
|        (list, dict, simple value).''' | ||||
|     def __init__(self, function): | ||||
|         # The pysap function obj that was called and that produced this result. | ||||
|         self.function = function | ||||
|     def __getattr__(self, name): | ||||
|         '''Allows a smart access to self.function's results.''' | ||||
|         if name.startswith('__'): raise AttributeError | ||||
|         paramValue = self.function[name] | ||||
|         paramType = paramValue.__class__.__name__ | ||||
|         if paramType == 'ItTable': | ||||
|             return paramValue.to_list() | ||||
|         elif paramType == 'STRUCT': | ||||
|             return paramValue.to_dict() | ||||
|         else: | ||||
|             return paramValue | ||||
| 
 | ||||
| # ------------------------------------------------------------------------------ | ||||
| class Sap: | ||||
|     '''Represents a remote SAP system. This class allows to connect to a distant | ||||
|        SAP system and perform RFC calls.''' | ||||
|     def __init__(self, host, sysnr, client, user, password): | ||||
|         self.host = host # Hostname or IP address of SAP server | ||||
|         self.sysnr = sysnr # The system number of SAP server/gateway | ||||
|         self.client = client # The instance/client number | ||||
|         self.user = user | ||||
|         self.password = password | ||||
|         self.sap = None # Will hold the handler to the SAP distant system. | ||||
|         self.functionName = None # The name of the next function to call. | ||||
|         if not hasSap: raise SapError(SAP_MODULE_ERROR) | ||||
| 
 | ||||
|     def connect(self): | ||||
|         '''Connects to the SAP system.''' | ||||
|         params = 'ASHOST=%s SYSNR=%s CLIENT=%s USER=%s PASSWD=%s' % (self.host, | ||||
|             self.sysnr, self.client, self.user, self.password) | ||||
|         try: | ||||
|             self.sap = pysap.Rfc_connection(conn_string = params) | ||||
|             self.sap.open() | ||||
|         except pysap.BaseSapRfcError as se: | ||||
|             # Put in the error message the connection string without the | ||||
|             # password. | ||||
|             connNoPasswd = params[:params.index('PASSWD')] + 'PASSWD=********' | ||||
|             raise SapError(SAP_CONNECT_ERROR % (connNoPasswd, str(se))) | ||||
| 
 | ||||
|     def createStructure(self, structDef, userData, paramName): | ||||
|         '''Create a struct corresponding to SAP/C structure definition | ||||
|            p_structDef and fills it with dict p_userData.''' | ||||
|         res = structDef() | ||||
|         for name, value in userData.items(): | ||||
|             if name not in structDef._sfield_names_: | ||||
|                 raise SapError(SAP_STRUCT_ELEM_NOT_FOUND % (paramName, name)) | ||||
|             sapType = structDef._sfield_sap_types_[name] | ||||
|             # Check if the value is valid according to the required type | ||||
|             if sapType[0] == 'C': | ||||
|                 sType = '%s%d' % (sapType[0], sapType[1]) | ||||
|                 # "None" value is tolerated. | ||||
|                 if value == None: value = '' | ||||
|                 if not isinstance(value, str): | ||||
|                     raise SapError( | ||||
|                         SAP_STRING_REQUIRED % (name, paramName, sType)) | ||||
|                 if len(value) > sapType[1]: | ||||
|                     raise SapError( | ||||
|                         SAP_STRING_OVERFLOW % (name, paramName, sType)) | ||||
|                 # Left-fill the string with blanks. | ||||
|                 v = value.ljust(sapType[1]) | ||||
|             else: | ||||
|                 v = value | ||||
|             res[name.lower()] = v | ||||
|         return res | ||||
| 
 | ||||
|     def call(self, functionName=None, **params): | ||||
|         '''Calls a function on the SAP server.''' | ||||
|         try: | ||||
|             if not functionName: | ||||
|                 functionName = self.functionName | ||||
|             function = self.sap.get_interface(functionName) | ||||
|             # Specify the parameters | ||||
|             for name, value in params.items(): | ||||
|                 if type(value) == dict: | ||||
|                     # The param corresponds to a SAP/C "struct" | ||||
|                     v = self.createStructure( | ||||
|                         self.sap.get_structure(name),value, name) | ||||
|                 elif type(value) in sequenceTypes: | ||||
|                     # The param must be a SAP/C "table" (a list of structs) | ||||
|                     # Retrieve the name of the struct type related to this | ||||
|                     # table. | ||||
|                     fDesc = self.sap.get_interface_desc(functionName) | ||||
|                     tableTypeName = '' | ||||
|                     for tDesc in fDesc.tables: | ||||
|                         if tDesc.name == name: | ||||
|                             # We have found the correct table param | ||||
|                             tableTypeName = tDesc.field_def | ||||
|                             break | ||||
|                     if not tableTypeName: | ||||
|                         raise SapError(\ | ||||
|                             SAP_TABLE_PARAM_ERROR % (name, functionName)) | ||||
|                     v = self.sap.get_table(tableTypeName) | ||||
|                     for dValue in value: | ||||
|                         v.append(self.createStructure(v.struc, dValue, name)) | ||||
|                 else: | ||||
|                     v = value | ||||
|                 function[name] = v | ||||
|             # Call the function | ||||
|             function() | ||||
|         except pysap.BaseSapRfcError as se: | ||||
|             raise SapError(SAP_FUNCTION_ERROR % (functionName, str(se))) | ||||
|         return SapResult(function) | ||||
| 
 | ||||
|     def __getattr__(self, name): | ||||
|         '''The user can directly call self.<sapFunctionName>(params) instead of | ||||
|            calling self.call(<sapFunctionName>, params).''' | ||||
|         if name.startswith('__'): raise AttributeError | ||||
|         self.functionName = name | ||||
|         return self.call | ||||
| 
 | ||||
|     def getTypeInfo(self, typeName): | ||||
|         '''Returns information about the type (structure) named p_typeName.''' | ||||
|         res = '' | ||||
|         tInfo = self.sap.get_structure(typeName) | ||||
|         for fName, fieldType in tInfo._fields_: | ||||
|             res += '  %s: %s (%s)\n' % (fName, tInfo.sap_def(fName), | ||||
|                                         tInfo.sap_type(fName)) | ||||
|         return res | ||||
| 
 | ||||
|     def getFunctionInfo(self, functionName): | ||||
|         '''Returns information about the RFC function named p_functionName.''' | ||||
|         try: | ||||
|             res = '' | ||||
|             usedTypes = set() # Names of type definitions used in parameters. | ||||
|             fDesc = self.sap.get_interface_desc(functionName) | ||||
|             functionDescr = str(fDesc).strip() | ||||
|             if functionDescr: res += functionDescr | ||||
|             # Import parameters | ||||
|             if fDesc.imports: | ||||
|                 res += '\nIMPORTS\n' | ||||
|                 for iDesc in fDesc.imports: | ||||
|                     res += '  %s\n' % str(iDesc) | ||||
|                     usedTypes.add(iDesc.field_def) | ||||
|             # Export parameters | ||||
|             if fDesc.exports: | ||||
|                 res += '\nEXPORTS\n' | ||||
|                 for eDesc in fDesc.exports: | ||||
|                     res += '  %s\n' % str(eDesc) | ||||
|                     usedTypes.add(eDesc.field_def) | ||||
|             if fDesc.tables: | ||||
|                 res += '\nTABLES\n' | ||||
|                 for tDesc in fDesc.tables: | ||||
|                     res += '  %s\n' % str(tDesc) | ||||
|                     usedTypes.add(tDesc.field_def) | ||||
|             if fDesc.exceptions: | ||||
|                 res += '\nEXCEPTIONS\n' | ||||
|                 for eDesc in fDesc.exceptions: | ||||
|                     res += '  %s\n' % str(eDesc) | ||||
|             # Add information about used types | ||||
|             if usedTypes: | ||||
|                 res += '\nTypes used by the parameters:\n' | ||||
|                 for typeName in usedTypes: | ||||
|                     # Dump info only if it is a structure, not a simple type | ||||
|                     try: | ||||
|                         self.sap.get_structure(typeName) | ||||
|                         res += '%s\n%s\n\n' % \ | ||||
|                             (typeName, self.getTypeInfo(typeName)) | ||||
|                     except pysap.BaseSapRfcError as ee: | ||||
|                         pass | ||||
|             return res | ||||
|         except pysap.BaseSapRfcError as se: | ||||
|             if se.value == 'FU_NOT_FOUND': | ||||
|                 raise SapError(SAP_FUNCTION_NOT_FOUND % (functionName)) | ||||
|             else: | ||||
|                 raise SapError(SAP_FUNCTION_INFO_ERROR % (functionName,str(se))) | ||||
| 
 | ||||
|     def getGroupInfo(self, groupName): | ||||
|         '''Gets information about the functions that are available in group of | ||||
|            functions p_groupName.''' | ||||
|         if groupName == '_all_': | ||||
|             # Search everything. | ||||
|             functions = self.sap.search_functions('*') | ||||
|         else: | ||||
|             functions = self.sap.search_functions('*', grpname=groupName) | ||||
|         if not functions: | ||||
|             raise SapError(SAP_GROUP_NOT_FOUND % (groupName)) | ||||
|         res = 'Available functions:\n' | ||||
|         for f in functions: | ||||
|             res += '  %s' % f.funcname | ||||
|             if groupName == '_all_': | ||||
|                 res += ' (group: %s)' % f.groupname | ||||
|             res += '\n' | ||||
|         return res | ||||
| 
 | ||||
|     def disconnect(self): | ||||
|         '''Disconnects from SAP.''' | ||||
|         try: | ||||
|             self.sap.close() | ||||
|         except pysap.BaseSapRfcError as se: | ||||
|             raise SapError(SAP_DISCONNECT_ERROR % str(se)) | ||||
| # ------------------------------------------------------------------------------ | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Stefan Klug
						Stefan Klug