PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/hgfixes/fix_bytes.py

https://bitbucket.org/mirror/mercurial/
Python | 98 lines | 70 code | 18 blank | 10 comment | 26 complexity | 2df69b5b8611163e30f6ab85cceead22 MD5 | raw file
Possible License(s): GPL-2.0
  1. """Fixer that changes plain strings to bytes strings."""
  2. import re
  3. from lib2to3 import fixer_base
  4. from lib2to3.pgen2 import token
  5. from lib2to3.fixer_util import Name
  6. from lib2to3.pygram import python_symbols as syms
  7. _re = re.compile(r'[rR]?[\'\"]')
  8. # XXX: Implementing a blacklist in 2to3 turned out to be more troublesome than
  9. # blacklisting some modules inside the fixers. So, this is what I came with.
  10. blacklist = ('mercurial/demandimport.py',
  11. 'mercurial/py3kcompat.py', # valid python 3 already
  12. 'mercurial/i18n.py',
  13. )
  14. def isdocstring(node):
  15. def isclassorfunction(ancestor):
  16. symbols = (syms.funcdef, syms.classdef)
  17. # if the current node is a child of a function definition, a class
  18. # definition or a file, then it is a docstring
  19. if ancestor.type == syms.simple_stmt:
  20. try:
  21. while True:
  22. if ancestor.type in symbols:
  23. return True
  24. ancestor = ancestor.parent
  25. except AttributeError:
  26. return False
  27. return False
  28. def ismodule(ancestor):
  29. # Our child is a docstring if we are a simple statement, and our
  30. # ancestor is file_input. In other words, our child is a lone string in
  31. # the source file.
  32. try:
  33. if (ancestor.type == syms.simple_stmt and
  34. ancestor.parent.type == syms.file_input):
  35. return True
  36. except AttributeError:
  37. return False
  38. def isdocassignment(ancestor):
  39. # Assigning to __doc__, definitely a string
  40. try:
  41. while True:
  42. if (ancestor.type == syms.expr_stmt and
  43. Name('__doc__') in ancestor.children):
  44. return True
  45. ancestor = ancestor.parent
  46. except AttributeError:
  47. return False
  48. if ismodule(node.parent) or \
  49. isdocassignment(node.parent) or \
  50. isclassorfunction(node.parent):
  51. return True
  52. return False
  53. def shouldtransform(node):
  54. specialnames = ['__main__']
  55. if node.value in specialnames:
  56. return False
  57. ggparent = node.parent.parent.parent
  58. sggparent = str(ggparent)
  59. if 'getattr' in sggparent or \
  60. 'hasattr' in sggparent or \
  61. 'setattr' in sggparent or \
  62. 'encode' in sggparent or \
  63. 'decode' in sggparent:
  64. return False
  65. return True
  66. class FixBytes(fixer_base.BaseFix):
  67. PATTERN = 'STRING'
  68. def transform(self, node, results):
  69. # The filename may be prefixed with a build directory.
  70. if self.filename.endswith(blacklist):
  71. return
  72. if node.type == token.STRING:
  73. if _re.match(node.value):
  74. if isdocstring(node):
  75. return
  76. if not shouldtransform(node):
  77. return
  78. new = node.clone()
  79. new.value = 'b' + new.value
  80. return new