Package: genpyteal
genpytealConverts Python to PyTeal. Your mileage will vary depending on how much you deviate from the examples.
Its quite easy to get an error by doing something not supported.  However, it often still outputs useful PyTeal that you can then
fix up.If you appreciate this tool, you are welcome to send ALGOs toRMONE54GR6CYOJREKZQNFCZAUGJHSPBUJNFRBTXS4NKNQL3NJQIHVCS53M.Installationpip3 install genpytealorpip install genpytealABIAs of this writing, if you use any ABI stuff, you will need to uninstall regular pyteal and do this:pip install -e git+https://github.com/algorand/pyteal@abi-types#egg=pytealb67a71a224eb1b8c477ae32b5c4d0ab01a680edbWarning: The scripts havepython3in them because that is what works on my system. It only works with Python 3.
There might be some system where it needs to saypythoninstead.  If so, maybe just pull the code from the github repo to change it?UsageTo generate PyTeal:genpyteal thescript.pyTo generate PyTeal and do syntax highlighting (requirespygmentizeandboxesto be installed):genpyteal thescript.py | niceoutTo generate PyTeal and then TEAL:genteal thescript.pyTo show the AST (FST) of a Python program (uses RedBaron .help(), and requiresipythoninstalled):showast thescript.pySupported constructsstatement list(= Seq),integer const( = Int(n)),if/else,while,print(=Log),+( = Concat(str1, str2) ),True/False(= 1/0),and/or/not...
(maybe something I am forgetting).DetailsYou can use a subset of Python. For scratch variables, you will need to initialize them at the beginning of a function, such asx = 0ors = "tom". It uses
that to determine the type. Sometimes you may need to specify Bytes or Int still. Integer/string literals get Int/Bytes added automatically. You can useprintinstead of Log.Name the main functionappto indicate a stateful application contract, orsigfor a LogicSig contract.For transaction fields, you can leave off the parenthesis, e.g.Txn.senderinstead ofTxn.sender().It will assume functions returnuint64unless you specify@bytesor there is no return, which will automatically insert@Subroutine(TealType.none)If you want to print a number in the log, you can use the numtostr function I made:fromlibimportutildefapp():print("Your number is "+util.numtostr(100))The best explanation is just to show the examples.Examplesexamples/abiadv.pyfromlib.utilimport*JUNK_ASSET=575753250fgGreen="\033[38;5;2m"fgYellow="\033[38;5;11m"fgPurple="\033[38;5;35m"fgWhite="\033[38;5;15m"fgRed='\033[38;5;31m'bgWhite='\033[48;2;250;250;250m'bgRed='\033[48;2;250;0;0m'resetColor="\033[0m\033[48;2;0;0;0m"yard="Front Yard\nYou are standing in front of a house. It is white, with green trim."yard_connects="NL"yard_conn_descr="To the north is the front door."living_room="""Living RoomThis is a small living room with a carpet that should have been replaced 15 years ago. There is a beat-up couch to sit on."""living_room_connects="ESSYWD"living_room_conn_descr="""From here you can enter the study to the east, the dining room (west), or go back outside (south)."""study="""StudyThere is an Ohio Scientific computer here from the late 1970s. A rickety bookshelf contains some old Dungeons & Dragons books."""study_connects="WL"study_conn_descr="To the west is the living room."dining="""Dining RoomThis is a small area with an old wooden table taking up most of the space. The layers of stains on the carpet are truly breathtaking.There is a merchant here. He has his goods spread out on the table."""dining_connects="EL"dining_conn_descr="To the east is the living room."computer="""The screen shows the following:\033[38;2;138;226;52m\033[48;2;0;21;0mA>dirA: MOVCPM   COMA: ASMAVM   COMA: CHIP8    COM\033[0m"""note="""Welcome to 'Mini-Adventure'. For a list of commands, type /menu.You probably already knew that though, or you would not have got to this point."""sign="""\033[38;5;2mSale!Only 0.02 ALGO per item\033[0mTo buy an item (if using the 'avmloop' client), enter the following command:\033[38;2;138;226;52m\033[48;2;0;21;0m> /optin 23423423,/pay 0.02,buy junk\033[0m"""@bytesdefget_connects(l):ifl=='Y':returnyard_connectsifl=='L':returnliving_room_connectsifl=='S':returnstudy_connectsifl=='D':returndining_connectsreturn''defmove_(location,direction):connects=""connects=get_connects(location)i=0l=0d=0print("Trying to move "+direction)whilei<Len(connects):ifExtract(connects,i,1)==direction:lput('location',Extract(connects,i+1,1))d=show(lgets('location'))returnTruei=i+2returnFalsedefprintloc(descr,conn_descr,connects):print(fgWhite)print(descr)print(fgYellow)print(conn_descr)show_at_location_()print(fgGreen)print(connects)print(resetColor)defshow(l):ifl=='Y':printloc(yard,yard_conn_descr,yard_connects)ifl=='L':printloc(living_room,living_room_conn_descr,living_room_connects)ifl=='S':printloc(study,study_conn_descr,study_connects)ifl=='D':printloc(dining,dining_conn_descr,dining_connects)return1defshow_inventory_():inv=StringArray(lgets('inventory'))print("You are carrying:")print(fgYellow)iflgeti('junk_count')>0:print(numtostr(lgeti('junk_count'))+' Garage Sale Junk')inv.init()i=0whilei<inv.size:print(abi.String(inv[i]).value)i=i+1print(resetColor)return1defshow_junk():print(numtostr(asset_bal(app_address,0))+" Garage Sale Junk")defshow_at_location_():items=StringArray(ggets(lgets('location')+'_items'))items.init()ifitems.size==0:n=0else:print('You see the following items here:')print(fgPurple)i=0whilei<items.size:print(abi.String(items[i]).value)i=i+1print(resetColor)defprintitem(i):print(fgWhite)ifi=='computer':print(computer)ifi=='note':print(note)ifi=='sign':print(sign)print(resetColor)defexists_item(item,loc):ifloc=='S'and(item=='computer'oritem=='books'):returnTrueifloc=='D'anditem=='sign':returnTrueifitem=='note':returnTruereturnFalsedefrolld20():returnrnd(1,20)defexamine_(i):ifexists_item(i,lgets('location')):printitem(i)else:s=""s=is="There is no "+ss=s+" here."print(s)return1defencounter():print('A')print(Concat(fgRed,clr('Bitcoin Maximalist ',bgWhite),fgRed,resetColor))print('suddenly appears. He attacks you with')print(Concat(clr('Nonsense',fgRed),resetColor))print('and runs away.')print(Concat(clr('You lose [10] hit points',bgRed),fgWhite,resetColor))return1defbuy_(asset,what):iffind_payment(20000):Begin()SetFields({TxnField.type_enum:TxnType.AssetTransfer,TxnField.sender:app_address,TxnField.asset_amount:1,TxnField.asset_receiver:Txn.sender,TxnField.xfer_asset:Txn.assets[Btoi(asset)]})Submit()print("You bought it.")lput('junk_count',asset_bal(Txn.sender,0))return1return0deffind_payment(amount):i=0found=0whilei<Global.group_size:if(Gtxn[i].sender==Txn.senderandGtxn[i].receiver==Global.current_application_addressandGtxn[i].amount==amount):found=Truei=i+1returnfounddeffind_axfer(assetid):i=0found=0whilei<Global.group_size:if(Gtxn[i].asset_id==assetidandGtxn[i].asset_receiver==Global.current_application_addressandGtxn[i].asset_amount==1):found=Truei=i+1returnfounddefoffer_(asset,what):ifwhat=="junk":Begin()SetFields({TxnField.type_enum:TxnType.AssetTransfer,TxnField.sender:Global.current_application_address,TxnField.asset_amount:0,TxnField.asset_receiver:Global.current_application_address,TxnField.xfer_asset:Txn.assets[asset]})Submit()print("The merchant will take your junk.")return1return0defuse_(item:bytes):ifarr_find(lgets('inventory'),item)==NOT_FOUND:print('You are not carrying that.')return1ifitem=='die'oritem=='dice'oritem=='d20':print("Rolling d20...")print(fgYellow)roll=0roll=rolld20()print("[ "+numtostr(roll)+" ]")print(resetColor)ifroll<10:returnencounter()else:print("You can't use that.")return1deftake_(what:TealType.bytes):inv=StringArray(lgets('inventory'))ind=0ind=arr_find(ggets(lgets('location')+'_items'),what)ifind==NOT_FOUND:print('You do not see that here, or it is not something you can take.')else:inv.init()inv.append(abi.String.encode(what))lput('inventory',inv.serialize())gput(lgets('location')+'_items',arr_del(ggets(lgets('location')+'_items'),ind))print('You take the '+what)return1defdrop_(what:TealType.bytes):items=StringArray(ggets(lgets('location')+'_items'))ind=0ind=arr_find(lgets('inventory'),what)ifind==NOT_FOUND:print('You are not carrying that.')else:lput('inventory',arr_del(lgets('inventory'),ind))items.init()items.append(abi.String.encode(what))print('You dropped the '+what)gput(lgets('location')+'_items',items.serialize())return1definit_local_array(name):strarr=StringArray("")strarr.init()ifname=='inventory':strarr.append(abi.String.encode('note'))lput(name,strarr.serialize())definit_global_array(name,df):strarr=StringArray("")strarr.init()ifdf!='':strarr.append(abi.String.encode(df))#if name == 'S_items':#  strarr.append(abi.String.encode('d20'))#if name == 'D_items':#  strarr.append(abi.String.encode('sign'))gput(name,strarr.serialize())defsetup_():lput('location','Y')lput('junk_count',0)init_local_array('inventory')init_global_array('Y_items','')init_global_array('L_items','')init_global_array('S_items','d20')init_global_array('D_items','sign')return1deflook()->abi.Uint32:returnshow(lgets('location'))defsetup()->abi.Uint32:returnsetup_()defmove(dir:String)->abi.Uint32:returnmove_(lgets('location'),abi.String(dir).value)deftake(what:String)->abi.Uint32:returntake_(abi.String(what).value)defdrop(what:String)->abi.Uint32:returndrop_(abi.String(what).value)definventory()->StringArray:returnlgets('inventory')defexamine(what:String)->abi.Uint32:returnexamine_(abi.String(what).value)defuse(item:String)->abi.Uint32:returnuse_(abi.String(item).value)defbuy(optin,pay,asset,item:String)->abi.Uint32:returnbuy_(asset,abi.String(item).value)defoffer(asset,item:String)->abi.Uint32:returnoffer_(asset,abi.String(item).value)examples/bool.pydefapp():amt=15returnamt>10andamt<20oramt==0examples/callscratch.pydefg(x):return3deff(n):returng(n)defapp():x=f(30)name="Bob"print(name)return100examples/checkgroup.pyPAYTO=Addr('6ZHGHH5Z5CTPCF5WCESXMGRSVK7QJETR63M3NY5FJCUYDHO57VTCMJOBGY')FEE=10*1000000ZERO=Global.zero_address()defno_close_to(i):Assert(Gtxn[i].close_remainder_to==ZERO)defno_rekey(i):Assert(Gtxn[i].rekey_to==ZERO)defverify_payment(i):Assert(Gtxn[i].receiver==PAYTOandGtxn[i].amount==Int(FEE)andGtxn[i].type_enum==TxnType.Payment)defapp():Assert(Global.group_size==2)no_close_to(1)no_rekey(1)verify_payment(1)App.globalPut('lastPaymentFrom',Gtxn[1].sender)Approve()examples/ifseq.pydeffoo(b):x=bdefapp():foo(10)if1==1:return1else:return0examples/inner.pydefpay(amount:uint64,receiver:bytes):Begin()SetFields({TxnField.type_enum:TxnType.Payment,TxnField.sender:Global.current_application_address,TxnField.amount:amount,TxnField.receiver:receiver})Submit()defapp():pay(10,Addr('6ZHGHH5Z5CTPCF5WCESXMGRSVK7QJETR63M3NY5FJCUYDHO57VTCMJOBGY'))result=0ifTxn.first_valid>1000000:result=1returnresultexamples/strargs.pydefapp():name=""name=Txn.application_args[0]age=Btoi(Txn.application_args[1])ifage>65:print("User "+name+" is at retirement age.")return1else:print("User "+name+" is still young.")return0examples/swap.py"""Atomic Swap"""alice=Addr("6ZHGHH5Z5CTPCF5WCESXMGRSVK7QJETR63M3NY5FJCUYDHO57VTCMJOBGY")bob=Addr("7Z5PWO2C6LFNQFGHWKSK5H47IQP5OJW2M3HA2QPXTY3WTNP5NU2MHBW27M")secret=Bytes("base32","2323232323232323")timeout=3000ZERO_ADDR=Global.zero_address()defsig(tmpl_seller=alice,tmpl_buyer=bob,tmpl_fee=1000,tmpl_secret=secret,tmpl_hash_fn=Sha256,tmpl_timeout=timeout,):fee_cond=Txn.fee<Int(tmpl_fee)is_payment=Txn.type_enum==TxnType.Paymentno_closeto=Txn.close_remainder_to==ZERO_ADDRno_rekeyto=Txn.rekey_to==ZERO_ADDRsafety_cond=is_paymentandno_rekeytoandno_closetorecv_cond=(Txn.receiver==tmpl_seller)and(tmpl_hash_fn(Arg(0))==tmpl_secret)esc_cond=(Txn.receiver==tmpl_buyer)and(Txn.first_valid>Int(tmpl_timeout))return(fee_condandsafety_cond)and(recv_condoresc_cond)examples/usenumtostr.pyfromlibimportutildefapp():print("The best number is "+util.numtostr(42))returnTrueexamples/usestrarr.pyfromlib.utilimport*defshow_inventory_():inv=StringArray(lgets('inventory'))inv.init()i=0whilei<inv.size:print(abi.String(inv[i]).value)i=i+1return1defpickup_(item):inv=StringArray(lgets('inventory'))inv.init()inv.append(item)lput('inventory',inv.serialize())returnshow_inventory_()definit_():inv=StringArray("")inv.init()lput('inventory',inv.serialize())return1definit()->abi.Uint32:returninit_()defget_inventory()->StringArray:returnlgets('inventory')defpickup(item:String)->abi.Uint32:returnpickup_(item)defshow_inventory()->abi.Uint32:returnshow_inventory_()examples/whilecallif.pyfromlib.utilimport*defproc(n):returnn*2defacceptable(n,target):ifn>=target:print("Acceptable. Diff is "+numtostr(n-target))returnTrueelse:returnFalsedefapp():total=1i=0whilenotacceptable(total,Btoi(Txn.application_args[0])):total=proc(total)i+=1returniexamples/whilesum.pydefapp():totalFees=0i=0whilei<Global.group_size:totalFees=totalFees+Gtxn[i].feei=i+1return1lib/util.pyfromtypingimportTuplefrompytealimport*frompytealutilsimportabifrom.libeximport*StringArray=abi.DynamicArray[abi.String]NOT_FOUND=Int(999)asset=abi.Uint8account=abi.Uint8application=abi.Uint8@bytesdefclr(s,ansi):returnConcat(ansi,s)defarr_find(str_arr_bytes:bytes,item:bytes):str_arr=StringArray(str_arr_bytes)str_arr.init()i=0whilei<str_arr.size.load():ifstr_arr[i]==abi.String.encode(item):returnii=i+1returnNOT_FOUND@bytesdefarr_del(str_arr_bytes,index_to_remove):str_arr=StringArray(str_arr_bytes)new_arr=StringArray("")new_arr.init()str_arr.init()i=0whilei<index_to_remove:new_arr.append(str_arr[i])i=i+1i=i+1whilei<str_arr.size.load():new_arr.append(str_arr[i])i=i+1returnnew_arr.serialize()defrnd(min_,max_):hash_=""rndcnt=0rndcnt=App.globalGet('rndcnt')hash_=Sha256(Concat(Txn.tx_id,Itob(Global.latest_timestamp)))bigRand=Btoi(Extract(hash_,rndcnt,7))+Global.latest_timestamp%100000rndcnt=rndcnt+1App.globalPut('rndcnt',rndcnt)returnmin_+bigRand%(max_-min_+1)@bytesdefnumtostr(num):out="             "i=0digit=0n=numdone=Falsewhilenotdone:digit=n%10out=SetByte(out,12-i,digit+48)n=n/10ifn==0:done=Truei=i+1returnExtract(out,12-i+Int(1),i)