Skip to content

Instantly share code, notes, and snippets.

@opicron
Forked from gesquive/self-update-script.py
Last active October 20, 2022 10:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save opicron/4184237599350b34d106f84b63462b90 to your computer and use it in GitHub Desktop.
Save opicron/4184237599350b34d106f84b63462b90 to your computer and use it in GitHub Desktop.
python self update #python
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment