Tkinter Text widget maximum recursion depth using idlelib Delegator/Percolator - python-3.x

After testing I have concluded that the error
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
text.mainloop()
File "C:\Program Files\Python32\lib\tkinter\__init__.py", line 1009, \
in mainloop
self.tk.mainloop(n)
RuntimeError: maximum recursion depth exceeded
occurs only after there is a character before the INSERT position and the user types a Backspace. Here is my code:
# Import
import tkinter
import tkinter.scrolledtext
import idlelib.Delegator
import idlelib.WidgetRedirector
import idlelib.Percolator
import idlelib.ColorDelegator
import time
import re
# Class
class Highlighter(idlelib.Delegator.Delegator):
def __init__(self):
idlelib.Delegator.Delegator.__init__(self)
self._syntaxes = {}
self._compiled = ""
def setdelegate(self, delegate):
idlelib.Delegator.Delegator.setdelegate(self, delegate)
if delegate is not None:
self.setup()
def insert(self, index, chars, *args):
index = self.index(index)
self.delegate.insert(index, chars, *args)
self.update(index, index + "+%dc" % len(chars))
def delete(self, index1, index2=None):
index = self.index(index1)
self.delete(index1, index2)
self.update(index)
def update(self, index1, index2=None):
self.tag_add("TODO", index1, index2)
self.after(1, self.syntax_highlight)
def setup(self):
background = self.cget("background")
self.tag_configure("TODO", foreground=background, background=None)
def syntax_configure(self, tag, syntax):
"""Configure syntax TAG with pattern SYNTAX."""
self._syntaxes[tag] = syntax
syntax_config = syntax_configure
def syntax_cget(self, tag):
"""Return the pattern of TAG."""
return self._syntaxes[tag]
def syntax_delete(self, tag):
"""Delete syntax TAG from the highlighter."""
self._syntaxes.pop(tag)
def syntax_clear(self):
"""Clear all syntaxes."""
self._syntaxes.clear()
def syntax_compile(self):
"""Compile all syntaxes."""
return "|".join("(?P<%s>%s)" % (tag, pattern)
for tag, pattern in self._syntaxes.items())
def syntax_highlight(self, start="1.0", end="end"):
start = self.index(start)
end = self.index(end)
pattern = self.syntax_compile()
if pattern:
for match in re.finditer(pattern, self.get(start, end)):
tag, sequence = list(match.groupdict().items())[0]
start, stop = match.span()
self.tag_remove("TODO", "1.0", "1.0+%dc" % match.span()[1])
self.tag_add(tag, "1.0+%dc" % start, "1.0+%dc" % stop)
self.tag_delete("TODO")
text = tkinter.Text()
text.pack()
p = idlelib.Percolator.Percolator(text)
h = Highlighter()
p.insertfilter(h)
text.mainloop()
If anyone could explain what the cause/source of the recursion is, it would be much appreciated. Thanks!

The issue was that instead of self.delete(index1, index2) in delete it should have been self.delegate.delete(index1, index2).

Related

I'm having problems reading a csv file and inserting the words into a text box in pyqt. The words are not printing into the textbox like they should

