Wednesday, June 22, 2011

Python, Bottle, Flask y SAP


Post original: Tasting the mix of Python and SAP

Ha pasado mucho tiempo desde mi ultimo "Tasting the mix of" blog post...pero aqui estamos para cambiar esto -;)

Ultimamente, he estado aprediendo Python...un lenguaje de programacion sexy, poderoso y facil de aprender...asi que desde luego...cada vez que aprendo algo nuevo, quiero aplicarlo al mundo de SAP...y como tengo mucha suerte, Piers Harding ha creado un conector llamado Python SAPRfc -:D

Asi que, con todo preparado y trabajando, empeze a trabajar en un emulador de SE16 utilizando una pantalla de DOS...pero luego me di cuenta de que aunque el no creo una SE16, mi buen amigo David Hull ya habia utilizado Python, SAPRfc y una pantalla DOS en su blog titulado Python and SAP Adventures.

Como ya habia trabajado antes con Micro Frameworks en Ruby, pense que seria una buena idea implementar lo mismo utilizando Python...asi que luego de un poco de investigacion, encontre dos interesantes candidatos (Notese que amo los Micro Frameworks y los Frameworks no tan populares...refiriendome a que no amo, no se y no utilizo Rails o Djanjo...me gusta mantener las cosas simples).

Estos Micro Frameworks se llaman Bottle y Flask (Nombre raros, no?).

Asi que para hacer las cosas simples, utilice YAML, donde utilizamos un archivo de configuracion donde vamos a poner nuestras cadenas de conexion...algo asi como el SAPLogon.ini


ashost: localhost
sysnr: "00"
client: "001"
lang: EN
trace: 1
loglevel: warn

Para los codigo fuentes, empecemos con Bottle.

SE16_Bottle.py

from bottle import get, post, request, run, redirect, route
import sapnwrfc

conn = ""


@get('/login')
def login_form():
return '''<DIV ALIGN='CENTER'><BR><BR><BR><BR>
<H1>Python (Bottle) & SAP - SE16 Emulator</H1>
<BR><TABLE BORDER='1' BORDERCOLOR='BLUE'
BGCOLOR='WHITE'>
<FORM METHOD='POST'>
<TR><TD>User</TD><TD>
<INPUT TYPE='TEXT' NAME='User'></TD></TR>
<TR><TD>Password</TD>
<TD><INPUT TYPE='PASSWORD' NAME='Passwd'></TD></TR>
<TR><TD COLSPAN='2' ALIGN='CENTER'>
<INPUT TYPE='SUBMIT' value='Log In' NAME='LOG_IN'>
<INPUT TYPE='RESET' value='Clear'></TD></TR>
</FORM>
<TABLE>
</DIV>'''


@post('/login')
def login_submit():
global conn
user = request.forms.get('User')
passwd = request.forms.get('Passwd')
sapnwrfc.base.config_location = "sap.yml"
sapnwrfc.base.load_config()
conn = sapnwrfc.base.rfc_connect({'user': user, 'passwd': passwd})
redirect("/choose")


@get('/choose')
def choose_table():
return '''<CENTER>
<FORM METHOD='POST'>
<INPUT TYPE='TEXT' NAME='Table'><BR>
<INPUT TYPE='SUBMIT' value='Show Table'
NAME='Show_Table'>
</FORM>
</CENTER>'''


@post('/choose')
def show_table():
global conn
fields = []
fields_name = []
table = request.forms.get('Table')
func_disc = conn.discover("RFC_READ_TABLE")
func = func_disc.create_function_call()
func.QUERY_TABLE(table)
func.DELIMITER("|")
func.invoke()
data_fields = func.DATA.value
data_names = func.FIELDS.value
long_fields = len(func.DATA())
long_names = len(func.FIELDS())

for line in range(0, long_fields):
fields.append(data_fields[line]["WA"].strip())
for line in range(0, long_names):
fields_name.append(data_names[line]["FIELDNAME"].strip())

output = "<table border='1'><tr>"
for line in range(0, long_names):
field_name = fields_name[line]
output += "<th> %s </th>" % field_name
output += "</tr>"
for line in range(0, long_fields):
output += "<tr>"
data_split = fields[line].split("|")
for line in range(0, long_names):
output += "<td> %s </td>" % data_split[line]
output += "</tr>"
output += "</table>"
return output
conn.close()

run(host='localhost', port=8080)




Ahora, continuemos con Flask:

SE16_Flask.py

from flask import Flask, redirect, request
import sapnwrfc
app = Flask(__name__)

conn = ""


@app.route("/")
def login():
return '''<DIV ALIGN='CENTER'><BR><BR><BR><BR>
<H1>Python (Flask) & SAP - SE16 Emulator</H1>
<BR><TABLE BORDER='1' BORDERCOLOR='BLUE'
BGCOLOR='WHITE'>
<FORM ACTION='/login_submit' METHOD='POST'>
<TR><TD>User</TD><TD>
<INPUT TYPE='TEXT' NAME='User'></TD></TR>
<TR><TD>Password</TD>
<TD><INPUT TYPE='PASSWORD' NAME='Passwd'></TD></TR>
<TR><TD COLSPAN='2' ALIGN='CENTER'>
<INPUT TYPE='SUBMIT' value='Log In' NAME='LOG_IN'>
<INPUT TYPE='RESET' value='Clear'></TD></TR>
</FORM>
<TABLE>
</DIV>'''


@app.route("/login_submit", methods=['GET', 'POST'])
def login_submit():
global conn
if request.method == 'POST':
user = request.form['User']
passwd = request.form['Passwd']
sapnwrfc.base.config_location = "sap.yml"
sapnwrfc.base.load_config()
conn = sapnwrfc.base.rfc_connect({'user': user,
'passwd': passwd})
return redirect("/choose")


@app.route("/choose")
def choose_table():
return '''<CENTER>
<FORM ACTION='/show' METHOD='POST'>
<INPUT TYPE='TEXT' NAME='Table'><BR>
<INPUT TYPE='SUBMIT' value='Show Table'
NAME='Show_Table'>
</FORM>
</CENTER>'''


@app.route("/show", methods=['GET', 'POST'])
def show_table():
global conn
if request.method == 'POST':
fields = []
fields_name = []
table = str(request.form['Table'])
func_disc = conn.discover("RFC_READ_TABLE")
func = func_disc.create_function_call()
func.QUERY_TABLE(table)
func.DELIMITER("|")
func.invoke()
data_fields = func.DATA.value
data_names = func.FIELDS.value
long_fields = len(func.DATA())
long_names = len(func.FIELDS())

for line in range(0, long_fields):
fields.append(data_fields[line]["WA"].strip())
for line in range(0, long_names):
fields_name.append(data_names[line]["FIELDNAME"].strip())

output = "<table border='1'><tr>"
for line in range(0, long_names):
field_name = fields_name[line]
output += "<th> %s </th>" % field_name
output += "</tr>"
for line in range(0, long_fields):
output += "<tr>"
data_split = fields[line].split("|")
for line in range(0, long_names):
output += "<td> %s </td>" % data_split[line]
output += "</tr>"
output += "</table>"
return output
conn.close()

if __name__ == "__main__":
app.run()




Mismo resultado, diferentes Micro Frameworks...excelente, no?

Nos vemos pronto con otra receta para el "Tasting the mix of..."

Saludos,

Blag.

No comments: