rewrite updater.

This commit is contained in:
St.Huang 2018-07-31 04:50:11 +08:00
parent 4d255f8608
commit ef662527fa
4 changed files with 349 additions and 413 deletions

View File

@ -36,8 +36,11 @@ __all__ = ['show_options', 'check_updates', 'show_fm_dialog', 'show_about_dialog
def check_updates(): def check_updates():
'''check add-on last version''' '''check add-on last version'''
try: try:
if not ankihub.update([Endpoint.check_version], False, Endpoint.version): state = ankihub.update([Endpoint.check_version], False, Endpoint.version)
if state == 0:
showInfo(_('LATEST_VERSION')) showInfo(_('LATEST_VERSION'))
elif state == -1:
showInfo(_('CHECK_FAILURE'))
except: except:
showInfo(_('CHECK_FAILURE')) showInfo(_('CHECK_FAILURE'))

View File

@ -1,42 +1,29 @@
from PyQt4 import QtCore,QtGui try:
import httplib import httplib
import urllib2 except:
import http.client as httplib
try:
import urllib2
except:
import urllib.request as urllib2
import json import json
import os import os
import sys import sys
import zipfile import zipfile
import traceback import traceback
import io import io
from AnkiHub.updates import Ui_DialogUpdates
from AnkiHub.markdown2 import markdown
import aqt import aqt
from aqt import mw from aqt import mw
from aqt.qt import *
from anki.hooks import addHook from anki.hooks import addHook
from anki.utils import isMac, isWin from anki.utils import isMac, isWin
from ..context import APP_ICON from ..context import APP_ICON
from .AnkiHub.updates import Ui_DialogUpdates
from .AnkiHub.markdown2 import markdown
# taken from Anki's aqt/profiles.py # taken from Anki's aqt/profiles.py
def defaultBase(): def defaultBase():
'''
print(mw.pm.addonFolder())
if isWin:
loc = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.DocumentsLocation)
return os.path.join(loc, "Anki")
elif isMac:
return os.path.expanduser("~/Documents/Anki")
else:
p = os.path.expanduser("~/Anki")
if os.path.exists(p):
return p
else:
loc = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.DocumentsLocation)
if loc[:-1] == QtGui.QDesktopServices.storageLocation(
QtGui.QDesktopServices.HomeLocation):
return os.path.expanduser("~/Documents/Anki")
else:
return os.path.join(loc, "Anki")
'''
path = mw.pm.addonFolder() path = mw.pm.addonFolder()
return os.path.dirname(os.path.abspath(path)) return os.path.dirname(os.path.abspath(path))
@ -45,53 +32,37 @@ headers = {"User-Agent": "AnkiHub"}
dataPath = os.path.join(defaultBase(),'.fastwq_2.0.x_ankihub.json') dataPath = os.path.join(defaultBase(),'.fastwq_2.0.x_ankihub.json')
class DialogUpdates(QtGui.QDialog, Ui_DialogUpdates): class DialogUpdates(QDialog, Ui_DialogUpdates):
def __init__(self, parent, data, oldData, callback, automaticAnswer=None,install=False):
QtGui.QDialog.__init__(self,parent) def __init__(self, parent, data, oldData, callback, install=False):
QDialog.__init__(self,parent)
self.setModal(True) self.setModal(True)
self.setWindowFlags( self.setWindowFlags(
self.windowFlags() & self.windowFlags() &
~QtCore.Qt.WindowContextHelpButtonHint ~Qt.WindowContextHelpButtonHint
) )
self.setWindowIcon(APP_ICON) self.setWindowIcon(APP_ICON)
self.setupUi(self) self.setupUi(self)
totalSize = sum(map(lambda x:x['size'],data['assets'])) totalSize = sum(map(lambda x:x['size'],data['assets']))
def answer(doUpdate,answ): def answer():
self.update.setEnabled(False) self.update.setEnabled(False)
#self.dont.setEnabled(False) callback(self.appendHtml, self.finish, install)
#self.always.setEnabled(False)
#self.never.setEnabled(False)
callback(doUpdate,answ,self.appendHtml,self.finish,install)
self.html = u'' self.html = u''
self.appendHtml(markdown(data['body'])) self.appendHtml(markdown(data['body']))
#if not automaticAnswer: #if not automaticAnswer:
self.connect(self.update,QtCore.SIGNAL('clicked()'), self.update.clicked.connect(lambda:answer())
lambda:answer(True,'ask'))
#self.connect(self.dont,QtCore.SIGNAL('clicked()'),
# lambda:answer(False,'ask'))
#self.connect(self.always,QtCore.SIGNAL('clicked()'),
# lambda:answer(True,'always'))
#self.connect(self.never,QtCore.SIGNAL('clicked()'),
# lambda:answer(False,'never'))
#else:
#self.update.setEnabled(False)
#self.dont.setEnabled(False)
#self.always.setEnabled(False)
#self.never.setEnabled(False)
# answer(True,automaticAnswer)
fromVersion = '' fromVersion = ''
if 'tag_name' in oldData: if 'tag_name' in oldData:
fromVersion = u'from {0} '.format(oldData['tag_name']) fromVersion = u'from {0} '.format(oldData['tag_name'])
self.labelUpdates.setText( self.labelUpdates.setText(
unicode(self.labelUpdates.text()).format( str(self.labelUpdates.text()).format(
data['name'], data['name'],
fromVersion, fromVersion,
data['tag_name'])) data['tag_name']))
def appendHtml(self,html='',temp=''): def appendHtml(self,html='',temp=''):
self.html += html self.html += html
self.textBrowser.setHtml(u'<html><body>{0}{1}{2}</body></html>'.format(self.html, temp, u'<div id="text_bottom"></div>')) self.textBrowser.setHtml(u'<html><body>{0}{1}{2}</body></html>'.format(self.html, temp, u'<div id="text_bottom"></div>'))
@ -122,101 +93,77 @@ def installZipFile(data, fname):
z.extract(n, base) z.extract(n, base)
return True return True
def asset(a): def asset(a):
return { return {
'url': a['browser_download_url'], 'url': a['browser_download_url'],
'size': a['size'] 'size': a['size']
} }
profileLoaded = True
def _profileLoaded():
profileLoaded = True
addHook("profileLoaded",_profileLoaded) def updateSingle(repositories, path, data):
def callback(appendHtml, onReady, install):
for asset in data['assets']:
code = asset['url']
p, fname = os.path.split(code)
appendHtml(temp='<br />Downloading {1}: {0}%<br/>'.format(0,fname))
urlthread = UrlThread(code)
urlthread.start()
urlthread.join()
response = urlthread.response#urllib2.urlopen(code)
meta = response.info()
file_size = int(meta.get("Content-Length"))
d = buffer('')
dl = 0
i = 0
lastPercent = None
while True:
dkb = response.read(1024)
if not dkb:
break
dl += len(dkb)
d += dkb
if dl*100/file_size>i:
lastPercent = int(dl*100/file_size)
i = lastPercent+1
appendHtml(temp='<br />Downloading {1}: {0}%<br/>'.format(lastPercent,fname))
QApplication.instance().processEvents()
appendHtml('<br />Downloading {1}: 100%<br/>'.format(int(dl*100/file_size),fname))
appendHtml('Installing ...<br/>')
if not installZipFile(d, fname):
appendHtml('Corrupt file<br/>')
else:
repositories[path] = data
repositories[path]['update'] = 'ask'
with open(dataPath,'w') as f:
json.dump(repositories,f,indent=2)
f.close()
appendHtml('Done.<br/>Please restart Anki.<br/>')
onReady() # close the AnkiHub update window
def updateSingle(repositories,path,data):
def callback(doUpdate,answer,appendHtml,onReady,install):
if doUpdate:
for asset in data['assets']:
code = asset['url']
p, fname = os.path.split(code)
response = urllib2.urlopen(code)
meta = response.info()
file_size = int(meta.getheaders("Content-Length")[0])
d = buffer('')
dl = 0
i = 0
lastPercent = None
while True:
dkb = response.read(1024)
if not dkb:
break
dl += len(dkb)
d += dkb
if dl*100/file_size>i:
lastPercent = int(dl*100/file_size)
i = lastPercent+1
appendHtml(temp='<br />Downloading {1}: {0}%<br/>'.format(lastPercent,fname))
QtGui.QApplication.instance().processEvents()
appendHtml('<br />Downloading {1}: 100%<br/>'.format(int(dl*100/file_size),fname))
def installData():
if install:
filesBefore = aqt.mw.addonManager.files()
#directoriesBefore = aqt.mw.addonManager.directories()
appendHtml('Installing ...<br/>')
if not installZipFile(d,fname):
appendHtml('Corrupt file<br/>')
else:
repositories[path] = data
repositories[path]['update'] = answer
with open(dataPath,'w') as file:
json.dump(repositories,file,indent=2)
file.close()
if install:
appendHtml('Executing new scripts...<br/>')
newFiles = set(aqt.mw.addonManager.files()) - set(filesBefore)
#newDirectories = set(aqt.mw.addonManager.directories()) - set(directoriesBefore)
for file in newFiles:
try:
__import__(file.replace(".py", ""))
except:
traceback.print_exc()
#for directory in newDirectories:
# try:
# __import__(directory)
# except:
# traceback.print_exc()
aqt.mw.addonManager.rebuildAddonsMenu()
appendHtml('Done.<br/>')
onReady() # close the AnkiHub update window
else:
appendHtml('Done.<br/>Please restart Anki.<br/>')
onReady() # close the AnkiHub update window
installData()
else:
repositories[path]['update'] = answer
with open(dataPath,'w') as file:
json.dump(repositories,file,indent=2)
file.close()
onReady()
return callback return callback
datas = []
def update(add=[],install=False, VERSION='v0.0.0'): def update(add=[], install=False, VERSION='v0.0.0'):
# progress win
progresswin = QProgressDialog('Update Checking...', 'FastWQ - Updater', 0, 0, mw)
progresswin.setWindowModality(Qt.ApplicationModal)
progresswin.setCancelButton(None)
progresswin.setWindowFlags(
progresswin.windowFlags() &
~Qt.WindowContextHelpButtonHint
)
progresswin.setWindowIcon(APP_ICON)
progresswin.resize(280, 60)
progresswin.show()
#
conn = httplib.HTTPSConnection("api.github.com") conn = httplib.HTTPSConnection("api.github.com")
try: try:
with open(dataPath,'r') as file: with open(dataPath,'r') as f:
repositories = json.load(file) repositories = json.load(f)
file.close() f.close()
except: except:
repositories = {} repositories = {}
# 'dayjaby/AnkiHub': {
# 'id': 4089471,
# 'update': 'ask'
# }
#}
for a in add: for a in add:
if a not in repositories: if a not in repositories:
@ -225,92 +172,115 @@ def update(add=[],install=False, VERSION='v0.0.0'):
'update': 'ask' 'update': 'ask'
} }
ret = False
for path,repository in repositories.items(): for path,repository in repositories.items():
username,repositoryName = path.split('/') username,repositoryName = path.split('/')
if repository['update'] != 'never': try:
try: urlthread = UrlThread("https://api.github.com/repos/{0}/releases/latest".format(path))
url = "https://api.github.com/repos/{0}/releases/latest".format(path) urlthread.start()
responseData = urllib2.urlopen(url, timeout=10).read() urlthread.join()
release = json.loads(responseData) release = json.loads(urlthread.response.read())
datas.append(responseData) except Exception as e:
except Exception as e: release = {}
datas.append(e)
release = {}
if 'id' in release: if 'id' in release:
if release['id'] != repository['id']: if release['id'] != repository['id']:
data = { data = {
'id': release['id'], 'id': release['id'],
'name': repositoryName, 'name': repositoryName,
'tag_name': release['tag_name'], 'tag_name': release['tag_name'],
'body': '### {0}\n'.format(release['name']) + release['body'], 'body': '### {0}\n'.format(release['name']) + release['body'],
'assets': [asset(release['assets'][0])],#map(asset,release['assets']), 'assets': [asset(release['assets'][0])],
'update': 'ask' 'update': 'ask'
} }
if 'tag_name' in repository: if 'tag_name' in repository:
oldVersion = map(int,repository['tag_name'][1:].split('.')) oldVersion = map(int,repository['tag_name'][1:].split('.'))
while len(oldVersion)<3: oldVersion = [x for x in oldVersion]
oldVersion.append(0) while len(oldVersion)<3:
else: oldVersion.append(0)
oldVersion = map(int,VERSION[1:].split('.'))#[0,0,0] else:
newVersion = map(int,data['tag_name'][1:].split('.')) oldVersion = map(int,VERSION[1:].split('.'))#[0,0,0]
isMinor = len(newVersion)>2 and newVersion[2]>0 oldVersion = [x for x in oldVersion]
while len(newVersion)<3: newVersion = map(int,data['tag_name'][1:].split('.'))
newVersion.append(0) newVersion = [x for x in newVersion]
i = oldVersion[2]+1 isMinor = len(newVersion)>2 and newVersion[2]>0
if oldVersion[0]<newVersion[0] or oldVersion[1]<newVersion[1]: while len(newVersion)<3:
if isMinor: newVersion.append(0)
i = 1 i = oldVersion[2]+1
while i<newVersion[2]: if oldVersion[0]<newVersion[0] or oldVersion[1]<newVersion[1]:
if isMinor:
i = 1
while i<newVersion[2]:
if progresswin.wasCanceled():
break
try:
minorTagName = 'v{0}.{1}.{2}'.format(newVersion[0],oldVersion[1],i)
urlthread = UrlThread("https://api.github.com/repos/{0}/releases/tags/{1}".format(path,minorTagName))
urlthread.start()
urlthread.join()
responseData = urlthread.response.read()
minor = json.loads(responseData)
data['body'] += '\n\n### {0}\n'.format(minor['name']) + minor['body']
except:
pass
i += 1
if oldVersion[0]<newVersion[0] or oldVersion[1]<newVersion[1]:
# new major release necessary!
# if the newest version is minor, fetch the additional assets from the major
if isMinor and not progresswin.wasCanceled():
try: try:
minorTagName = 'v{0}.{1}.{2}'.format(newVersion[0],oldVersion[1],i)
response = urllib2.urlopen("https://api.github.com/repos/{0}/releases/tags/{1}".format(path,minorTagName))
responseData = response.read()
minor = json.loads(responseData)
data['body'] += '\n\n### {0}\n'.format(minor['name']) + minor['body']
#data['assets'] += map(asset,minor['assets'])
except:
pass
i += 1
if oldVersion[0]<newVersion[0] or oldVersion[1]<newVersion[1]:
# new major release necessary!
if isMinor: # if the newest version is minor, fetch the additional assets from the major
majorTagName = 'v{0}.{1}'.format(newVersion[0],newVersion[1]) majorTagName = 'v{0}.{1}'.format(newVersion[0],newVersion[1])
try: urlthread = UrlThread(
response = urllib2.urlopen("https://api.github.com/repos/{0}/releases/tags/{1}".format(path,majorTagName)) "https://api.github.com/repos/{0}/releases/tags/{1}".format(path,majorTagName),
except: "https://api.github.com/repos/{0}/releases/tags/{1}.0".format(path,majorTagName)
response = urllib2.urlopen("https://api.github.com/repos/{0}/releases/tags/{1}.0".format(path,majorTagName)) )
responseData = response.read() urlthread.start()
urlthread.join()
responseData = urlthread.response.read()
major = json.loads(responseData) major = json.loads(responseData)
data['body'] += '\n\n### {0}\n'.format(major['name']) + major['body'] data['body'] += '\n\n### {0}\n'.format(major['name']) + major['body']
#data['assets'] += map(asset,major['assets']) except:
pass
if repository['update'] == 'always':
dialog = DialogUpdates(None,data,repository,updateSingle(repositories,path,data),'always') if not progresswin.wasCanceled():
elif install: progresswin.hide()
dialog = DialogUpdates(None,data,repository,updateSingle(repositories,path,data),'ask',install=True) progresswin.destroy()
else: dialog = DialogUpdates(None, data, repository, updateSingle(repositories, path, data))
dialog = DialogUpdates(None,data,repository,updateSingle(repositories,path,data))
dialog.exec_() dialog.exec_()
ret = True dialog.destroy()
else:
progresswin.hide()
progresswin.destroy()
return 1
else:
progresswin.hide()
progresswin.destroy()
return 0
progresswin.hide()
progresswin.destroy()
return -1
class UrlThread(QThread):
def __init__(self, url, backurl=None):
super(UrlThread, self).__init__()
self.response = None
self.url = url
self.backurl = backurl
self.finished = False
with open(dataPath,'w') as file: def run(self):
json.dump(repositories,file,indent=2) try:
file.close() self.response = urllib2.urlopen(self.url)
return ret except:
if self.backurl:
try:
self.response = urllib2.urlopen(self.backurl)
except:
pass
self.finished = True
#update() def join(self):
while not self.finished:
#def addRepository(): QApplication.instance().processEvents()
# repo, ok = QtGui.QInputDialog.getText(aqt.mw,'Add GitHub repository', self.wait(30)
# 'Path:',text='<name>/<repository>')
# if repo and ok:
# update([repo],install=True)
#
#firstAction = aqt.mw.form.menuPlugins.actions()[0]
#action = QtGui.QAction('From GitHub', aqt.mw)
#action.setIconVisibleInMenu(True)
#action.triggered.connect(addRepository)
#aqt.mw.form.menuPlugins.insertAction(firstAction,action)

