File I/O has many potential uses, and in the case of network file shares, messaging can be conducted by creating files in a directory and scanning for new files to find new messages. In the case where there are restrictions within a network that prevent opening server sockets or creating and using client sockets, the technique in this recipe may be used with file shares instead. The program is simple and was written in about fifty minutes, so there are a great deal of enhancements that could be made to the recipe and its capabilities. Hopefully, this will provide inspiration for other program writers.
If you have any comments or wish to down-vote this recipe, please provide your insight as to what could be improved upon and how you would go about fixing any problems that you might find.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | import tkinter
import tkinter.ttk
import getpass
import uuid
import os
import time
import traceback
# XXX The file will be obsolete by tomorrow.
HOLD = 'Logos Storage'
################################################################################
class Logos(tkinter.ttk.Frame):
@classmethod
def main(cls):
# Create and configure the root.
tkinter.NoDefaultRoot()
root = tkinter.Tk()
root.title('Logos')
root.minsize(200, 200)
# Create Logos and setup for resizing.
view = cls(root)
view.grid(row=0, column=0, sticky=tkinter.NSEW)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
# Enter the main GUI event loop.
root.mainloop()
########################################################################
# These are all instance methods.
def __init__(self, master):
super().__init__(master)
# Get the username and save list of found files.
self.__user = getpass.getuser()
self.__dirlist = set()
# Create widgets.
self.__log = tkinter.Text(self)
self.__bar = tkinter.ttk.Scrollbar(self, orient=tkinter.VERTICAL,
command=self.__log.yview)
self.__ent = tkinter.ttk.Entry(self, cursor='xterm')
# Configure widgets.
self.__log.configure(state=tkinter.DISABLED, wrap=tkinter.WORD,
yscrollcommand=self.__bar.set)
# Create binding.
self.__ent.bind('<Return>', self.create_message)
# Position widgets.
self.__log.grid(row=0, column=0, sticky=tkinter.NSEW)
self.__bar.grid(row=0, column=1, sticky=tkinter.NS)
self.__ent.grid(row=1, column=0, columnspan=2, sticky=tkinter.EW)
# Configure resizing.
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
# Focus entry.
self.__ent.focus_set()
# Schedule message discovery.
self.after_idle(self.get_messages)
def get_messages(self):
# Schedule method for one second from now.
self.after(1000, self.get_messages)
# Get a list of new files.
files = set(os.listdir(HOLD))
diff = files - self.__dirlist
self.__dirlist = files
# Load each new message.
messages = []
for name in diff:
path = os.path.join(HOLD, name)
try:
with open(path) as file:
user, clock, message = self.load_message(file)
messages.append((user, float(clock), message))
except:
# Print any error for debugging purposes.
traceback.print_exc()
os.remove(path)
# Sort the messages according to time and display them.
messages.sort(key=lambda m: m[1])
for m in messages:
self.display_message(m[0], m[2])
def display_message(self, user, text):
# Put a new message on the screen.
self.__log['state'] = tkinter.NORMAL
message = '{} - {}\n'.format(user, text)
self.__log.insert('1.0', message)
self.__log['state'] = tkinter.DISABLED
def create_message(self, event):
# Get the text, clear it, show on screen, and create file.
text = event.widget.get()
event.widget.delete(0, tkinter.END)
self.display_message(self.__user, text)
self.save_file(text)
def save_file(self, message):
# Save message in HOLD using a UUID for the name.
name = uuid.uuid1().hex
path = os.path.join(HOLD, name)
self.__dirlist.add(name)
with open(path, 'w') as file:
self.save_message(file, message)
########################################################################
# If one the format is changed, both methods must be altered.
def load_message(self, file):
# Read the file, splitting on newline, and get first three lines.
user, clock, message = file.read().split('\n')[:3]
return user, clock, message
def save_message(self, file, message):
# Save username, timestamp, and message on separate lines.
print(self.__user, file=file)
print(time.time(), file=file)
print(message, file=file, end='')
################################################################################
if __name__ == '__main__':
Logos.main()
|