Skip to content

Instantly share code, notes, and snippets.

@Alex-duzhichao
Created July 7, 2018 03: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 Alex-duzhichao/00c4e35b505f88aa5b3a12323b69f496 to your computer and use it in GitHub Desktop.
Save Alex-duzhichao/00c4e35b505f88aa5b3a12323b69f496 to your computer and use it in GitHub Desktop.
import requests
import lxml.html
import re
import sys
import os
import contextlib
import subprocess
class BaseError(Exception):
"""
base error exception, all error exceptions should inherent from this class.
"""
def __str__(self):
return '{}: {}'.format(type(self).__name__, self.args)
class StatusCodeError(BaseError):
"""
status code error exception.
"""
def __init__(self, msg, statusCode):
"""
init StatusCodeError
Args:
msg: described error msg
statusCode: error status code
"""
errmsg = '{}, status code error, code: {}'.format(msg, str(statusCode))
super().__init__(errmsg)
class FileExistsError(BaseError):
"""
file exists error exception.
"""
def __init__(self, msg, file_name):
"""
init FileExistsError
Args:
msg: described error msg
file_name: file name
"""
errmsg = '{}, file exists error, file: {}'.format(msg, file_name)
super().__init__(errmsg)
class TaskNotExistsError(BaseError):
"""
task do not implemented.
"""
def __init__(self, task_name):
"""
init TaskNotExistsError
Args:
task_name: task name
"""
errmsg = 'task not exists error, task: {}'.format(task_name)
super().__init__(errmsg)
class ProgressBar(object):
def __init__(self,
title,
count=0.0,
run_status=None,
fin_status=None,
total=100.0,
unit='',
sep='/',
chunk_size=1.0):
super().__init__()
self.info = "[%s] %s %.2f %s %s %.2f %s"
self.title = title
self.total = total
self.count = count
self.chunk_size = chunk_size
self.status = run_status or ""
self.fin_status = fin_status or " " * len(self.status)
self.unit = unit
self.seq = sep
def __get_info(self):
# [Title]status progress unit splitor total unit
_info = self.info % (self.title, self.status,
self.count/self.chunk_size, self.unit, self.seq, self.total/self.chunk_size, self.unit)
return _info
def refresh(self, count=1, status=None):
self.count += count
# if status is not None:
self.status = status or self.status
end_str = "\r"
if self.count >= self.total:
end_str = '\n'
self.status = status or self.fin_status
print(self.__get_info(), end=end_str)
def CheckCall(args, **kwargs):
exit_message = kwargs.get('exit_message', None)
kwargs.pop('exit_message', None)
try:
subprocess.check_call(args, **kwargs)
except subprocess.CalledProcessError as error:
if exit_message:
sys.exit(exit_message)
sys.exit(error.returncode)
def readBoolChar(prompt):
"""
read a char from stdin, and return bool value
Args:
prompt: prompt
Returns:
if input char is y or Y, then return True
if input char is n or N, then return False
else loop until right char in inputed.
"""
while True:
print('{} [Y/y] or [N/n]: '.format(prompt), end='', flush=True)
ch = sys.stdin.readline()
ch = ch[:-1]
if ch == 'Y' or ch == 'y':
return True
if ch == 'N' or ch == 'n':
return False
def readNumChar(prompt, num=20):
"""
read a char from stdin, and return int value
Args:
prompt: prompt
num: the upper bound of input value(default is 20)
Returns:
an int value of input char
"""
while True:
print('{} [0 -- {}): '.format(prompt, num), end='', flush=True)
ch = sys.stdin.readline()
ch = ch[:-1]
if ch.isnumeric() and int(ch) < num:
return int(ch)
def getExeURLsFromPage(page):
"""
get all urls with end of *exe* from page.
Args:
page: page url to crawl
Return:
A list of urls can be downloaded
"""
response = requests.get(page)
if response.status_code != 200:
raise StatusCodeError("getExeURLsFromPage: " + page, response.status_code)
html = response.text
tree = lxml.html.fromstring(html)
aNodes = tree.xpath("//a")
exeUrlsList = []
for node in aNodes:
url = node.get("href")
if url is None:
continue
if re.search("exe$", url) is not None:
exeUrlsList.append(url)
return exeUrlsList
def downloadURL(file_name, url):
"""
download url and save to file_name
Args:
file_name: file to write
url: url to download
"""
print("downloding {}".format(url))
if os.path.exists(file_name):
raise FileExistsError("downloadURL", file_name)
with contextlib.closing(requests.get(url, stream = True)) as response:
chunk_size = 1024
content_size = int(response.headers['content-length'])
print(chunk_size, content_size)
progress = ProgressBar(file_name, total = content_size,
unit = "KB", chunk_size = chunk_size, run_status = "downloding",
fin_status = "finished")
with open(file_name, "wb") as file:
for data in response.iter_content(chunk_size = chunk_size):
file.write(data)
progress.refresh(count = len(data))
def installSogouPinyin(**kwargs):
name = kwargs.get("name")
page = kwargs.get("page")
print("installExe {} {}".format(name, page))
exeUrlsList = getExeURLsFromPage(page)
for i in range(len(exeUrlsList)):
print("{}) {}\n".format(i, exeUrlsList[i]), end='')
index = readNumChar("input num to download", len(exeUrlsList))
downloadURL(name + ".exe", exeUrlsList[index])
subprocess.run("./" + name + ".exe")
def downloadExeAndInstall(**kwargs):
name = kwargs.get("name")
url = kwargs.get("url")
print("downloadExeAndInstall {} {}".format(name, url))
downloadURL(name + ".exe", url)
bin = "./" + name + ".exe"
subprocess.run("./" + name + ".exe")
def installVimPlugin(**kwargs):
name = kwargs.get("name")
vimPlugUrl = kwargs.get("vimPlugUrl")
vimrcUrl = kwargs.get("vimrcUrl")
vimBundlesUrl = kwargs.get("vimBundlesUrl")
home = os.environ["USERPROFILE"]
vimPluginPath = os.path.join(home, ".vim")
vimPlugPath = os.path.join(vimPluginPath, "vim-plug", "autoload")
if os.path.exists(vimPluginPath) is False:
print("makedirs {} {} ".format(vimPluginPath, vimPlugPath))
os.makedirs(vimPluginPath)
os.makedirs(vimPlugPath)
#download vim-plug
vimPlugFile = os.path.join(vimPlugPath, "plug.vim")
downloadURL(vimPlugFile, vimPlugUrl)
#download vimrc
vimrcFile = os.path.join(home, ".vimrc")
downloadURL(vimrcFile, vimrcUrl)
#download vimrc bundles
vimrcBundlesFile = os.path.join(home, ".vimrc.bundles")
downloadURL(vimrcBundlesFile, vimBundlesUrl)
def downloadZipAndInstall(**kwargs):
name = kwargs.get("name")
url = kwargs.get("url")
path = kwargs.get("path")
option = kwargs.get("option", "")
file = name + ".zip"
print("downloadZipAndInstall {} {}".format(name, url))
downloadURL(file, url)
if os.path.exists(path) is False:
print("makedirs {} ".format(path))
os.makedirs(path)
CheckCall(["unzip", file, option, "-d", path])
def main():
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
print(os.environ["USERPROFILE"])
tasks = {
"sogou_pinyin": {
"func": installSogouPinyin,
"page": "https://pinyin.sogou.com/",
},
"env_editor": {
"func": downloadExeAndInstall,
"url": "http://eveditor.com/downloads/EveditorFree-1.5.0.exe",
},
"xshell": {
"func": downloadExeAndInstall,
"url": "https://softpedia-secure-download.com/dl/8a747b175758708c69b2e3d075217bf2/5b377005/100187987/software/network/Xshell-6.0.0091.exe",
},
"qq": {
"func": downloadExeAndInstall,
"url": "https://dldir1.qq.com/qqfile/qq/QQ9.0.4/23780/QQ9.0.4.exe",
},
"wechat": {
"func": downloadExeAndInstall,
"url": "http://dlglobal.qq.com/weixin/Windows/WeChat_C1018.exe",
},
"vim-plugin": {
"func": installVimPlugin,
"vimPlugUrl": "https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim",
"vimrcUrl": "https://gist.githubusercontent.com/Alex-duzhichao/d9b19971e295c36b67531b7827f9453b/raw/3d787367326a3e04e3eddbcd1b997c3dd4f12492/vimrc",
"vimBundlesUrl": "https://gist.githubusercontent.com/Alex-duzhichao/2339c5c72557d7ffc1490c88059d6cff/raw/079407f53afcdea2da9234f16eaff5d1368ed354/vimrc.bundles",
},
"ctags": {
"func": downloadZipAndInstall,
"url": "https://github.com/universal-ctags/ctags-win32/releases/download/2018-07-03%2F1e2c63fb/ctags-2018-07-03_1e2c63fb-x64.zip",
"path": os.path.join(os.environ["VIMPATH"], "bin"),
"option": "ctags.exe",
},
"cscope": {
"func": downloadZipAndInstall,
"url": "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/cscope-win32/cscope-15.8a-win64rev1-static.zip",
"path": os.path.join(os.environ["VIMPATH"], "bin"),
"option": "cscope.exe",
},
}
if len(sys.argv) <= 1:
print("python installSoftware.py task_name")
print(tasks)
return
for task in sys.argv[1:]:
if task not in tasks:
raise TaskNotExistsError(task)
else:
val = tasks[task]
if readBoolChar("Do you want to install " + task) == False:
continue
val["name"] = task
func = val["func"]
func(**val)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment