HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Tortoise Helper Program

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
helperprogramtortoise

Problem

Recently, the following code was written to help automate some processes that are typically executed while working with a Mercurial database. What is shown below is basically a first draft of the program and was quickly written to test out the idea of creating a GUI tool for others to use.

Question: Are there any obvious flaws in how the program works or how the code is formatted and arranged that might be improved for future versions?

```
import sys
import subprocess
import tkFileDialog
import Tkinter

class TortoiseHelper(Tkinter.Tk):

def __init__(self):
Tkinter.Tk.__init__(self)
self.initialize()
self.create_controls()
if len(sys.argv) > 1:
if TortoiseHelper.validate_repo(sys.argv[1]):
self.repoPath.set(sys.argv[1])
self.refresh_repo()

def change_repo(self):
newPath = tkFileDialog.askdirectory(parent=self)
if TortoiseHelper.validate_repo(newPath):
self.repoPath.set(newPath)
self.refresh_repo()

def create_controls(self):
mainFrame = Tkinter.Frame(self)
mainFrame.grid(row=0, column=0, padx=10, pady=10, sticky=(Tkinter.N, Tkinter.E, Tkinter.S, Tkinter.W))
mainFrame.columnconfigure(1, weight=1)
mainFrame.rowconfigure(13, weight=1)

repoLabel = Tkinter.Label(mainFrame)
repoLabel['text'] = 'Repository'
repoLabel.grid(row=0, column=0, sticky=Tkinter.E)

lblRepo = Tkinter.Label(mainFrame)
lblRepo['textvariable'] = self.repoPath
lblRepo['relief'] = Tkinter.SUNKEN
lblRepo['anchor'] = Tkinter.W
lblRepo.grid(row=0, column=1, ipadx=4, pady=2, sticky=(Tkinter.E, Tkinter.W))

btnRefresh = Tkinter.Button(mainFrame)
btnRefresh['text'] = 'Refresh'
btnRefresh['command'] = self.refresh_repo
btnRefresh.grid(row=0, column=2, padx=2)

btnChange = Tkinter.Button(mainFrame)
btnChange['text'] = 'Change'
btnCh

Solution

The code could be redesigned to make porting to Python 3.X easier in the future. A lot of refactoring is needed, and the following is only a partial redesign. The biggest problem that the program still has is how it locks up while trying to complete long-running operations. My recommendation is to take the following code and use at the starting point for an even more detailed rewrite.

```
#! /usr/bin/env python2
# http://codereview.stackexchange.com/questions/144238
from __future__ import division # PEP 238
from __future__ import absolute_import # PEP 328
from __future__ import print_function # PEP 3105
from __future__ import unicode_literals # PEP 3112

import subprocess
import sys

import Tkinter as tkinter
from Tkconstants import *

import tkFileDialog
tkinter.filedialog = tkFileDialog
del tkFileDialog

class TortoiseTool(tkinter.Frame, object):

__DEFAULT = object()

@classmethod
def main(cls, argv=None):
tkinter.NoDefaultRoot()
root = tkinter.Tk()
# Configure the main window.
root.title('Tortoise Helper')
root.wm_minsize(400, 500)
# Create the application with placement.
tool = cls(root, argv=argv)
tool.grid(sticky=NSEW)
# Configure the resizing capabilities.
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
root.mainloop()

def __init__(self, master=None, cnf=__DEFAULT, **kw):
argv = kw.pop('argv', None)
super(TortoiseTool, self).__init__(master, self.__eval(cnf, {}), **kw)
# Initialize the variables used with the widgets.
self.repo_path = tkinter.StringVar(self)
self.repo_status = tkinter.StringVar(self)
self.repo_branch = tkinter.StringVar(self)
self.option_commit = tkinter.BooleanVar(self)
self.new_branch_name = tkinter.StringVar(self)
self.option_close = tkinter.BooleanVar(self)
self.option_merge_test = tkinter.BooleanVar(self)
self.option_silent_merge_test = tkinter.BooleanVar(self)
self.option_merge_production = tkinter.BooleanVar(self)
self.option_silent_merge_production = tkinter.BooleanVar(self)
self.option_push = tkinter.BooleanVar(self)
# Create all widgets used in the applications.
self.repo_label = tkinter.Label(self, text='Repository')
self.lbl_repo = tkinter.Label(
self, textvariable=self.repo_path, relief=SUNKEN, anchor=W
)
self.btn_refresh = tkinter.Button(
self, text='Refresh', command=self.refresh_repo
)
self.btn_change = tkinter.Button(
self, text='Change', command=self.change_repo
)
self.status_label = tkinter.Label(self, text='Status')
self.lbl_status = tkinter.Label(
self, textvariable=self.repo_status, relief=SUNKEN, anchor=W,
justify=LEFT
)
self.branch_label = tkinter.Label(self, text='Branch')
self.lbl_branch = tkinter.Label(
self, textvariable=self.repo_branch, relief=SUNKEN, anchor=W
)
self.chk_commit = tkinter.Checkbutton(
self, text='Commit', variable=self.option_commit,
command=self.on_commit_click
)
self.ent_branch_name = tkinter.Entry(
self, textvariable=self.new_branch_name
)
self.branch_name_label = tkinter.Label(self, text='New branch name')
self.commit_message_label = tkinter.Label(self, text='Commit message')
self.txt_commit_message = tkinter.Text(self, height=4)
self.chk_close = tkinter.Checkbutton(
self, text='Close branch', variable=self.option_close
)
self.chk_merge_test = tkinter.Checkbutton(
self, text='Merge with Test', variable=self.option_merge_test,
command=self.on_merge_test_click
)
self.chk_merge_test_silent = tkinter.Checkbutton(
self, text='Attempt silent merge', state=DISABLED,
variable=self.option_silent_merge_test
)
self.chk_merge_production = tkinter.Checkbutton(
self, text='Merge with Production',
variable=self.option_merge_production,
command=self.on_merge_production_click
)
self.chk_merge_production_silent = tkinter.Checkbutton(
self, text='Attempt silent merge', state=DISABLED,
variable=self.option_silent_merge_production
)
self.chk_push = tkinter.Checkbutton(
self, text='Push', variable=self.option_push
)
self.btn_run = tkinter.Button(self, text='Run', command=self.run)
self.btn_cancel = tkinter.Button(
self, text='Cancel', command=self.quit
)
self.txt_output = tkinter.Text(self, state=DISABLED)
# Finish the setup process and configure parameters.
self.grid_all_widgets()
self.adjust_resizing_weights()

Code Snippets

#! /usr/bin/env python2
# http://codereview.stackexchange.com/questions/144238
from __future__ import division             # PEP 238
from __future__ import absolute_import      # PEP 328
from __future__ import print_function       # PEP 3105
from __future__ import unicode_literals     # PEP 3112

import subprocess
import sys

import Tkinter as tkinter
from Tkconstants import *

import tkFileDialog
tkinter.filedialog = tkFileDialog
del tkFileDialog


class TortoiseTool(tkinter.Frame, object):

    __DEFAULT = object()

    @classmethod
    def main(cls, argv=None):
        tkinter.NoDefaultRoot()
        root = tkinter.Tk()
        # Configure the main window.
        root.title('Tortoise Helper')
        root.wm_minsize(400, 500)
        # Create the application with placement.
        tool = cls(root, argv=argv)
        tool.grid(sticky=NSEW)
        # Configure the resizing capabilities.
        root.grid_columnconfigure(0, weight=1)
        root.grid_rowconfigure(0, weight=1)
        root.mainloop()

    def __init__(self, master=None, cnf=__DEFAULT, **kw):
        argv = kw.pop('argv', None)
        super(TortoiseTool, self).__init__(master, self.__eval(cnf, {}), **kw)
        # Initialize the variables used with the widgets.
        self.repo_path = tkinter.StringVar(self)
        self.repo_status = tkinter.StringVar(self)
        self.repo_branch = tkinter.StringVar(self)
        self.option_commit = tkinter.BooleanVar(self)
        self.new_branch_name = tkinter.StringVar(self)
        self.option_close = tkinter.BooleanVar(self)
        self.option_merge_test = tkinter.BooleanVar(self)
        self.option_silent_merge_test = tkinter.BooleanVar(self)
        self.option_merge_production = tkinter.BooleanVar(self)
        self.option_silent_merge_production = tkinter.BooleanVar(self)
        self.option_push = tkinter.BooleanVar(self)
        # Create all widgets used in the applications.
        self.repo_label = tkinter.Label(self, text='Repository')
        self.lbl_repo = tkinter.Label(
            self, textvariable=self.repo_path, relief=SUNKEN, anchor=W
        )
        self.btn_refresh = tkinter.Button(
            self, text='Refresh', command=self.refresh_repo
        )
        self.btn_change = tkinter.Button(
            self, text='Change', command=self.change_repo
        )
        self.status_label = tkinter.Label(self, text='Status')
        self.lbl_status = tkinter.Label(
            self, textvariable=self.repo_status, relief=SUNKEN, anchor=W,
            justify=LEFT
        )
        self.branch_label = tkinter.Label(self, text='Branch')
        self.lbl_branch = tkinter.Label(
            self, textvariable=self.repo_branch, relief=SUNKEN, anchor=W
        )
        self.chk_commit = tkinter.Checkbutton(
            self, text='Commit', variable=self.option_commit,
            command=self.on_commit_click
        )
        self.ent_branch_name = tkinter.Entry(
            self, textvariable=self.new_branch_name
      

Context

StackExchange Code Review Q#144238, answer score: 2

Revisions (0)

No revisions yet.