PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/logilab-astng-0.23.1/mixins.py

#
Python | 136 lines | 62 code | 20 blank | 54 comment | 11 complexity | 24622beccb850d24e1370f1bb54db44d MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. # This program is free software; you can redistribute it and/or modify it under
  2. # the terms of the GNU Lesser General Public License as published by the Free Software
  3. # Foundation; either version 2 of the License, or (at your option) any later
  4. # version.
  5. #
  6. # This program is distributed in the hope that it will be useful, but WITHOUT
  7. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
  9. #
  10. # You should have received a copy of the GNU Lesser General Public License along with
  11. # this program; if not, write to the Free Software Foundation, Inc.,
  12. # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  13. # copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
  14. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
  15. # copyright 2003-2010 Sylvain Thenault, all rights reserved.
  16. # contact mailto:thenault@gmail.com
  17. #
  18. # This file is part of logilab-astng.
  19. #
  20. # logilab-astng is free software: you can redistribute it and/or modify it
  21. # under the terms of the GNU Lesser General Public License as published by the
  22. # Free Software Foundation, either version 2.1 of the License, or (at your
  23. # option) any later version.
  24. #
  25. # logilab-astng is distributed in the hope that it will be useful, but
  26. # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  27. # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
  28. # for more details.
  29. #
  30. # You should have received a copy of the GNU Lesser General Public License along
  31. # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
  32. """This module contains some mixins for the different nodes.
  33. """
  34. from logilab.astng.exceptions import (ASTNGBuildingException, InferenceError,
  35. NotFoundError)
  36. class BlockRangeMixIn(object):
  37. """override block range """
  38. def set_line_info(self, lastchild):
  39. self.fromlineno = self.lineno
  40. self.tolineno = lastchild.tolineno
  41. self.blockstart_tolineno = self._blockstart_toline()
  42. def _elsed_block_range(self, lineno, orelse, last=None):
  43. """handle block line numbers range for try/finally, for, if and while
  44. statements
  45. """
  46. if lineno == self.fromlineno:
  47. return lineno, lineno
  48. if orelse:
  49. if lineno >= orelse[0].fromlineno:
  50. return lineno, orelse[-1].tolineno
  51. return lineno, orelse[0].fromlineno - 1
  52. return lineno, last or self.tolineno
  53. class FilterStmtsMixin(object):
  54. """Mixin for statement filtering and assignment type"""
  55. def _get_filtered_stmts(self, _, node, _stmts, mystmt):
  56. """method used in _filter_stmts to get statemtents and trigger break"""
  57. if self.statement() is mystmt:
  58. # original node's statement is the assignment, only keep
  59. # current node (gen exp, list comp)
  60. return [node], True
  61. return _stmts, False
  62. def ass_type(self):
  63. return self
  64. class AssignTypeMixin(object):
  65. def ass_type(self):
  66. return self
  67. def _get_filtered_stmts(self, lookup_node, node, _stmts, mystmt):
  68. """method used in filter_stmts"""
  69. if self is mystmt:
  70. return _stmts, True
  71. if self.statement() is mystmt:
  72. # original node's statement is the assignment, only keep
  73. # current node (gen exp, list comp)
  74. return [node], True
  75. return _stmts, False
  76. class ParentAssignTypeMixin(AssignTypeMixin):
  77. def ass_type(self):
  78. return self.parent.ass_type()
  79. class FromImportMixIn(FilterStmtsMixin):
  80. """MixIn for From and Import Nodes"""
  81. def _infer_name(self, frame, name):
  82. return name
  83. def do_import_module(self, modname):
  84. """return the ast for a module whose name is <modname> imported by <self>
  85. """
  86. # handle special case where we are on a package node importing a module
  87. # using the same name as the package, which may end in an infinite loop
  88. # on relative imports
  89. # XXX: no more needed ?
  90. mymodule = self.root()
  91. level = getattr(self, 'level', None) # Import as no level
  92. # XXX we should investigate deeper if we really want to check
  93. # importing itself: modname and mymodule.name be relative or absolute
  94. if mymodule.relative_to_absolute_name(modname, level) == mymodule.name:
  95. # FIXME: we used to raise InferenceError here, but why ?
  96. return mymodule
  97. try:
  98. return mymodule.import_module(modname, level=level)
  99. except ASTNGBuildingException:
  100. raise InferenceError(modname)
  101. except SyntaxError, ex:
  102. raise InferenceError(str(ex))
  103. def real_name(self, asname):
  104. """get name from 'as' name"""
  105. for name, _asname in self.names:
  106. if name == '*':
  107. return asname
  108. if not _asname:
  109. name = name.split('.', 1)[0]
  110. _asname = name
  111. if asname == _asname:
  112. return name
  113. raise NotFoundError(asname)