Preventing jedi to complete everything after space - python-3.x

I am trying to use jedi to complete python code inside a PyQt application, using QCompleter and QStringListModel to store the possible completion.
Here's a simple working demo:
#!/usr/bin/env python3
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import jedi
import sys
class JediEdit(QLineEdit):
def __init__(self, parent=None):
super().__init__(parent)
self._model = QStringListModel()
self._compl = QCompleter()
self._compl.setModel(self._model)
self.setCompleter(self._compl)
self.textEdited.connect(self.update_model)
def update_model(self, cur_text):
script = jedi.Script(cur_text)
compl = script.completions()
strings = list(cur_text + c.complete for c in compl)
self._model.setStringList(strings)
if __name__ == '__main__':
app = QApplication(sys.argv)
line = JediEdit()
line.show()
sys.exit(app.exec_())
If you run the application and write a code which is not completing anything (e.g. or foo =), the completion will actually show all the possible tokens that can go in that position.
So, if I run and write a space in the field, lots of things pops up, from abs to __version__.
I would like to prevent this: is it possible to query jedi.Script to understand if the token is being completed or if a completely new token is starting?
EDIT: another little question: say that I am running an interpreter which is detached from jedi current state. How can I provide local and global variables to jedi.Script so that it will take into account those, instead of its own completions?

Autocompletion
Jedi's autocompletion will always show all possible tokens in a place. That's the whole point in autocompletion.
If you don't want that behavior just scan the last few characters for whitespace and certain other characters like = or :, it would be a very simple regex command. (You could also try to look up Jedi's internals and use the way how Jedi knows about this context. However I'm not going to tell you, because it's not a public API and IMHO regex calls suffice.)
In the future something like that might be possible. (See https://github.com/davidhalter/jedi/issues/253).
Now that I think about it, there might be another way that you could experiment with this: You can try to play with Completion.name and Completion.complete. The latter only gives you what could come after the current token, while the name would be the full thing. So you can compare and if they are equal than you might not want to display anything.
Have fun playing with the API :-)
Interpreter
If you're running an interpreter, you can use jedi.Interpreter to combine code with actual Python objects. It's pretty flexible. But please note that the current Interpreter (0.8.1) is very buggy. Please use the master branch from Github (0.9.0).

Related

Print Current Time In Tkinter

I have written some code in python for a live time in tkinter.
Whenever I run the code it comes up with some numbers on the tkinter window like 14342816time. Is there a way to fix this?
import tkinter
import datetime
window = tkinter.Tk()
def time():
datetime.datetime.now().time()
datetime.time(17, 3,)
print(datetime.datetime.now().time())
tkinter.Label(window, text = time).pack()
window.mainloop()
After some fixes to your code, I came up with the following, which should at least get you started toward what you want:
import datetime
import tkinter
def get_time():
return datetime.datetime.now().time()
root = tkinter.Tk()
tkinter.Label(root, text = get_time()).pack()
root.mainloop()
The imports are needed so that your program knows about the contents of the datetime and tkinter modules - you may be importing them already, however, I can't tell that for certain from what you posted. You need to create a window into which you put your label, which wasn't happening; following convention, I called that parent (and only) window "root". Then I put the Label into root. I changed the name of your time() function to get_time(), since it's best to avoid confusing fellow programmers (and maybe yourself) with a function that shares its name with another (the time() function in time). I removed two lines in get_time() that don't actually accomplish anything. Finally, I changed the print you had to a return, so that the value can be used by the code calling the function.
There are other improvements possible here. If you're content with the time as it is, you could eliminate the get_time function and just use datetime.datetime.now().time() instead of calling get_time(). However, I suspect you might want to do something to clean up that time before it is displayed, so I left it there. You might want to research the datetime and time modules some more, to see how to clean things up.

I want to embed python console in my tkinter window.. How can i do it?

