import os import sys import string import tkinter import time import traceback time.clock() LINKTYPES_L = ['Symbolic file', 'Hardlink file', 'Symbolic dir', 'Junction dir'] LINKTYPES = {'Symbolic file': '', 'Hardlink file': '/H', 'Symbolic dir': '/D', 'Junction dir': '/J' } LINKTYPES_DIR = ['Symbolic dir', 'Junction dir', LINKTYPES['Symbolic dir'], LINKTYPES['Junction dir']] LINKTYPES_FILE = ['Symbolic file', 'Hardlink file', LINKTYPES['Symbolic file'], LINKTYPES['Hardlink file']] TRACER_AUTOVERIFY_DELAY = 0.5 COLOR_BLACK = '#000' COLOR_YELLOW = '#aa0' COLOR_GREEN = '#0a0' COLOR_RED = '#a00' def assert_linktypes(linktype, symbolpath, actualpath): if os.path.isdir(actualpath) and linktype not in LINKTYPES_DIR or \ os.path.isfile(actualpath) and linktype not in LINKTYPES_FILE: message = 'Invalid linktype {linktype} for target path {target}' message = message.format(linktype=repr(linktype), target=repr(actualpath)) raise TypeError(message) def mklink(linktype, symbolpath, actualpath): symbolpath = os.path.abspath(symbolpath) actualpath = os.path.abspath(actualpath) try: assert_linktypes(linktype, symbolpath, actualpath) except TypeError: traceback.print_exc() return False command = 'mklink {linktype} "{symbolpath}" "{actualpath}"' command = command.format(linktype=linktype, symbolpath=symbolpath, actualpath=actualpath) print(''.join(c for c in command if c in string.printable)) status_code = os.system(command) if status_code != 0: return False if linktype in LINKTYPES_DIR: symtype = 'symlink' if linktype == '/D' else 'junction' symlink_info = symtype + time.strftime('_%Y%m%d-%H%M%S.txt') symlink_info = os.path.join(actualpath, symlink_info) symlink_info = open(symlink_info, 'w') symlink_info.write('actual: ' + actualpath) symlink_info.write('\n') symlink_info.write(symtype + ': ' + symbolpath) symlink_info.close() class LinkGUI: def __init__(self): self.t = tkinter.Tk() self.tracer_nextautoverify = 0 self.tracer_lastkeystroke_verified = False self.tracer_activewaiter = False self.stringvar_actualpath = tkinter.StringVar() self.stringvar_dropdown = tkinter.StringVar() self.label_actualpath = tkinter.Label(self.t, text='Actual path:') self.label_symbolpath = tkinter.Label(self.t, text='Symbol path:') self.entry_actualpath = tkinter.Entry(self.t, width=70, textvariable=self.stringvar_actualpath) self.entry_symbolpath = tkinter.Entry(self.t, width=70) self.dropdown_linktype = tkinter.OptionMenu(self.t, self.stringvar_dropdown, *LINKTYPES_L) self.dropdown_linktype.configure(width=15) self.button_do_it = tkinter.Button(self.t, text='Do it.', command=self.do_it) self.stringvar_actualpath.trace('w', self.tracewatcher) self.stringvar_dropdown.trace('w', lambda *bb: self.tracer_verify_colors(False)) self.stringvar_actualpath.set(os.getcwd()) self.entry_symbolpath.insert(0, os.getcwd()) self.label_actualpath.grid(row=0, column=0, sticky='e') self.label_symbolpath.grid(row=1, column=0, sticky='e') self.entry_actualpath.grid(row=0, column=1, sticky='ew') self.entry_symbolpath.grid(row=1, column=1, sticky='ew') self.dropdown_linktype.grid(row=2, column=0) self.button_do_it.grid(row=2, column=1, sticky='e') self.t.grid_columnconfigure(1, weight=1) self.t.mainloop() def do_it(self, *bb): linktype = self.stringvar_dropdown.get() linktype = LINKTYPES[linktype] actualpath = self.entry_actualpath.get() symbolpath = self.entry_symbolpath.get() status = mklink(linktype, actualpath=actualpath, symbolpath=symbolpath) if status is False: self.button_do_it.configure(bg=COLOR_RED) else: self.button_do_it.configure(bg=COLOR_GREEN) def tracewatcher(self, *bb): self.tracer_lastkeystroke_verified = False self.tracer_nextautoverify = time.time() + TRACER_AUTOVERIFY_DELAY if self.tracer_activewaiter is False: self.tracer_verify() def tracer_verify(self): now = time.time() if self.tracer_lastkeystroke_verified is True: return if now < self.tracer_nextautoverify: delay = int(TRACER_AUTOVERIFY_DELAY * 1000) self.t.after(delay, self.tracer_verify) self.tracer_activewaiter = True self.dropdown_linktype.config(fg=COLOR_YELLOW) return self.tracer_lastkeystroke_verified = True self.tracer_activewaiter = False self.tracer_verify_colors(set_for_me=True) def tracer_verify_colors(self, set_for_me=False, *bb): path = self.stringvar_actualpath.get() linktype = self.stringvar_dropdown.get() if os.path.isfile(path): if set_for_me and linktype not in LINKTYPES_FILE: self.stringvar_dropdown.set('Symbolic file') return if linktype in LINKTYPES_FILE: self.dropdown_linktype.config(fg=COLOR_GREEN) else: self.dropdown_linktype.config(fg=COLOR_BLACK) elif os.path.isdir(path): if set_for_me and linktype not in LINKTYPES_DIR: self.stringvar_dropdown.set('Symbolic dir') return if linktype in LINKTYPES_DIR: self.dropdown_linktype.config(fg=COLOR_GREEN) else: self.dropdown_linktype.config(fg=COLOR_BLACK) else: self.dropdown_linktype.config(fg=COLOR_BLACK) #mklink(LINKTYPE_SYMBOLIC_DIR, 'examples\\symbolic_dir', 'examples\\actual_dir') #mklink(LINKTYPE_JUNCTION_DIR, 'examples\\junction_dir', 'examples\\actual_dir') #mklink(LINKTYPE_SYMBOLIC_FILE, 'examples\\symbolic_file.txt', 'examples\\actual_file.txt') #mklink(LINKTYPE_HARDLINK_FILE, 'examples\\hardlink_file.txt', 'examples\\actual_file.txt') linker = LinkGUI() print('[ {0} elapsed ]'.format(round(time.clock(), 3)))