With open inside of a class - python-3.x

Hello I am doing an assignment and I have a similar problem as to here but in this case I am unable to change the file = logsys(file_location) part due to the assignment rules. Is there any way I can do the "with" part inside of the class?
My code is shown below
doc = write("test_2.txt")
class HtmlTable:
def __init__(self, filename):
self.filename = filename
self.fp = None
def tag(self, text):
self.fp.write('<' + text+ '>' +'\n')
def __iadd__(self, text):
self.fp.write(text)
def __enter__(self):
self.fp = open(self.filename, "a+")
return self
def __exit__(self, exception_type, exception_value, traceback):
self.fp.close()
The idea is that i want to call the class and let it handle the with part for me

Related

Why does one property work and the other not?

It happens that I have two property implementations. but one works and the other does not. That is, that in one it does not even enter the setters.
I gave myself the task of wandering online, and this happens to me is very rare, both are supposed to work.
Do you know why this happens?
Thank you
class QuickTasks():
def __init__(self, name=None, value=None):
self.name = name
self.value = value
#property
def name(self):
return self._name
#name.setter
def name(self, value):
if isinstance(value, str):
self._name = value
else:
raise TypeError("name must be str")
#property
def value(self):
return self._value
#value.setter
def value(self, value):
if isinstance(value, int):
self._value = value
else:
raise TypeError("value must be int")
obj = QuickTasks(name=4, value='j')
print(obj.name)
obj.name = 5
print(obj.name)
################################################################
class TreeNode(object):
def __init__(self, value = None):
self.value = value
self._left_node = None
self._right_node = None
#property
def value(self):
return self._value
#value.setter
def value(self, value):
if isinstance(value, int):
self._value = 8
else:
raise TypeError("value must be int")
def main():
tree_node = TreeNode(3)
#tree_node.value = 3
print (tree_node.value)
if __name__ == '__main__':
print("")
main()
When you hit the line:
obj = QuickTasks(name=4, value='j')
and it assigns to self.name in the QuickTasks initializer, it raises a TypeError, which you don't catch. That bypasses the rest of your code entirely, skipping all uses of the value property (and of TreeNode entirely).

using wxpython calling frame function python interpreter returns error

class MyFrame(wx.Frame):
def __init__(self, parent, title):
super(MyFrame, self).__init__(parent, title=title, size=(620, 665))
splitter = wx.SplitterWindow(self, wx.ID_ANY)
self.MainPanel = NewPanel(splitter)
self.MyNotebook = Nbook(splitter)
splitter.SplitHorizontally(self.MainPanel, self.MyNotebook, sashPosition=210)
self.sb = self.CreateStatusBar(3)
self.MainPanel.Show()
self.Centre()
def setNotebookDisabled(self):
self.MyNotebook.Enabled = False
def PrintSomething(self):
print("Something")
class NewPanel(wx.Panel):
def __init__(self, parent):
super(NewPanel, self).__init__(parent=parent)
def Disable_Controls(self):
self.GrandParent.MyNotebook.Enabled = False
class Nbook(wx.Notebook):
def __init__(self, parent):
super(Nbook, self).__init__(parent)
# self.MyNotebook = wx.Notebook(splitter,wx.ID_ANY)
page_one = NbPanel1(self)
page_two = NbPanel2(self)
page_three = NbPanel3(self)
self.AddPage(page_one, "Cable")
self.AddPage(page_two, "Busduct")
self.AddPage(page_three, "Transformer")
I can call PrintSomething() with success however...
The error:
File "c:/Users/Mark/Documents/FaultWireCalc/FCCalc.py", line 331, in Disable_Controls
self.GrandParent.MyNotebook.Enabled = False
AttributeError: 'MyFrame' object has no attribute 'MyNotebook'
This is not so much an answer as a work in progress, given that a comment simply wouldn't hack it.
Given that you haven't stated when or how the error occurs and it's occurring somewhere in 1000 lines of code, which we can't see, right about now might be a good time for
a minimal, complete and verifiable example (mcve)
https://stackoverflow.com/help/minimal-reproducible-example
As you seem reluctant to provide one, let's try this:
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super(MyFrame, self).__init__(parent, title=title, size=(620, 665))
splitter = wx.SplitterWindow(self, wx.ID_ANY)
self.MainPanel = NewPanel(splitter)
self.MyNotebook = Nbook(splitter)
splitter.SplitHorizontally(self.MainPanel, self.MyNotebook, sashPosition=210)
self.sb = self.CreateStatusBar(3)
self.MainPanel.Show()
self.Centre()
self.Show()
def setNotebookDisabled(self):
self.MyNotebook.Enabled = False
def PrintSomething(self):
print("Something")
class NewPanel(wx.Panel):
def __init__(self, parent):
super(NewPanel, self).__init__(parent=parent)
testbut = wx.Button(self, -1, "Panel Hit Me")
self.Bind(wx.EVT_BUTTON, self.Disable_Controls)
def Disable_Controls(self, event):
self.GrandParent.MyNotebook.Enabled = not self.GrandParent.MyNotebook.IsEnabled()
class Nbook(wx.Notebook):
def __init__(self, parent):
super(Nbook, self).__init__(parent)
# self.MyNotebook = wx.Notebook(splitter,wx.ID_ANY)
page_one = wx.Panel(self)
page_two = wx.Panel(self)
page_three = wx.Panel(self)
self.AddPage(page_one, "Cable")
self.AddPage(page_two, "Busduct")
self.AddPage(page_three, "Transformer")
if __name__ == "__main__":
app = wx.App()
frame = MyFrame(None, "Test")
app.MainLoop()
As you can see, it does function (below) the notebook can be enabled/disabled.
So, can you make this produce the error or deduce from it, how your code differs in the way or when the code is called, that produces the error?
You may find that GrandParent is not what you think it is! (I suspect splitter is involved)
You might try:
print("I am",self)
print("My parent is",self.Parent)
print("Granddad is",self.GrandParent)
print("His parent is",self.GrandParent.GetParent())
The other thing you might try when calling the routine, is to call it directly:
MyFrame.setNotebookDisabled(parent.GetParent())
or a variation to get the right parent, depending on where you are calling it from.
Over to you.

