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 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. # Copyright (c) 2006, 2008, 2010, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
  2. # Copyright (c) 2014 Brett Cannon <brett@python.org>
  3. # Copyright (c) 2014 Arun Persaud <arun@nubati.net>
  4. # Copyright (c) 2015-2017 Claudiu Popa <pcmanticore@gmail.com>
  5. # Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro>
  6. # Copyright (c) 2017 hippo91 <guillaume.peillex@gmail.com>
  7. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  8. # For details: https://github.com/PyCQA/pylint/blob/master/COPYING
  9. """
  10. generic classes/functions for pyreverse core/extensions
  11. """
  12. from __future__ import print_function
  13. import os
  14. import re
  15. import sys
  16. ########### pyreverse option utils ##############################
  17. RCFILE = '.pyreverserc'
  18. def get_default_options():
  19. """
  20. Read config file and return list of options
  21. """
  22. options = []
  23. home = os.environ.get('HOME', '')
  24. if home:
  25. rcfile = os.path.join(home, RCFILE)
  26. try:
  27. options = open(rcfile).read().split()
  28. except IOError:
  29. pass # ignore if no config file found
  30. return options
  31. def insert_default_options():
  32. """insert default options to sys.argv
  33. """
  34. options = get_default_options()
  35. options.reverse()
  36. for arg in options:
  37. sys.argv.insert(1, arg)
  38. # astroid utilities ###########################################################
  39. SPECIAL = re.compile('^__[A-Za-z0-9]+[A-Za-z0-9_]*__$')
  40. PRIVATE = re.compile('^__[_A-Za-z0-9]*[A-Za-z0-9]+_?$')
  41. PROTECTED = re.compile('^_[_A-Za-z0-9]*$')
  42. def get_visibility(name):
  43. """return the visibility from a name: public, protected, private or special
  44. """
  45. if SPECIAL.match(name):
  46. visibility = 'special'
  47. elif PRIVATE.match(name):
  48. visibility = 'private'
  49. elif PROTECTED.match(name):
  50. visibility = 'protected'
  51. else:
  52. visibility = 'public'
  53. return visibility
  54. ABSTRACT = re.compile('^.*Abstract.*')
  55. FINAL = re.compile('^[A-Z_]*$')
  56. def is_abstract(node):
  57. """return true if the given class node correspond to an abstract class
  58. definition
  59. """
  60. return ABSTRACT.match(node.name)
  61. def is_final(node):
  62. """return true if the given class/function node correspond to final
  63. definition
  64. """
  65. return FINAL.match(node.name)
  66. def is_interface(node):
  67. # bw compat
  68. return node.type == 'interface'
  69. def is_exception(node):
  70. # bw compat
  71. return node.type == 'exception'
  72. # Helpers #####################################################################
  73. _CONSTRUCTOR = 1
  74. _SPECIAL = 2
  75. _PROTECTED = 4
  76. _PRIVATE = 8
  77. MODES = {
  78. 'ALL' : 0,
  79. 'PUB_ONLY' : _SPECIAL + _PROTECTED + _PRIVATE,
  80. 'SPECIAL' : _SPECIAL,
  81. 'OTHER' : _PROTECTED + _PRIVATE,
  82. }
  83. VIS_MOD = {'special': _SPECIAL, 'protected': _PROTECTED,
  84. 'private': _PRIVATE, 'public': 0}
  85. class FilterMixIn(object):
  86. """filter nodes according to a mode and nodes' visibility
  87. """
  88. def __init__(self, mode):
  89. "init filter modes"
  90. __mode = 0
  91. for nummod in mode.split('+'):
  92. try:
  93. __mode += MODES[nummod]
  94. except KeyError as ex:
  95. print('Unknown filter mode %s' % ex, file=sys.stderr)
  96. self.__mode = __mode
  97. def show_attr(self, node):
  98. """return true if the node should be treated
  99. """
  100. visibility = get_visibility(getattr(node, 'name', node))
  101. return not self.__mode & VIS_MOD[visibility]
  102. class ASTWalker(object):
  103. """a walker visiting a tree in preorder, calling on the handler:
  104. * visit_<class name> on entering a node, where class name is the class of
  105. the node in lower case
  106. * leave_<class name> on leaving a node, where class name is the class of
  107. the node in lower case
  108. """
  109. def __init__(self, handler):
  110. self.handler = handler
  111. self._cache = {}
  112. def walk(self, node, _done=None):
  113. """walk on the tree from <node>, getting callbacks from handler"""
  114. if _done is None:
  115. _done = set()
  116. if node in _done:
  117. raise AssertionError((id(node), node, node.parent))
  118. _done.add(node)
  119. self.visit(node)
  120. for child_node in node.get_children():
  121. assert child_node is not node
  122. self.walk(child_node, _done)
  123. self.leave(node)
  124. assert node.parent is not node
  125. def get_callbacks(self, node):
  126. """get callbacks from handler for the visited node"""
  127. klass = node.__class__
  128. methods = self._cache.get(klass)
  129. if methods is None:
  130. handler = self.handler
  131. kid = klass.__name__.lower()
  132. e_method = getattr(handler, 'visit_%s' % kid,
  133. getattr(handler, 'visit_default', None))
  134. l_method = getattr(handler, 'leave_%s' % kid,
  135. getattr(handler, 'leave_default', None))
  136. self._cache[klass] = (e_method, l_method)
  137. else:
  138. e_method, l_method = methods
  139. return e_method, l_method
  140. def visit(self, node):
  141. """walk on the tree from <node>, getting callbacks from handler"""
  142. method = self.get_callbacks(node)[0]
  143. if method is not None:
  144. method(node)
  145. def leave(self, node):
  146. """walk on the tree from <node>, getting callbacks from handler"""
  147. method = self.get_callbacks(node)[1]
  148. if method is not None:
  149. method(node)
  150. class LocalsVisitor(ASTWalker):
  151. """visit a project by traversing the locals dictionary"""
  152. def __init__(self):
  153. ASTWalker.__init__(self, self)
  154. self._visited = {}
  155. def visit(self, node):
  156. """launch the visit starting from the given node"""
  157. if node in self._visited:
  158. return None
  159. self._visited[node] = 1 # FIXME: use set ?
  160. methods = self.get_callbacks(node)
  161. if methods[0] is not None:
  162. methods[0](node)
  163. if hasattr(node, 'locals'): # skip Instance and other proxy
  164. for local_node in node.values():
  165. self.visit(local_node)
  166. if methods[1] is not None:
  167. return methods[1](node)
  168. return None