This is the modules that are needed.
import sys
import csv
from csv import *
from PyQt4 import QtCore, QtGui, uic
qtCreatorFile = "Inquiry.ui" # Enter file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class MyApp(QtGui.QMainWindow, Ui_MainWindow):
Hebrew = {'a':1,'b':2,'c':3,'d':4,'e':5,'f':6,'g':7,'h':8,'i':9,\
'j':600,'k':10,'l':20,'m':30,'n':40,'o':50,'p':60,'q':70,'r':80,\
's':90,'t':100,'u':200,'v':700,'w':900,'x':300,'y':400,'z':500}
Some other code that is important to help reproduce the problem:
Create the GUI:
def __init__(self):
"Create UI"
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.btnCalculate.clicked.connect(self.Calculate)
def Calculate(self):
The Event:
try:
Event = str(self.txtInquiry)
except TypeError:
pass
The Word Text File Path:
y = 'C:/Users/Jacob-C/Documents/words_alpha.txt'
These are the functions used.
Calculates the value of each word from the key mappings in the gematria system used.
def gematric_value(x, L):
value = 0
for v in x.lower():
try:
value = value + L[v]
except KeyError:
pass
return value
Modulo Function used heavily in integer reduction.
def MOD_CALC(x, y):
return (x % y)
This function takes a number and integer reduces it.
def Check_Value(x):
if x > 9 and MOD_CALC(x, 9) == 0:
return (MOD_CALC(x, 9) + 9)
elif x > 9 and MOD_CALC(x, 9) != 0:
return MOD_CALC(x, 9)
else:
return x
This is the function that does not insert the words into the plain textbox.
def Gematria(f, Hebrew, EN):
opens text file and converts it to a csv file. Then reads each word in the text file and compares the gematric value of the word and the gematric value of the event. If they match, the word is inserted to the plain text box on the qt form. This function does not do what is intended. Instead it doesn't insert anything into the plain text box.
with open(f, 'r', newline='') as input_file_name:
input_file = csv.reader(input_file_name, delimiter=' ', quotechar='|')
for word in input_file:
GV = Check_Value(gematric_value(word, L))
if GV == EN:
self.txtWords.insertPlainText(", ".join(word))
Integer reduces the Event Number
HN = gematric_value(Event, Hebrew) # Hebrew Event Number
MOD_HN = Check_Value(HN) # Reduced Hebrew Event Number
The Call:
Gematria(y, Hebrew, MOD_HN)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
Traceback (most recent call last):
File "C:\Users\Jacob-C\Documents\Numerology_Predict.py", line 146, in <module>
Launch_Program()
File "C:\Users\Jacob-C\Documents\Numerology_Predict.py", line 144, in Launch_Program
Gematria(y, L, EN)
File "C:\Users\Jacob-C\Documents\Numerology_Predict.py", line 116, in Gematria
GV = Check_Value(Event_Number(word, L))
File "C:\Users\Jacob-C\Documents\Numerology_Predict.py", line 95, in Event_Number
for e in E.lower():
AttributeError: 'list' object has no attribute 'lower'
My Answer:
def Gematria(f, L, EN):
with open(f, 'r') as input_file:
for word in input_file:
GV = Check_Value(Event_Number(word, L))
if GV == EN:
print(word)

Python AttributeError / NameError with confirmed imports

I have two files, InvertedIndex.py and gui.py for an Inverted Index program I'm working on.
Both files work correctly on their own and have the correct imports. When I run python InvertedIndex.py things function properly and return the values to the interface, but when I run python gui.py, enter my search term and click search I am met with this:
C:\Users\MTXIII\Documents\Dev\Python\Projects\InvIndex\gui\InvInd\Test>python gui.py
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\MTXIII\Anaconda3\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\Users\MTXIII\Documents\Dev\Python\Projects\InvIndex\gui\InvInd\Test\gui.py", line 17, in open
for line in bck.index_lookup_query(Term.get()):
AttributeError: module 'InvertedIndex' has no attribute 'index_lookup_query'
Furthermore, when I run these checks I get NameError: name 'bck' is not defined (bck is the alias given in file for InvertedIndex.py)
>>> import gui
>>> print(bck)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'bck' is not defined
>>> print(dir(bck))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'bck' is not defined
>>> for line in bck.index_lookup_query(Term.get()):
...
I have also confirmed that index_lookup_query is within the namespace of InvertedIndex.
>>> import InvertedIndex >>> print(dir(InvertedIndex)) ['Appearance', 'Database', 'InvertedIndex', 'builtins', 'cached', 'doc', 'file', 'loader', 'name', 'package', 'spec', 'g', 'index_documents', 'index_lookup_query', 'main', 're'] >>>
My Code is below:
gui.py:
```
from tkinter import *
import InvertedIndex as bck
# from InvertedIndex import index_lookup_query
LARGE_FONT = ("Verdana", 12)
NORM_FONT = ("Verdana", 10)
SMALL_FONT = ("Verdana", 8)
def open():
top = Toplevel()
searching = 'Occurences of the term: ' + Term.get()
lbl = Label(top, text=searching, width = 60, font = LARGE_FONT).pack()
listbox = Listbox(top)
listbox.pack()
# for line in bck.index_lookup_query(Term.get()):
for line in bck.index_lookup_query(Term.get()):
listbox.insert(END, line)
#create the tkinter window.
root = Tk()
root.geometry('300x85')
# frame = Frame(root, width=100, height=15, bg='white')
# frame.pack()
# to rename the title of the root
root.title("Term Search")
#Label for entry box.
# Label(root, text = "Enter the term you would like to search for:").grid(row = 0)
# Entry box.
Term = Entry(root, width=30)
Term.pack(side = TOP)
Term.insert(0,"Enter the term to search for:")
# Term.grid(row = 0, column = 0)
# Search button.
search_for = "Searching for " + Term.get()
b1 = Button(root, text = "Search!", bg = 'grey', fg = "red", width = 30, command = open)
b1.pack()
# b1.grid(row = 1, column = 0) #'fg or foreground' is for coloring the contents (buttons)
mainloop()
```
InvertedIndex.py:
```
import re
import gui as g
class Appearance:
"""
Represents the appearance of a term in a given document, along with the
frequency of appearances in the same one.
"""
def __init__(self, docId, frequency):
self.docId = docId
self.frequency = frequency
def __repr__(self):
"""
String representation of the Appearance object
"""
return str(self.__dict__)
class Database:
"""
In memory database representing the already indexed documents.
"""
def __init__(self):
self.db = dict()
def __repr__(self):
"""
String representation of the Database object
"""
return str(self.__dict__)
def get(self, id):
return self.db.get(id, None)
def add(self, document):
"""
Adds a document to the DB.
"""
return self.db.update({document['id']: document})
def remove(self, document):
"""
Removes document from DB.
"""
return self.db.pop(document['id'], None)
class InvertedIndex:
"""
Inverted Index class.
"""
def __init__(self, db):
self.index = dict()
self.db = db
def __repr__(self):
"""
String representation of the Database object
"""
return str(self.index)
def index_document(self, document):
"""
Process a given document, save it to the DB and update the index.
"""
# Remove punctuation from the text.
clean_text = re.sub(r'[^\w\s]','', document['text'])
terms = clean_text.split(' ')
appearances_dict = dict()
# Dictionary with each term and the frequency it appears in the text.
for term in terms:
term_frequency = appearances_dict[term].frequency if term in appearances_dict else 0
appearances_dict[term] = Appearance(document['id'], term_frequency + 1)
# Update the inverted index
update_dict = { key: [appearance]
if key not in self.index
else self.index[key] + [appearance]
for (key, appearance) in appearances_dict.items() }
self.index.update(update_dict)
# Add the document into the database
self.db.add(document)
return document
def lookup_query(self, query):
"""
Returns the dictionary of terms with their correspondent Appearances.
This is a very naive search since it will just split the terms and show
the documents where they appear.
"""
return { term: self.index[term] for term in query.split(' ') if term in self.index }
def index_documents(index):
document1 = {
'id': '1',
'text': 'It resides in a cavern on the moon.'
}
document2 = {
'id': '2',
'text': 'The lunar brew expedition.'
}
document3 = {
'id': '3',
'text': 'beer beer beer!'
}
document4 = {
'id': '4',
'text': 'Space travel has changed to way we consume beer.'
}
document5 = {
'id': '5',
'text': 'Over the moon brew.'
}
document6 = {
'id': '6',
'text': 'Deep in the caverns of the moon, beer.'
}
index.index_document(document1)
index.index_document(document2)
index.index_document(document3)
index.index_document(document4)
index.index_document(document5)
index.index_document(document6)
def index_lookup_query(search_term):
db = Database()
index = InvertedIndex(db)
index_documents(index)
result = index.lookup_query(search_term)
for key, value in result.items():
for appearance in value:
yield '{}, {}'.format(appearance.docId, appearance.frequency)
def main():
search_term = input('Enter term to search for: ')
#
# result = index.lookup_query(search_term)
for line in index_lookup_query(search_term):
print(line)
print("-----------------------------")
if __name__ == "__main__":
main()
```
You have a case of circular dependency.
module1.py
import module2
module2.func()
module2.py
import module1
def func():
print("hello")
Now if you run
python module1.py
You will run into module 'module2' has no attribute 'func' error.
The reason this happens is that the line module2.func() isn't executed when you think it will be executed. Here is how the program flows:
import module2 at line1, module1 (program now goes to module2)
import mudule1 at line1, module2 (program now goes to module1 again)
import module2 at line1, module1 (program doesn't go to module2 again because module2 has been imported before.)
module2.func() at line2, module1. (throws an error because we have never reached to the func definition at line2, module2. So, module2 doesn't yet have func
The easiest way to solve this problem is to get rid of the circular import. In your case, remove import gui as g from the InvertedIndex.py since it seems unnecessary.

How i can parse efficiency Html in Python?

I will parse the Html code efficiency without an external libarry.
I have all ready tried with for and had check which symbol is it.
It was this:
list = []
html = """<html><p>Hello</p></html>"""
m = 0
for a in html:
if a == "<":
m = 1
list.append([])
elif a == ">":
m = 0
list.append([])
else:
list[-1] = a
print(list)
The code was on 50KB Files very slow.
May I recommend starting with a simple HTML parser like the one shown below? It uses the standard library that comes with Python and has no external dependencies. You may need to alter and extend it according to your needs, but it gives you a basic DOM API that should be a good beginning point to work from. The code works for the simple case it is meant to tackle; but depending on your needs, you may need to add further functionality to accomplish whatever your end goal may be.
#! /usr/bin/env python3
import html.parser
import pprint
import xml.dom.minidom
def main():
# noinspection PyPep8
document = '''
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
Elsie,
Lacie and
Tillie;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
'''
parser = DocumentParser()
parser.feed(document)
parser.close()
model = parser.document.documentElement
model.normalize()
print(model.toprettyxml())
first_title = model.getElementsByTagName('title')[0]
print(first_title.toxml())
print(first_title.tagName)
print(first_title.firstChild.data)
print(first_title.parentNode.tagName)
first_p = model.getElementsByTagName('p')[0]
print(first_p.toxml())
print(first_p.getAttribute('class'))
all_a = model.getElementsByTagName('a')
print(all_a[0].toxml())
pprint.pprint([element.toxml() for element in all_a])
pprint.pprint([element.toxml() for element in find(model, id='link3')])
for element in all_a:
print(element.getAttribute('href'))
print(*get_text(model), sep='\n')
class DocumentParser(html.parser.HTMLParser):
# noinspection SpellCheckingInspection
def __init__(self, *, convert_charrefs=True):
super().__init__(convert_charrefs=convert_charrefs)
self.document = self.focus = xml.dom.minidom.DOMImplementation() \
.createDocument(None, None, None)
#property
def document_has_focus(self):
return self.document is self.focus
def handle_starttag(self, tag, attrs):
element = self.document.createElement(tag)
for name, value in attrs:
element.setAttribute(name, value)
self.focus.appendChild(element)
self.focus = element
def handle_endtag(self, tag):
while self.focus.tagName != tag:
self.focus = self.focus.parentNode
self.focus = self.focus.parentNode
def handle_data(self, data):
if not self.document_has_focus and not data.isspace():
self.focus.appendChild(self.document.createTextNode(data.strip()))
def error(self, message):
raise RuntimeError(message)
def close(self):
super().close()
while not self.document_has_focus:
self.focus = self.focus.parentNode
def find(element, **kwargs):
get_attribute = getattr(element, 'getAttribute', None)
if get_attribute and \
all(get_attribute(key) == value for key, value in kwargs.items()):
yield element
for child in element.childNodes:
yield from find(child, **kwargs)
def get_nodes_by_type(node, node_type):
if node.nodeType == node_type:
yield node
for child in node.childNodes:
yield from get_nodes_by_type(child, node_type)
def get_text(node):
return (node.data for node in get_nodes_by_type(node, node.TEXT_NODE))
if __name__ == '__main__':
main()

Drag and drop in QTreeView fails with items that hold a QImage

I have a list of items in a QTreeView. Each item holds a QImage object. If I try to drag and drop the item, the program freezes. But when I comment out the line objMod._Image = QImage(flags = Qt.AutoColor), the program runs fine.
How can I drag and drop the items with the QImage object? The QImage holds an image which is rendered. The rendering process takes a while, so it would be nice to keep the QImage object.
import sys
import os
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtUiTools import *
from PIL import Image, ImageCms, ImageQt
class ObjModel:
def __init__(self):
self._Image = None
class DragMoveTest(QMainWindow):
def __init__(self):
super(DragMoveTest,self).__init__()
self.initGUI()
self.show()
def initGUI(self):
self.treeView = QTreeView()
modelTreeView = QStandardItemModel()
self.treeView.setModel(modelTreeView)
for i in range(0, 4):
objMod = ObjModel()
objMod._Image = None
objMod._Image = QImage(flags = Qt.AutoColor)
item = QStandardItem('Test: %s' % str(i))
item.setData(objMod, Qt.UserRole + 1)
modelTreeView.invisibleRootItem().appendRow(item)
self.treeView.setDragDropMode(QAbstractItemView.InternalMove)
self.setCentralWidget(self.treeView)
def main(args):
app = QApplication(sys.argv)
qt_main_wnd = DragMoveTest()
ret = app.exec_()
sys.exit(ret)
if __name__ == "__main__":
main(sys.argv)
This is caused by a bug in PySide. During a drag and drop operation, the data in the dragged item must be serialized. This will be handled by Qt for most data-types, but for types that are specific to Python, special handling is required. This special handling seems to be broken in PySide. If your example is converted to PyQt, a TypeError is raised when trying to drag items, but the program does not freeze.
The source of the problem is that you are storing data using a custom Python class. PyQt uses pickle to serialize custom data-types, but it is not possible to also pickle the QImage that is stored in its __dict__, so the operation fails. I assume PySide must attempt something similar, but for some reason it does not raise an error when it fails. Qt grabs the mouse whilst dragging, so if the operation fails abnormally, it won't be released again, and the program will appear to freeze.
The simplest way to fix this is to avoid using a custom class to hold the QImage, and instead store the image directly in the item:
image = QImage()
item = QStandardItem('Test: %s' % i)
item.setData(image, Qt.UserRole + 1)
To store more data items, you can either use a different data-role for each one, or use a dict to hold them all:
data = {'image': QImage(), 'title': 'foo', 'timestamp': 1756790}
item.setData(data, Qt.UserRole + 1)
However, if you do this, you must always use string keys in the dict, otherwise you will face the same problems as before. (Using string keys means the dict can be converted into a QMap, which Qt knows how to serialize).
(NB: if you want to know whether a Qt class can be serialized, check the docs to see whether it defines the datastream operators).
I come up with a different solution. It is easier to have a object that holds a io.BytesIO. Your store the ImageData into the bytesIO variable. Upon on your image library you can open the image from the bytesIO variable.
In the demo the class ObjModel can handle QImage and Image from Pillow/PIL. If you use the set methods the image object will be converted into a bytesIO.
In short here a working example:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
import io
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtUiTools import *
from PIL import Image, ImageCms, ImageQt
########################################################################
class ObjModel:
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self._ImageByteIO = None
#----------------------------------------------------------------------
def getObjByte(self):
""""""
return self._ImageByteIO
#----------------------------------------------------------------------
def getQImage(self):
""""""
try:
self._ImageByteIO.seek(0)
qImg = QImage.fromData(self._ImageByteIO.getvalue())
return qImg
except:
return None
#----------------------------------------------------------------------
def getPILImage(self):
""""""
try:
self._ImageByteIO.seek(0)
img = Image.open(tBytesIO)
return img
except:
return None
#----------------------------------------------------------------------
def setObjByte(self, fileName):
""""""
try:
tBytesIO = io.BytesIO()
f = open (fileName, 'rb')
tBytesIO.write(f.read())
f.close()
self._ImageByteIO = tBytesIO
except:
self._ImageByteIO = None
#----------------------------------------------------------------------
def setQImage(self, qImg):
""""""
try:
tBytesIO = io.BytesIO()
qByteArray = QByteArray()
qBuf = QBuffer(qByteArray)
qBuf.open(QIODevice.ReadWrite)
qImg.save(qBuf, 'PNG')
tBytesIO = io.BytesIO()
tBytesIO.write(qByteArray.data())
self._ImageByteIO = tBytesIO
except:
self._ImageByteIO = None
#----------------------------------------------------------------------
def setPILImage(self, pImg):
""""""
tBytesIO = io.BytesIO()
pImg.save(tBytesIO, 'png')
self._ImageByteIO = tBytesIO
#----------------------------------------------------------------------
class DragMoveTest(QMainWindow):
def __init__(self):
""""""
super(DragMoveTest,self).__init__()
self.initGUI()
self.show()
#----------------------------------------------------------------------
def initGUI(self):
""""""
self.treeView = QTreeView()
modelTreeView = QStandardItemModel()
self.treeView.setModel(modelTreeView)
for i in range(0, 4):
objMod = ObjModel()
objMod.setQImage(QImage(flags = Qt.AutoColor))
item = QStandardItem('Test: %s' % str(i))
item.setData(objMod, Qt.UserRole + 1)
modelTreeView.invisibleRootItem().appendRow(item)
self.treeView.setDragDropMode(QAbstractItemView.InternalMove)
self.setCentralWidget(self.treeView)
#----------------------------------------------------------------------
def main(args):
app = QApplication(sys.argv)
qt_main_wnd = DragMoveTest()
ret = app.exec_()
sys.exit(ret)
#----------------------------------------------------------------------
if __name__ == "__main__":
main(sys.argv)

self.assertTrue throwing traceback error in Python 3.x unittesting

I am running a small unittest to check the roman number converter. Here is my code :-
class RomConverter(object):
def __init__(self):
self.digital_mapping = {"M":1000, "D":500, "C":100, "L":50, "X":10, "V":5, "I":1}
def convert(self, rom_num):
value = 0
for char in rom_num:
val += self.digital_mapping[char]
return value
import unittest
class RomConverterTest(unittest.TestCase):
def settingUp(self):
print ("Creating a new RomConverter...")
self.cvt = RomConverter()
def tearDown(self):
print ("Destroying the RomConverter...")
self.cvt = None
def test_empty_num(self):
self.assertTrue(self.cvt.convert("") == 0)
self.assertFalse(self.cvt.convert("") > 0)
def test_no_rom_num(self):
self.assertRaises(TypeError,self.cvt.convert, None)
if __name__ == "__main__":
unittest.main()
But I am getting this message when I run the code :-
Traceback (most recent call last):
File "receipe2 - Copy.py", line 31, in test_empty_roman_numeral
self.assertTrue(self.cvt.convert_to_decimal("") == 0)
AssertionError: False is not true
I see two problems in your code.
First def settingUp(self): should be def setUp(self):
And the return of def convert(self, rom_num): is indented to much. In result the method does not return 0 incase of an empty string.
Here is a working version:
class RomConverter(object):
def __init__(self):
self.digital_mapping = {"M":1000, "D":500, "C":100, "L":50, "X":10, "V":5, "I":1}
def convert(self, rom_num):
value = 0
for char in rom_num:
value += self.digital_mapping[char]
return value
import unittest
class RomConverterTest(unittest.TestCase):
def setUp(self):
print ("Creating a new RomConverter...")
self.cvt = RomConverter()
def tearDown(self):
print ("Destroying the RomConverter...")
self.cvt = None
def test_empty_num(self):
self.assertTrue(self.cvt.convert("") == 0)
self.assertFalse(self.cvt.convert("") > 0)
def test_no_rom_num(self):
self.assertRaises(TypeError,self.cvt.convert, None)
if __name__ == "__main__":
unittest.main()

Resources