wrapper class with __enter__/__exit__ in python3

I have a code that perfectly works in Python 2, but it doesn't work in Python 3.
There is an aggregator class data and a few classes to work with specific data formats.
class data():
def __init__(self, file, format="x"):
if format == "x":
self.data = xdata(file)
elif format == "y":
self.data = ydata(file)
# Redirect functions to the specific class
self.__enter__ = self.data.__enter__
self.__exit__ = self.data.__exit__
class xdata():
def __init__(self, file):
#do something
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
#do something
class ydata():
def __init__(self, file):
#do something
def __enter__(self):
return self
def __exit__(self,exc_type, exc_value, traceback):
#do something
In python2 I was able to execute the following code without any errors,
with data("newfile.x") as sd:
#do something with data
but python3 returns an error AttributeError: __enter__
Any ideas on how to fix it?
__enter__ and __exit__ will be resolved as descriptors, which means that resolution bypasses the attributes of the class. You can provide your own descriptors for __enter__ and __exit__ using property:
class xdata():
def __init__(self, file):
self.attr = 'x'
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
pass
class ydata():
def __init__(self, file):
self.attr = 'y'
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
pass
class data():
def __init__(self, file, format="x"):
if format == "x":
self.data = xdata(file)
elif format == "y":
self.data = ydata(file)
# Redirect functions to the specific class
#property
def __enter__(self):
return self.data.__enter__
#property
def __exit__(self):
return self.data.__exit__
with data("", "x") as d:
print(d.attr) # x
with data("", "y") as d:
print(d.attr) # y

When I'm trying to open file into tkinter text widget, but receiving error "'str' object has no attribute 'tk'"

