| 
									
										
										
										
											2018-01-24 17:43:35 -06:00
										 |  |  | # -*- coding: utf-8 -*- | 
					
						
							| 
									
										
										
										
											2018-01-26 12:56:50 -06:00
										 |  |  | import os | 
					
						
							|  |  |  | import requests | 
					
						
							| 
									
										
										
										
											2018-01-24 17:43:35 -06:00
										 |  |  | import threading | 
					
						
							|  |  |  | import logging | 
					
						
							| 
									
										
										
										
											2019-06-17 06:01:55 -05:00
										 |  |  | import types | 
					
						
							| 
									
										
										
										
											2019-07-08 13:04:00 -05:00
										 |  |  | import services | 
					
						
							| 
									
										
										
										
											2019-06-24 09:41:22 -05:00
										 |  |  | from importlib import reload | 
					
						
							| 
									
										
										
										
											2018-01-26 12:56:50 -06:00
										 |  |  | from pubsub import pub | 
					
						
							| 
									
										
										
										
											2018-01-24 17:43:35 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | log = logging.getLogger("utils") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def call_threaded(func, *args, **kwargs): | 
					
						
							|  |  |  | 	#Call the given function in a daemonized thread and return the thread. | 
					
						
							|  |  |  | 	def new_func(*a, **k): | 
					
						
							|  |  |  | 		func(*a, **k) | 
					
						
							|  |  |  | 	thread = threading.Thread(target=new_func, args=args, kwargs=kwargs) | 
					
						
							| 
									
										
										
										
											2019-05-06 02:20:01 -05:00
										 |  |  | 	thread.daemon = True | 
					
						
							| 
									
										
										
										
											2018-01-24 17:43:35 -06:00
										 |  |  | 	thread.start() | 
					
						
							|  |  |  | 	return thread | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RepeatingTimer(threading.Thread): | 
					
						
							|  |  |  | 	"""Call a function after a specified number of seconds, it will then repeat again after the specified number of seconds
 | 
					
						
							|  |  |  | 		Note: If the function provided takes time to execute, this time is NOT taken from the next wait period | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t = RepeatingTimer(30.0, f, args=[], kwargs={}) | 
					
						
							|  |  |  | 	t.start() | 
					
						
							|  |  |  | 	t.cancel() # stop the timer's actions | 
					
						
							|  |  |  | 	"""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def __init__(self, interval, function, daemon=True, *args, **kwargs): | 
					
						
							|  |  |  | 		threading.Thread.__init__(self) | 
					
						
							|  |  |  | 		self.daemon = daemon | 
					
						
							|  |  |  | 		self.interval = float(interval) | 
					
						
							|  |  |  | 		self.function = function | 
					
						
							|  |  |  | 		self.args = args | 
					
						
							|  |  |  | 		self.kwargs = kwargs | 
					
						
							|  |  |  | 		self.finished = threading.Event() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def cancel(self): | 
					
						
							|  |  |  | 		"""Stop the timer if it hasn't finished yet""" | 
					
						
							|  |  |  | 		log.debug("Stopping repeater for %s" % (self.function,)) | 
					
						
							|  |  |  | 		self.finished.set() | 
					
						
							|  |  |  | 	stop = cancel | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def run(self): | 
					
						
							|  |  |  | 		while not self.finished.is_set(): | 
					
						
							|  |  |  | 			self.finished.wait(self.interval) | 
					
						
							|  |  |  | 			if not self.finished.is_set():  #In case someone has canceled while waiting | 
					
						
							|  |  |  | 				try: | 
					
						
							|  |  |  | 					self.function(*self.args, **self.kwargs) | 
					
						
							|  |  |  | 				except: | 
					
						
							|  |  |  | 					log.exception("Execution failed. Function: %r args: %r and kwargs: %r" % (self.function, self.args, self.kwargs)) | 
					
						
							| 
									
										
										
										
											2018-01-26 12:56:50 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | def download_file(url, local_filename): | 
					
						
							| 
									
										
										
										
											2018-03-12 17:11:05 -06:00
										 |  |  | 	log.debug("Download started: filename={0}, url={1}".format(local_filename, url)) | 
					
						
							| 
									
										
										
										
											2018-01-26 12:56:50 -06:00
										 |  |  | 	r = requests.get(url, stream=True) | 
					
						
							|  |  |  | 	pub.sendMessage("change_status", status=_(u"Downloading {0}.").format(local_filename,)) | 
					
						
							|  |  |  | 	total_length = r.headers.get("content-length") | 
					
						
							|  |  |  | 	dl = 0 | 
					
						
							|  |  |  | 	total_length = int(total_length) | 
					
						
							| 
									
										
										
										
											2018-03-12 17:11:05 -06:00
										 |  |  | 	log.debug("Downloading file of {0} bytes".format(total_length)) | 
					
						
							| 
									
										
										
										
											2018-01-26 12:56:50 -06:00
										 |  |  | 	with open(local_filename, 'wb') as f: | 
					
						
							|  |  |  | 		for chunk in r.iter_content(chunk_size=64):  | 
					
						
							|  |  |  | 			if chunk: # filter out keep-alive new chunks | 
					
						
							|  |  |  | 				dl += len(chunk) | 
					
						
							|  |  |  | 				f.write(chunk) | 
					
						
							|  |  |  | 				done = int(100 * dl / total_length) | 
					
						
							|  |  |  | 				msg = _(u"Downloading {0} ({1}%).").format(os.path.basename(local_filename), done) | 
					
						
							|  |  |  | 				pub.sendMessage("change_status", status=msg) | 
					
						
							| 
									
										
										
										
											2019-06-24 12:45:09 -05:00
										 |  |  | 				pub.sendMessage("update-progress", value=done) | 
					
						
							| 
									
										
										
										
											2018-02-28 17:44:18 -06:00
										 |  |  | 	pub.sendMessage("download_finished", file=os.path.basename(local_filename)) | 
					
						
							| 
									
										
										
										
											2018-03-12 17:11:05 -06:00
										 |  |  | 	log.debug("Download finished successfully") | 
					
						
							| 
									
										
										
										
											2018-01-26 12:56:50 -06:00
										 |  |  | 	return local_filename | 
					
						
							| 
									
										
										
										
											2019-06-17 06:01:55 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-08 13:04:00 -05:00
										 |  |  | def get_services(import_all=False): | 
					
						
							|  |  |  | 	""" Function for importing everything wich is located in the services package and has a class named interface.""" | 
					
						
							| 
									
										
										
										
											2019-06-17 06:01:55 -05:00
										 |  |  | 	module_type = types.ModuleType | 
					
						
							| 
									
										
										
										
											2019-06-24 09:41:22 -05:00
										 |  |  | 	# first of all, import all classes for the package so we can reload everything if they have changes in config. | 
					
						
							| 
									
										
										
										
											2019-07-08 13:04:00 -05:00
										 |  |  | 	_classes = [m for m in services.__dict__.values() if type(m) == module_type and hasattr(m, 'interface')] | 
					
						
							| 
									
										
										
										
											2019-06-24 09:41:22 -05:00
										 |  |  | 	for cls in _classes: | 
					
						
							|  |  |  | 		reload(cls) | 
					
						
							|  |  |  | 	if not import_all: | 
					
						
							| 
									
										
										
										
											2019-07-08 13:04:00 -05:00
										 |  |  | 		classes = [m for m in services.__dict__.values() if type(m) == module_type and hasattr(m, 'interface') and m.interface.enabled != False] | 
					
						
							| 
									
										
										
										
											2019-06-24 09:41:22 -05:00
										 |  |  | 	else: | 
					
						
							| 
									
										
										
										
											2019-07-08 13:04:00 -05:00
										 |  |  | 		classes = [m for m in services.__dict__.values() if type(m) == module_type and hasattr(m, 'interface')] | 
					
						
							|  |  |  | 	return classes |