-
-
Save Haaruun-I/7742df86770cc7c2066b99dca05186e9 to your computer and use it in GitHub Desktop.
Stick this in a python script to self update the script from an online source
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__version__ = "1" | |
def update(dl_url, force_update=False): | |
""" | |
Attempts to download the update url in order to find if an update is needed. | |
If an update is needed, the current script is backed up and the update is | |
saved in its place. | |
""" | |
import urllib | |
import re | |
import os | |
import sys | |
from subprocess import call | |
def compare_versions(vA, vB): | |
""" | |
Compares two version number strings | |
@param vA: first version string to compare | |
@param vB: second version string to compare | |
@author <a href="http_stream://sebthom.de/136-comparing-version-numbers-in-jython-pytho/">Sebastian Thomschke</a> | |
@return negative if vA < vB, zero if vA == vB, positive if vA > vB. | |
""" | |
if vA == vB: return 0 | |
def num(s): | |
if s.isdigit(): return int(s) | |
return s | |
seqA = map(num, re.findall('\d+|\w+', vA.replace('-SNAPSHOT', ''))) | |
seqB = map(num, re.findall('\d+|\w+', vB.replace('-SNAPSHOT', ''))) | |
# this is to ensure that 1.0 == 1.0.0 in cmp(..) | |
lenA, lenB = len(seqA), len(seqB) | |
for i in range(lenA, lenB): seqA += (0,) | |
for i in range(lenB, lenA): seqB += (0,) | |
rc = cmp(seqA, seqB) | |
if rc == 0: | |
if vA.endswith('-SNAPSHOT'): return -1 | |
if vB.endswith('-SNAPSHOT'): return 1 | |
return rc | |
# dl the first 256 bytes and parse it for version number | |
try: | |
http_stream = urllib.urlopen(dl_url) | |
update_file = http_stream.read(256) | |
http_stream.close() | |
except IOError, (errno, strerror): | |
print "Unable to retrieve version data" | |
print "Error %s: %s" % (errno, strerror) | |
return | |
match_regex = re.search(r'__version__ *= *"(\S+)"', update_file) | |
if not match_regex: | |
print "No version info could be found" | |
return | |
update_version = match_regex.group(1) | |
if not update_version: | |
print "Unable to parse version data" | |
return | |
if force_update: | |
print "Forcing update, downloading version %s..." \ | |
% update_version | |
else: | |
cmp_result = compare_versions(__version__, update_version) | |
if cmp_result < 0: | |
print "Newer version %s available, downloading..." % update_version | |
elif cmp_result > 0: | |
print "Local version %s newer then available %s, not updating." \ | |
% (__version__, update_version) | |
return | |
else: | |
print "You already have the latest version." | |
return | |
# dl, backup, and save the updated script | |
app_path = os.path.realpath(sys.argv[0]) | |
if not os.access(app_path, os.W_OK): | |
print "Cannot update -- unable to write to %s" % app_path | |
dl_path = app_path + ".new" | |
backup_path = app_path + ".old" | |
try: | |
dl_file = open(dl_path, 'w') | |
http_stream = urllib.urlopen(dl_url) | |
total_size = None | |
bytes_so_far = 0 | |
chunk_size = 8192 | |
try: | |
total_size = int(http_stream.info().getheader('Content-Length').strip()) | |
except: | |
# The header is improper or missing Content-Length, just download | |
dl_file.write(http_stream.read()) | |
while total_size: | |
chunk = http_stream.read(chunk_size) | |
dl_file.write(chunk) | |
bytes_so_far += len(chunk) | |
if not chunk: | |
break | |
percent = float(bytes_so_far) / total_size | |
percent = round(percent*100, 2) | |
sys.stdout.write("Downloaded %d of %d bytes (%0.2f%%)\r" % | |
(bytes_so_far, total_size, percent)) | |
if bytes_so_far >= total_size: | |
sys.stdout.write('\n') | |
http_stream.close() | |
dl_file.close() | |
except IOError, (errno, strerror): | |
print "Download failed" | |
print "Error %s: %s" % (errno, strerror) | |
return | |
try: | |
os.rename(app_path, backup_path) | |
except OSError, (errno, strerror): | |
print "Unable to rename %s to %s: (%d) %s" \ | |
% (app_path, backup_path, errno, strerror) | |
return | |
try: | |
os.rename(dl_path, app_path) | |
except OSError, (errno, strerror): | |
print "Unable to rename %s to %s: (%d) %s" \ | |
% (dl_path, app_path, errno, strerror) | |
return | |
try: | |
import shutil | |
shutil.copymode(backup_path, app_path) | |
except: | |
os.chmod(app_path, 0755) | |
print "New version installed as %s" % app_path | |
print "(previous version backed up to %s)" % (backup_path) | |
return | |
update("https://gist.githubusercontent.com/Haaruun-I/7742df86770cc7c2066b99dca05186e9/raw/6d1c687b311978b71d083ee0914d2e56938b20e5/self-update-script.py") | |
def main(): | |
# Here is the first line of the main function's code. | |
root = tkinter.Tk() | |
root.title("Draw!") | |
cv = tkinter.Canvas(root,width=600,height=600) | |
cv.pack(side = tkinter.LEFT) | |
# This is how we create a turtle to draw on the canvas we created above. | |
t = turtle.RawTurtle(cv) | |
screen = t.getscreen() | |
# With the lines below, the "turtle" will look like a pencil. | |
screen.register_shape("pencil.gif") | |
t.shape("pencil.gif") | |
# This sets the lower left corner to 0,0 and the upper right corner to 600,600. | |
screen.setworldcoordinates(0,0,600,600) | |
screen.bgcolor("white") | |
# A frame is an invisible widget that holds other widgets. This frame goes | |
# on the right hand side of the window and holds the buttons and Entry widgets. | |
frame = tkinter.Frame(root) | |
frame.pack(side = tkinter.RIGHT,fill=tkinter.BOTH) | |
pointLabel = tkinter.Label(frame,text="Width") | |
pointLabel.pack() | |
# This entry widget allows the user to pick a width for their lines. | |
# With the pointSize variable below you can write pointSize.get() to to | |
# the contents of the entry widget and pointSize.set(val) to set the value | |
# of the entry widget to val. Initially the pointSize is set to 1. str(1) is needed because | |
# the entry widget must be given a string. | |
pointSize = tkinter.StringVar() | |
pointEntry = tkinter.Entry(frame,textvariable=pointSize) | |
pointEntry.pack() | |
pointSize.set(str(1)) | |
# This is an event handler. Handling the quit button press results in destroying the window | |
# and quitting the application. | |
def quitHandler(): | |
root.destroy() | |
root.quit() | |
# This is how a button is created in the frame. The quitHandler is the event handler for button | |
# presses of the "Quit" button. | |
quitButton = tkinter.Button(frame, text = "Quit", command=quitHandler) | |
quitButton.pack() | |
# Here is another event handler. This one handles mouse clicks on the screen. | |
def clickHandler(x,y): | |
# When a mouse click occurs, get the pointSize entry value and set the width of the | |
# turtle called "t" to the pointSize value. The int(pointSize.get()) is needed because | |
# the width is an integer, but the entry widget stores it as a string. | |
t.width(int(pointSize.get())) | |
t.goto(x,y) | |
# Here is how we tie the clickHandler to mouse clicks. | |
screen.onclick(clickHandler) | |
# Finally, this code is last. It tells the application to enter its event processing loop | |
# so the application will respond to events. | |
tkinter.mainloop() | |
# Python jumps right here after executing the def main() line. These two lines tell | |
# Python to jump to the first line of the main function above. Seems a little strange, | |
# but there are good reasons for this which you'll learn if you take some computer | |
# science. | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment