Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

utils.py 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2016 Andi Albrecht, albrecht.andi@gmail.com
  4. #
  5. # This module is part of python-sqlparse and is released under
  6. # the BSD License: https://opensource.org/licenses/BSD-3-Clause
  7. import itertools
  8. import re
  9. from collections import deque
  10. from contextlib import contextmanager
  11. from sqlparse.compat import text_type
  12. # This regular expression replaces the home-cooked parser that was here before.
  13. # It is much faster, but requires an extra post-processing step to get the
  14. # desired results (that are compatible with what you would expect from the
  15. # str.splitlines() method).
  16. #
  17. # It matches groups of characters: newlines, quoted strings, or unquoted text,
  18. # and splits on that basis. The post-processing step puts those back together
  19. # into the actual lines of SQL.
  20. SPLIT_REGEX = re.compile(r"""
  21. (
  22. (?: # Start of non-capturing group
  23. (?:\r\n|\r|\n) | # Match any single newline, or
  24. [^\r\n'"]+ | # Match any character series without quotes or
  25. # newlines, or
  26. "(?:[^"\\]|\\.)*" | # Match double-quoted strings, or
  27. '(?:[^'\\]|\\.)*' # Match single quoted strings
  28. )
  29. )
  30. """, re.VERBOSE)
  31. LINE_MATCH = re.compile(r'(\r\n|\r|\n)')
  32. def split_unquoted_newlines(stmt):
  33. """Split a string on all unquoted newlines.
  34. Unlike str.splitlines(), this will ignore CR/LF/CR+LF if the requisite
  35. character is inside of a string."""
  36. text = text_type(stmt)
  37. lines = SPLIT_REGEX.split(text)
  38. outputlines = ['']
  39. for line in lines:
  40. if not line:
  41. continue
  42. elif LINE_MATCH.match(line):
  43. outputlines.append('')
  44. else:
  45. outputlines[-1] += line
  46. return outputlines
  47. def remove_quotes(val):
  48. """Helper that removes surrounding quotes from strings."""
  49. if val is None:
  50. return
  51. if val[0] in ('"', "'") and val[0] == val[-1]:
  52. val = val[1:-1]
  53. return val
  54. def recurse(*cls):
  55. """Function decorator to help with recursion
  56. :param cls: Classes to not recurse over
  57. :return: function
  58. """
  59. def wrap(f):
  60. def wrapped_f(tlist):
  61. for sgroup in tlist.get_sublists():
  62. if not isinstance(sgroup, cls):
  63. wrapped_f(sgroup)
  64. f(tlist)
  65. return wrapped_f
  66. return wrap
  67. def imt(token, i=None, m=None, t=None):
  68. """Helper function to simplify comparisons Instance, Match and TokenType
  69. :param token:
  70. :param i: Class or Tuple/List of Classes
  71. :param m: Tuple of TokenType & Value. Can be list of Tuple for multiple
  72. :param t: TokenType or Tuple/List of TokenTypes
  73. :return: bool
  74. """
  75. clss = i
  76. types = [t, ] if t and not isinstance(t, list) else t
  77. mpatterns = [m, ] if m and not isinstance(m, list) else m
  78. if token is None:
  79. return False
  80. elif clss and isinstance(token, clss):
  81. return True
  82. elif mpatterns and any(token.match(*pattern) for pattern in mpatterns):
  83. return True
  84. elif types and any(token.ttype in ttype for ttype in types):
  85. return True
  86. else:
  87. return False
  88. def consume(iterator, n):
  89. """Advance the iterator n-steps ahead. If n is none, consume entirely."""
  90. deque(itertools.islice(iterator, n), maxlen=0)
  91. @contextmanager
  92. def offset(filter_, n=0):
  93. filter_.offset += n
  94. yield
  95. filter_.offset -= n
  96. @contextmanager
  97. def indent(filter_, n=1):
  98. filter_.indent += n
  99. yield
  100. filter_.indent -= n