upgrade.py 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. """The ``celery upgrade`` command, used to upgrade from previous versions."""
  2. from __future__ import absolute_import, print_function, unicode_literals
  3. import codecs
  4. from celery.app import defaults
  5. from celery.bin.base import Command
  6. from celery.utils.functional import pass1
  7. class upgrade(Command):
  8. """Perform upgrade between versions."""
  9. choices = {'settings'}
  10. def add_arguments(self, parser):
  11. group = parser.add_argument_group('Upgrading Options')
  12. group.add_argument(
  13. '--django', action='store_true', default=False,
  14. help='Upgrade Django project',
  15. )
  16. group.add_argument(
  17. '--compat', action='store_true', default=False,
  18. help='Maintain backwards compatibility',
  19. )
  20. group.add_argument(
  21. '--no-backup', action='store_true', default=False,
  22. help='Dont backup original files',
  23. )
  24. def usage(self, command):
  25. return '%(prog)s <command> settings [filename] [options]'
  26. def run(self, *args, **kwargs):
  27. try:
  28. command = args[0]
  29. except IndexError:
  30. raise self.UsageError(
  31. 'missing upgrade type: try `celery upgrade settings` ?')
  32. if command not in self.choices:
  33. raise self.UsageError('unknown upgrade type: {0}'.format(command))
  34. return getattr(self, command)(*args, **kwargs)
  35. def settings(self, command, filename,
  36. no_backup=False, django=False, compat=False, **kwargs):
  37. lines = self._slurp(filename)
  38. keyfilter = self._compat_key if django or compat else pass1
  39. print('processing {0}...'.format(filename), file=self.stderr)
  40. # gives list of tuples: ``(did_change, line_contents)``
  41. new_lines = [
  42. self._to_new_key(line, keyfilter) for line in lines
  43. ]
  44. if any(n[0] for n in new_lines): # did have changes
  45. if not no_backup:
  46. self._backup(filename)
  47. with codecs.open(filename, 'w', 'utf-8') as write_fh:
  48. for _, line in new_lines:
  49. write_fh.write(line)
  50. print('Changes to your setting have been made!',
  51. file=self.stdout)
  52. else:
  53. print('Does not seem to require any changes :-)',
  54. file=self.stdout)
  55. def _slurp(self, filename):
  56. with codecs.open(filename, 'r', 'utf-8') as read_fh:
  57. return [line for line in read_fh]
  58. def _backup(self, filename, suffix='.orig'):
  59. lines = []
  60. backup_filename = ''.join([filename, suffix])
  61. print('writing backup to {0}...'.format(backup_filename),
  62. file=self.stderr)
  63. with codecs.open(filename, 'r', 'utf-8') as read_fh:
  64. with codecs.open(backup_filename, 'w', 'utf-8') as backup_fh:
  65. for line in read_fh:
  66. backup_fh.write(line)
  67. lines.append(line)
  68. return lines
  69. def _to_new_key(self, line, keyfilter=pass1, source=defaults._TO_NEW_KEY):
  70. # sort by length to avoid, for example, broker_transport overriding
  71. # broker_transport_options.
  72. for old_key in reversed(sorted(source, key=lambda x: len(x))):
  73. new_line = line.replace(old_key, keyfilter(source[old_key]))
  74. if line != new_line and 'CELERY_CELERY' not in new_line:
  75. return 1, new_line # only one match per line.
  76. return 0, line
  77. def _compat_key(self, key, namespace='CELERY'):
  78. key = key.upper()
  79. if not key.startswith(namespace):
  80. key = '_'.join([namespace, key])
  81. return key