options.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. """Option handling polyfill for Flake8 2.x and 3.x."""
  2. import optparse
  3. import os
  4. def register(parser, *args, **kwargs):
  5. r"""Register an option for the Option Parser provided by Flake8.
  6. :param parser:
  7. The option parser being used by Flake8 to handle command-line options.
  8. :param \*args:
  9. Positional arguments that you might otherwise pass to ``add_option``.
  10. :param \*\*kwargs:
  11. Keyword arguments you might otherwise pass to ``add_option``.
  12. """
  13. try:
  14. # Flake8 3.x registration
  15. parser.add_option(*args, **kwargs)
  16. except (optparse.OptionError, TypeError):
  17. # Flake8 2.x registration
  18. # Pop Flake8 3 parameters out of the kwargs so they don't cause a
  19. # conflict.
  20. parse_from_config = kwargs.pop('parse_from_config', False)
  21. comma_separated_list = kwargs.pop('comma_separated_list', False)
  22. normalize_paths = kwargs.pop('normalize_paths', False)
  23. # In the unlikely event that the developer has specified their own
  24. # callback, let's pop that and deal with that as well.
  25. base_callback = kwargs.pop('callback', store_callback)
  26. callback = generate_callback_from(comma_separated_list,
  27. normalize_paths,
  28. base_callback)
  29. kwargs['callback'] = callback
  30. kwargs['action'] = 'callback'
  31. # We've updated our args and kwargs and can now rather confidently
  32. # call add_option.
  33. option = parser.add_option(*args, **kwargs)
  34. if parse_from_config:
  35. parser.config_options.append(option.get_opt_string().lstrip('-'))
  36. def parse_comma_separated_list(value):
  37. """Parse a comma-separated list.
  38. :param value:
  39. String or list of strings to be parsed and normalized.
  40. :returns:
  41. List of values with whitespace stripped.
  42. :rtype:
  43. list
  44. """
  45. if not value:
  46. return []
  47. if not isinstance(value, (list, tuple)):
  48. value = value.split(',')
  49. return [item.strip() for item in value]
  50. def normalize_path(path, parent=os.curdir):
  51. """Normalize a single-path.
  52. :returns:
  53. The normalized path.
  54. :rtype:
  55. str
  56. """
  57. # NOTE(sigmavirus24): Using os.path.sep allows for Windows paths to
  58. # be specified and work appropriately.
  59. separator = os.path.sep
  60. if separator in path:
  61. path = os.path.abspath(os.path.join(parent, path))
  62. return path.rstrip(separator)
  63. def parse_normalized_paths(value):
  64. """Normalize the path(s) value."""
  65. if isinstance(value, list):
  66. normalized = [normalize_path(s) for s in value]
  67. else:
  68. normalized = normalize_path(value)
  69. return normalized
  70. def store_callback(option, opt_str, value, parser, *args, **kwargs):
  71. """Implement optparse's "store" action as a callback."""
  72. setattr(parser.values, option.dest, value)
  73. def generate_callback_from(comma_separated_list, normalize_paths,
  74. base_callback):
  75. """Generate a callback from parameters provided for the option."""
  76. def _callback(option, opt_str, value, parser, *args, **kwargs):
  77. """Wrap `base_callback` by transforming `value` for option params."""
  78. if comma_separated_list:
  79. value = parse_comma_separated_list(value)
  80. if normalize_paths:
  81. value = parse_normalized_paths(value)
  82. base_callback(option, opt_str, value, parser, *args, **kwargs)
  83. return _callback