miércoles, 22 de junio de 2011

Python, EasyGui and SAP


Original Post: Tasting the mix of Python and SAP - Volume 2

This blog post continues my Python learning adventures, and as I love Web Micro Frameworks, I also love simple graphical frameworks...this time, we're going to use EasyGui, which is wrapper for Tkinter which is also a layer for Tk.

So what's the fuzz about EasyGui? Well...it's an easy way to do GUI's...got it? Easy-Gui...

Anyway, it's not as complete as TKinter but it's for sure easier to learn and easier to develop. Enough talk...let's see the source code...

First, I used Yaml again to hide most of the connection parameters from the user.


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

SE16_EasyGui.py

from easygui import *
import sapnwrfc

TITLE = "Python (Easy Gui) & SAP - SE16 Emulator"
conn = ""
table = ""


def Login():
global conn
msg = "Python (Easy Gui) & SAP - SE16 Emulator"
title = "Login"
fieldNames = ["User", "Passwd"]
fieldValues = []
fieldValues = multpasswordbox(msg, title, fieldNames)
user, passwd = fieldValues[0], fieldValues[1]
sapnwrfc.base.config_location = "sap.yml"
sapnwrfc.base.load_config()
conn = sapnwrfc.base.rfc_connect({'user': user, 'passwd': passwd})
ChooseTable()


def ChooseTable():
global table
table = enterbox("Show Table")
if table != " ":
ShowTable()


def ShowTable():
global conn, table
fields = []
fields_name = []
fields_length = []
output = []
header = ""
lines = ""
separator = ""
counter = 0
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):
counter = counter + 1
fields_name.append(data_names[line]["FIELDNAME"].strip())
fields_length.append(data_names[line]["LENGTH"].strip())

for line in range(0, long_names):
field_name = fields_name[line]
field_length = fields_length[line]
if len(field_name) > field_length:
field_length = len(field_name)
field_length = int(field_length) - len(field_name)
spaces = " " * int(field_length)
counter = counter + len(field_name) + len(spaces)
header = header + field_name + spaces + "|"

separator = "-" * counter
output.append(header)
output.append(separator)

for line in range(0, long_fields):
lines = ""
field_length = ""
spaces = ""
data_split = fields[line].split("|")
for line in range(0, long_names):
field_name = fields_name[line]
field_length = fields_length[line]
if len(field_name) > int(field_length):
field_length = len(field_name)
field_length = int(field_length) -
len(data_split[line])
else:
field_length = 0
spaces = " " * int(field_length)
lines = lines + data_split[line] + spaces + "|"
output.append(lines)


codebox("", TITLE, "\n".join(output))

if __name__ == "__main__":
Login()

Now, some images of course -:)





Hope you like this one...see ya next time...

Greetings,

Blag.

Python, Bottle, Flask and SAP


Original post: Tasting the mix of Python and SAP

It's been a very long time since my last "Tasting the mix of" blog post...but here we are to change that -;)

Lately, I have been learning Python...a sexy, powerful and easy to learn programming language...so of course...every time I learn something new, I want to apply it to the SAP world...and lucky me, Piers Harding had already creating an Python SAPRfc connector -:D

So, with everything setup and working I proceeded to start working on the SE16 emulator using the DOS screen...but then I realized that even when didn't do an SE16, my good friend David Hull was already using Python, SAPRfc and DOS screen in his blog entitled Python and SAP Adventures.

As I had already worked with Micro Frameworks in Ruby, I thought it was a good idea to implement the same using Python...so after my research I found two nice candidates (Take note that I love Micro Frameworks and not so streamed Frameworks...meaning that I don't like, don't know and don't use Rails or Djanjo...I like to keep it simple).

These Micro Frameworks are called Bottle and Flask (Weird name, huh?).

So, to make things simple, I used the YAML approach, where we use a configuration like file where we are going to put our connection strings...something like the SAPLogon.ini


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

For the source codes, let's start with 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)




Now, let's continue with 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()




Same output, different Micro Frameworks...nice, isn't it?

See you soon with another recipe for the "Tasting the mix of..."

Greetings,

Blag.