viernes, 15 de julio de 2011

wxPython and SAP


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

Hello and welcome back to this little corner of Scripting Languages fun -:)

Today, we're going to see how can we use wxPython and SAP to make an SE16 emulation.

So, what's wxPython? It's a Python wrapper of the C++'s wxWidgets that allows us to create rich UI applications.

For this blog I was tempted to use Tkinter but gotta admit that I like wxPython more...as I have already used it in my Ruby projects. Anyway in Ruby it was a little bit easier than in Python -:P

Enough talk, let's go to the source code...(That could fit nice on a T-Shirt, right?)

Again, and as always in my Python/SAP projects...I used YAML to host the SAP connections parameters.

sap.yml

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

SE16_wxPython.py

import wx
import sapnwrfc
import wx.grid as wxGrid

conn = ""
table = ""


class MyApp(wx.App):

def OnInit(self):
self.frame = MyFrame(None, title="Login")
self.SetTopWindow(self.frame)
self.frame.Show()
return True


class MyFrame(wx.Frame):

def __init__(self, parent, id=wx.ID_ANY, title="",
pos=wx.DefaultPosition, size=(210, 150),
style=wx.DEFAULT_FRAME_STYLE,
name="MyFrame"):
super(MyFrame, self).__init__(parent, id, title, pos,
size, style, name)

self.panel = wx.Panel(self)
self.text_font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
self.t_user = wx.StaticText(self.panel, -1, "User",
size=(40, 20), pos=(10, 12))
self.t_password = wx.StaticText(self.panel, -1, "Password",
size=(40, 20), pos=(10, 32))
self.t_user.SetFont(self.text_font)
self.t_password.SetFont(self.text_font)
self.user = wx.TextCtrl(self.panel, value="", pos=(90, 10))
self.password = wx.TextCtrl(self.panel, value="",
pos=(90, 30),
style=wx.TE_PASSWORD)
self.btnConnect = wx.Button(self.panel, label="Connect",
pos=(70, 80))

self.Bind(wx.EVT_BUTTON, self.OnButtonConnect,
self.btnConnect)

def OnButtonConnect(self, event):
global conn
user = self.user.GetValue()
password = self.password.GetValue()
sapnwrfc.base.config_location = "sap.yml"
sapnwrfc.base.load_config()
conn = sapnwrfc.base.rfc_connect({'user': user,
'passwd': password})
self.Close()
myGrid = GridFrame(None, title="SE16 Emulator")
myGrid.Show()


class GridFrame(wx.Frame):

def __init__(self, parent, id=wx.ID_ANY, title="",
pos=wx.DefaultPosition, size=(600, 400),
style=wx.DEFAULT_FRAME_STYLE,
name="GridFrame"):
super(GridFrame, self).__init__(parent, id, title, pos,
size, style, name)

self.panel = wx.Panel(self)
self.text_font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
self.t_table = wx.StaticText(self.panel, -1, "Table",
size=(40, 20), pos=(180, 12))
self.t_table.SetFont(self.text_font)
self.table = wx.TextCtrl(self.panel, value="", pos=(225, 10))
self.btnShow = wx.Button(self.panel, label="Show Table",
pos=(330, 10))

self.Bind(wx.EVT_BUTTON, self.OnButtonShow, self.btnShow)

def OnButtonShow(self, event):
global conn
table = self.table.GetValue()
fields = []
fields_name = []
func_disc = conn.discover("RFC_READ_TABLE")
func = func_disc.create_function_call()
func.QUERY_TABLE(str(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())

self.grid = wxGrid.Grid(self.panel, pos=(0, 40),
size=(853, 320))
self.grid.EnableEditing(False)
self.grid.CreateGrid(long_fields, long_names)

for line in range(0, long_names):
field_name = fields_name[line]
self.grid.SetColLabelValue(line, field_name)
for line_f in range(0, long_fields):
data_split = fields[line_f].split("|")
for line_n in range(0, long_names):
self.grid.SetCellValue(line_f, line_n,
data_split[line_n])

def onClose(self, event):
global conn
conn.close()


if __name__ == "__main__":
app = MyApp(False)
app.MainLoop() 

Now, the images:




So basically, what we have here is a Login screen with the Username and Password and a connection button. When we connect to SAP, then the window dissapeared and a new window pops out. This new windows ask us for a table name and displays a grid containing all the information.

See ya next time -;)

Blag.

lunes, 4 de julio de 2011

Decimals to Romans and LCD Number in Python


As part of my Python learning, I'm taking my old Ruby codes and ported them to Python...and believe me...there's no better way to learn -:)

The first program that I took off was Decimals to Romans, which I discovered that wasn't working right for big numbers -:( After a few tweaks on Python, it's ready for action -;)


Roman_Table = {1000: 'M', 900: 'CM', 500: 'D', 400: 'CD',
100: 'C', 90: 'XC', 50: 'L', 40: 'XL',
10: 'X', 9: 'IX', 5: 'V', 4: 'IV', 1: 'I'}

global result
keys = []

def reverse_numeric(x, y):
return y - x

def Roman_Number(number):
result = ""
keys = Roman_Table.keys()
keys = sorted(keys, cmp=reverse_numeric)
while number > 0:
for i in keys:
if number >= i:
result += str(Roman_Table.get(i, 0))
number -= i
break
return result

number = input("\nEnter a number: ")
result = Roman_Number(number)
print ("\n" + result)


The next one was LCD Numbers which believe it or not...I manage to cut down from the 160 lines of Ruby code, to only 35 lines...awesome, right?


global line1, line2, line3

line1 = ""
line2 = ""
line3 = ""

zero = {1: ' _ ', 2: '| | ', 3: '|_| '}
one = {1: ' ', 2: '| ', 3: '| '}
two = {1: ' _ ', 2: ' _| ', 3: '|_ '}
three = {1: '_ ', 2: '_| ', 3: '_| '}
four = {1: ' ', 2: '|_| ', 3: ' | '}
five = {1: ' _ ', 2: '|_ ', 3: ' _| '}
six = {1: ' _ ', 2: '|_ ', 3: '|_| '}
seven = {1: '_ ', 2: ' | ', 3: ' | '}
eight = {1: ' _ ', 2: '|_| ', 3: '|_| '}
nine = {1: ' _ ', 2: '|_| ', 3: ' _| '}

num_lines = {0: zero, 1: one, 2: two, 3: three, 4: four,
5: five, 6: six, 7: seven, 8: eight, 9: nine}

def Lines(number):
global line1, line2, line3
line1 += number.get(1, 0)
line2 += number.get(2, 0)
line3 += number.get(3, 0)

number = str(input("\nEnter a number: "))
length = len(number)
for i in range(0, length):
Lines(num_lines.get(int(number[i:i+1]), 0))

print ("\n")
print line1
print line2
print line3
print ("\n")


I'm really sorry about Ruby, because I still love it...but Python is making so much efforts to become my scripting language of choice -;)

Greetings,

Blag.