OXYGENHUB
◆ main openmsx / build / download.py
2.2 KiB · Python · last changed chore(): initial commit 1 month ago source blame history raw
1
from os import remove, stat
2
from os.path import basename, isdir, isfile, join as joinpath
3
from urllib.parse import urlparse
4
from urllib.request import urlopen
5
6
import sys
7
8
class StatusLine(object):
9
10
	def __init__(self, out):
11
		self._out = out
12
13
	def __call__(self, message, progress = False):
14
		raise NotImplementedError
15
16
class InteractiveStatusLine(StatusLine):
17
	__length = 0
18
19
	def __call__(self, message, progress = False):
20
		self._out.write(('\r%-' + str(self.__length) + 's') % message)
21
		self.__length = max(self.__length, len(message))
22
23
class NoninteractiveStatusLine(StatusLine):
24
25
	def __call__(self, message, progress = False):
26
		if not progress:
27
			self._out.write(message + '\n')
28
29
def createStatusLine(out):
30
	if out.isatty():
31
		return InteractiveStatusLine(out)
32
	else:
33
		return NoninteractiveStatusLine(out)
34
35
def downloadURL(url, localDir):
36
	if not isdir(localDir):
37
		raise OSError('Local directory "%s" does not exist' % localDir)
38
39
	fileName = basename(urlparse(url).path)
40
	localPath = joinpath(localDir, fileName)
41
	prefix = 'Downloading %s: ' % fileName
42
43
	statusLine = createStatusLine(sys.stdout)
44
	statusLine(prefix + 'contacting server...')
45
46
	def reportProgress(doneSize, totalSize):
47
		statusLine(prefix + (
48
			'%d/%d bytes (%1.1f%%)...' % (
49
				doneSize, totalSize, (100.0 * doneSize) / totalSize
50
				)
51
			if totalSize > 0 else
52
			'%d bytes...' % doneSize
53
			), True)
54
55
	try:
56
		try:
57
			with urlopen(url) as inp:
58
				totalSize = int(inp.info().get('Content-Length', '0'))
59
				with open(localPath, 'wb') as out:
60
					doneSize = 0
61
					reportProgress(doneSize, totalSize)
62
					while True:
63
						data = inp.read(16384)
64
						if not data:
65
							break
66
						out.write(data)
67
						doneSize += len(data)
68
						reportProgress(doneSize, totalSize)
69
		except OSError:
70
			statusLine(prefix + 'FAILED.')
71
			raise
72
		else:
73
			statusLine(prefix + 'done.')
74
		finally:
75
			print()
76
	except:
77
		if isfile(localPath):
78
			statusLine(prefix + 'removing partial download.')
79
			remove(localPath)
80
		raise
81
82
if __name__ == '__main__':
83
	if len(sys.argv) == 3:
84
		try:
85
			downloadURL(*sys.argv[1 : ])
86
		except OSError as ex:
87
			print(ex, file=sys.stderr)
88
			sys.exit(1)
89
	else:
90
		print('Usage: python3 download.py url localdir', file=sys.stderr)
91
		sys.exit(2)