While building an editor based on TKINTER, I have added several options into menu bar, but open command returns some error. 'str' object has no attribute 'tk'
Please be informed, I was checking with code structure & tkinter text insert document. But cant get any suitable way for this issue.
self.tk.call((self._w, 'insert', index, chars) + args)
I was checking, for Custom.insert(END, contents, END + '-1c').
But still cant get rid of this on going issue.
Sorry for my bad English &
Thanks in advance.
root = tk.Tk()
def open():
print('Open an existing file from the system.')
# return 'EOF'
file = filedialog.askopenfile(parent=root, mode='rb', title='Select a file')
if file != None:
contents = file.read()
#import pdb;
#pdb.set_trace()
CustomText.insert(END, contents, END + '-1c')
file.close()
#t = threading.Thread(target=open__file)
class TextLineNumbers(tk.Canvas):
def __init__(self, *args, **kwargs):
tk.Canvas.__init__(self, *args, **kwargs)
self.textwidget = None
def attach(self, text_widget):
self.textwidget = text_widget
def redraw(self, *args):
'''redraw line numbers'''
self.delete("all")
i = self.textwidget.index("#0,0")
while True :
dline= self.textwidget.dlineinfo(i)
if dline is None: break
y = dline[1]
linenum = str(i).split(".")[0]
self.create_text(2,y,anchor="nw", text=linenum)
i = self.textwidget.index("%s+1line" % i)
class CustomText(tk.Text):
def __init__(self, *args, **kwargs):
tk.Text.__init__(self, *args, **kwargs)
# create a proxy for the underlying widget
self._orig = self._w + "_orig"
self.tk.call("rename", self._w, self._orig)
self.tk.createcommand(self._w, self._proxy)
def _proxy(self, *args):
# let the actual widget perform the requested action
cmd = (self._orig,) + args
result = self.tk.call(cmd)
# generate an event if something was added or deleted,
# or the cursor position changed
if (args[0] in ("insert", "replace", "delete") or
args[0:3] == ("mark", "set", "insert") or
args[0:2] == ("xview", "moveto") or
args[0:2] == ("xview", "scroll") or
args[0:2] == ("yview", "moveto") or
args[0:2] == ("yview", "scroll")
):
self.event_generate("<<Change>>", when="tail")
# return what the actual widget returned
return result
class Example(tk.Frame):
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
self.text = CustomText(self)
self.vsb = tk.Scrollbar(orient="vertical", command=self.text.yview)
self.text.configure(yscrollcommand=self.vsb.set)
self.text.tag_configure("bigfont", font=("Helvetica", "24", "bold"))
self.linenumbers = TextLineNumbers(self, width=30)
self.linenumbers.attach(self.text)
self.vsb.pack(side="right", fill="y")
self.linenumbers.pack(side="left", fill="y")
self.text.pack(side="right", fill="both", expand=True)
self.text.bind("<<Change>>", self._on_change)
self.text.bind("<Configure>", self._on_change)
def _on_change(self, event):
self.linenumbers.redraw()
menubar = Menu(root, background='#000099', foreground='white',
activebackground='#004c99', activeforeground='white')
filemanu = Menu(menubar, tearoff=0, background="grey", foreground='black',
activebackground='#004c99', activeforeground='white')
menubar.add_cascade(label='File', menu=filemanu)
filemanu.add_command(label='open', command=open)
root.config(bg='#2A2C2B', menu=Example.menubar)
if __name__ == "__main__":
Example(root).pack(side="top", fill="both", expand=True)
root.mainloop()
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:/Users//PycharmProjects/Sub_packages/open_issue.py", line 15, in open
CustomText.insert(END, contents, END + '-1c')
File "C:\Users\\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 3272, in insert
self.tk.call((self._w, 'insert', index, chars) + args)
AttributeError: 'str' object has no attribute 'tk'```
Consider this code:
CustomText.insert(END, contents, END + '-1c')
You are calling the insert method on the class rather than an instance of a class.
You need to save a reference to the instance, and provide a way for your function to access that instance. In your case, the instance is saved as an attribute on the Example class, so you can save a reference to the instance of Example and use that:
def open():
...
example.text.insert(END, contents, END + '-1c')
...
if __name__ == "__main__":
example = Example(root)
example.pack(side="top", fill="both", expand=True)
root.mainloop()
Even better would be to move open into the Example class so that you can use self.text. You also should move the code for creating the menu into the __init__ function.
class Example(tk.Frame):
def __init__(self, *args, **kwargs):
...
menubar = Menu(root, background='#000099', foreground='white',
activebackground='#004c99', activeforeground='white')
filemanu = Menu(menubar, tearoff=0, background="grey", foreground='black',
activebackground='#004c99', activeforeground='white')
menubar.add_cascade(label='File', menu=filemanu)
filemanu.add_command(label='open', command=self.open)
...
def open(self):
...
self.text.insert(END, contents, END + '-1c')
...

Memoized objects still have their __init__() invoked?

So I am creating a memoized class, and have been observing a strange behavior.
Here's the snippet of the code:
class SomeClass(object):
_Memoized = {}
def __new__(cls, id: str, *args, **kwargs):
if id not in cls._Memoized:
print('New Instance')
cls._Memoized[id] = super(SomeClass, cls).__new__(cls, *args, **kwargs)
else:
print('Existing Instance')
return cls._Memoized[id]
def __init__(self, id: str):
print('Running init')
self.id = id
def test():
w1 = SomeClass(id='w1')
wx = SomeClass(id='w1')
print(id(w1), id(wx), id(w1) == id(wx))
test()
Running the above code results in:
New Instance
Running init
Existing Instance
Running init <===-------------------???
140008534476784 140008534476784 True
My questions: During the second invocation of SomeClass(), why does it execute the __init__ constructor? Wasn't the __init__ constructor only invoked on instantiating? Is there a way to prevent the __init__ from being invoked?
The purpose of __new__ is to create a new instance, which is why Python calls __init__ on it. You might instead override __call__ on a metaclass to avoid creating a new instance.
class MemoMeta(type):
def __init__(self, name, bases, namespace):
super().__init__(name, bases, namespace)
self.cache = {}
def __call__(self, id_, *args, **kwargs):
if id_ not in self.cache:
print('New Instance')
self.cache[id_] = super().__call__(id_, *args, **kwargs)
else:
print('Existing Instance')
return self.cache[id_]
class SomeClass(metaclass=MemoMeta):
def __init__(self, id_, *args, **kwargs):
print('Running init')
self.id = id_
def test():
w1 = SomeClass(id_='w1')
wx = SomeClass(id_='w1')
print(id(w1), id(wx), id(w1) == id(wx))
test()

Resources