I'm still republishing a python 2.x script in 3.x.
at some point, the script must replace the "print" function with "disp" (equivalent in TI basic language) except that it no longer works because of parentheses. anyone have an idea to fix it?
The code :
elif (line.find("print ")==idepth(line)):
line = replace(line,"print ","Disp ")
if (line[-1] == ","):
line = line[:-1].rstrip() # Trailing , not legal for ti basic
thanks in advance
Edit: full code :
import sys
import os
import re
#GUI:
import tkinter as tk
from tkinter import filedialog
import tkinter.simpledialog
import tkinter.messagebox
GUI_MODE = False
TAB_REPLACE = " "
def main():
args = sys.argv[1:]
global GUI_MODE
print (args)
if (len(args)==0):
GUI_MODE=True
root = tk.Tk()
root.withdraw()
inp = filedialog.askopenfilename(title="Select a python script to convert")
if (inp==''):
print ("cancelled")
return 0
else:
inp=args[0]
#now input file is known
file=open(inp)
prog = file.read().replace("\r","").split("\n") # Lines of code
#Get a program name:
if (prog[0][:1]=="#" and (prog[0].upper().find("NAME:")>-1 or prog[0].upper().find("PROGRAM:")>-1 )):
outname=prog[0][prog[0].find(":")+1:]
else:
outname=tkinter.simpledialog.askstring("File name","What do you want to name this program?")
fixed = format(prog)
#Write the converted program in this folder:
print ("\n--Converted to TI-Basic code:--")
print (fixed)
print ("")
print ("Making output files: "+outname+".tib, "+outname+".8xp ...")
#Write the converted program in this folder:
outfile=open(outname+".tib","w")
outfile.write(fixed)
outfile.close()
#Write the .8xp program
outfile=open(outname+".8xp","w")
outfile.write(fixed)
outfile.close()
#assuming the compiler tibasic.exe is in this folder:
if (sys.platform[:3]=="win"):
if (os.system('tibasic.exe '+outname+'.tib')): #Returns non-0, error:
errReport("Error trying to run tibasic.exe! Make sure it is in the current folder.")
else:
if (os.system('wine tibasic.exe '+outname+'.tib')): #Returns non-0, error:
errReport("Error trying to run tibasic.exe! Make sure it is in the current folder, and w.i.n.e is installed.\n"+
"(See http://www.winehq.org/ for installer)")
os.remove(outname+".tib")
a=input("Done! Press enter to exit:") #pause
return 0
def format(linesArray): #converts lines from Python to ti-basic.
for i in range(len(linesArray)):
linesArray[i]=linesArray[i].replace("\t",TAB_REPLACE) #Important! see idepth()
i=0;
linesArray.append("") # 0-indent ending so blockAddEnd won't mess up.
while (i<len(linesArray)):
#Convert control blocks (if, for, while) from indented (python) to END (TI)
line = linesArray[i]
if isBlockStart(line,"for "):
linesArray = blockAddEnd(linesArray, i, "End")
elif isBlockStart(line,"if "):
linesArray = blockAddEnd(linesArray, i, "End")
elif isBlockStart(line,"while "):
linesArray = blockAddEnd(linesArray, i, "End")
elif isBlockStart(line,"repeat "): #not in python, but works on TI.
linesArray = blockAddEnd(linesArray, i, "End")
i+=1
# Don't need indentations anymore, do the rest of the conversions:
for i in range(len(linesArray)):
linesArray[i]=convLine(linesArray[i],i+1)
#Remove blanks:
for i in range(linesArray.count("")):
linesArray.remove("")
return "\n".join(linesArray)
def convLine(line,num): #Line by line conversion.
line = line.rstrip().lstrip() #trim indentation.
lnum = "Line "+str(num)+": "
if line.count("#"):
comment = line[line.find("#"):]
if (comment[0:6] == "#no-ti"):
#Does not work on the ti.
return ""
elif (comment[0:4] == "#ti:"):
# Only for ti:
return comment[4:]
else:
line = line[:line.find("#")] # take comment off code
#No imports in ti-basic!
if line.startswith("import ") or (line.count(" import ") and line.startswith("from ")):
return ""
#Errors and warnings:
if (toolong(line)):
print (lnum+"Warning: Text string too long to fit on a TI83/84 screen. The calculator screen is 16 characters wide, 8 characters high.")
if (line.find("\n")>-1):
print (lnum+"Warning: newline \\n is not allowed in TI-Basic.")
if (line.find("'''")>-1):
print (lnum+"Warning: ''' quotes are not allowed, you must use \" quotes on a single line for TI-Basic.")
if (replace(line,"pow(","")!=line):
errReport(lnum+"TI calculators don't have the pow() command, you must use a**b instead of pow(a,b).")
if (replace(line,"import ","")!=line):
print (lnum+"import ignored. No import statements in TI-Basic!")
return "" # ignore import statements!
if (replace(line,"-=","")!=line):
errReport(lnum+"The -= operator is not allowed.\nTry +=- or a=a+-number instead.")
if (replace(line,"def ","")!=line):
errReport(lnum+"Functions are not supported in TI-Basic! However, you can run another program with \"prgmPRGNAME\".")
if (replace(line,"//","")!=line):
print (lnum+"// division converted to / division: For int division, try int(a/b).")
line=replace(line,"//","/")
if (replace(line,"-","")!=line):
print (lnum+"Warning: The - is changed to negative sign on the calculator. If you wanted to subtract, use a+-b instead of a-b.")
if (replace(line,"open(","")!=line):
errReport(lnum+"Error: TI calculators can't use \"open(filename)\" in programs. To store text, try using variables STR0, STR1, ... STR9.")
if (replace(line,"%","")!=line):
errReport(lnum+"Error: TI83/84 calculators don't have Mod.\n Instead of a % b, try (a/b-int(a/b))*b instead.")
# Replace excess spaces, they cause errors in the calculator:
line=replace(line,", ",",")
line=replace(line," + ","+")
line=replace(line," - ","-")
line=replace(line," +- ","+-")
line=replace(line," * ","*")
line=replace(line," / ","/")
line=replace(line," == ","==")
line=replace(line," > ",">")
line=replace(line," < ","<")
line=replace(line," != ","!=")
#TODO: Arrays converted to lists?
line=replace(line,"theta","[theta]") # variable
line=replace(line,"**","^")
line=mathReplace(line)
#round, max, min already works.
line=replace(line,"float(","(")
line=replace(line,"len(","dim(")
line=replace(line,"math.pi","[pi]")
line=replace(line,"math.e","[e]")
line=replace(line,"eval(","expr(")
line=replace(line,"-","[neg]") # use +- instead of - operator.
line=replace(line,"==","=")
line=replace(line," and ","&")
line=replace(line," or ","|")
line=replace(line,"random.random()","rand")
line=replace(line,"random.randint","RandInt")
line=replace(line,"int(","iPart(")
if (replace(line,"input(","") != line):
line=inputConv(line,num)
if isBlockStart(line,"for "):
line=forConv(line,num)
elif (isBlockStart(line,"if ")):
line = replace(line,"if ","If ")
line = replace(line,":",":Then")
elif (isBlockStart(line,"while ")):
line = replace(line,"while ","While ")
line = replace(line,":","")
elif (isBlockStart(line,"repeat")):
line = replace(line,"repeat","Repeat")
line = replace(line,":","")
elif (isBlockStart(line,"else")):
line = replace(line,"else:","Else")
elif isBlockStart(line,"elif"):
errReport(lnum+"""Error: There is no else-if command on the TI83/84. However, you can use this instead:
if <condition>:
...
else:
if <condition>:
...
else:
...""")
elif (line.find("print ")==idepth(line)):
line = re.sub(r"print *\((.+)\)", r"disp \1", line)
if (line[-1] == ","):
line = line[:-1].rstrip() # Trailing , not legal for ti basic
elif (replace(line,"=","")!=line): #assignment is -> on the calculator.
eqspace = line.find("=")
line = line[eqspace+1:].rstrip().lstrip() + "->" + line[:eqspace].rstrip().lstrip() # sto arrow.
line = fixEQ(line)
return replace(line,"+[neg]","-") #lastly, switch back the negative.
def fixEQ(line):
# fix +=, *=, /=.
# A+=1 changes to 1->A+, so fix it now.
if (line[-1]=="+" or line[-1]=="*" or line[-1]=="/"):
line = line[:-1].rstrip()+line[-1] # remove any spaces in "a +" etc
pre = line[line.find("->")+2:]
#pre = pre[:-1].rstrip()+pre[-1]
line= pre + "("+line[:line.find("->")]+")"+ line[line.find("->"):-1]
return line
def inputConv(line,num):
lnum = "Line "+str(num)+": "
if (replace(line,"raw_input(","")!=line and line==replace(line,"=","")):
#raw_input not assigned to variable is like Pause.
return "Pause "
else:
var = line[:line.find("=")].rstrip().lstrip()
if (len(var)>1 and var!="theta"): # might be invalid.
print (lnum+"Warning: Program tries to store to variable \"%s\"." % var)
prompt = line[line.find("input(")+6:]
prompt = prompt[:prompt.find(")")]
# Now return the TI basic input with var spaces removed:
return "Input "+prompt+","+var
def forConv(line,num):
lnum = "Line "+str(num)+": "
# split "for i in range(...):"
var = line[line.find("for ")+4:line.find(" in range")]
#print var
part = line[line.find("in range(")+9:] # only "...) : "
part = part.rstrip(": ")[:-1] # remove extra " " or ":", remove last ).
#print "'"+line+"'"
out = part.split(",")
if len(out)==1:
return "For(%s,0,(%s)-1)" % (var, out[0])
elif len(out)==2:
return "For(%s,(%s),(%s)-1)" % (var, out[0], out[1])
elif len(out)==3:
return "For(%s,(%s),(%s)-1,(%s)" % (var, out[0], out[1], out[2])
else:
errReport(lnum+"Too many commas in for loop!")
return "couldn't convert: "+line
def blockAddEnd(lines, startLine, endText):
# Takes an array, line #, and end text.
# Adds end for that indentation block.
startInd = idepth(lines[startLine])
if idepth(lines[startLine+1]) <= startInd:
errReport("Expected indent after line "+str(startLine+1)+".")
i = startLine+1
#continue searching for the end while it's indented or it's an else line:
while idepth(lines[i]) > startInd or (isBlockStart(lines[i],"else")):
i+=1
# now insert.
lines.insert(i,endText)
return lines
def idepth(text):
# get indentation depth of line.
depth=0
line = text.replace("\t",TAB_REPLACE) #tab is 4 spaces.
while (line[:1]==" "):
line=line[1:]
depth+=1
return depth
def replace(text, changethis, tothis):
# replaces text, but not in quotes.
arr = text.split("\"")
for i in range(0,len(arr),2):
arr[i]=arr[i].replace(changethis, tothis)
return "\"".join(arr)
def toolong(text):
# checks for too long string:
arr = text.split("\"")
for i in range(1,len(arr),2):
#print arr[i]
if (len(arr[i]) > 16):
return True
return False
def parMatch(text,num): # given "(stuff()...()))", returns the parentheses block.
lnum = "Line "+str(num)+": "
for i in range(len(text)):
part = text[:i-1]
if (part.count("(")==part.count(")")):
return part[1:-1] #without outside parentheses.
errReport(lnum+"Invalid parentheses")
def isBlockStart(line, type):
# Check if the line is start of a <type> block.
# checks if it starts with <type>, and ends with ":".
# example: isBlockStart("for i in range(8) : ","for") is true.
return (line.find(type) == idepth(line) and line.rstrip(" ")[-1]==":")
def errReport(text):
print (text)
if (GUI_MODE):
root = tk.Tk()
root.withdraw()
tkinter.messagebox.showerror("Error",text)
sys.exit(1)
def mathReplace(line):
""" Replaces mathematical functions with ti basic functions. """
#Same function in both Python and TI-basic:
same = ["sin", "cos", "tan", "asin", "acos", "atan", "sinh", "cosh", "tanh", "asinh", "acosh", "atanh"]
line=replace(line,"math.sqrt(","[root]^2(")
line=replace(line,"math.fabs(","abs(")
for func in same:
line = replace(line,"math.%s(" % func,func)
line=replace(line,"math.log(","ln(")
line=replace(line,"math.exp(","e^(")
line=replace(line,"math.floor(","int(")
line=replace(line,"math.log10(","log(")
#same, but without "math." They might use
#from math import sqrt etc...
line=replace(line,"sqrt(","[root]^2(")
line=replace(line,"fabs(","abs(")
for func in same:
line = replace(line, "%s(" % func,func)
#(Redundant lines deleted)
line=replace(line,"log(","ln(")
line=replace(line,"exp(","e^(")
line=replace(line,"floor(","int(")
line=replace(line,"log10(","log(")
return line
if __name__ == '__main__': main()
it's the original code with changement propose below
You can use python's regular expression library to perform more advanced string matching and replacement than replace(). Specifically, re.sub(), which functions the same as replace() but takes regular expressions instead of simple strings.
Be sure to first import it with import re. You can then do the following:
elif (line.find("print ")==idepth(line)):
line = re.sub(r"print *\(\"(.+)\"\)", r"disp \1", line)
if (line[-1] == ","):
line = line[:-1].rstrip() # Trailing , not legal for ti basic
This will look for a string of the format "print("&1")" or "print ("&1")" and replace it with "disp &1", where &1 is the contents between the quotes.
Edit: You had initially specified that you wanted the output "without the quotes", but it seems you've edited that comment. If you want to include the quotes in the output, use this line instead:
line = re.sub(r"print *\((.+)\)", r"disp \1", line)
I have project in internet security class. My partner started the project and wrote some python code and i have to continue from where he stopped. But i don't know python and i was planning to learn by running his code and checking how it works. however when i am executing his code i get an error which is "IndexError: list index out of range".
import os
# Deauthenticate devices
os.system("python2 ~/Downloads/de_auth.py -s 00:22:b0:07:58:d4 -d & sleep 30; kill $!")
# renew DHCP on linux "sudo dhclient -v -r & sudo dhclient -v"
# Capture DHCP Packet
os.system("tcpdump -lenx -s 1500 port bootps or port bootpc -v > dhcp.txt & sleep 20; kill $!")
# read packet txt file
DHCP_Packet = open("dhcp.txt", "r")
# Get info from txt file of saved packet
line1 = DHCP_Packet.readline()
line1 = line1.split()
sourceMAC = line1[1]
destMAC = line1[3]
TTL = line1[12]
length = line1[8]
#Parse packet
line = DHCP_Packet.readline()
while "0x0100" not in line:
line = DHCP_Packet.readline()
packet = line + DHCP_Packet.read()
packet = packet.replace("0x0100:", "")
packet = packet.replace("0x0110:", "")
packet = packet.replace("0x0120:", "")
packet = packet.replace("0x0130:", "")
packet = packet.replace("0x0140:", "")
packet = packet.replace("0x0150:", "")
packet = packet.replace("\n", "")
packet = packet.replace(" ", "")
packet = packet.replace(" ", "")
packet = packet.replace("000000000000000063825363", "")
# Locate option (55) = 0x0037
option = "0"
i=0
length = 0
while option != "37":
option = packet[i:i+2]
hex_length = packet[i+2:i+4]
length = int(packet[i+2:i+4], 16)
i = i+ length*2 + 4
i = i - int(hex_length, 16)*2
print "Option (55): " + packet[i:i+length*2 ] + "\nLength: " + str(length) + " Bytes"
print "Source MAC: " + sourceMAC
Thank you a lot
The index error probably means you have an empty or undefined section (index) in your lists. It's most likely in the loop condition at the bottom:
while option != "37":
option = packet[i:i+2]
hex_length = packet[i+2:i+4]
length = int(packet[i+2:i+4], 16)
i = i+ length*2 + 4
Alternatively, it could be earlier in reading your text file:
# Get info from txt file of saved packet
line1 = DHCP_Packet.readline()
line1 = line1.split()
sourceMAC = line1[1]
destMAC = line1[3]
TTL = line1[12]
length = line1[8]
Try actually opening the text file and make sure all the lines are referred to correctly.
If you're new to coding and not used to understanding error messages or using a debugger yet, one way to find the problem area is including print ('okay') between lines in the code, moving it down progressively until the line no longer prints.
I'm pretty new to python as well, but I find it easier to learn by writing your own code and googling what you want to achieve (especially when a partner leaves you code like that...). This website provides documentation on in-built commands (choose your version at the top): https://docs.python.org/3.4/contents.html,
and this website contains more in-depth tutorials for common functions: http://www.tutorialspoint.com/python/index.htm
I think the variable line1 that being split does not have as much as 13 numbers,so you will get error when executing statement TTL = line1[12].
Maybe you do not have the same environment as your partner worked with ,so the result you get(file dhcp.txt) by executing os.system("") maybe null(or with a bad format).
You should check the content of the file dhcp.txt or add statement print line1 after line1 = DHCP_Packet.readline() to check if it has a correct format.
I am creating a Python script that asks for input from the command line. The user will have the ability to edit a part of a file. I can ask for the new information and overwrite it in the file, no problem. But I would rather have the to-edit part of the file already put in the command line, so it does not have to be typed completely over. Is this possible?
File:
1|This file
2|is not empty
Example:
>>>edit line 2
Fetching line 2
Edit the line then hit enter
>>>is not empty #This is written here by the script, not by the user
Which then can be changed to
>>>is not full either
Edited file
Afther which the file has changed to:
1|This file
2|is not full either
I hope it's clear what I am trying to accomplish.
This question has been said to answer my question, it does to a certain extent. It does when I am running Linux with readline. However, I am not. I am using Windows and am not using readline. I would like to only use the standard library.
An answer for Windows is also provided with that question. However, I get an ImportError with win32console, it might be because mentioned question is not about Python3.4, but mine is.
Also, I was wondering if this was possible with the standard library, not with an external library.
Unfortunately, I don't know if kind of input() with default value is available in standard library.
There is an external solution - use win32console as mentioned in this answer. However, it has two pitfalls as far as I can see. First, the import is bundled in a package pywin32. So you would use pip install pywin32, except it does not work, because of the second pitfall: the information about the package at pypi is outdated, it says that package is incompatible with Python 3.4...
But in fact, it can work! You should follow the "Download URL" visible at pypi project page (i.e. https://sourceforge.net/projects/pywin32/files/pywin32/ ) and install latest build. I just installed build 219 for Py3.4, as I myself also use this Python version. On the page installers are provided for several Python versions for 32bit and 64bit Windows.
Also, I've tweaked the code from above-linked SO answer to work in Python 3:
import win32console
_stdin = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE)
def input_def(prompt, default=''):
keys = []
for c in str(default):
evt = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT)
evt.Char = c
evt.RepeatCount = 1
evt.KeyDown = True
keys.append(evt)
_stdin.WriteConsoleInput(keys)
return input(prompt)
if __name__ == '__main__':
name = input_def('Folder name: ', 'it works!!!')
print()
print(name)
This works on my Windows machine... If this does not work on yours, can you provide the error message?
I have written a line editor which hopefully does what you are looking for. But it is a quick-and-dirty hack. It is Windows only and written with CPython 3.6.5 on Windows 10, so its use might be limited. It has been tested on codepage 1252 (ANSI Latin 1; Western European (Windows)) and codepage 65001 (utf-8). It is very basic and a bit sluggish as it is not speed-optimized. (I should rewrite it in C but I do not have the time.) It is hardly tested and poorly documented.
import msvcrt
import os
import sys
if os.name != 'nt':
raise NotImplementedError('This module works only on MS Windows!')
CTRL_00 = 0
CTRL_E0 = 224
KEY_BACKSPACE = 8
KEY_DELETE = 83 # CTRL
KEY_END = 79 # CTRL
KEY_ESC = 27
KEY_HOME = 71 # CTRL
KEY_INSERT = 82 # CTRL
KEY_LEFT = 75 # CTRL
KEY_RETURN = 13
KEY_RIGHT = 77 # CTRL
flush = sys.stdout.flush
write = sys.stdout.write
mode = ('[OVR]> ', '[INS]> ') # overwrite, insert
prefix = len(mode[0])
def _update_line(insert, source, length, line, target):
"""Write a new line and position the cursor.
source: previous cursor position
length: old line length
line: edited line
target: next cursor position
"""
write('\b' * source) # set cursor to start of line
write(' ' * length) # erase old line
write('\b' * length) # again, set cursor to start of line
write(mode[insert] + line[prefix:]) # write updated line
write('\b' * (len(line) - target)) # set cursor to new position
flush() # write buffer to screen
def mswin_line_edit(default_string, insert=True):
"""Edit a MS Windows CLI line."""
insert = insert
line = mode[insert] + default_string
count = len(line)
before = line[:count]
after = line[count:]
print(line, end='', flush=True)
cursor = count
while True:
key = msvcrt.getwch()
num = ord(key)
if num == KEY_ESC: # abort edit
return default_string
if num == KEY_RETURN: # finish edit
return line
if num == KEY_BACKSPACE: # delete character before cursor
if cursor > prefix:
before = line[:cursor - 1]
after = line[cursor:]
line = before + after
_update_line(insert, cursor, count, line, cursor - 1)
cursor -= 1
count = len(line)
elif num == CTRL_E0 or num == CTRL_00: # CTRL
ctrl = ord(msvcrt.getwch())
if ctrl == KEY_END: # set cursor after last character
if cursor < count:
before = line
after = ''
_update_line(insert, cursor, count, line, count)
cursor = count
elif ctrl == KEY_HOME: # set cursor before first character
if cursor > prefix:
before = ''
after = line
_update_line(insert, cursor, count, line, prefix)
cursor = prefix
elif ctrl == KEY_LEFT: # move cursor 1 character to the left
if cursor > prefix:
before = line[:cursor]
after = line[cursor:]
_update_line(insert, cursor, count, line, cursor - 1)
cursor -= 1
elif ctrl == KEY_RIGHT: # move cursor 1 character to the right
if cursor < count:
before = line[:cursor]
after = line[cursor:]
_update_line(insert, cursor, count, line, cursor + 1)
cursor += 1
elif ctrl == KEY_DELETE: # delete character after cursor
if cursor < count:
before = line[:cursor]
after = line[cursor + 1:]
line = before + after
_update_line(insert, cursor, count, line, cursor)
count = len(line)
elif ctrl == KEY_INSERT: # switch insert/overwrite mode
insert ^= True
_update_line(insert, cursor, count, line, cursor)
else: # ordinary character
before = line[:cursor] + key
if insert:
after = line[cursor:]
else:
after = line[cursor + 1:]
line = before + after
_update_line(insert, cursor, count, line, cursor + 1)
cursor += 1
count = len(line)
if __name__ == '__main__':
test_string = input('test string: ')
result = mswin_line_edit(test_string)
print(f'\n{result}')
You could do it with tkinter:
from tkinter import *
def enter():
global commandEntry
command = commandEntry.get()
# Do stuff with command
commandEntry.delete(0, END)
def edit_line(line):
global commandEntry
commandEntry.insert(0, line)
root = Tk()
messageVar = StringVar()
messageVar.set("Enter a command:")
message = Label(root, textvariable=messageVar)
commandEntry = Entry(root)
enterButton = Button(root, text="Enter", command=enter)
root.mainloop()
You should just have 2 variables: one for standard string, one for string that will user change by itself.
Like:
str1 = 'String that is standard'
str2 = str1 #it usually will be standard string
usr = input('your text goes here')
if len(usr) != 0:
str2 = usr
#and here goes code for writing string into file