Last active
November 3, 2024 09:35
-
-
Save gesquive/8363131 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 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
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 | |
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 |
T
This needs to get updated. Almost everything has changed since this was last updated even though the method is still accurate.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It'll look online at a URL you provided and compare the version the user is running with the version online. If the one online is newer, this will download that newer version and replace the script so that its update to date. Whenever a new version is pushed out, the application can always fetch the most up to date version. You could have it auto do this or you could give your end users the option to "check for updates". Just makes it easier for them to stay up to date.