importinfo.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. class ImportStatement(object):
  2. """Represent an import in a module
  3. `readonly` attribute controls whether this import can be changed
  4. by import actions or not.
  5. """
  6. def __init__(self, import_info, start_line, end_line,
  7. main_statement=None, blank_lines=0):
  8. self.start_line = start_line
  9. self.end_line = end_line
  10. self.readonly = False
  11. self.main_statement = main_statement
  12. self._import_info = None
  13. self.import_info = import_info
  14. self._is_changed = False
  15. self.new_start = None
  16. self.blank_lines = blank_lines
  17. def _get_import_info(self):
  18. return self._import_info
  19. def _set_import_info(self, new_import):
  20. if not self.readonly and \
  21. new_import is not None and not new_import == self._import_info:
  22. self._is_changed = True
  23. self._import_info = new_import
  24. import_info = property(_get_import_info, _set_import_info)
  25. def get_import_statement(self):
  26. if self._is_changed or self.main_statement is None:
  27. return self.import_info.get_import_statement()
  28. else:
  29. return self.main_statement
  30. def empty_import(self):
  31. self.import_info = ImportInfo.get_empty_import()
  32. def move(self, lineno, blank_lines=0):
  33. self.new_start = lineno
  34. self.blank_lines = blank_lines
  35. def get_old_location(self):
  36. return self.start_line, self.end_line
  37. def get_new_start(self):
  38. return self.new_start
  39. def is_changed(self):
  40. return self._is_changed or (self.new_start is not None or
  41. self.new_start != self.start_line)
  42. def accept(self, visitor):
  43. return visitor.dispatch(self)
  44. class ImportInfo(object):
  45. def get_imported_primaries(self, context):
  46. pass
  47. def get_imported_names(self, context):
  48. return [primary.split('.')[0]
  49. for primary in self.get_imported_primaries(context)]
  50. def get_import_statement(self):
  51. pass
  52. def is_empty(self):
  53. pass
  54. def __hash__(self):
  55. return hash(self.get_import_statement())
  56. def _are_name_and_alias_lists_equal(self, list1, list2):
  57. if len(list1) != len(list2):
  58. return False
  59. for pair1, pair2 in zip(list1, list2):
  60. if pair1 != pair2:
  61. return False
  62. return True
  63. def __eq__(self, obj):
  64. return isinstance(obj, self.__class__) and \
  65. self.get_import_statement() == obj.get_import_statement()
  66. def __ne__(self, obj):
  67. return not self.__eq__(obj)
  68. @staticmethod
  69. def get_empty_import():
  70. return EmptyImport()
  71. class NormalImport(ImportInfo):
  72. def __init__(self, names_and_aliases):
  73. self.names_and_aliases = names_and_aliases
  74. def get_imported_primaries(self, context):
  75. result = []
  76. for name, alias in self.names_and_aliases:
  77. if alias:
  78. result.append(alias)
  79. else:
  80. result.append(name)
  81. return result
  82. def get_import_statement(self):
  83. result = 'import '
  84. for name, alias in self.names_and_aliases:
  85. result += name
  86. if alias:
  87. result += ' as ' + alias
  88. result += ', '
  89. return result[:-2]
  90. def is_empty(self):
  91. return len(self.names_and_aliases) == 0
  92. class FromImport(ImportInfo):
  93. def __init__(self, module_name, level, names_and_aliases):
  94. self.module_name = module_name
  95. self.level = level
  96. self.names_and_aliases = names_and_aliases
  97. def get_imported_primaries(self, context):
  98. if self.names_and_aliases[0][0] == '*':
  99. module = self.get_imported_module(context)
  100. return [name for name in module
  101. if not name.startswith('_')]
  102. result = []
  103. for name, alias in self.names_and_aliases:
  104. if alias:
  105. result.append(alias)
  106. else:
  107. result.append(name)
  108. return result
  109. def get_imported_resource(self, context):
  110. """Get the imported resource
  111. Returns `None` if module was not found.
  112. """
  113. if self.level == 0:
  114. return context.pycore.find_module(
  115. self.module_name, folder=context.folder)
  116. else:
  117. return context.pycore.find_relative_module(
  118. self.module_name, context.folder, self.level)
  119. def get_imported_module(self, context):
  120. """Get the imported `PyModule`
  121. Raises `rope.base.exceptions.ModuleNotFoundError` if module
  122. could not be found.
  123. """
  124. if self.level == 0:
  125. return context.pycore.get_module(
  126. self.module_name, context.folder)
  127. else:
  128. return context.pycore.get_relative_module(
  129. self.module_name, context.folder, self.level)
  130. def get_import_statement(self):
  131. result = 'from ' + '.' * self.level + self.module_name + ' import '
  132. for name, alias in self.names_and_aliases:
  133. result += name
  134. if alias:
  135. result += ' as ' + alias
  136. result += ', '
  137. return result[:-2]
  138. def is_empty(self):
  139. return len(self.names_and_aliases) == 0
  140. def is_star_import(self):
  141. return len(self.names_and_aliases) > 0 and \
  142. self.names_and_aliases[0][0] == '*'
  143. class EmptyImport(ImportInfo):
  144. names_and_aliases = []
  145. def is_empty(self):
  146. return True
  147. def get_imported_primaries(self, context):
  148. return []
  149. class ImportContext(object):
  150. def __init__(self, pycore, folder):
  151. self.pycore = pycore
  152. self.folder = folder