utils.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. from __future__ import unicode_literals
  2. import os
  3. from subprocess import PIPE, Popen
  4. import sys
  5. from django.utils.encoding import force_text, DEFAULT_LOCALE_ENCODING
  6. from django.utils import six
  7. from .base import CommandError
  8. def popen_wrapper(args, os_err_exc_type=CommandError):
  9. """
  10. Friendly wrapper around Popen.
  11. Returns stdout output, stderr output and OS status code.
  12. """
  13. try:
  14. p = Popen(args, shell=False, stdout=PIPE, stderr=PIPE,
  15. close_fds=os.name != 'nt', universal_newlines=True)
  16. except OSError as e:
  17. strerror = force_text(e.strerror, DEFAULT_LOCALE_ENCODING,
  18. strings_only=True)
  19. six.reraise(os_err_exc_type, os_err_exc_type('Error executing %s: %s' %
  20. (args[0], strerror)), sys.exc_info()[2])
  21. output, errors = p.communicate()
  22. return (
  23. output,
  24. force_text(errors, DEFAULT_LOCALE_ENCODING, strings_only=True),
  25. p.returncode
  26. )
  27. def handle_extensions(extensions=('html',), ignored=('py',)):
  28. """
  29. Organizes multiple extensions that are separated with commas or passed by
  30. using --extension/-e multiple times. Note that the .py extension is ignored
  31. here because of the way non-*.py files are handled in make_messages() (they
  32. are copied to file.ext.py files to trick xgettext to parse them as Python
  33. files).
  34. For example: running 'django-admin makemessages -e js,txt -e xhtml -a'
  35. would result in an extension list: ['.js', '.txt', '.xhtml']
  36. >>> handle_extensions(['.html', 'html,js,py,py,py,.py', 'py,.py'])
  37. set(['.html', '.js'])
  38. >>> handle_extensions(['.html, txt,.tpl'])
  39. set(['.html', '.tpl', '.txt'])
  40. """
  41. ext_list = []
  42. for ext in extensions:
  43. ext_list.extend(ext.replace(' ', '').split(','))
  44. for i, ext in enumerate(ext_list):
  45. if not ext.startswith('.'):
  46. ext_list[i] = '.%s' % ext_list[i]
  47. return set(x for x in ext_list if x.strip('.') not in ignored)
  48. def find_command(cmd, path=None, pathext=None):
  49. if path is None:
  50. path = os.environ.get('PATH', '').split(os.pathsep)
  51. if isinstance(path, six.string_types):
  52. path = [path]
  53. # check if there are funny path extensions for executables, e.g. Windows
  54. if pathext is None:
  55. pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD').split(os.pathsep)
  56. # don't use extensions if the command ends with one of them
  57. for ext in pathext:
  58. if cmd.endswith(ext):
  59. pathext = ['']
  60. break
  61. # check if we find the command on PATH
  62. for p in path:
  63. f = os.path.join(p, cmd)
  64. if os.path.isfile(f):
  65. return f
  66. for ext in pathext:
  67. fext = f + ext
  68. if os.path.isfile(fext):
  69. return fext
  70. return None