View File

@ -36,8 +36,11 @@ __all__ = ['show_options', 'check_updates', 'show_fm_dialog', 'show_about_dialog
def check_updates(): def check_updates():
'''check add-on last version''' '''check add-on last version'''
try: try:
if not ankihub.update([Endpoint.check_version], False, Endpoint.version): state = ankihub.update([Endpoint.check_version], False, Endpoint.version)
if state == 0:
showInfo(_('LATEST_VERSION')) showInfo(_('LATEST_VERSION'))
elif state == -1:
showInfo(_('CHECK_FAILURE'))
except: except:
showInfo(_('CHECK_FAILURE')) showInfo(_('CHECK_FAILURE'))

View File

@ -24,25 +24,6 @@ from .AnkiHub.markdown2 import markdown
# taken from Anki's aqt/profiles.py # taken from Anki's aqt/profiles.py
def defaultBase(): def defaultBase():
'''
print(mw.pm.addonFolder())
if isWin:
loc = QDesktopServices.storageLocation(QDesktopServices.DocumentsLocation)
return os.path.join(loc, "Anki")
elif isMac:
return os.path.expanduser("~/Documents/Anki")
else:
p = os.path.expanduser("~/Anki")
if os.path.exists(p):
return p
else:
loc = QDesktopServices.storageLocation(QDesktopServices.DocumentsLocation)
if loc[:-1] == QDesktopServices.storageLocation(
QDesktopServices.HomeLocation):
return os.path.expanduser("~/Documents/Anki")
else:
return os.path.join(loc, "Anki")
'''
path = mw.pm.addonFolder() path = mw.pm.addonFolder()
return os.path.dirname(os.path.abspath(path)) return os.path.dirname(os.path.abspath(path))
@ -52,7 +33,8 @@ dataPath = os.path.join(defaultBase(),'.fastwq_2.1.x_ankihub.json')
class DialogUpdates(QDialog, Ui_DialogUpdates): class DialogUpdates(QDialog, Ui_DialogUpdates):
def __init__(self, parent, data, oldData, callback, automaticAnswer=None,install=False):
def __init__(self, parent, data, oldData, callback, install=False):
QDialog.__init__(self,parent) QDialog.__init__(self,parent)
self.setModal(True) self.setModal(True)
self.setWindowFlags( self.setWindowFlags(
@ -62,32 +44,15 @@ class DialogUpdates(QDialog, Ui_DialogUpdates):
self.setWindowIcon(APP_ICON) self.setWindowIcon(APP_ICON)
self.setupUi(self) self.setupUi(self)
totalSize = sum(map(lambda x:x['size'],data['assets'])) totalSize = sum(map(lambda x:x['size'],data['assets']))
def answer(doUpdate,answ): def answer():
self.update.setEnabled(False) self.update.setEnabled(False)
#self.dont.setEnabled(False) callback(self.appendHtml, self.finish, install)
#self.always.setEnabled(False)
#self.never.setEnabled(False)
callback(doUpdate,answ,self.appendHtml,self.finish,install)
self.html = u'' self.html = u''
self.appendHtml(markdown(data['body'])) self.appendHtml(markdown(data['body']))
#if not automaticAnswer: #if not automaticAnswer:
self.update.clicked.connect(lambda:answer(True,'ask')) self.update.clicked.connect(lambda:answer())
#self.connect(self.update,SIGNAL('clicked()'),
# lambda:answer(True,'ask'))
#self.connect(self.dont,SIGNAL('clicked()'),
# lambda:answer(False,'ask'))
#self.connect(self.always,SIGNAL('clicked()'),
# lambda:answer(True,'always'))
#self.connect(self.never,SIGNAL('clicked()'),
# lambda:answer(False,'never'))
#else:
#self.update.setEnabled(False)
#self.dont.setEnabled(False)
#self.always.setEnabled(False)
#self.never.setEnabled(False)
# answer(True,automaticAnswer)
fromVersion = '' fromVersion = ''
if 'tag_name' in oldData: if 'tag_name' in oldData:
@ -98,7 +63,6 @@ class DialogUpdates(QDialog, Ui_DialogUpdates):
fromVersion, fromVersion,
data['tag_name'])) data['tag_name']))
def appendHtml(self,html='',temp=''): def appendHtml(self,html='',temp=''):
self.html += html self.html += html
self.textBrowser.setHtml(u'<html><body>{0}{1}{2}</body></html>'.format(self.html, temp, u'<div id="text_bottom"></div>')) self.textBrowser.setHtml(u'<html><body>{0}{1}{2}</body></html>'.format(self.html, temp, u'<div id="text_bottom"></div>'))
@ -129,101 +93,77 @@ def installZipFile(data, fname):
z.extract(n, base) z.extract(n, base)
return True return True
def asset(a): def asset(a):
return { return {
'url': a['browser_download_url'], 'url': a['browser_download_url'],
'size': a['size'] 'size': a['size']
} }
profileLoaded = True
def _profileLoaded():
profileLoaded = True
addHook("profileLoaded",_profileLoaded) def updateSingle(repositories, path, data):
def callback(appendHtml, onReady, install):
for asset in data['assets']:
code = asset['url']
p, fname = os.path.split(code)
appendHtml(temp='<br />Downloading {1}: {0}%<br/>'.format(0,fname))
urlthread = UrlThread(code)
urlthread.start()
urlthread.join()
response = urlthread.response#urllib2.urlopen(code)
meta = response.info()
file_size = int(meta.get("Content-Length"))
d = b''
dl = 0
i = 0
lastPercent = None
while True:
dkb = response.read(1024)
if not dkb:
break
dl += len(dkb)
d += dkb
if dl*100/file_size>i:
lastPercent = int(dl*100/file_size)
i = lastPercent+1
appendHtml(temp='<br />Downloading {1}: {0}%<br/>'.format(lastPercent,fname))
QApplication.instance().processEvents()
appendHtml('<br />Downloading {1}: 100%<br/>'.format(int(dl*100/file_size),fname))
appendHtml('Installing ...<br/>')
if not installZipFile(d, fname):
appendHtml('Corrupt file<br/>')
else:
repositories[path] = data
repositories[path]['update'] = 'ask'
with open(dataPath,'w') as f:
json.dump(repositories,f,indent=2)
f.close()
appendHtml('Done.<br/>Please restart Anki.<br/>')
onReady() # close the AnkiHub update window
def updateSingle(repositories,path,data):
def callback(doUpdate,answer,appendHtml,onReady,install):
if doUpdate:
for asset in data['assets']:
code = asset['url']
p, fname = os.path.split(code)
response = urllib2.urlopen(code)
meta = response.info()
file_size = int(meta.get("Content-Length"))
d = b''
dl = 0
i = 0
lastPercent = None
while True:
dkb = response.read(1024)
if not dkb:
break
dl += len(dkb)
d += dkb
if dl*100/file_size>i:
lastPercent = int(dl*100/file_size)
i = lastPercent+1
appendHtml(temp='<br />Downloading {1}: {0}%<br/>'.format(lastPercent,fname))
QApplication.instance().processEvents()
appendHtml('<br />Downloading {1}: 100%<br/>'.format(int(dl*100/file_size),fname))
def installData():
if install:
filesBefore = aqt.mw.addonManager.files()
#directoriesBefore = aqt.mw.addonManager.directories()
appendHtml('Installing ...<br/>')
if not installZipFile(d,fname):
appendHtml('Corrupt file<br/>')
else:
repositories[path] = data
repositories[path]['update'] = answer
with open(dataPath,'w') as file:
json.dump(repositories,file,indent=2)
file.close()
if install:
appendHtml('Executing new scripts...<br/>')
newFiles = set(aqt.mw.addonManager.files()) - set(filesBefore)
#newDirectories = set(aqt.mw.addonManager.directories()) - set(directoriesBefore)
for file in newFiles:
try:
__import__(file.replace(".py", ""))
except:
traceback.print_exc()
#for directory in newDirectories:
# try:
# __import__(directory)
# except:
# traceback.print_exc()
aqt.mw.addonManager.rebuildAddonsMenu()
appendHtml('Done.<br/>')
onReady() # close the AnkiHub update window
else:
appendHtml('Done.<br/>Please restart Anki.<br/>')
onReady() # close the AnkiHub update window
installData()
else:
repositories[path]['update'] = answer
with open(dataPath,'w') as file:
json.dump(repositories,file,indent=2)
file.close()
onReady()
return callback return callback
datas = []
def update(add=[],install=False, VERSION='v0.0.0'): def update(add=[], install=False, VERSION='v0.0.0'):
# progress win
progresswin = QProgressDialog('Update Checking...', 'FastWQ - Updater', 0, 0, mw)
progresswin.setWindowModality(Qt.ApplicationModal)
progresswin.setCancelButton(None)
progresswin.setWindowFlags(
progresswin.windowFlags() &
~Qt.WindowContextHelpButtonHint
)
progresswin.setWindowIcon(APP_ICON)
progresswin.resize(280, 60)
progresswin.show()
#
conn = httplib.HTTPSConnection("api.github.com") conn = httplib.HTTPSConnection("api.github.com")
try: try:
with open(dataPath,'r') as file: with open(dataPath,'r') as f:
repositories = json.load(file) repositories = json.load(f)
file.close() f.close()
except: except:
repositories = {} repositories = {}
# 'dayjaby/AnkiHub': {
# 'id': 4089471,
# 'update': 'ask'
# }
#}
for a in add: for a in add:
if a not in repositories: if a not in repositories:
@ -232,95 +172,115 @@ def update(add=[],install=False, VERSION='v0.0.0'):
'update': 'ask' 'update': 'ask'
} }
ret = False
for path,repository in repositories.items(): for path,repository in repositories.items():
username,repositoryName = path.split('/') username,repositoryName = path.split('/')
if repository['update'] != 'never': try:
try: urlthread = UrlThread("https://api.github.com/repos/{0}/releases/latest".format(path))
url = "https://api.github.com/repos/{0}/releases/latest".format(path) urlthread.start()
responseData = urllib2.urlopen(url, timeout=10).read() urlthread.join()
release = json.loads(responseData) release = json.loads(urlthread.response.read())
datas.append(responseData) except Exception as e:
except Exception as e: release = {}
datas.append(e)
release = {}
if 'id' in release: if 'id' in release:
if release['id'] != repository['id']: if release['id'] != repository['id']:
data = { data = {
'id': release['id'], 'id': release['id'],
'name': repositoryName, 'name': repositoryName,
'tag_name': release['tag_name'], 'tag_name': release['tag_name'],
'body': '### {0}\n'.format(release['name']) + release['body'], 'body': '### {0}\n'.format(release['name']) + release['body'],
'assets': [asset(release['assets'][1])],#map(asset,release['assets']), 'assets': [asset(release['assets'][1])],
'update': 'ask' 'update': 'ask'
} }
if 'tag_name' in repository: if 'tag_name' in repository:
oldVersion = map(int,repository['tag_name'][1:].split('.')) oldVersion = map(int,repository['tag_name'][1:].split('.'))
oldVersion = [x for x in oldVersion] oldVersion = [x for x in oldVersion]
while len(oldVersion)<3: while len(oldVersion)<3:
oldVersion.append(0) oldVersion.append(0)
else: else:
oldVersion = map(int,VERSION[1:].split('.'))#[0,0,0] oldVersion = map(int,VERSION[1:].split('.'))#[0,0,0]
oldVersion = [x for x in oldVersion] oldVersion = [x for x in oldVersion]
newVersion = map(int,data['tag_name'][1:].split('.')) newVersion = map(int,data['tag_name'][1:].split('.'))
newVersion = [x for x in newVersion] newVersion = [x for x in newVersion]
isMinor = len(newVersion)>2 and newVersion[2]>0 isMinor = len(newVersion)>2 and newVersion[2]>0
while len(newVersion)<3: while len(newVersion)<3:
newVersion.append(0) newVersion.append(0)
i = oldVersion[2]+1 i = oldVersion[2]+1
if oldVersion[0]<newVersion[0] or oldVersion[1]<newVersion[1]: if oldVersion[0]<newVersion[0] or oldVersion[1]<newVersion[1]:
if isMinor: if isMinor:
i = 1 i = 1
while i<newVersion[2]: while i<newVersion[2]:
if progresswin.wasCanceled():
break
try:
minorTagName = 'v{0}.{1}.{2}'.format(newVersion[0],oldVersion[1],i)
urlthread = UrlThread("https://api.github.com/repos/{0}/releases/tags/{1}".format(path,minorTagName))
urlthread.start()
urlthread.join()
responseData = urlthread.response.read()
minor = json.loads(responseData)
data['body'] += '\n\n### {0}\n'.format(minor['name']) + minor['body']
except:
pass
i += 1
if oldVersion[0]<newVersion[0] or oldVersion[1]<newVersion[1]:
# new major release necessary!
# if the newest version is minor, fetch the additional assets from the major
if isMinor and not progresswin.wasCanceled():
try: try:
minorTagName = 'v{0}.{1}.{2}'.format(newVersion[0],oldVersion[1],i)
response = urllib2.urlopen("https://api.github.com/repos/{0}/releases/tags/{1}".format(path,minorTagName))
responseData = response.read()
minor = json.loads(responseData)
data['body'] += '\n\n### {0}\n'.format(minor['name']) + minor['body']
#data['assets'] += map(asset,minor['assets'])
except:
pass
i += 1
if oldVersion[0]<newVersion[0] or oldVersion[1]<newVersion[1]:
# new major release necessary!
if isMinor: # if the newest version is minor, fetch the additional assets from the major
majorTagName = 'v{0}.{1}'.format(newVersion[0],newVersion[1]) majorTagName = 'v{0}.{1}'.format(newVersion[0],newVersion[1])
try: urlthread = UrlThread(
response = urllib2.urlopen("https://api.github.com/repos/{0}/releases/tags/{1}".format(path,majorTagName)) "https://api.github.com/repos/{0}/releases/tags/{1}".format(path,majorTagName),
except: "https://api.github.com/repos/{0}/releases/tags/{1}.0".format(path,majorTagName)
response = urllib2.urlopen("https://api.github.com/repos/{0}/releases/tags/{1}.0".format(path,majorTagName)) )
responseData = response.read() urlthread.start()
urlthread.join()
responseData = urlthread.response.read()
major = json.loads(responseData) major = json.loads(responseData)
data['body'] += '\n\n### {0}\n'.format(major['name']) + major['body'] data['body'] += '\n\n### {0}\n'.format(major['name']) + major['body']
#data['assets'] += map(asset,major['assets']) except:
pass
if repository['update'] == 'always':
dialog = DialogUpdates(None,data,repository,updateSingle(repositories,path,data),'always') if not progresswin.wasCanceled():
elif install: progresswin.hide()
dialog = DialogUpdates(None,data,repository,updateSingle(repositories,path,data),'ask',install=True) progresswin.destroy()
else: dialog = DialogUpdates(None, data, repository, updateSingle(repositories, path, data))
dialog = DialogUpdates(None,data,repository,updateSingle(repositories,path,data))
dialog.exec_() dialog.exec_()
ret = True dialog.destroy()
else:
progresswin.hide()
progresswin.destroy()
return 1
else:
progresswin.hide()
progresswin.destroy()
return 0
progresswin.hide()
progresswin.destroy()
return -1
class UrlThread(QThread):
def __init__(self, url, backurl=None):
super(UrlThread, self).__init__()
self.response = None
self.url = url
self.backurl = backurl
self.finished = False
with open(dataPath,'w') as file: def run(self):
json.dump(repositories,file,indent=2) try:
file.close() self.response = urllib2.urlopen(self.url)
return ret except:
if self.backurl:
try:
self.response = urllib2.urlopen(self.backurl)
except:
pass
self.finished = True
#update() def join(self):
while not self.finished:
#def addRepository(): QApplication.instance().processEvents()
# repo, ok = QInputDialog.getText(aqt.mw,'Add GitHub repository', self.wait(30)
# 'Path:',text='<name>/<repository>')
# if repo and ok:
# update([repo],install=True)
#
#firstAction = aqt.mw.form.menuPlugins.actions()[0]
#action = QAction('From GitHub', aqt.mw)
#action.setIconVisibleInMenu(True)
#action.triggered.connect(addRepository)
#aqt.mw.form.menuPlugins.insertAction(firstAction,action)