I am making a text editor and want to add a feature of IDLE in my app. So i want an frame with python IDLE embedded in it with all menus and features which original python IDLE gives.
I looked in source of idle lib but cannot find a solution.
try:
import idlelib.pyshell
except ImportError:
# IDLE is not installed, but maybe pyshell is on sys.path:
from . import pyshell
import os
idledir = os.path.dirname(os.path.abspath(pyshell.__file__))
if idledir != os.getcwd():
# We're not in the IDLE directory, help the subprocess find run.py
pypath = os.environ.get('PYTHONPATH', '')
if pypath:
os.environ['PYTHONPATH'] = pypath + ':' + idledir
else:
os.environ['PYTHONPATH'] = idledir
pyshell.main()
else:
idlelib.pyshell.main()
This code is of pyshell.pyw found under idlelib folder in all python install
I searched the idle.pyw and found that it uses a program pyshell which is real shell. So how can i embed it.
I want a Tkinter frame with python IDLE shell embedded in it.Please give the code. Thanks in advance.
idlelib implements IDLE. While you are free to use it otherwise, it is private in the sense that code and interfaces can change in any release without the usual back-compatibility constraints. Import and use idlelib modules at your own rish.
Currently, a Shell window is a Toplevel with a Menu and a Frame. The latter has a Text and vertical Scrollbar. It is not possible to visually embed a Toplevel within a frame (or within another Toplevel or root = Tk()). top = Toplevel(myframe) works, but top cannot be placed, packed, or gridded within myframe.
I hope in the future to refactor editor.py and pyshell.py so as to separate the window with menu from the frame with scrollable text. The result should include embeddable EditorFrame and ShellFrame classes that have parent as an arguments. But that is in the future.
Currently, one can run IDLE from within python with import idlelib.idle. However, because this runs mainloop() (on its own root), it blocks and does not finish until all IDLE windows are closed. This may not be what one wants.
If having Shell run in a separate window is acceptable, one could extract from python.main the 10-20 lines needed to just run Shell. Some experimentation would be needed. If the main app uses tkinter, this function should take the app's root as an argument and not call mainloop().
Tcl having Tkcon.tcl . when each thread source (means run/exec) the Tkcon.tcl
each thread will pop up a Tk shell/Tk console/tkcon.tcl very good idea for debug. and print message individually by thread.
Python having idle.py ... and how to use it ? still finding out the example .
The are same Tk base . why can't find an suitable example? so far ... keep finding...

Can a tkinter button return a value from an entry on-click?

I'm doing an extended project as one of my qualifications in my current College and I chose to write a python Strategy/RPG game. As a result, I ended up with the highest level of Python knowledge (Surpassing my Computing Teacher who only ever uses the basics... and used Tkinter only once a few years ago. Every one else who has decided to make a program, are either coding in Lua, Java, C++, HTML/CSS/Java-Script or, those who are coding in python, they are only using the basics learned from our teacher.)
I say "Highest level of Python knowledge" but really it isn't that high... I only know a little beyond the basics.
As a result, a forum post is the best place I can turn to for help.
So in my game I defined this function:
#"Given_String" is the question that one would want to ask. (With the answer being an integer between 1 and "Choice_Range" (inclusive)
def Value_Error(Given_String,Error_Message,Choice_Range):
while True:
try:
Temp=int(input(Given_String))
if Temp<1 or Temp>Choice_Range:
print(Error_Message)
else:
break
except ValueError:
print(Error_Message)
return Temp
I then wanted to add tkinter to my code, because the game would have to be in a separate window, and not in the console. As a result, I had to change this code so that it displays the "Given_Message" and the "Error_Message" in a tkinter window, and uses the value that has been typed into an entry box when defining "Temp".
I wrote this code to make this work: (Or at least most of it)
#This code is stored in a different file for neatness and hence I had to import "sys" to avoid circular imports.
#This code is made to be flexible so that I can later re-use it when necessary.
#This code starts with the function all the way at the bottom. The rest are made to add flexibility and to structure the algorithm.
#This code hasn't been fully run (Because of the Error crashing the Python Shell) so it can contain other Run-time Errors that I'm not aware of yet.
import sys
def Generate_Window(Window_Name,X_Parameter=5,Y_Parameter=50):
Temp=sys.modules['tkinter'].Tk()
Temp.title(Window_Name)
Temp.geometry(str(X_Parameter)+"x"+str(Y_Parameter))
return Temp
def Generate_Button(Master,Text="Submit"):
Temp=sys.modules["tkinter"].Button(Master,text=Text)
return Temp
def Generate_Entry(Master):
Temp=sys.modules["tkinter"].Entry(Master)
return Temp
def Generate_Label(Master,Given_String):
Temp=sys.modules["tkinter"].Label(Master,text=Given_String)
return Temp
def Com_Get_Entry(Given_Window,Given_Entry):
Temp=Given_Entry.get()
Given_Window.destroy()
return Temp
def Com_Confirm(Given_Window):
Given_Window.destroy()
def Generate_Entry_Box(Given_String):
Entry_Window=Generate_Window("Entry",X_Parameter=300)
Entry_Label=Generate_Label(Entry_Window,Given_String)
Entry_Entry=Generate_Entry(Entry_Window)
Entry_Button=Generate_Button(Entry_Window)
Entry_Button.configure(command=lambda:Com_Get_Entry(Entry_Window,Entry_Entry))
Entry_Label.grid(row=0,columnspan=2)
Entry_Entry.grid(row=1,column=0)
Entry_Button.grid(row=1,column=1)
def Generate_Alert_Message(Given_String):
Alert_Window=Generate_Window("Alert",X_Parameter=300)
Alert_Label=Generate_Label(Alert_Window,Given_String)
Alert_Button=Generate_Button(Alert_Window,Text="OK")
Alert_Button.configure(command=lambda:Com_Confirm(Alert_Window))
Alert_Label.grid(row=0,columnspan=2)
Alert_Button.grid(row=1,column=1)
def Get_Interger_Input_In_Range(Given_String,Error_Message,Choice_Range):
while True:
try:
Returned_Value=int(Generate_Entry_Box(Given_String))
if Returned_Value<1 or Returned_Value>Choice_Range:
Generate_Alert_Message(Error_Message)
else:
break
except ValueError:
Generate_Alert_Message(Error_Message)
return Temp
I already included in my code all that I was struggling with and that I could find an answer to.
I.E: On-click, do a certain action with given parameters.
One thing I could not find, is how to return the entered value to the original (Get_Interger_Input_In_Range()) function after the button has been clicked.
What I mean is something like this:
def Function1(GivenParameter1,GivenParameter2):
Temp=Function2(GivenParameter1)
Temp+=GiverParameter2 #random action
return Temp
def Function2(GivenParameter):
Button=Button(Master,command=Function3).grid()
Entry=Entry(Master).grid()
def Function3():
Temp=Entry.get()
return Temp
In Function1 I want Temp to equal the entered value from Function2.
Is there any way to do this without using classes? (I'm not too familiar with classes yet)
Is there any way to do this at all?
I haven't seen anyone give the answer I was looking for...
Because even if they said to use classes... I still didn't know how to return it (Explanation just below)
#The following code was written quickly for purposes of explaining what I mean. It doesn't actually work... (It seems that the button command is being called automatically...)
from tkinter import *
class Return_Value_In_Entry():
def __init__(self):
self.Master=Tk()
self.Entry=Entry(self.Master)
self.Button=Button(self.Master,text="Submit",command=self.Return())
def Return(self):
self.TempVar=self.Entry.get()
return self.TempVar
The way I see it, the Return() function would return the value to the button and not the function/assignment that called the class ... Which is the same problem I'm having with my code.
If you read this all then I really appreciate it. I hope someone can answer my question and tell me (if it's impossible otherwise) how to use classes to solve my "Little" yet large problem.
I fixed your example code (I think). The main problem is that this:
command=self.Return()
does not do what you think it does. It just assigns return value from Return() to command. This is incorrect. It should be
command=self.Return
This assigns function Return to command. Subsequently, when ever button is pressed, self.Return() is executed.
The full example is here:
from tkinter import *
class Return_Value_In_Entry():
def __init__(self):
self.Master=Tk()
self.Entry=Entry(self.Master)
self.Entry.pack()
self.Button=Button(self.Master,text="Submit",command=self.Return)
self.Button.pack()
self.Master.mainloop()
def Return(self):
self.TempVar=self.Entry.get()
print(self.TempVar)
Return_Value_In_Entry()
Now, whenever you press the Button, the value from the Entry widget is saved into self.TempVar and printed out, just to check if its working. Hope this helps.
Gif showing how the example program works:

accessing clipboard via win32clipboard

I am working on a project in which i have to continuouly check clipboard content. If clipboard content matches with certain specified data, then it should be deleted from clipboard.
After doing a lot of googling, I find out that it can be done easily by win32clipboard api.
I am using Python as a programming language.
Following is a code for file(CF_HDROP) format:
import win32clipboard
import win32con
def filecopy():
try:
win32clipboard.OpenClipboard()
print win32clipboard.GetClipboardData(win32con.CF_HDROP)
win32clipboard.CloseClipboard()
except TypeError:
pass
Following is a code for text format:
import win32clipboard
def textcopy():
try:
win32clipboard.OpenClipboard()
data = win32clipboard.GetClipboardData()
print data
win32clipboard.CloseClipboard()
except TypeError:
pass
I am calling above functions in a infinite loop.
Individual function works correctly. But the problem with win32clipboard is that,
after win32clipboard.OpenClipboard() command, win32clipboard lock the clipboard and only realise it after CloseClipboard() command. In between i cant copy anything in clipboard.
How can i solve this problem??
Any other suggestion are also welcome to achieve ultimate aim.
NOTE: Its not necessary to use python. You can use any other language or any other approach.
An infinite polling loop (especially one without delays) is going to be a problem since there's no way to read the contents without locking. Instead you should look into becoming a Clipboard viewer (pywin32 and msdn), that way you are notified of the clipboard contents change and then you can inspect it (get it and get out). If you google a bit on pywin32 and WM_DRAWCLIPBOARD, you'll find some python implementations.

python 3.3 basic error

I have python 3.3 installed.
i use the example they use on their site:
import urllib.request
response = urllib.request.urlopen('http://python.org/')
html = response.read()
the only thing that happens when I run it is I get this :
======RESTART=========
I know I am a rookie but I figured the example from python's own website should be able to work.
It doesn't. What am I doing wrong?Eventually I want to run this script from the website below. But I think urllib is not going to work as it is on that site. Can someone tell me if the code will work with python3.3???
http://flowingdata.com/2007/07/09/grabbing-weather-underground-data-with-beautifulsoup/
I think I see what's probably going on. You're likely using IDLE, and when it starts a new run of a program, it prints the
======RESTART=========
line to tell you that a fresh program is starting. That means that all the variables currently defined are reset and/or deleted, as appropriate.
Since your program didn't print any output, you didn't see anything.
The two lines I suggested adding were just tests to figure out what was going on, they're not needed in general. [Unless the window itself is automatically closing, which it shouldn't.] But as a rule, if you want to see output, you'll have to print what you're interested in.
Your example works for me. However, I suggest using requests instead of urllib2.
To simplify the example you linked to, it would look like:
from bs4 import BeautifulSoup
import requests
resp = requests.get("http://www.wunderground.com/history/airport/KBUF/2007/12/16/DailyHistory.html")
soup = BeautifulSoup(resp.text)

Resources