| 
					
				 | 
			
			
				@@ -6,8 +6,9 @@ The :program:`celery` umbrella command. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .. program:: celery 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-from __future__ import absolute_import, unicode_literals 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from __future__ import absolute_import, unicode_literals, print_function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import codecs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import numbers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import os 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import sys 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -17,10 +18,12 @@ from importlib import import_module 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from kombu.utils import json 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from celery.app import defaults 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from celery.five import string_t, values 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from celery.platforms import EX_OK, EX_FAILURE, EX_UNAVAILABLE, EX_USAGE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from celery.utils import term 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from celery.utils import text 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from celery.utils.functional import pass1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from celery.utils.timeutils import maybe_iso8601 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 # Cannot use relative imports here due to a Windows issue (#1111). 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -55,7 +58,9 @@ DEBUG = os.environ.get('C_DEBUG', False) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 command_classes = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ('Main', ['worker', 'events', 'beat', 'shell', 'multi', 'amqp'], 'green'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ('Remote Control', ['status', 'inspect', 'control'], 'blue'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ('Utils', ['purge', 'list', 'migrate', 'call', 'result', 'report'], None), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ('Utils', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     ['purge', 'list', 'migrate', 'call', 'result', 'report', 'upgrade'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     None), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 if DEBUG:  # pragma: no cover 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     command_classes.append( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -658,6 +663,71 @@ class shell(Command):  # pragma: no cover 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         bpython.embed(self.locals) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class upgrade(Command): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Perform upgrade between versions.""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    option_list = Command.option_list + ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Option('--django', action='store_true', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               help='Upgrade Django project'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Option('--compat', action='store_true', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               help='Maintain backwards compatibility'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Option('--no-backup', action='store_true', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               help='Dont backup original files'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    choices = {'settings'} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def usage(self, command): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return "%prog <command> settings [filename] [options]" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def run(self, *args, **kwargs): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            command = args[0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        except IndexError: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            raise self.UsageError('missing upgrade type') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if command not in self.choices: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            raise self.UsageError('unknown upgrade type: {0}'.format(command)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return getattr(self, command)(*args, **kwargs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def settings(self, command, filename, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 no_backup=False, django=False, compat=False, **kwargs): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lines = self._slurp(filename) if no_backup else self._backup(filename) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        keyfilter = self._compat_key if django or compat else pass1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        print('processing {0}...'.format(filename), file=self.stderr) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        with codecs.open(filename, 'w', 'utf-8') as write_fh: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for line in lines: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                write_fh.write(self._to_new_key(line, keyfilter)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def _slurp(self, filename): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        with codecs.open(filename, 'r', 'utf-8') as read_fh: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return [line for line in read_fh] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def _backup(self, filename, suffix='.orig'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lines = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        backup_filename = ''.join([filename, suffix]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        print('writing backup to {0}...'.format(backup_filename), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              file=self.stderr) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        with codecs.open(filename, 'r', 'utf-8') as read_fh: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            with codecs.open(backup_filename, 'w', 'utf-8') as backup_fh: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                for line in read_fh: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    backup_fh.write(line) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    lines.append(line) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return lines 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def _to_new_key(self, line, keyfilter=pass1, source=defaults._TO_NEW_KEY): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # sort by length to avoid e.g. broker_transport overriding 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # broker_transport_options. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for old_key in reversed(sorted(source, key=lambda x: len(x))): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            new_line = line.replace(old_key, keyfilter(source[old_key])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if line != new_line: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return new_line  # only one match per line. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def _compat_key(self, key, namespace='CELERY'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        key = key.upper() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if not key.startswith(namespace): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            key = '_'.join([namespace, key]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return key 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 class help(Command): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """Show help screen and exit.""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -702,6 +772,7 @@ class CeleryCommand(Command): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         'result': result, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         'shell': shell, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         'status': status, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'upgrade': upgrade, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         'worker': worker, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 |