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