From ff47d1c93026851405fe304ae88487b82b0d7bec Mon Sep 17 00:00:00 2001 From: "Edward K. Ream" Date: Mon, 28 Nov 2022 06:18:52 -0600 Subject: [PATCH 1/4] Remove all references to pycompat. Define basestring as (str, bytes) --- rope.leo | 80392 ++++++++++++++++++++++++ rope/base/builtins.py | 14 +- rope/base/fscommands.py | 2 - rope/base/oi/runmod.py | 5 +- rope/base/oi/type_hinting/evaluate.py | 1 - rope/base/oi/type_hinting/utils.py | 1 - rope/base/prefs.py | 6 +- rope/base/pyobjectsdef.py | 22 +- rope/refactor/extract.py | 11 +- rope/refactor/patchedast.py | 13 +- rope/refactor/suites.py | 1 - ropetest/advanced_oi_test.py | 1 - ropetest/refactor/patchedasttest.py | 5 +- 13 files changed, 80419 insertions(+), 55 deletions(-) create mode 100644 rope.leo diff --git a/rope.leo b/rope.leo new file mode 100644 index 000000000..e5dab7415 --- /dev/null +++ b/rope.leo @@ -0,0 +1,80392 @@ + + + + + + + + +Startup + Recursive import script +@button backup +@button diff-master..head +@settings +@bool run-pyflakes-on-write = True +Find panel defaults +@bool ignore-case = False +@bool whole-word = True + + +scripts +script: diff-branches/revs (all files) +script: diff-branches/revs (one file) +script: diff-two-revs-wo-comments +function: make_diff_outlines_ignoring_comments +function: strip_comments + + + +Notes +Installation notes + +Files +@path bin +@clean tag-release.py +get_changelog +remove_headings +insert_date + + +@path docs +@clean conf.py +@clean default_config.py +set_prefs +project_opened + + +@path rope +@clean __init__.py +@path base +@clean __init__.py +@clean arguments.py +class Arguments +Arguments.__init__ +Arguments.get_arguments +Arguments.get_pynames +Arguments.get_instance_pyname +Arguments._evaluate + +create_arguments +class ObjectArguments +ObjectArguments.__init__ +ObjectArguments.get_arguments +ObjectArguments.get_pynames +ObjectArguments.get_instance_pyname + +class MixedArguments +MixedArguments.__init__ +MixedArguments.get_pynames +MixedArguments.get_arguments +MixedArguments.get_instance_pyname + +_is_method_call + +@clean ast.py +parse +walk +get_child_nodes +call_for_nodes +get_children + +@clean builtins.py +class BuiltinModule +BuiltinModule.__init__ +BuiltinModule.parent = None +BuiltinModule.get_attributes +BuiltinModule.get_doc +BuiltinModule.get_name +BuiltinModule.attributes +BuiltinModule.module + +class _BuiltinElement +_BuiltinElement.__init__ +_BuiltinElement.get_doc +_BuiltinElement.get_name +_BuiltinElement.parent + +class BuiltinClass +BuiltinClass.__init__ +BuiltinClass.get_attributes +BuiltinClass.get_module + +class BuiltinFunction +BuiltinFunction.__init__ +BuiltinFunction.get_returned_object +BuiltinFunction.get_param_names + +class BuiltinUnknown +BuiltinUnknown.__init__ +BuiltinUnknown.get_name +BuiltinUnknown.get_attributes + +_object_attributes +_create_builtin_type_getter +_get_builtin + +_create_builtin_getter +class _CallContext +_CallContext.__init__ +_CallContext._get_scope_and_pyname +_CallContext.get_argument +_CallContext.get_pyname +_CallContext.get_arguments +_CallContext.get_pynames +_CallContext.get_per_name +_CallContext.save_per_name + +class _AttributeCollector +_AttributeCollector.__init__ +_AttributeCollector.__call__ +_AttributeCollector.__setitem__ + +class List +List.__init__ +List._new_list +List._list_add +List._self_set +List._list_get +List._iterator_get +List._self_get + +get_list = _create_builtin_getter(List) +class Dict +Dict.__init__ +Dict._new_dict +Dict._dict_add +Dict._item_get +Dict._value_get +Dict._key_get +Dict._value_list +Dict._key_list +Dict._item_list +Dict._value_iter +Dict._key_iter +Dict._item_iter +Dict._self_get +Dict._self_set + +get_dict = _create_builtin_getter(Dict) +class Tuple +Tuple.__init__ +Tuple.get_holding_objects +Tuple._new_tuple + +get_tuple = _create_builtin_getter(Tuple) +class Set +Set.__init__ +Set._new_set +Set._set_add +Set._self_set +Set._set_get +Set._iterator_get +Set._self_get + +get_set = _create_builtin_getter(Set) +class Str +Str.__init__ +Str.get_doc + +get_str = _create_builtin_getter(Str) +class BuiltinName +BuiltinName.__init__ +BuiltinName.get_object +BuiltinName.get_definition_location + +class Iterator +Iterator.__init__ +Iterator.get_attributes +Iterator.get_returned_object + +get_iterator = _create_builtin_getter(Iterator) +class Generator +Generator.__init__ +Generator.get_attributes +Generator.get_returned_object + +get_generator = _create_builtin_getter(Generator) +class File +File.__init__ + +get_file = _create_builtin_getter(File) +class Property +Property.__init__ +Property.get_property_object + +_property_function +class Lambda +Lambda.__init__ +Lambda.get_returned_object +Lambda.get_module +Lambda.get_scope +Lambda.get_kind +Lambda.get_ast +Lambda.get_attributes +Lambda.get_name +Lambda.get_param_names +Lambda.parent + +class BuiltinObject +class BuiltinType +_infer_sequence_for_pyname +_create_builtin +_open_function +_range_function +_reversed_function +_sorted_function +_super_function +_zip_function +_enumerate_function +_iter_function +_input_function + +@clean change.py +class Change +Change.do +Change.undo +Change.get_description +Change.get_changed_resources +Change._operations + +class ChangeSet +ChangeSet.__init__ +ChangeSet.do +ChangeSet.undo +ChangeSet.add_change +ChangeSet.get_description +ChangeSet.__str__ +ChangeSet.get_changed_resources + +_handle_job_set +call + +class ChangeContents +ChangeContents.__init__ +ChangeContents.do +ChangeContents.undo +ChangeContents.__str__ +ChangeContents.get_description +ChangeContents.get_changed_resources + +class MoveResource +MoveResource.__init__ +MoveResource.do +MoveResource.undo +MoveResource.__str__ +MoveResource.get_description +MoveResource.get_changed_resources + +class CreateResource +CreateResource.__init__ +CreateResource.do +CreateResource.undo +CreateResource.__str__ +CreateResource.get_description +CreateResource.get_changed_resources +CreateResource._get_child_path + +class CreateFolder +CreateFolder.__init__ + +class CreateFile +CreateFile.__init__ + +class RemoveResource +RemoveResource.__init__ +RemoveResource.do +RemoveResource.undo +RemoveResource.__str__ +RemoveResource.get_changed_resources + +count_changes +create_job_set +class _ResourceOperations +_ResourceOperations.__init__ +_ResourceOperations._get_fscommands +_ResourceOperations.write_file +_ResourceOperations.move +_ResourceOperations.create +_ResourceOperations.remove +_ResourceOperations._create_resource + +_get_destination_for_move +class ChangeToData +ChangeToData.convertChangeSet +ChangeToData.convertChangeContents +ChangeToData.convertMoveResource +ChangeToData.convertCreateResource +ChangeToData.convertRemoveResource +ChangeToData.__call__ + +class DataToChange +DataToChange.__init__ +DataToChange.makeChangeSet +DataToChange.makeChangeContents +DataToChange.makeMoveResource +DataToChange.makeCreateResource +DataToChange.makeRemoveResource +DataToChange.__call__ + + +@clean codeanalyze.py +class ChangeCollector +ChangeCollector.__init__ +ChangeCollector.add_change +ChangeCollector.get_changed + +class SourceLinesAdapter +SourceLinesAdapter.__init__ +SourceLinesAdapter._initialize_line_starts +SourceLinesAdapter.get_line +SourceLinesAdapter.length +SourceLinesAdapter.get_line_number +SourceLinesAdapter.get_line_start +SourceLinesAdapter.get_line_end + +class ArrayLinesAdapter +ArrayLinesAdapter.__init__ +ArrayLinesAdapter.get_line +ArrayLinesAdapter.length + +class LinesToReadline +LinesToReadline.__init__ +LinesToReadline.readline +LinesToReadline.__call__ + +class _CustomGenerator +_CustomGenerator.__init__ +_CustomGenerator.__call__ +_CustomGenerator.Matches all backslashes before the token, to detect escaped quotes +_CustomGenerator._analyze_line + +custom_generator +class LogicalLineFinder +LogicalLineFinder.__init__ +LogicalLineFinder.logical_line_in +LogicalLineFinder.generate_starts +LogicalLineFinder.generate_regions +LogicalLineFinder._block_logical_line +LogicalLineFinder._calculate_logical +LogicalLineFinder._logical_lines +LogicalLineFinder._first_non_blank + +tokenizer_generator +class CachingLogicalLineFinder +CachingLogicalLineFinder.__init__ +CachingLogicalLineFinder._starts = None +CachingLogicalLineFinder.starts +CachingLogicalLineFinder._ends = None +CachingLogicalLineFinder.ends +CachingLogicalLineFinder._init_logicals +CachingLogicalLineFinder.logical_line_in +CachingLogicalLineFinder.generate_starts + +get_block_start +_block_start_pattern = None +get_block_start_patterns +count_line_indents +get_string_pattern_with_prefix +get_string_pattern +get_formatted_string_pattern +get_any_string_pattern +get_comment_pattern + +@clean evaluate.py +eval_location +eval_location2 +eval_node +eval_node2 +eval_str +eval_str2 +class ScopeNameFinder +ScopeNameFinder.__init__ +ScopeNameFinder._is_defined_in_class_body +ScopeNameFinder._is_function_name_in_function_header +ScopeNameFinder.get_pyname_at +ScopeNameFinder.get_primary_and_pyname_at +ScopeNameFinder.get_enclosing_function +ScopeNameFinder._find_module + +class StatementEvaluator +StatementEvaluator.__init__ +StatementEvaluator._Name +StatementEvaluator._Attribute +StatementEvaluator._Call +StatementEvaluator._Str +StatementEvaluator._Num +StatementEvaluator._Constant +StatementEvaluator._get_builtin_name +StatementEvaluator._BinOp +StatementEvaluator._BoolOp +StatementEvaluator._Repr +StatementEvaluator._UnaryOp +StatementEvaluator._Compare +StatementEvaluator._Dict +StatementEvaluator._List +StatementEvaluator._ListComp +StatementEvaluator._GeneratorExp +StatementEvaluator._what_does_comprehension_hold +StatementEvaluator._make_comprehension_scope +StatementEvaluator._Tuple +StatementEvaluator._get_object_for_node +StatementEvaluator._get_primary_and_object_for_node +StatementEvaluator._Subscript +StatementEvaluator._Slice +StatementEvaluator._call_function +StatementEvaluator._Lambda + +_get_evaluated_names + +@clean exceptions.py +class RopeError +class ResourceNotFoundError +class RefactoringError +class InterruptedTaskError +class HistoryError +class ModuleNotFoundError +class AttributeNotFoundError +class NameNotFoundError +class BadIdentifierError +class ModuleSyntaxError +ModuleSyntaxError.__init__ + +class ModuleDecodeError + +@clean fscommands.py +create_fscommands +class FileSystemCommands +FileSystemCommands.create_file +FileSystemCommands.create_folder +FileSystemCommands.move +FileSystemCommands.remove +FileSystemCommands.write +FileSystemCommands.read + +class SubversionCommands +SubversionCommands.__init__ +SubversionCommands.create_file +SubversionCommands.create_folder +SubversionCommands.move +SubversionCommands.remove +SubversionCommands.write +SubversionCommands.read + +class MercurialCommands +MercurialCommands.__init__ +MercurialCommands._import_mercurial +MercurialCommands.create_file +MercurialCommands.create_folder +MercurialCommands.move +MercurialCommands.remove +MercurialCommands.write +MercurialCommands.read + +class GITCommands +GITCommands.__init__ +GITCommands.create_file +GITCommands.create_folder +GITCommands.move +GITCommands.remove +GITCommands.write +GITCommands.read +GITCommands._do +GITCommands._in_dir + +class DarcsCommands +DarcsCommands.__init__ +DarcsCommands.create_file +DarcsCommands.create_folder +DarcsCommands.move +DarcsCommands.remove +DarcsCommands.read +DarcsCommands.write +DarcsCommands._do + +_execute +unicode_to_file_data +file_data_to_unicode +_decode_data +read_str_coding +_find_coding + +@clean history.py +class History +History.__init__ +History._load_history +History.do +History._remove_extra_items +History._is_change_interesting +History.undo +History.redo +History._move_front +History._find_dependencies +History._perform_undos +History._perform_redos +History.contents_before_current_change +History._search_for_change_contents +History.write +History.get_file_undo_list +History.__str__ +History.undo_list = property(lambda self: self._undo_list) +History.tobe_undone +History.tobe_redone +History.max_undos +History.save +History.compress +History.clear + +class _FindChangeDependencies +_FindChangeDependencies.__init__ +_FindChangeDependencies.__call__ +_FindChangeDependencies._depends_on + + +@clean libutils.py +path_to_resource +path_relative_to_project_root +relative +report_change +analyze_module +analyze_modules +get_string_module +get_string_scope +is_python_file +modname + +@clean prefs.py +class Prefs +Prefs.set +Prefs.add +Prefs.get +Prefs.add_callback +Prefs.__setitem__ +Prefs.__getitem__ + +class _RopeConfigSource +_RopeConfigSource.__init__ +_RopeConfigSource._read +_RopeConfigSource.parse + +get_config + +@clean project.py +class _Project +_Project.__init__ +_Project.get_resource +_Project.get_module +_Project.get_python_path_folders +_Project.get_source_folders +_Project.validate +_Project.add_observer +_Project.remove_observer +_Project.do +_Project.get_pymodule +_Project.get_pycore +_Project.get_file +_Project.get_folder +_Project.get_prefs +_Project.get_relative_module +_Project.find_module +_Project.find_relative_module +_Project.is_ignored +_Project._get_resource_path +_Project.history +_Project.pycore +_Project.close + +class Project +Project.__init__ +Project.__repr__ +Project._init_source_folders +Project.get_files +Project.get_python_files +Project._get_resource_path +Project._init_ropefolder +Project._create_recursively +Project._init_prefs +Project._init_other_parts +Project.is_ignored +Project.sync +Project.close +Project.set +Project.ropefolder +Project.validate + +class NoProject +NoProject.__init__ +NoProject._get_resource_path +NoProject.get_resource +NoProject.get_files +NoProject.get_python_files + +get_no_project +class _FileListCacher +_FileListCacher.__init__ +_FileListCacher.get_files +_FileListCacher._add_files +_FileListCacher._changed +_FileListCacher._invalid + +class _DataFiles +_DataFiles.__init__ +_DataFiles.read_data +_DataFiles.write_data +_DataFiles.add_write_hook +_DataFiles.write +_DataFiles._can_compress +_DataFiles._import_old_files +_DataFiles._get_opener +_DataFiles._get_file + +_realpath +_find_module_in_folder + +@clean pycore.py +class PyCore +PyCore.__init__ +PyCore._init_python_files +PyCore._init_resource_observer +PyCore._init_automatic_soa +PyCore.automatic_soa +PyCore._file_changed_for_soa +PyCore.is_python_file +PyCore.get_module +PyCore._builtin_submodules +PyCore.builtin_module +PyCore.get_relative_module +PyCore.get_string_module +PyCore.get_string_scope +PyCore._invalidate_resource_cache +PyCore.get_python_path_folders +PyCore.find_module +PyCore.find_relative_module +PyCore.get_source_folders +PyCore.resource_to_pyobject (unique) +PyCore.get_python_files +PyCore._is_package +PyCore._find_source_folders +PyCore.run_module +PyCore.analyze_module +PyCore.get_classes +PyCore.__str__ +PyCore.modname +PyCore.extension_modules + +class _ModuleCache +_ModuleCache.__init__ +_ModuleCache._invalidate_resource +_ModuleCache.get_pymodule +_ModuleCache.forget_all_data +_ModuleCache.__str__ + +class _ExtensionCache +_ExtensionCache.__init__ +_ExtensionCache.get_pymodule + +perform_soa_on_changed_scopes +class _TextChangeDetector +_TextChangeDetector.__init__ +_TextChangeDetector._set_diffs +_TextChangeDetector.is_changed +_TextChangeDetector.consume_changes +_TextChangeDetector._get_changed + + +@clean pynames.py +class PyName +PyName.get_object +PyName.get_definition_location + +class DefinedName +DefinedName.__init__ +DefinedName.get_object +DefinedName.get_definition_location + +class AssignedName +AssignedName.__init__ +AssignedName._get_inferred (*** tests self.module is not None) +AssignedName.get_object +AssignedName.get_definition_location +AssignedName.invalidate + +class UnboundName +UnboundName.__init__ +UnboundName.get_object +UnboundName.get_definition_location + +class AssignmentValue +AssignmentValue.__init__ +AssignmentValue.get_lineno + +class EvaluatedName +EvaluatedName.__init__ +EvaluatedName.get_object +EvaluatedName.get_definition_location +EvaluatedName.invalidate + +class ParameterName +ParameterName.__init__ +ParameterName.get_object +ParameterName.get_objects +ParameterName.get_definition_location + +class ImportedModule +ImportedModule.__init__ +ImportedModule._current_folder +ImportedModule._get_pymodule +ImportedModule.get_object +ImportedModule.get_definition_location + +class ImportedName +ImportedName.__init__ +ImportedName._get_imported_pyname +ImportedName.get_object +ImportedName.get_definition_location + +_get_concluded_data +_circular_inference +class _Inferred +_Inferred.__init__ +_Inferred.get +_Inferred.set +_Inferred._get + + +@clean pyobjects.py +class PyObject +PyObject.__init__ +PyObject.get_attributes +PyObject.get_attribute +PyObject.get_type +PyObject.__getitem__ +PyObject.__contains__ +PyObject.__eq__ +PyObject.__ne__ +PyObject.__hash__ +PyObject.__iter__ +PyObject._types = None +PyObject._get_base_type + +get_base_type +get_unknown +class AbstractClass +AbstractClass.__init__ +AbstractClass.get_name +AbstractClass.get_doc +AbstractClass.get_superclasses + +class AbstractFunction +AbstractFunction.__init__ +AbstractFunction.get_name +AbstractFunction.get_doc +AbstractFunction.get_param_names +AbstractFunction.get_returned_object + +class AbstractModule (PyObject) +AbstractModule.__init__ +AbstractModule.get_doc +AbstractModule.get_resource + +class PyDefinedObject +PyDefinedObject.__init__ +PyDefinedObject.__repr__ +PyDefinedObject.absolute_name +PyDefinedObject.visitor_class = None +PyDefinedObject._get_structural_attributes +PyDefinedObject._get_concluded_attributes +PyDefinedObject.get_attributes +PyDefinedObject.get_attribute +PyDefinedObject.get_scope +PyDefinedObject.get_module +PyDefinedObject.get_doc (changed) +PyDefinedObject._get_defined_objects +PyDefinedObject._create_structural_attributes +PyDefinedObject._create_concluded_attributes +PyDefinedObject.get_ast +PyDefinedObject._create_scope + +class PyFunction +class PyComprehension +class PyClass +class _ConcludedData +_ConcludedData.__init__ +_ConcludedData.set +_ConcludedData.get +_ConcludedData.data = property(get, set) +_ConcludedData._invalidate +_ConcludedData.__str__ + +class _PyModule(PyDefinedObject, AbstractModule) +_PyModule.__init__ +_PyModule.absolute_name +_PyModule._get_concluded_data +_PyModule._forget_concluded_data +_PyModule.get_resource + +class PyModule (placeholder, pyobjects.py) +class PyPackage (placeholder, pyobjects.py) +class IsBeingInferredError + +@clean pyobjectsdef.py +<< imports: pyobjectsdef >> +class PyFunction +PyFunction.__init__ +PyFunction._create_structural_attributes +PyFunction._create_concluded_attributes +PyFunction._create_scope +PyFunction._infer_parameters +PyFunction._infer_returned +PyFunction._handle_special_args +PyFunction._set_parameter_pyobjects +PyFunction.get_parameters +PyFunction.get_parameter +PyFunction.get_returned_object +PyFunction.get_name +PyFunction.get_param_names +PyFunction.get_kind +PyFunction.decorators + +class PyComprehension +PyComprehension.__init__ +PyComprehension._create_scope +PyComprehension.get_kind + +class PyClass +PyClass.__init__ +PyClass.get_superclasses +PyClass.get_name +PyClass._create_concluded_attributes +PyClass._get_bases +PyClass._create_scope + +class PyModule (pyobjectsdef.py) +PyModule.__init__ +PyModule._init_source +PyModule._create_concluded_attributes +PyModule._create_scope +PyModule.lines +PyModule.logical_lines +PyModule.get_name + +class PyPackage (real, pyobjectsdef.py) +PyPackage.__init__ +PyPackage._create_structural_attributes +PyPackage._create_concluded_attributes +PyPackage._get_child_resources +PyPackage._get_init_dot_py +PyPackage._create_scope +PyPackage.get_module +PyPackage.get_name + +class _AnnAssignVisitor +_AnnAssignVisitor.__init__ +_AnnAssignVisitor._AnnAssign +_AnnAssignVisitor._assigned +_AnnAssignVisitor._Name +_AnnAssignVisitor._Tuple +_AnnAssignVisitor._Annotation +_AnnAssignVisitor._Attribute +_AnnAssignVisitor._Subscript +_AnnAssignVisitor._Slice + +class _ExpressionVisitor +_ExpressionVisitor.__init__ +_ExpressionVisitor._assigned +_ExpressionVisitor._GeneratorExp +_ExpressionVisitor._SetComp +_ExpressionVisitor._ListComp +_ExpressionVisitor._DictComp +_ExpressionVisitor._NamedExpr + +class _AssignVisitor +_AssignVisitor.__init__ +_AssignVisitor._Assign +_AssignVisitor._assigned +_AssignVisitor._Name +_AssignVisitor._Tuple +_AssignVisitor._Attribute +_AssignVisitor._Subscript +_AssignVisitor._Slice + +class _ScopeVisitor(_ExpressionVisitor) +_ScopeVisitor.__init__ +_ScopeVisitor.get_module (trace) +_ScopeVisitor._ClassDef +_ScopeVisitor._FunctionDef (pyobjectsdef.py) +_ScopeVisitor._AsyncFunctionDef +_ScopeVisitor._Assign +_ScopeVisitor._AnnAssign +_ScopeVisitor._AugAssign +_ScopeVisitor._For +_ScopeVisitor._AsyncFor +_ScopeVisitor._assigned +_ScopeVisitor._update_evaluated +_ScopeVisitor._With +_ScopeVisitor._AsyncWith +_ScopeVisitor._excepthandler +_ScopeVisitor._ExceptHandler +_ScopeVisitor._Import +_ScopeVisitor._ImportFrom (trace) +_ScopeVisitor._is_ignored_import (unique) +_ScopeVisitor._Global + +class _ComprehensionVisitor +_ComprehensionVisitor._comprehension +_ComprehensionVisitor._Name +_ComprehensionVisitor._get_pyobject + +class _GlobalVisitor(_ScopeVisitor) +class _ClassVisitor +_ClassVisitor.__init__ +_ClassVisitor._FunctionDef + +class _FunctionVisitor +_FunctionVisitor.__init__ +_FunctionVisitor._Return +_FunctionVisitor._Yield + +class _ClassInitVisitor +_ClassInitVisitor.__init__ +_ClassInitVisitor._Attribute (changed) +_ClassInitVisitor._Tuple +_ClassInitVisitor._Name +_ClassInitVisitor._FunctionDef +_ClassInitVisitor._ClassDef +_ClassInitVisitor._For +_ClassInitVisitor._With + +class StarImport +StarImport.__init__ +StarImport.get_names + + +@clean pyscopes.py +class Scope +Scope.__init__ +Scope.get_names +Scope.get_defined_names +Scope.get_name +Scope.__getitem__ +Scope.__contains__ +Scope.get_scopes +Scope.lookup +Scope.get_propagated_names +Scope._propagated_lookup +Scope._create_scopes +Scope._get_global_scope +Scope.get_start +Scope.get_body_start +Scope.get_end +Scope.get_logical_end +Scope.start = property(get_start) +Scope.get_kind +Scope.get_region +Scope._calculate_scope_regions_for_module +Scope.in_region + +class GlobalScope +GlobalScope.__init__ +GlobalScope.get_start +GlobalScope.get_kind +GlobalScope.get_name +GlobalScope._calculate_scope_regions +GlobalScope._get_source +GlobalScope.get_names +GlobalScope.get_inner_scope_for_line +GlobalScope.get_inner_scope_for_offset +GlobalScope._scope_finder +GlobalScope.builtin_names + +class ComprehensionScope +ComprehensionScope.__init__ +ComprehensionScope._get_names +ComprehensionScope.get_names +ComprehensionScope._visit_comprehension +ComprehensionScope.get_logical_end +ComprehensionScope.logical_end = property(get_logical_end) +ComprehensionScope.get_body_start + +class FunctionScope +FunctionScope.__init__ +FunctionScope._get_names +FunctionScope._visit_function +FunctionScope._get_returned_asts +FunctionScope._is_generator +FunctionScope.get_names +FunctionScope._create_scopes +FunctionScope.get_kind +FunctionScope.invalidate_data + +class ClassScope +ClassScope.__init__ +ClassScope.get_kind +ClassScope.get_propagated_names + +class _HoldingScopeFinder +_HoldingScopeFinder.__init__ +_HoldingScopeFinder.get_indents +_HoldingScopeFinder._get_scope_indents +_HoldingScopeFinder.get_holding_scope +_HoldingScopeFinder._is_empty_line +_HoldingScopeFinder._get_body_indents +_HoldingScopeFinder.get_holding_scope_for_offset +_HoldingScopeFinder.find_scope_end +_HoldingScopeFinder.lines +_HoldingScopeFinder.code +_HoldingScopeFinder.logical_lines + +class TemporaryScope +TemporaryScope.__init__ +TemporaryScope.get_names +TemporaryScope.get_defined_names +TemporaryScope._create_scopes +TemporaryScope.get_kind + + +@clean resourceobserver.py +class ResourceObserver +ResourceObserver.__init__ +ResourceObserver.resource_changed +ResourceObserver.resource_moved +ResourceObserver.resource_created +ResourceObserver.resource_removed +ResourceObserver.validate + +class FilteredResourceObserver +FilteredResourceObserver.__init__ +FilteredResourceObserver.add_resource +FilteredResourceObserver.remove_resource +FilteredResourceObserver.clear_resources +FilteredResourceObserver.resource_changed +FilteredResourceObserver._update_changes_caused_by_changed +FilteredResourceObserver._update_changes_caused_by_moved +FilteredResourceObserver._is_parent_changed +FilteredResourceObserver.resource_moved +FilteredResourceObserver.resource_created +FilteredResourceObserver._update_changes_caused_by_created +FilteredResourceObserver.resource_removed +FilteredResourceObserver._perform_changes +FilteredResourceObserver.validate +FilteredResourceObserver._search_resource_creations +FilteredResourceObserver._search_resource_moves +FilteredResourceObserver._search_resource_changes +FilteredResourceObserver._is_changed +FilteredResourceObserver._calculate_new_resource + +class ChangeIndicator +ChangeIndicator.get_indicator + +class _Changes +_Changes.__init__ +_Changes.add_changed +_Changes.add_removed +_Changes.add_created + + +@clean resources.py +class Resource +Resource.__init__ +Resource.__repr__ +Resource.move +Resource.remove +Resource.is_folder +Resource.create +Resource.exists +Resource.parent +Resource.path +Resource.name +Resource.real_path +Resource.pathlib +Resource.__eq__ +Resource.__ne__ +Resource.__hash__ +Resource._perform_change + +class File +File.__init__ +File.read +File.read_bytes +File.write +File.is_folder +File.create + +class Folder +Folder.__init__ +Folder.is_folder +Folder.get_children +Folder.create_file +Folder.create_folder +Folder._get_child_path +Folder.get_child +Folder.has_child +Folder.get_files +Folder.get_folders +Folder.contains +Folder.create + +class _ResourceMatcher +_ResourceMatcher.__init__ +_ResourceMatcher.set_patterns +_ResourceMatcher._add_pattern +_ResourceMatcher.does_match +_ResourceMatcher.compiled_patterns + + +@clean simplify.py +real_code +ignored_regions + +@clean stdmods.py +_stdlib_path +standard_modules +python_modules +normalize_so_name +dynload_modules + +@clean taskhandle.py +class BaseJobSet +BaseJobSet.started_job +BaseJobSet.finished_job +BaseJobSet.check_status +BaseJobSet.get_active_job_name +BaseJobSet.get_percent_done +BaseJobSet.get_name +BaseJobSet.increment + +class BaseTaskHandle +BaseTaskHandle.stop +BaseTaskHandle.current_jobset +BaseTaskHandle.add_observer +BaseTaskHandle.is_stopped +BaseTaskHandle.get_jobsets +BaseTaskHandle.create_jobset +BaseTaskHandle._inform_observers + +class TaskHandle +TaskHandle.__init__ +TaskHandle.stop +TaskHandle.current_jobset +TaskHandle.add_observer +TaskHandle.is_stopped +TaskHandle.get_jobsets +TaskHandle.create_jobset +TaskHandle._inform_observers + +class JobSet +JobSet.__init__ +JobSet.started_job +JobSet.finished_job +JobSet.check_status +JobSet.get_active_job_name +JobSet.get_percent_done +JobSet.get_name +JobSet.increment + +class NullTaskHandle +NullTaskHandle.__init__ +NullTaskHandle.is_stopped +NullTaskHandle.stop +NullTaskHandle.create_jobset +NullTaskHandle.get_jobsets +NullTaskHandle.add_observer +NullTaskHandle.current_jobset + +class NullJobSet +NullJobSet.__init__ +NullJobSet.started_job +NullJobSet.finished_job +NullJobSet.check_status +NullJobSet.get_active_job_name +NullJobSet.get_percent_done +NullJobSet.get_name +NullJobSet.increment + + +@clean worder.py +get_name_at +class Worder +Worder.__init__ +Worder._init_ignores +Worder._context_call +Worder.get_primary_at +Worder.get_word_at +Worder.get_primary_range +Worder.get_splitted_primary_before +Worder.get_word_range +Worder.is_function_keyword_parameter +Worder.is_a_class_or_function_name_in_header +Worder.is_from_statement_module +Worder.is_from_aliased +Worder.is_import_statement_aliased_module +Worder.find_parens_start_from_inside +Worder.is_a_name_after_from_import +Worder.is_from_statement +Worder.get_from_aliased +Worder.is_import_statement +Worder.is_assigned_here +Worder.is_a_function_being_called +Worder.get_word_parens_range +Worder.is_name_assigned_in_class_body +Worder.is_on_function_call_keyword +Worder._find_parens_start +Worder.get_parameters +Worder.get_from_module +Worder.is_assigned_in_a_tuple_assignment +Worder.get_assignment_type +Worder.get_function_and_args_in_header +Worder.get_lambda_and_args +Worder.find_function_offset + +class _RealFinder +_RealFinder.__init__ +_RealFinder._find_word_start +_RealFinder._find_word_end +_RealFinder._find_last_non_space_char +_RealFinder.get_word_at +_RealFinder._get_fixed_offset +_RealFinder._is_id_char +_RealFinder._find_string_start +_RealFinder._find_parens_start +_RealFinder._find_atom_start +_RealFinder._find_primary_without_dot_start +_RealFinder._find_primary_start +_RealFinder.get_primary_at +_RealFinder.get_splitted_primary_before +_RealFinder._get_line_start +_RealFinder._get_line_end +_RealFinder.is_name_assigned_in_class_body +_RealFinder.is_a_class_or_function_name_in_header +_RealFinder._find_first_non_space_char +_RealFinder.is_a_function_being_called +_RealFinder._find_import_end +_RealFinder.is_import_statement +_RealFinder.is_from_statement +_RealFinder.is_from_statement_module +_RealFinder.is_import_statement_aliased_module +_RealFinder._has_enough_len_for_as +_RealFinder._find_import_main_part_end +_RealFinder.is_a_name_after_from_import +_RealFinder.get_from_module +_RealFinder.is_from_aliased +_RealFinder.get_from_aliased +_RealFinder.is_function_keyword_parameter +_RealFinder.is_on_function_call_keyword +_RealFinder.find_parens_start_from_inside +_RealFinder.is_assigned_here +_RealFinder.get_assignment_type +_RealFinder.get_primary_range +_RealFinder.get_word_range +_RealFinder.get_word_parens_range +_RealFinder.get_parameters +_RealFinder.__strip_type_hint +_RealFinder.is_assigned_in_a_tuple_assignment +_RealFinder.get_function_and_args_in_header +_RealFinder.find_function_offset +_RealFinder.get_lambda_and_args + + + +@path base/oi +@clean doa.py +_compat_compare_digest +try: +class PythonFileRunner +PythonFileRunner.__init__ +PythonFileRunner.run +PythonFileRunner._init_data_receiving +PythonFileRunner._receive_information +PythonFileRunner.wait_process +PythonFileRunner.kill_process +PythonFileRunner.add_finishing_observer + +class _MessageReceiver +class _SocketReceiver +_SocketReceiver.__init__ +_SocketReceiver.get_send_info +_SocketReceiver.receive_data + +class _FIFOReceiver +_FIFOReceiver.__init__ +_FIFOReceiver._get_file_name +_FIFOReceiver.get_send_info +_FIFOReceiver.receive_data + + +@clean memorydb.py +class MemoryDB +MemoryDB.__init__ +MemoryDB._load_files +MemoryDB.keys +MemoryDB.__iter__ +MemoryDB.__len__ +MemoryDB.__setitem__ +MemoryDB.__contains__ +MemoryDB.__getitem__ +MemoryDB.create +MemoryDB.rename +MemoryDB.__delitem__ +MemoryDB.write +MemoryDB.compress +MemoryDB.persist + +class FileInfo +FileInfo.__init__ +FileInfo.create_scope +FileInfo.keys +FileInfo.__contains__ +FileInfo.__getitem__ +FileInfo.__delitem__ +FileInfo.__iter__ +FileInfo.__len__ +FileInfo.__setitem__ + +class ScopeInfo +ScopeInfo.__init__ +ScopeInfo.get_per_name +ScopeInfo.save_per_name +ScopeInfo.get_returned +ScopeInfo.get_call_infos +ScopeInfo.add_call +ScopeInfo.__getstate__ +ScopeInfo.__setstate__ + + +@clean objectdb.py +class ObjectDB +ObjectDB.__init__ +ObjectDB.validate_files +ObjectDB.validate_file +ObjectDB.file_moved +ObjectDB.get_files +ObjectDB.get_returned +ObjectDB.get_pername +ObjectDB.get_callinfos +ObjectDB.add_callinfo +ObjectDB.add_pername +ObjectDB.add_file_list_observer +ObjectDB.write +ObjectDB._get_scope_info +ObjectDB._file_removed +ObjectDB._file_added +ObjectDB.__str__ + +class _NullScopeInfo +_NullScopeInfo.__init__ +_NullScopeInfo.get_per_name +_NullScopeInfo.save_per_name +_NullScopeInfo.get_returned +_NullScopeInfo.get_call_infos +_NullScopeInfo.add_call + +class FileInfo +class FileDict +class ScopeInfo +ScopeInfo.get_per_name +ScopeInfo.save_per_name +ScopeInfo.get_returned +ScopeInfo.get_call_infos +ScopeInfo.add_call + +class CallInfo +CallInfo.__init__ +CallInfo.get_parameters +CallInfo.get_returned + +class FileListObserver + +@clean objectinfo.py +class ObjectInfoManager +ObjectInfoManager.__init__ +ObjectInfoManager._init_objectdb +ObjectInfoManager._init_validation +ObjectInfoManager._resource_changed +ObjectInfoManager._resource_moved +ObjectInfoManager.get_returned +ObjectInfoManager.get_exact_returned +ObjectInfoManager._args_to_textual +ObjectInfoManager.get_parameter_objects +ObjectInfoManager.get_passed_objects +ObjectInfoManager.doa_data_received +ObjectInfoManager.function_called +ObjectInfoManager.save_per_name +ObjectInfoManager.get_per_name +ObjectInfoManager._save_data +ObjectInfoManager._get_scope +ObjectInfoManager.sync +ObjectInfoManager.__str__ + +class TextualValidation +TextualValidation.__init__ +TextualValidation.is_value_valid +TextualValidation.is_more_valid +TextualValidation.is_file_valid +TextualValidation.is_scope_valid + +class _FileListObserver +_FileListObserver.__init__ +_FileListObserver.removed +_FileListObserver.added + + +@clean runmod.py +__rope_start_everything +class _MessageSender +class _SocketSender +class _FileSender +_cached +class _FunctionCallDataSender +_FunctionCallDataSender.global_trace + +_realpath + + +@clean soa.py +analyze_module +_analyze_node +class SOAVisitor +SOAVisitor.__init__ +SOAVisitor._FunctionDef +SOAVisitor._ClassDef +SOAVisitor._Call +SOAVisitor._args_with_self +SOAVisitor._call +SOAVisitor._parameter_objects +SOAVisitor._AnnAssign +SOAVisitor._Assign +SOAVisitor._evaluate_assign_value + +class _SOAAssignVisitor +_SOAAssignVisitor.__init__ +_SOAAssignVisitor._added + + +@clean soi.py +infer_returned_object +infer_parameter_objects +_handle_first_parameter +infer_assigned_object +get_passed_objects +_infer_returned +_parameter_objects +_infer_assignment & helpers +_follow_levels +_follow_pyname +_follow_evaluations +_get_lineno_for_node +_get_attribute + + +@clean transform.py +class PyObjectToTextual +PyObjectToTextual.__init__ +PyObjectToTextual.transform +PyObjectToTextual.__call__ +PyObjectToTextual.PyObject_to_textual +PyObjectToTextual.PyFunction_to_textual +PyObjectToTextual.PyClass_to_textual +PyObjectToTextual._defined_to_textual +PyObjectToTextual.PyModule_to_textual +PyObjectToTextual.PyPackage_to_textual +PyObjectToTextual.List_to_textual +PyObjectToTextual.Dict_to_textual +PyObjectToTextual.Tuple_to_textual +PyObjectToTextual.Set_to_textual +PyObjectToTextual.Iterator_to_textual +PyObjectToTextual.Generator_to_textual +PyObjectToTextual.Str_to_textual +PyObjectToTextual.File_to_textual +PyObjectToTextual.BuiltinFunction_to_textual +PyObjectToTextual._get_pymodule_path +PyObjectToTextual.resource_to_path + +class TextualToPyObject +TextualToPyObject.__init__ +TextualToPyObject.__call__ +TextualToPyObject.transform +TextualToPyObject.builtin_to_pyobject +TextualToPyObject.builtin_str_to_pyobject +TextualToPyObject.builtin_list_to_pyobject +TextualToPyObject.builtin_dict_to_pyobject +TextualToPyObject.builtin_tuple_to_pyobject +TextualToPyObject.builtin_set_to_pyobject +TextualToPyObject.builtin_iter_to_pyobject +TextualToPyObject.builtin_generator_to_pyobject +TextualToPyObject.builtin_file_to_pyobject +TextualToPyObject.builtin_function_to_pyobject +TextualToPyObject.unknown_to_pyobject +TextualToPyObject.none_to_pyobject +TextualToPyObject._module_to_pyobject +TextualToPyObject._hierarchical_defined_to_pyobject +TextualToPyObject.defined_to_pyobject +TextualToPyObject.instance_to_pyobject +TextualToPyObject._get_pymodule +TextualToPyObject.path_to_resource + +class DOITextualToPyObject +DOITextualToPyObject._function_to_pyobject +DOITextualToPyObject._class_to_pyobject +DOITextualToPyObject.defined_to_pyobject +DOITextualToPyObject._find_occurrence +DOITextualToPyObject.path_to_resource + + +@clean __init__.py +<< docstring: oi/__init__ >> + +@path type_hinting +@@clean __init__.py +@clean oi/type_hinting/evaluate.py +class SymbolBase +SymbolBase.__init__ +SymbolBase.nud +SymbolBase.led +SymbolBase.evaluate +SymbolBase.__repr__ + +class SymbolTable +SymbolTable.multi +SymbolTable.__init__ +SymbolTable.get +SymbolTable.__getitem__ +SymbolTable.__iter__ +SymbolTable.symbol +class S + +infix +infix_r +ternary +prefix +postfix + +symbol_table = SymbolTable() +class Lexer +Lexer.__init__ +Lexer.tokenize +Lexer._tokenize_expr + +class Parser +Parser.__init__ +Parser.parse +Parser.expression +Parser.advance + +method +bind + +symbol, infix, infix_r, prefix, postfix, ternary = ( +nud +evaluate +led +evaluate +nud +led +evaluate +evaluate +class Compiler +Compiler._make_parser +Compiler.__call__ + +compile = Compiler() +class Evaluator +Evaluator.__call__ + + +@clean factory.py +class TypeHintingFactory +TypeHintingFactory.make_param_provider +TypeHintingFactory.make_return_provider +TypeHintingFactory.make_assignment_provider +TypeHintingFactory.make_resolver + +default_type_hinting_factory = TypeHintingFactory() +class TypeHintingFactoryAccessor +TypeHintingFactoryAccessor.__call__ +TypeHintingFactoryAccessor._get_factory + + +@clean interfaces.py +class ITypeHintingFactory +ITypeHintingFactory.make_param_provider +ITypeHintingFactory.make_return_provider +ITypeHintingFactory.make_assignment_provider +ITypeHintingFactory.make_resolver + + +@clean utils.py +get_super_func +get_super_assignment +get_class_with_attr_name +get_lineno_for_node +get_mro +resolve_type (utils.py) +class ParametrizeType +ParametrizeType.__call__ +ParametrizeType._get_type_factory + + +@path providers +@@clean __init__.py +@clean composite.py +class ParamProvider +ParamProvider.__init__ +ParamProvider.__call__ + +class ReturnProvider +ReturnProvider.__init__ +ReturnProvider.__call__ + +class AssignmentProvider +AssignmentProvider.__init__ +AssignmentProvider.__call__ + + +@clean docstrings.py +class ParamProvider +ParamProvider.__init__ +ParamProvider.__call__ + +class ReturnProvider +ReturnProvider.__init__ +ReturnProvider.__call__ + +class AssignmentProvider +AssignmentProvider.__init__ +AssignmentProvider.__call__ + +class IParamParser +class IReturnParser +class DocstringParamParser +DocstringParamParser.__init__ +DocstringParamParser.__call__ + +class DocstringReturnParser +DocstringReturnParser.__init__ +DocstringReturnParser.__call__ + +class RSTRoleStrip +RSTRoleStrip.__call__ + + +@clean inheritance.py +class ParamProvider +ParamProvider.__init__ +ParamProvider.__call__ + +class ReturnProvider +ReturnProvider.__init__ +ReturnProvider.__call__ + +class AssignmentProvider +AssignmentProvider.__init__ +AssignmentProvider.__call__ + + +@clean interfaces.py +class IParamProvider +IParamProvider.__call__ + +class IReturnProvider +IReturnProvider.__call__ + +class IAssignmentProvider +IAssignmentProvider.__call__ + + +@clean numpydocstrings.py +class NumPyDocstringParamParser +NumPyDocstringParamParser.__call__ + +class _DummyParamParser + +@clean pep0484_type_comments.py +class AssignmentProvider +AssignmentProvider.__init__ +AssignmentProvider.PEP0484_TYPE_COMMENT_PATTERNS = (re.compile(r"type:/s*([^/n]+)"),) +AssignmentProvider.__call__ +AssignmentProvider._search_type_in_type_comment + + + +@path resolvers +@@clean __init__.py +@clean composite.py +class Resolver +Resolver.__init__ +Resolver.__call__ + + +@clean interfaces.py +@clean types.py +class Resolver +Resolver.__call__ + + + + + +@path base/utils +@clean __init__.py +saveit +_wrapper + +cacheit = saveit +prevent_recursion +decorator + +ignore_exception +_decorator + +deprecated +_decorator + +cached +decorator + +class _Cached +_Cached.__init__ +_Cached.__call__ + +resolve +guess_def_lineno +is_inline_body + + +@clean astutils.py +class _NodeNameCollector +_NodeNameCollector.__init__ +_NodeNameCollector._add_node +_NodeNameCollector._added +_NodeNameCollector._Name +_NodeNameCollector._ExceptHandler +_NodeNameCollector._Tuple +_NodeNameCollector._Subscript +_NodeNameCollector._Attribute +_NodeNameCollector._Slice + +function: call_for_nodes +function: get_child_nodes +function: get_children +function: get_name_levels +function: parse +function: walk + +@clean datastructures.py +class OrderedSet +OrderedSet.__init__ +OrderedSet.__len__ +OrderedSet.__contains__ +OrderedSet.add +OrderedSet.intersection +OrderedSet.discard +OrderedSet.__iter__ +OrderedSet.__reversed__ +OrderedSet.pop +OrderedSet.__repr__ +OrderedSet.__eq__ + + +@clean pycompat.py + +@path contrib +@clean changestack.py +class ChangeStack +ChangeStack.__init__ +ChangeStack.push +ChangeStack.pop_all +ChangeStack.merged +ChangeStack._basic_changes + + +@clean codeassist.py +code_assist +starting_offset +get_doc +get_calltip +get_definition_location +find_occurrences +get_canonical_path +class CompletionProposal +CompletionProposal.__init__ +CompletionProposal.__str__ +CompletionProposal.__repr__ +CompletionProposal.parameters +CompletionProposal.type +CompletionProposal._get_scope +CompletionProposal.get_doc +CompletionProposal.kind + +leaved for backward compatibility +class NamedParamProposal +NamedParamProposal.__init__ +NamedParamProposal.get_default + +sorted_proposals +starting_expression +default_templates +class _PythonCodeAssist +_PythonCodeAssist.__init__ +_PythonCodeAssist.keywords = keyword.kwlist +_PythonCodeAssist._find_starting_offset +_PythonCodeAssist._matching_keywords +_PythonCodeAssist.__call__ +_PythonCodeAssist._dotted_completions +_PythonCodeAssist._undotted_completions +_PythonCodeAssist._from_import_completions +_PythonCodeAssist._find_module +_PythonCodeAssist._is_defined_after +_PythonCodeAssist._code_completions +_PythonCodeAssist._keyword_parameters + +class _ProposalSorter +_ProposalSorter.__init__ +_ProposalSorter.get_sorted_proposal_list +_ProposalSorter._proposal_key + +class PyDocExtractor +PyDocExtractor.get_doc +PyDocExtractor.get_calltip +PyDocExtractor._get_class_docstring +PyDocExtractor._get_function_docstring +PyDocExtractor._is_method +PyDocExtractor._get_single_function_docstring +PyDocExtractor._get_super_methods +PyDocExtractor._get_function_signature +PyDocExtractor._location +PyDocExtractor._get_module +PyDocExtractor._trim_docstring + +Deprecated classes +class TemplateProposal +class Template +Template.__init__ +Template.variables +Template.substitute +Template.get_cursor_location + + +@clean finderrors.py +find_errors +class _BadAccessFinder +_BadAccessFinder.__init__ +_BadAccessFinder._Name +_BadAccessFinder._Attribute +_BadAccessFinder._add_error +_BadAccessFinder._is_defined_after + +class Error + +@clean findit.py +find_occurrences +is_match + +find_implementations +is_defined +not_self + +find_definition +class Location +_find_locations + +@clean fixmodnames.py +class FixModuleNames +FixModuleNames.__init__ +FixModuleNames.get_changes +FixModuleNames._count_fixes +FixModuleNames._tobe_fixed +FixModuleNames._name + + +@clean fixsyntax.py +class FixSyntax +FixSyntax.__init__ +FixSyntax.get_pymodule +FixSyntax.commenter +FixSyntax.pyname_at + +class _Commenter +_Commenter.__init__ +_Commenter.comment +_Commenter.transfered_offset +_Commenter._last_non_blank +_Commenter._get_block_end +_Commenter._get_stmt_end +_Commenter._fix_incomplete_try_blocks +_Commenter._find_matching_deindent +_Commenter._set +_Commenter._insert + +_logical_start +_get_line_indents + +@clean generate.py +create_generate +create_module +create_package +class _Generate +_Generate.__init__ +_Generate._generate_info +_Generate._check_exceptional_conditions +_Generate.get_changes +_Generate.get_location +_Generate._get_element_kind +_Generate._get_element + +class GenerateFunction +GenerateFunction._generate_info +GenerateFunction._get_element +GenerateFunction._get_element_kind + +class GenerateVariable +class GenerateClass +class GenerateModule +GenerateModule.get_changes +GenerateModule.get_location + +class GeneratePackage +GeneratePackage.get_changes +GeneratePackage.get_location + +_add_import_to_module +_add_relative_import_to_module +class _GenerationInfo +_GenerationInfo.__init__ +_GenerationInfo._init_fields +_GenerationInfo._get_goal_scope +_GenerationInfo._get_goal_module +_GenerationInfo._get_source_scope +_GenerationInfo.get_insertion_lineno +_GenerationInfo.get_insertion_resource +_GenerationInfo.get_insertion_offsets +_GenerationInfo.get_scope_indents +_GenerationInfo.get_blank_lines +_GenerationInfo.get_package +_GenerationInfo.primary_is_found +_GenerationInfo.element_already_exists +_GenerationInfo.get_name + +class _FunctionGenerationInfo +_FunctionGenerationInfo._get_goal_scope +_FunctionGenerationInfo.element_already_exists +_FunctionGenerationInfo.is_static_method +_FunctionGenerationInfo.is_method +_FunctionGenerationInfo.is_constructor +_FunctionGenerationInfo.is_instance +_FunctionGenerationInfo.get_name +_FunctionGenerationInfo.get_passed_args +_FunctionGenerationInfo._is_id + + +@clean __init__.py +@path autoimport +@clean defs.py +class Source +class ModuleInfo +class ModuleFile +class ModuleCompiled +class PackageType +class NameType +class Package +class Name +class PartialName +class SearchResult + +@clean models.py +class FinalQuery +class Query +Query.__init__ +Query.select +Query.select_star +Query.where +Query.insert_into +Query.drop_table +Query.delete_from + +class Name +Name.create_table + +class Package +Package.create_table + + +@clean parse.py +get_type_ast +get_names_from_file +get_type_object +get_names +get_names_from_compiled +combine + +@clean pickle.py +class AutoImport +AutoImport.__init__ +AutoImport.import_assist +AutoImport.get_modules +AutoImport.get_all_names +AutoImport.get_name_locations +AutoImport.generate_cache +AutoImport.generate_modules_cache +AutoImport.clear_cache +AutoImport.find_insertion_line +AutoImport.update_resource +AutoImport.update_module +AutoImport._module_name +AutoImport._add_names +AutoImport._write +AutoImport._changed +AutoImport._moved +AutoImport._removed + +submodules + +@clean sqlite.py +get_future_names +filter_packages +class AutoImport +AutoImport.__init__ +AutoImport._setup_db +AutoImport.import_assist +AutoImport.search +AutoImport.search_full +AutoImport._search_name +AutoImport._search_module +AutoImport.get_modules +AutoImport.get_all_names +AutoImport._dump_all +AutoImport.generate_cache +AutoImport.generate_modules_cache +AutoImport._get_packages_from_modules +AutoImport.update_module +AutoImport.close +AutoImport.get_name_locations +AutoImport.clear_cache +AutoImport.find_insertion_line +AutoImport.update_resource +AutoImport._changed +AutoImport._moved +AutoImport._del_if_exist +AutoImport._get_python_folders +AutoImport._get_available_packages +AutoImport._add_packages +AutoImport._get_packages_from_cache +AutoImport._removed +AutoImport._add_future_names +AutoImport._convert_name +AutoImport._add_names +AutoImport._add_name +AutoImport._find_package_path +AutoImport._resource_to_module +AutoImport._execute +AutoImport._executemany + + +@clean utils.py +get_package_tuple +get_package_source +get_modname_from_path +sort_and_deduplicate +sort_and_deduplicate_tuple +should_parse +get_files + +@clean __init__.py + + +@path refactor +@clean __init__.py +@clean change_signature.py +class ChangeSignature +ChangeSignature.__init__ +ChangeSignature._set_name_and_pyname +ChangeSignature._change_calls +ChangeSignature.get_args +ChangeSignature.is_method +ChangeSignature.get_definition_info +ChangeSignature._definfo +ChangeSignature.normalize +ChangeSignature.remove +ChangeSignature.add +ChangeSignature.inline_default +ChangeSignature.reorder +ChangeSignature.get_changes + +class _FunctionChangers +_FunctionChangers.__init__ +_FunctionChangers._get_changed_definition_infos +_FunctionChangers.change_definition +_FunctionChangers.change_call + +class _ArgumentChanger +class ArgumentNormalizer +class ArgumentRemover +ArgumentRemover.__init__ +ArgumentRemover.change_definition_info +ArgumentRemover.change_argument_mapping + +class ArgumentAdder +ArgumentAdder.__init__ +ArgumentAdder.change_definition_info +ArgumentAdder.change_argument_mapping + +class ArgumentDefaultInliner +ArgumentDefaultInliner.__init__ +ArgumentDefaultInliner.change_definition_info +ArgumentDefaultInliner.change_argument_mapping + +class ArgumentReorderer +ArgumentReorderer.__init__ +ArgumentReorderer.change_definition_info + +class _ChangeCallsInModule +_ChangeCallsInModule.__init__ +_ChangeCallsInModule.get_changed_module +_ChangeCallsInModule.pymodule +_ChangeCallsInModule.source +_ChangeCallsInModule.lines + +class _MultipleFinders +_MultipleFinders.__init__ +_MultipleFinders.find_occurrences + + +@clean encapsulate_field.py +class EncapsulateField +EncapsulateField.__init__ +EncapsulateField.get_changes +EncapsulateField.get_field_name +EncapsulateField._is_an_attribute +EncapsulateField._get_defining_class_scope +EncapsulateField._get_defining_scope +EncapsulateField._change_holding_module + +class GetterSetterRenameInModule +GetterSetterRenameInModule.__init__ +GetterSetterRenameInModule.get_changed_module + +class _FindChangesForModule +_FindChangesForModule.__init__ +_FindChangesForModule.get_changed_module +_FindChangesForModule._manage_writes +_FindChangesForModule._is_assigned_in_a_tuple_assignment +_FindChangesForModule.source +_FindChangesForModule.lines +_FindChangesForModule.worder + + +@clean extract.py +class _ExtractRefactoring +_ExtractRefactoring.__init__ +_ExtractRefactoring._fix_start +_ExtractRefactoring._fix_end +_ExtractRefactoring.get_changes +_ExtractRefactoring._get_kind_from_name +_ExtractRefactoring._validate_kind_prefix +_ExtractRefactoring._get_kind + +class ExtractMethod +ExtractMethod._get_kind + +class ExtractVariable +ExtractVariable.__init__ +ExtractVariable.kind = "variable" +ExtractVariable._get_kind + +class _ExtractInfo +_ExtractInfo.__init__ +_ExtractInfo._init_parts +_ExtractInfo.logical_lines +_ExtractInfo._init_scope +_ExtractInfo._get_scope_region +_ExtractInfo._choose_closest_line_end +_ExtractInfo.one_line +_ExtractInfo.global_ +_ExtractInfo.method +_ExtractInfo.indents +_ExtractInfo.scope_indents +_ExtractInfo.extracted +_ExtractInfo._cached_parsed_extraced = None +_ExtractInfo._parsed_extracted +_ExtractInfo._returned = None +_ExtractInfo.returned +_ExtractInfo._returning_named_expr = None +_ExtractInfo.returning_named_expr +_ExtractInfo._returning_generator = None +_ExtractInfo.returning_generator_exp + +class _ExtractCollector +_ExtractCollector.__init__ + +class _ExtractPerformer +_ExtractPerformer.__init__ +_ExtractPerformer.extract +_ExtractPerformer._replace_occurrences +_ExtractPerformer._collect_info +_ExtractPerformer._find_matches +_ExtractPerformer._is_assignment +_ExtractPerformer._where_to_search +_ExtractPerformer._find_definition_location +_ExtractPerformer._find_definition + +class _DefinitionLocationFinder +_DefinitionLocationFinder.__init__ +_DefinitionLocationFinder.find_lineno +_DefinitionLocationFinder._find_toplevel +_DefinitionLocationFinder.find_indents +_DefinitionLocationFinder._get_before_line +_DefinitionLocationFinder._get_after_scope + +class _ExceptionalConditionChecker +_ExceptionalConditionChecker.__call__ +_ExceptionalConditionChecker.base_conditions +_ExceptionalConditionChecker.one_line_conditions +_ExceptionalConditionChecker.multi_line_conditions +_ExceptionalConditionChecker._is_region_on_a_word +_ExceptionalConditionChecker._is_on_a_word + +class _ExtractMethodParts +_ExtractMethodParts.__init__ +_ExtractMethodParts._get_kind_by_scope +_ExtractMethodParts._check_constraints +_ExtractMethodParts._extacting_from_staticmethod +_ExtractMethodParts._extracting_from_classmethod +_ExtractMethodParts.get_definition +_ExtractMethodParts.get_replacement_pattern +_ExtractMethodParts.get_body_pattern +_ExtractMethodParts._get_body +_ExtractMethodParts._find_temps +_ExtractMethodParts.get_checks +_ExtractMethodParts._create_info_collector +_ExtractMethodParts._get_function_definition +_ExtractMethodParts._append_decorators +_ExtractMethodParts._extracting_classmethod +_ExtractMethodParts._extracting_staticmethod +_ExtractMethodParts._get_function_signature +_ExtractMethodParts._extracting_method +_ExtractMethodParts._get_self_name +_ExtractMethodParts._get_scope_self_name +_ExtractMethodParts._get_function_call +_ExtractMethodParts._get_function_call_prefix +_ExtractMethodParts._get_comma_form +_ExtractMethodParts._get_call +_ExtractMethodParts._find_function_arguments +_ExtractMethodParts._find_function_returns +_ExtractMethodParts._get_unindented_function_body +_ExtractMethodParts._get_multiline_function_body +_ExtractMethodParts._get_single_expression_function_body +_ExtractMethodParts._insert_globals +_ExtractMethodParts._get_globals_in_body + +class _ExtractVariableParts +_ExtractVariableParts.__init__ +_ExtractVariableParts.get_definition +_ExtractVariableParts.get_body_pattern +_ExtractVariableParts.get_replacement_pattern +_ExtractVariableParts.get_checks + +class _FunctionInformationCollector +_FunctionInformationCollector.__init__ +_FunctionInformationCollector._read_variable +_FunctionInformationCollector._written_variable +_FunctionInformationCollector._FunctionDef +_FunctionInformationCollector._Global +_FunctionInformationCollector._AsyncFunctionDef +_FunctionInformationCollector._Name +_FunctionInformationCollector._MatchAs +_FunctionInformationCollector._Assign +_FunctionInformationCollector._AugAssign +_FunctionInformationCollector._ClassDef +_FunctionInformationCollector._ListComp +_FunctionInformationCollector._GeneratorExp +_FunctionInformationCollector._SetComp +_FunctionInformationCollector._DictComp +_FunctionInformationCollector._comp_exp +_FunctionInformationCollector._flatten_nested_tuple_of_names +_FunctionInformationCollector._If +_FunctionInformationCollector._While +_FunctionInformationCollector._For +_FunctionInformationCollector._handle_conditional_node +_FunctionInformationCollector._handle_conditional_context +_FunctionInformationCollector._handle_loop_context + +_get_argnames +class _VariableReadsAndWritesFinder +_VariableReadsAndWritesFinder.__init__ +_VariableReadsAndWritesFinder._Name +_VariableReadsAndWritesFinder._FunctionDef +_VariableReadsAndWritesFinder._Class +_VariableReadsAndWritesFinder.find_reads_and_writes +_VariableReadsAndWritesFinder.find_reads_for_one_liners + +class _BaseErrorFinder +_BaseErrorFinder.has_errors + +class _UnmatchedBreakOrContinueFinder +_UnmatchedBreakOrContinueFinder.__init__ +_UnmatchedBreakOrContinueFinder._For +_UnmatchedBreakOrContinueFinder._While +_UnmatchedBreakOrContinueFinder.loop_encountered +_UnmatchedBreakOrContinueFinder._Break +_UnmatchedBreakOrContinueFinder._Continue +_UnmatchedBreakOrContinueFinder.check_loop +_UnmatchedBreakOrContinueFinder._FunctionDef +_UnmatchedBreakOrContinueFinder._ClassDef + +class _AsyncStatementFinder +_AsyncStatementFinder.__init__ +_AsyncStatementFinder._AsyncFor +_AsyncStatementFinder._AsyncWith +_AsyncStatementFinder._FunctionDef +_AsyncStatementFinder._ClassDef + +class _GlobalFinder +_get_function_kind +_parse_text +_join_lines +_get_single_expression_body + +@clean functionutils.py +class DefinitionInfo +DefinitionInfo.__init__ +DefinitionInfo.to_string +DefinitionInfo.arguments_to_string +DefinitionInfo._read +DefinitionInfo.read + +class CallInfo +CallInfo.__init__ +CallInfo.to_string +CallInfo.read +CallInfo._is_method_call +CallInfo._is_class +CallInfo._is_method +CallInfo._is_classmethod + +class ArgumentMapping +ArgumentMapping.__init__ +ArgumentMapping.to_call_info + +class _FunctionParser +_FunctionParser.__init__ +_FunctionParser.get_parameters +_FunctionParser.get_instance +_FunctionParser.get_function_name +_FunctionParser.is_called_as_a_method + + +@clean inline.py +unique_prefix +create_inline +class _Inliner +_Inliner.__init__ +_Inliner.get_changes +_Inliner.get_kind + +class InlineMethod +InlineMethod.__init__ +InlineMethod._init_imports +InlineMethod._get_scope_range +InlineMethod.get_changes +InlineMethod._get_removed_range +InlineMethod._defining_file_changes +InlineMethod._get_method_replacement +InlineMethod._is_the_last_method_of_a_class +InlineMethod.get_kind + +class InlineVariable +InlineVariable.__init__ +InlineVariable._check_exceptional_conditions +InlineVariable.get_changes +InlineVariable._change_main_module +InlineVariable._init_imports +InlineVariable._change_module +InlineVariable.check_aim + +InlineVariable.get_kind + +class InlineParameter +InlineParameter.__init__ +InlineParameter._function_location +InlineParameter.get_changes +InlineParameter.get_kind + +_join_lines +class _DefinitionGenerator +_DefinitionGenerator.__init__ +_DefinitionGenerator._get_definition_info +_DefinitionGenerator._get_definition_params +_DefinitionGenerator.get_function_name +_DefinitionGenerator.get_definition +_DefinitionGenerator._calculate_header +_DefinitionGenerator._calculate_definition +_DefinitionGenerator._replace_returns_with +_DefinitionGenerator._check_nothing_after_return +_DefinitionGenerator._get_return_pattern +_DefinitionGenerator.named_pattern + + +class _InlineFunctionCallsForModuleHandle +_InlineFunctionCallsForModuleHandle.__init__ +_InlineFunctionCallsForModuleHandle.occurred_inside_skip +_InlineFunctionCallsForModuleHandle.occurred_outside_skip +_InlineFunctionCallsForModuleHandle._find_end_parens +_InlineFunctionCallsForModuleHandle.pymodule +_InlineFunctionCallsForModuleHandle.source +_InlineFunctionCallsForModuleHandle.lines + +_inline_variable +_getvardef +_assigned_lineno +_add_imports +_get_pyname +_remove_from + +@clean introduce_factory.py +class IntroduceFactory +IntroduceFactory.__init__ +IntroduceFactory.get_changes +IntroduceFactory.get_name +IntroduceFactory._change_module +IntroduceFactory._change_resource +IntroduceFactory._get_insertion_offset +IntroduceFactory._get_factory_method +IntroduceFactory._get_scope_indents +IntroduceFactory._new_function_name +IntroduceFactory._rename_occurrences + + +@clean introduce_parameter.py +class IntroduceParameter +IntroduceParameter.__init__ +IntroduceParameter._get_primary +IntroduceParameter._get_name_and_pyname +IntroduceParameter.get_changes +IntroduceParameter._get_header_offsets +IntroduceParameter._change_function_occurrences + + +@clean localtofield.py +class LocalToField +LocalToField.__init__ +LocalToField.get_changes +LocalToField._check_redefinition +LocalToField._get_field_name +LocalToField._is_a_method_local + + +@clean method_object.py +class MethodObject +MethodObject.__init__ +MethodObject.get_new_class +MethodObject.get_changes +MethodObject._get_class_insertion_point +MethodObject._get_body +MethodObject._get_init +MethodObject._get_parameter_names + + +@clean move.py +create_move +class MoveMethod +MoveMethod.__init__ +MoveMethod.get_changes +MoveMethod.get_method_name +MoveMethod._get_used_imports +MoveMethod._get_changes_made_by_old_class +MoveMethod._get_scope_indents +MoveMethod._get_changes_made_by_new_class +MoveMethod.get_new_method +MoveMethod._get_unchanged_body +MoveMethod._get_body +MoveMethod._get_self_name +MoveMethod._get_new_header +MoveMethod._get_passed_arguments_string +MoveMethod._is_host_used + +class MoveGlobal +MoveGlobal.__init__ +MoveGlobal._import_filter +MoveGlobal._check_exceptional_conditions +MoveGlobal._raise_refactoring_error +MoveGlobal._is_global +MoveGlobal._is_variable +MoveGlobal.get_changes +MoveGlobal._calculate_changes +MoveGlobal._source_module_changes +MoveGlobal._new_modname +MoveGlobal._dest_module_changes +MoveGlobal._get_moving_element_with_imports +MoveGlobal._get_module_with_imports +MoveGlobal._get_moving_element +MoveGlobal._get_moving_region +MoveGlobal._add_imports2 + +class MoveModule +MoveModule.__init__ +MoveModule.get_changes +MoveModule._calculate_changes +MoveModule._new_modname +MoveModule._new_import +MoveModule._change_moving_module +MoveModule._change_occurrences_in_module +MoveModule._change_import_statements +MoveModule._handle_moving_in_from_import_stmt + +class _ChangeMoveOccurrencesHandle +_ChangeMoveOccurrencesHandle.__init__ +_ChangeMoveOccurrencesHandle.occurred_inside_skip +_ChangeMoveOccurrencesHandle.occurred_outside_skip + +class _MoveTools +_MoveTools.__init__ +_MoveTools.remove_old_imports +_MoveTools.__call__ + +_MoveTools.rename_in_module +_MoveTools.occurs_in_module +_MoveTools._create_finder +_MoveTools.new_pymodule +_MoveTools.new_source +_MoveTools.add_imports + +_add_imports_to_module +moving_code_with_imports +class ModuleSkipRenamerHandle +class ModuleSkipRenamer +ModuleSkipRenamer.__init__ +ModuleSkipRenamer.get_changed_module + + +@clean multiproject.py +class MultiProjectRefactoring +MultiProjectRefactoring.__init__ +MultiProjectRefactoring.__call__ + +class _MultiRefactoring +_MultiRefactoring.__init__ +_MultiRefactoring.get_all_changes +_MultiRefactoring.__getattr__ +_MultiRefactoring._resources_for_args +_MultiRefactoring._change_project_resource +_MultiRefactoring.project +_MultiRefactoring.main_refactoring + +perform + +@clean occurrences.py +class Finder +Finder.__init__ +Finder.find_occurrences + +create_finder +class Occurrence +Occurrence.__init__ +Occurrence.get_word_range +Occurrence.get_primary_range +Occurrence.get_pyname +Occurrence.get_primary_and_pyname +Occurrence.is_in_import_statement +Occurrence.is_called +Occurrence.is_defined +Occurrence.is_a_fixed_primary +Occurrence.is_written +Occurrence.is_unsure +Occurrence.is_function_keyword_parameter +Occurrence.lineno + +same_pyname +unsure_pyname +class PyNameFilter +PyNameFilter.__init__ +PyNameFilter.__call__ + +class InHierarchyFilter +InHierarchyFilter.__init__ +InHierarchyFilter.__call__ +InHierarchyFilter._get_containing_class +InHierarchyFilter._get_root_classes + +class UnsureFilter +UnsureFilter.__init__ +UnsureFilter.__call__ + +class NoImportsFilter +class CallsFilter +class NoKeywordsFilter +class _TextualFinder +_TextualFinder.__init__ +_TextualFinder.find_offsets +_TextualFinder._re_search +_TextualFinder._search_in_f_string +_TextualFinder._normal_search +_TextualFinder._is_id_char +_TextualFinder._fast_file_query +_TextualFinder._get_source +_TextualFinder._get_occurrence_pattern +_TextualFinder.any + +class _OccurrenceToolsCreator +_OccurrenceToolsCreator.__init__ +_OccurrenceToolsCreator.name_finder +_OccurrenceToolsCreator.source_code +_OccurrenceToolsCreator.word_finder +_OccurrenceToolsCreator.resource +_OccurrenceToolsCreator.pymodule + + +@clean patchedast.py +get_patched_ast +patch_ast +node_region +write_ast +class MismatchedTokenError +class _PatchingASTWalker +_PatchingASTWalker.__init__ +_PatchingASTWalker.Number = object() +_PatchingASTWalker.__call__ +_PatchingASTWalker._handle (changed) +_PatchingASTWalker._handle_parens +_PatchingASTWalker._eat_surrounding_parens +_PatchingASTWalker._count_needed_parens +_PatchingASTWalker._find_next_statement_start +_PatchingASTWalker._join +_PatchingASTWalker._flatten_keywords +_PatchingASTWalker._child_nodes +_PatchingASTWalker._operators = { +_PatchingASTWalker._get_op +_PatchingASTWalker._Attribute +_PatchingASTWalker._Assert +_PatchingASTWalker._Assign +_PatchingASTWalker._AugAssign +_PatchingASTWalker._AnnAssign +_PatchingASTWalker._Repr +_PatchingASTWalker._BinOp +_PatchingASTWalker._BoolOp +_PatchingASTWalker._Break +_PatchingASTWalker._Call (changed) +_PatchingASTWalker._ClassDef +_PatchingASTWalker._Compare +_PatchingASTWalker._Delete +_PatchingASTWalker._Constant +_PatchingASTWalker._Num +_PatchingASTWalker._Str +_PatchingASTWalker._Bytes +_PatchingASTWalker._JoinedStr +_PatchingASTWalker._FormattedValue +_PatchingASTWalker._Continue +_PatchingASTWalker._Dict +_PatchingASTWalker._Ellipsis +_PatchingASTWalker._Expr +_PatchingASTWalker._NamedExpr +_PatchingASTWalker._Exec +_PatchingASTWalker._ExtSlice +_PatchingASTWalker._handle_for_loop_node +_PatchingASTWalker._For +_PatchingASTWalker._AsyncFor +_PatchingASTWalker._ImportFrom +_PatchingASTWalker._alias +_PatchingASTWalker._handle_function_def_node +_PatchingASTWalker._FunctionDef +_PatchingASTWalker._AsyncFunctionDef +_PatchingASTWalker._arguments +_PatchingASTWalker._add_args_to_children +_PatchingASTWalker._add_tuple_parameter +_PatchingASTWalker._GeneratorExp +_PatchingASTWalker._comprehension +_PatchingASTWalker._Global +_PatchingASTWalker._If +_PatchingASTWalker._is_elif +_PatchingASTWalker._IfExp +_PatchingASTWalker._Import +_PatchingASTWalker._keyword +_PatchingASTWalker._Lambda +_PatchingASTWalker._List +_PatchingASTWalker._ListComp +_PatchingASTWalker._Set +_PatchingASTWalker._SetComp +_PatchingASTWalker._DictComp +_PatchingASTWalker._Module +_PatchingASTWalker._Name +_PatchingASTWalker._NameConstant +_PatchingASTWalker._arg +_PatchingASTWalker._Pass +_PatchingASTWalker._Print +_PatchingASTWalker._Raise +_PatchingASTWalker._Return +_PatchingASTWalker._Sliceobj +_PatchingASTWalker._Index +_PatchingASTWalker._Subscript +_PatchingASTWalker._Slice +_PatchingASTWalker._TryFinally +_PatchingASTWalker._TryExcept +_PatchingASTWalker._Try +_PatchingASTWalker._ExceptHandler +_PatchingASTWalker._excepthandler +_PatchingASTWalker._Tuple +_PatchingASTWalker._UnaryOp +_PatchingASTWalker._Await +_PatchingASTWalker._Yield +_PatchingASTWalker._YieldFrom +_PatchingASTWalker._While +_PatchingASTWalker._handle_with_node +_PatchingASTWalker._With +_PatchingASTWalker._AsyncWith +_PatchingASTWalker._Starred +_PatchingASTWalker._Match +_PatchingASTWalker._match_case +_PatchingASTWalker._MatchAs +_PatchingASTWalker._MatchClass +_PatchingASTWalker._MatchValue + +class _Source +_Source.__init__ +_Source.consume (changed) +_Source.consume_joined_string +_Source.consume_string +_Source.consume_number +_Source.consume_empty_tuple +_Source.consume_not_equal +_Source.consume_except_as_or_semicolon +_Source.consume_exec_open_paren_or_space +_Source.consume_exec_in_or_comma +_Source.consume_exec_close_paren_or_space +_Source.consume_with_or_comma_context_manager +_Source._good_token +_Source._skip_comment +_Source._get_location +_Source._consume_pattern +_Source.till_token +_Source.rfind_token +_Source.from_offset +_Source.find_backwards +_Source.__getitem__ +_Source.__getslice__ +_Source._get_number_pattern + + +@clean rename.py +class Rename +Rename.__init__ +Rename.get_old_name +Rename.get_changes +Rename.unsure_func + +Rename._is_allowed_to_move +Rename._is_renaming_a_module +Rename.is_method +Rename._rename_module + +class ChangeOccurrences +ChangeOccurrences.__init__ +ChangeOccurrences.get_old_name +ChangeOccurrences._get_scope_offset +ChangeOccurrences.get_changes + +rename_in_module +_is_local + +@clean restructure.py +class Restructure +Restructure.__init__ +Restructure.get_changes +Restructure._compute_changes +Restructure._add_imports +Restructure._get_import_infos +Restructure.make_checks +Restructure._evaluate +class _BuiltinsStub + + +replace +class _ChangeComputer +_ChangeComputer.__init__ +_ChangeComputer.get_changed +_ChangeComputer._is_expression +_ChangeComputer._get_matched_text +_ChangeComputer._get_node_text +_ChangeComputer._auto_indent +_ChangeComputer._get_nearest_roots + + +@clean similarfinder.py +class BadNameInCheckError +class SimilarFinder +SimilarFinder.__init__ +SimilarFinder.get_matches +SimilarFinder.get_match_regions +SimilarFinder._does_match + +class RawSimilarFinder +RawSimilarFinder.__init__ +RawSimilarFinder._simple_does_match +RawSimilarFinder._init_using_ast +RawSimilarFinder.get_matches +RawSimilarFinder._get_matched_asts +RawSimilarFinder._create_pattern +RawSimilarFinder._replace_wildcards + +class _ASTMatcher +_ASTMatcher.__init__ +_ASTMatcher.find_matches +_ASTMatcher._check_node +_ASTMatcher._check_expression +_ASTMatcher._check_statements +_ASTMatcher.__check_stmt_list +_ASTMatcher._match_nodes +_ASTMatcher._get_children +_ASTMatcher._match_stmts +_ASTMatcher._match_wildcard + +class Match +Match.__init__ +Match.get_region +Match.get_ast + +class ExpressionMatch +class StatementMatch +class CodeTemplate +CodeTemplate.__init__ +CodeTemplate._find_names +CodeTemplate.get_names +CodeTemplate.substitute +CodeTemplate._match_pattern = None +CodeTemplate._get_pattern + +class _RopeVariable +_RopeVariable.get_var +_RopeVariable.is_var +_RopeVariable.get_base +_RopeVariable._get_normal +_RopeVariable._get_any +_RopeVariable._is_normal +_RopeVariable._is_var + +make_pattern +does_match + +_pydefined_to_str + +@clean sourceutils.py +get_indents +find_minimum_indents +indent_lines +fix_indentation +add_methods +get_body +get_body_region +get_indent + +@clean suites.py +find_visible +find_visible_for_suite +valid + +ast_suite_tree +class Suite +Suite.__init__ +Suite.get_start +Suite.get_children +Suite.local_start +Suite.local_end +Suite.find_suite +Suite._get_level + +class _SuiteWalker +_SuiteWalker.__init__ +_SuiteWalker._If +_SuiteWalker._For +_SuiteWalker._While +_SuiteWalker._With +_SuiteWalker._AsyncWith +_SuiteWalker._Match +_SuiteWalker._TryFinally +_SuiteWalker._Try +_SuiteWalker._TryExcept +_SuiteWalker._add_if_like_node +_SuiteWalker._FunctionDef +_SuiteWalker._AsyncFunctionDef +_SuiteWalker._ClassDef + + +@clean topackage.py +class ModuleToPackage +ModuleToPackage.__init__ +ModuleToPackage.get_changes +ModuleToPackage._transform_relatives_to_absolute + + +@clean usefunction.py +class UseFunction +UseFunction.__init__ +UseFunction._check_returns +UseFunction.get_changes +UseFunction.get_function_name +UseFunction._restructure +UseFunction._find_temps +UseFunction._module_name +UseFunction._make_pattern +UseFunction._get_body +UseFunction._make_goal +UseFunction._does_return +UseFunction._is_expression + +find_temps +_returns_last +_namedexpr_last +_yield_count +_return_count +_named_expr_count +class _ReturnOrYieldFinder +_ReturnOrYieldFinder.__init__ +_ReturnOrYieldFinder._Return +_ReturnOrYieldFinder._NamedExpr +_ReturnOrYieldFinder._Yield +_ReturnOrYieldFinder._FunctionDef +_ReturnOrYieldFinder._ClassDef +_ReturnOrYieldFinder.start_walking + + +@clean wildcards.py +class Wildcard +class Suspect +class DefaultWildcard +DefaultWildcard.__init__ +DefaultWildcard.get_name +DefaultWildcard.matches +DefaultWildcard._check_object +DefaultWildcard._check_exact + +parse_arg +class _CheckObject +_CheckObject.__init__ +_CheckObject.__call__ +_CheckObject._get_super_classes +_CheckObject._same_pyobject +_CheckObject._same_pyname +_CheckObject._unsure_pyname +_CheckObject._split_name +_CheckObject._evaluate_node +_CheckObject._evaluate +class _BuiltinsStub + + + +@path importutils +@clean actions.py +class ImportInfoVisitor +ImportInfoVisitor.dispatch +ImportInfoVisitor.visitEmptyImport +ImportInfoVisitor.visitNormalImport +ImportInfoVisitor.visitFromImport + +class RelativeToAbsoluteVisitor +RelativeToAbsoluteVisitor.__init__ +RelativeToAbsoluteVisitor.visitNormalImport +RelativeToAbsoluteVisitor._get_relative_to_absolute_list +RelativeToAbsoluteVisitor.visitFromImport + +class FilteringVisitor +FilteringVisitor.__init__ +FilteringVisitor._transform_can_select +FilteringVisitor.visitNormalImport +FilteringVisitor.visitFromImport + +class RemovingVisitor +RemovingVisitor.__init__ +RemovingVisitor.dispatch + +class AddingVisitor +AddingVisitor.__init__ +AddingVisitor.dispatch +AddingVisitor.visitNormalImport +AddingVisitor.visitFromImport + +class ExpandStarsVisitor +ExpandStarsVisitor.__init__ +ExpandStarsVisitor.visitNormalImport +ExpandStarsVisitor.visitFromImport + +class SelfImportVisitor +SelfImportVisitor.__init__ +SelfImportVisitor.visitNormalImport +SelfImportVisitor.visitFromImport +SelfImportVisitor._importing_names_from_self + +class SortingVisitor +SortingVisitor.__init__ +SortingVisitor.visitNormalImport +SortingVisitor.visitFromImport +SortingVisitor._check_imported_resource + +class LongImportVisitor +LongImportVisitor.__init__ +LongImportVisitor.visitNormalImport +LongImportVisitor._is_long + +class RemovePyNameVisitor +RemovePyNameVisitor.__init__ +RemovePyNameVisitor.visitFromImport +RemovePyNameVisitor.dispatch + +_is_future + +@clean importinfo.py +class ImportStatement +ImportStatement.__init__ +ImportStatement._get_import_info +ImportStatement._set_import_info +ImportStatement.import_info = property(_get_import_info, _set_import_info) +ImportStatement.get_import_statement +ImportStatement.empty_import +ImportStatement.move +ImportStatement.get_old_location +ImportStatement.get_new_start +ImportStatement.is_changed +ImportStatement.accept + +class ImportInfo +ImportInfo.get_imported_primaries +ImportInfo.get_imported_names +ImportInfo.get_import_statement +ImportInfo.is_empty +ImportInfo.__hash__ +ImportInfo._are_name_and_alias_lists_equal +ImportInfo.__eq__ +ImportInfo.__ne__ +ImportInfo.get_empty_import + +class NormalImport +NormalImport.__init__ +NormalImport.get_imported_primaries +NormalImport.get_import_statement +NormalImport.is_empty + +class FromImport +FromImport.__init__ +FromImport.get_imported_primaries +FromImport.get_imported_resource +FromImport.get_imported_module +FromImport.get_import_statement +FromImport.is_empty +FromImport.is_star_import + +class EmptyImport +EmptyImport.is_empty +EmptyImport.get_imported_primaries + +class ImportContext + +@clean module_imports.py +class ModuleImports +ModuleImports.__init__ +ModuleImports.imports +ModuleImports._get_unbound_names +ModuleImports._get_all_star_list +ModuleImports.remove_unused_imports +ModuleImports.get_used_imports +ModuleImports.get_changed_source +ModuleImports._get_import_location +ModuleImports._get_location +ModuleImports._remove_imports +ModuleImports._rewrite_imports +ModuleImports._first_non_blank_line +ModuleImports.add_import +ModuleImports._get_new_import_blanks +ModuleImports._get_new_import_lineno +ModuleImports.filter_names +ModuleImports.expand_stars +ModuleImports.remove_duplicates +ModuleImports.force_single_imports +ModuleImports.get_relative_to_absolute_list +ModuleImports.get_self_import_fix_and_rename_list +ModuleImports._current_folder +ModuleImports.sort_imports +ModuleImports._first_import_line +ModuleImports._get_import_name +ModuleImports._key_imports +ModuleImports._move_imports +ModuleImports.handle_long_imports +ModuleImports.remove_pyname + +get_first_decorator_or_function_start_line +_count_blank_lines +class _OneTimeSelector +_OneTimeSelector.__init__ +_OneTimeSelector.__call__ +_OneTimeSelector._get_dotted_tokens +_OneTimeSelector._can_name_be_added + +class _UnboundNameFinder +_UnboundNameFinder.__init__ +_UnboundNameFinder._visit_child_scope +_UnboundNameFinder._FunctionDef +_UnboundNameFinder._ClassDef +_UnboundNameFinder._Name +_UnboundNameFinder._Attribute +_UnboundNameFinder._get_root +_UnboundNameFinder.is_bound +_UnboundNameFinder.add_unbound + +class _GlobalUnboundNameFinder +_GlobalUnboundNameFinder.__init__ +_GlobalUnboundNameFinder._get_root +_GlobalUnboundNameFinder.is_bound +_GlobalUnboundNameFinder.add_unbound +_GlobalUnboundNameFinder._is_node_interesting + +class _LocalUnboundNameFinder +_LocalUnboundNameFinder.__init__ +_LocalUnboundNameFinder._get_root +_LocalUnboundNameFinder.is_bound +_LocalUnboundNameFinder.add_unbound + +class _GlobalImportFinder +_GlobalImportFinder.__init__ +_GlobalImportFinder.visit_import +_GlobalImportFinder._count_empty_lines_before +_GlobalImportFinder._count_empty_lines_after +_GlobalImportFinder.get_separating_line_count +_GlobalImportFinder._get_text +_GlobalImportFinder.visit_from +_GlobalImportFinder._get_names +_GlobalImportFinder.find_import_statements + + +@clean __init__.py +class ImportOrganizer +ImportOrganizer.__init__ +ImportOrganizer.organize_imports +ImportOrganizer.expand_star_imports +ImportOrganizer.froms_to_imports +ImportOrganizer.relatives_to_absolutes +ImportOrganizer.handle_long_imports +ImportOrganizer._perform_command_on_import_tools +ImportOrganizer._line_filter + +class ImportTools +ImportTools.__init__ +ImportTools.get_import +ImportTools.get_from_import +ImportTools.module_imports +ImportTools.froms_to_imports +ImportTools.expand_stars +ImportTools._from_to_normal +ImportTools._clean_up_imports +ImportTools.relatives_to_absolutes +ImportTools._is_transformable_to_normal +ImportTools.organize_imports +ImportTools._remove_self_imports +ImportTools._rename_in_module +ImportTools.sort_imports +ImportTools.handle_long_imports + +get_imports +get_module_imports +add_import + + + + +@path ropetest +@clean advanced_oi_test.py +class DynamicOITest +DynamicOITest.setUp +DynamicOITest.tearDown +DynamicOITest.test_simple_dti +DynamicOITest.test_module_dti +DynamicOITest.test_class_from_another_module_dti +DynamicOITest.test_class_dti +DynamicOITest.test_instance_dti +DynamicOITest.test_method_dti +DynamicOITest.test_function_argument_dti +DynamicOITest.test_classes_with_the_same_name +DynamicOITest.test_nested_classes +DynamicOITest.test_function_argument_dti2 +DynamicOITest.test_dti_and_concluded_data_invalidation +DynamicOITest.test_list_objects_and_dynamicoi +DynamicOITest.test_for_loops_and_dynamicoi +DynamicOITest.test_dict_objects_and_dynamicoi +DynamicOITest.test_dict_keys_and_dynamicoi +DynamicOITest.test_dict_keys_and_dynamicoi2 +DynamicOITest.test_strs_and_dynamicoi +DynamicOITest.test_textual_transformations +DynamicOITest.test_arguments_with_keywords +DynamicOITest.test_a_function_with_different_returns +DynamicOITest.test_a_function_with_different_returns2 +DynamicOITest.test_ignoring_star_args +DynamicOITest.test_ignoring_double_star_args +DynamicOITest.test_invalidating_data_after_changing +DynamicOITest.test_invalidating_data_after_moving + +class NewStaticOITest +NewStaticOITest.setUp +NewStaticOITest.tearDown +NewStaticOITest.test_static_oi_for_simple_function_calls +NewStaticOITest.test_static_oi_not_failing_when_callin_callables +NewStaticOITest.test_static_oi_for_nested_calls +NewStaticOITest.test_static_oi_class_methods +NewStaticOITest.test_static_oi_preventing_soi_maximum_recursion_exceptions +NewStaticOITest.test_static_oi_for_infer_return_typs_from_funcs_based_on_params +NewStaticOITest.test_a_function_with_different_returns +NewStaticOITest.test_not_reporting_out_of_date_information +NewStaticOITest.test_invalidating_concluded_data_in_a_function +NewStaticOITest.test_handling_generator_functions_for_strs +NewStaticOITest.xxx_test_handl_generator_functions_when_unknown_type_is_yielded +NewStaticOITest.test_static_oi_for_lists_depending_on_append_function +NewStaticOITest.test_static_oi_for_lists_per_object_for_get_item +NewStaticOITest.test_static_oi_for_lists_per_object_for_fields +NewStaticOITest.test_static_oi_for_lists_per_object_for_set_item +NewStaticOITest.test_static_oi_for_lists_per_object_for_extending_lists +NewStaticOITest.test_static_oi_for_lists_per_object_for_iters +NewStaticOITest.test_static_oi_for_dicts_depending_on_append_function +NewStaticOITest.test_static_oi_for_dicts_depending_on_for_loops +NewStaticOITest.test_static_oi_for_dicts_depending_on_update +NewStaticOITest.test_static_oi_for_dicts_depending_on_update_on_seqs +NewStaticOITest.test_static_oi_for_sets_per_object_for_set_item +NewStaticOITest.test_properties_and_calling_get_property +NewStaticOITest.test_soi_on_constructors +NewStaticOITest.test_soi_on_literal_assignment +NewStaticOITest.test_soi_on_typed_assignment +NewStaticOITest.test_not_saving_unknown_function_returns +NewStaticOITest.test_using_the_best_callinfo +NewStaticOITest.test_call_function_and_parameters +NewStaticOITest.test_report_change_in_libutils +NewStaticOITest.test_report_libutils_and_analyze_all_modules +NewStaticOITest.test_validation_problems_for_objectdb_retrievals +NewStaticOITest.test_validation_problems_for_changing_builtin_types +NewStaticOITest.test_always_returning_containing_class_for_selfs +NewStaticOITest.test_following_function_calls_when_asked_to +NewStaticOITest.test_set_comprehension + + +@clean builtinstest.py +class BuiltinTypesTest +BuiltinTypesTest.setUp +BuiltinTypesTest.tearDown +BuiltinTypesTest.test_simple_case +BuiltinTypesTest.test_holding_type_information +BuiltinTypesTest.test_get_items +BuiltinTypesTest.test_get_items_for_lists +BuiltinTypesTest.test_get_items_from_slices +BuiltinTypesTest.test_simple_for_loops +BuiltinTypesTest.test_definition_location_for_loop_variables +BuiltinTypesTest.test_simple_case_for_dicts +BuiltinTypesTest.test_get_item_for_dicts +BuiltinTypesTest.test_dict_function_parent +BuiltinTypesTest.test_popping_dicts +BuiltinTypesTest.test_getting_keys_from_dicts +BuiltinTypesTest.test_getting_values_from_dicts +BuiltinTypesTest.test_getting_iterkeys_from_dicts +BuiltinTypesTest.test_getting_itervalues_from_dicts +BuiltinTypesTest.test_using_copy_for_dicts +BuiltinTypesTest.test_tuple_assignments_for_items +BuiltinTypesTest.test_tuple_assignment_for_lists +BuiltinTypesTest.test_tuple_assignments_for_iteritems_in_fors +BuiltinTypesTest.test_simple_tuple_assignments +BuiltinTypesTest.test_overriding_builtin_names +BuiltinTypesTest.test_simple_builtin_scope_test +BuiltinTypesTest.test_simple_sets +BuiltinTypesTest.test_making_lists_using_the_passed_argument_to_init +BuiltinTypesTest.test_making_tuples_using_the_passed_argument_to_init +BuiltinTypesTest.test_making_sets_using_the_passed_argument_to_init +BuiltinTypesTest.test_making_dicts_using_the_passed_argument_to_init +BuiltinTypesTest.test_range_builtin_function +BuiltinTypesTest.test_reversed_builtin_function +BuiltinTypesTest.test_sorted_builtin_function +BuiltinTypesTest.test_super_builtin_function +BuiltinTypesTest.test_file_builtin_type +BuiltinTypesTest.test_property_builtin_type +BuiltinTypesTest.test_lambda_functions +BuiltinTypesTest.test_lambda_function_definition +BuiltinTypesTest.test_lambdas_that_return_unknown +BuiltinTypesTest.test_builtin_zip_function +BuiltinTypesTest.test_builtin_zip_function_with_more_than_two_args +BuiltinTypesTest.test_wrong_arguments_to_zip_function +BuiltinTypesTest.test_enumerate_builtin_function +BuiltinTypesTest.test_builtin_class_get_name +BuiltinTypesTest.test_star_args_and_double_star_args +BuiltinTypesTest.test_simple_list_comprehension_test +BuiltinTypesTest.test_simple_list_generator_expression +BuiltinTypesTest.test_iter_builtin_function +BuiltinTypesTest.test_simple_int_type +BuiltinTypesTest.test_simple_float_type +BuiltinTypesTest.test_simple_float_type2 +BuiltinTypesTest.test_simple_complex_type +BuiltinTypesTest.test_handling_unaryop_on_ints +BuiltinTypesTest.test_handling_binop_on_ints +BuiltinTypesTest.test_handling_compares +BuiltinTypesTest.test_handling_boolops +BuiltinTypesTest.test_binary_or_left_value_unknown +BuiltinTypesTest.test_unknown_return_object +BuiltinTypesTest.test_abstractmethods_attribute + +class BuiltinModulesTest +BuiltinModulesTest.setUp +BuiltinModulesTest.tearDown +BuiltinModulesTest.test_simple_case +BuiltinModulesTest.test_ignored_extensions +BuiltinModulesTest.test_ignored_extensions_2 +BuiltinModulesTest.test_nonexistent_modules +BuiltinModulesTest.test_nonexistent_modules_2 +BuiltinModulesTest.test_time_in_std_mods +BuiltinModulesTest.test_timemodule_normalizes_to_time + + +@clean codeanalyzetest.py +class SourceLinesAdapterTest +SourceLinesAdapterTest.test_source_lines_simple +SourceLinesAdapterTest.test_source_lines_get_line_number +SourceLinesAdapterTest.test_source_lines_get_line_start +SourceLinesAdapterTest.test_source_lines_get_line_end +SourceLinesAdapterTest.test_source_lines_last_line_with_no_new_line + +class WordRangeFinderTest +WordRangeFinderTest._find_primary +WordRangeFinderTest._annotated_code +WordRangeFinderTest._make_offset_annotation +WordRangeFinderTest.assert_equal_annotation +WordRangeFinderTest.test_keyword_before_parens +WordRangeFinderTest.test_inside_parans +WordRangeFinderTest.test_simple_names +WordRangeFinderTest.test_function_calls +WordRangeFinderTest.test_attribute_accesses +WordRangeFinderTest.test_word_finder_on_word_beginning +WordRangeFinderTest.test_word_finder_on_primary_beginning +WordRangeFinderTest.test_word_finder_on_word_ending +WordRangeFinderTest.test_word_finder_on_primary_ending +WordRangeFinderTest.test_word_finder_on_primaries_with_dots_inside_parens +WordRangeFinderTest.test_word_finder_on_primary_like_keyword +WordRangeFinderTest.test_keyword_before_parens_no_space +WordRangeFinderTest.test_strings +WordRangeFinderTest.test_function_calls2 +WordRangeFinderTest.test_parens +WordRangeFinderTest.test_function_with_no_param +WordRangeFinderTest.test_function_with_multiple_param +WordRangeFinderTest.test_param_expressions +WordRangeFinderTest.test_string_parens +WordRangeFinderTest.test_extra_spaces +WordRangeFinderTest.test_relative_import +WordRangeFinderTest.test_functions_on_ending_parens +WordRangeFinderTest.test_splitted_statement +WordRangeFinderTest.test_empty_splitted_statement +WordRangeFinderTest.test_empty_splitted_statement2 +WordRangeFinderTest.test_empty_splitted_statement3 +WordRangeFinderTest.test_empty_splitted_statement4 +WordRangeFinderTest.test_empty_splitted_statement5 +WordRangeFinderTest.test_operators_inside_parens +WordRangeFinderTest.test_dictionaries +WordRangeFinderTest.test_following_parens +WordRangeFinderTest.test_comments_for_finding_statements +WordRangeFinderTest.test_str_in_comments_for_finding_statements +WordRangeFinderTest.test_comments_for_finding_statements2 +WordRangeFinderTest.test_comments_for_finding_statements3 +WordRangeFinderTest.test_is_import_statement +WordRangeFinderTest.test_is_import_statement_finding +WordRangeFinderTest.test_is_import_statement_finding2 +WordRangeFinderTest.test_word_parens_range +WordRangeFinderTest.test_getting_primary_before_get_index +WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line +WordRangeFinderTest.test_getting_primary_and_not_crossing_newlines +WordRangeFinderTest.xxx_test_getting_primary_cancatenating_strs +WordRangeFinderTest.test_is_a_function_being_called_with_parens_on_next_line +WordRangeFinderTest.xxx_test_triple_quotes +WordRangeFinderTest.test_triple_quotes_spanning_multiple_lines +WordRangeFinderTest.test_get_word_parens_range_and_string_literals +WordRangeFinderTest.test_is_assigned_here_for_equality_test +WordRangeFinderTest.test_is_assigned_here_for_not_equal_test +WordRangeFinderTest.xxx_test_is_assigned_here_for_tuple_assignment +WordRangeFinderTest.test_is_from_statement +WordRangeFinderTest.test_is_from_statement_module +WordRangeFinderTest.test_is_import_statement_aliased_module +WordRangeFinderTest.test_is_from_aliased +WordRangeFinderTest.test_is_from_with_from_import_and_multiline_parens +WordRangeFinderTest.test_is_from_with_from_import_and_line_breaks_in_the_middle +WordRangeFinderTest.test_is_function_keyword_parameter +WordRangeFinderTest.test_one_letter_is_function_keyword_parameter +WordRangeFinderTest.test_find_parens_start +WordRangeFinderTest.test_underlined_find_parens_start +WordRangeFinderTest.test_find_parens_start_with_multiple_entries +WordRangeFinderTest.test_find_parens_start_with_nested_parens +WordRangeFinderTest.test_find_parens_start_with_parens_in_strs +WordRangeFinderTest.test_find_parens_start_with_parens_in_strs_in_multiple_lines +WordRangeFinderTest.test_is_on_function_call_keyword +WordRangeFinderTest.test_is_on_function_keyword_partial +WordRangeFinderTest.test_get_word_range_with_fstring + +class ScopeNameFinderTest +ScopeNameFinderTest.setUp +ScopeNameFinderTest.tearDown +ScopeNameFinderTest.xxx_test_global_name_in_class_body +ScopeNameFinderTest.test_class_variable_attribute_in_class_body +ScopeNameFinderTest.test_class_variable_attribute_in_class_body2 +ScopeNameFinderTest.test_class_method_attribute_in_class_body +ScopeNameFinderTest.test_inner_class_attribute_in_class_body +ScopeNameFinderTest.test_class_method_in_class_body_but_not_indexed +ScopeNameFinderTest.test_function_but_not_indexed +ScopeNameFinderTest.test_modules_after_from_statements +ScopeNameFinderTest.test_renaming_functions_with_from_import_and_parens +ScopeNameFinderTest.test_relative_modules_after_from_statements +ScopeNameFinderTest.test_relative_modules_after_from_statements2 +ScopeNameFinderTest.test_get_pyname_at_on_language_keywords +ScopeNameFinderTest.test_one_liners +ScopeNameFinderTest.test_one_liners_with_line_breaks +ScopeNameFinderTest.test_one_liners_with_line_breaks2 +ScopeNameFinderTest.test_var_in_list_comprehension_differs_from_var_outside + +class LogicalLineFinderTest +LogicalLineFinderTest._logical_finder +LogicalLineFinderTest.test_normal_lines +LogicalLineFinderTest.test_normal_lines2 +LogicalLineFinderTest.test_implicit_continuation +LogicalLineFinderTest.test_explicit_continuation +LogicalLineFinderTest.test_explicit_continuation_comments +LogicalLineFinderTest.test_multiple_indented_ifs +LogicalLineFinderTest.test_list_comprehensions_and_fors +LogicalLineFinderTest.test_generator_expressions_and_fors +LogicalLineFinderTest.test_fors_and_block_start +LogicalLineFinderTest.test_problems_with_inner_indentations +LogicalLineFinderTest.test_problems_with_inner_indentations2 +LogicalLineFinderTest.test_logical_lines_for_else +LogicalLineFinderTest.test_logical_lines_for_lines_with_wrong_continues +LogicalLineFinderTest.test_logical_lines_for_multiline_string_with_extra_quotes_front +LogicalLineFinderTest.test_logical_lines_for_multiline_string_with_escaped_quotes +LogicalLineFinderTest.test_generating_line_starts +LogicalLineFinderTest.test_generating_line_starts2 +LogicalLineFinderTest.test_generating_line_starts3 +LogicalLineFinderTest.test_generating_line_starts_for_multi_line_statements +LogicalLineFinderTest.test_generating_line_starts_and_unmatched_deindents +LogicalLineFinderTest.test_false_triple_quoted_string + +class TokenizerLogicalLineFinderTest +class CustomLogicalLineFinderTest + +@clean doatest.py +cve_2014_3539_attacker +class DOATest +DOATest.try_CVE_2014_3539_exploit +DOATest.test_CVE_2014_3539_no_encoding +DOATest.test_CVE_2014_3539_signature_mismatch +DOATest.test_CVE_2014_3539_sanity +DOATest.test_compare_digest_compat + + +@clean historytest.py +class HistoryTest +HistoryTest.setUp +HistoryTest.tearDown +HistoryTest.test_undoing_writes +HistoryTest.test_moving_files +HistoryTest.test_moving_files_to_folders +HistoryTest.test_writing_files_that_does_not_change_contents + +class IsolatedHistoryTest +IsolatedHistoryTest.setUp +IsolatedHistoryTest.tearDown +IsolatedHistoryTest.test_simple_undo +IsolatedHistoryTest.test_tobe_undone +IsolatedHistoryTest.test_tobe_redone +IsolatedHistoryTest.test_undo_limit +IsolatedHistoryTest.test_simple_redo +IsolatedHistoryTest.test_simple_re_undo +IsolatedHistoryTest.test_multiple_undos +IsolatedHistoryTest.test_undo_list_underflow +IsolatedHistoryTest.test_redo_list_underflow +IsolatedHistoryTest.test_dropping_undone_changes +IsolatedHistoryTest.test_undoing_choosen_changes +IsolatedHistoryTest.test_undoing_choosen_changes2 +IsolatedHistoryTest.test_undoing_choosen_changes_not_undoing_others +IsolatedHistoryTest.test_undoing_writing_after_moving +IsolatedHistoryTest.test_undoing_folder_movements_for_undoing_writes_inside_it +IsolatedHistoryTest.test_undoing_changes_that_depend_on_a_dependant_change +IsolatedHistoryTest.test_undoing_writes_for_undoing_folder_movements_containing_it +IsolatedHistoryTest.test_undoing_not_available_change +IsolatedHistoryTest.test_ignoring_ignored_resources +IsolatedHistoryTest.test_get_file_undo_list_simple +IsolatedHistoryTest.test_get_file_undo_list_for_moves +IsolatedHistoryTest.xxx_test_get_file_undo_list_and_moving_its_contining_folder +IsolatedHistoryTest.test_clearing_redo_list_after_do +IsolatedHistoryTest.test_undoing_a_not_yet_performed_change +IsolatedHistoryTest.test_clearing_up_the_history +IsolatedHistoryTest.test_redoing_choosen_changes_not_undoing_others + +class SavingHistoryTest +SavingHistoryTest.setUp +SavingHistoryTest.tearDown +SavingHistoryTest.test_simple_set_saving +SavingHistoryTest.test_simple_change_content_saving +SavingHistoryTest.test_move_resource_saving +SavingHistoryTest.test_move_resource_saving_for_folders +SavingHistoryTest.test_create_file_saving +SavingHistoryTest.test_create_folder_saving +SavingHistoryTest.test_create_resource_saving +SavingHistoryTest.test_remove_resource_saving +SavingHistoryTest.test_change_set_saving +SavingHistoryTest.test_writing_and_reading_history +SavingHistoryTest.test_writing_and_reading_history2 + + +@clean objectdbtest.py +_do_for_all_dbs +class _MockValidation +_MockValidation.is_value_valid +_MockValidation.is_more_valid +_MockValidation.is_file_valid +_MockValidation.is_scope_valid + +class _MockFileListObserver +_MockFileListObserver.added +_MockFileListObserver.removed + +class ObjectDBTest +ObjectDBTest.setUp +ObjectDBTest.tearDown +ObjectDBTest.test_simple_per_name +ObjectDBTest.test_simple_per_name_does_not_exist +ObjectDBTest.test_simple_per_name_after_syncing +ObjectDBTest.test_getting_returned +ObjectDBTest.test_getting_returned_when_does_not_match +ObjectDBTest.test_getting_call_info +ObjectDBTest.test_invalid_per_name +ObjectDBTest.test_overwriting_per_name +ObjectDBTest.test_not_overwriting_with_invalid_per_name +ObjectDBTest.test_getting_invalid_returned +ObjectDBTest.test_not_overwriting_with_invalid_returned +ObjectDBTest.test_get_files +ObjectDBTest.test_validating_files +ObjectDBTest.test_validating_file_for_scopes +ObjectDBTest.test_validating_file_moved +ObjectDBTest.test_using_file_list_observer + + +@clean objectinfertest.py +class ObjectInferTest +ObjectInferTest.setUp +ObjectInferTest.tearDown +ObjectInferTest.test_simple_type_inferencing +ObjectInferTest.test_simple_type_inferencing_classes_defined_in_holding_scope +ObjectInferTest.test_simple_type_inferencing_classes_in_class_methods +ObjectInferTest.test_simple_type_inferencing_class_attributes +ObjectInferTest.test_simple_type_inferencing_for_in_class_assignments +ObjectInferTest.test_simple_type_inferencing_for_chained_assignments +ObjectInferTest.test_following_chained_assignments_avoiding_circles +ObjectInferTest.test_function_returned_object_static_type_inference1 +ObjectInferTest.test_function_returned_object_static_type_inference2 +ObjectInferTest.test_recursive_function_returned_object_static_type_inference +ObjectInferTest.test_func_returned_obj_using_call_spec_func_static_type_infer +ObjectInferTest.test_list_type_inferencing +ObjectInferTest.test_attributed_object_inference +ObjectInferTest.test_getting_property_attributes +ObjectInferTest.test_getting_property_attributes_with_method_getters +ObjectInferTest.test_lambda_functions +ObjectInferTest.test_mixing_subscript_with_tuple_assigns +ObjectInferTest.test_mixing_ass_attr_with_tuple_assignment +ObjectInferTest.test_mixing_slice_with_tuple_assigns +ObjectInferTest.test_nested_tuple_assignments +ObjectInferTest.test_empty_tuples +ObjectInferTest.test_handling_generator_functions +ObjectInferTest.test_handling_generator_functions_for_strs +ObjectInferTest.test_considering_nones_to_be_unknowns +ObjectInferTest.test_basic_list_comprehensions +ObjectInferTest.test_basic_generator_expressions +ObjectInferTest.test_list_comprehensions_and_loop_var +ObjectInferTest.test_list_comprehensions_and_multiple_loop_var +ObjectInferTest.test_list_comprehensions_and_multiple_iters +ObjectInferTest.test_we_know_the_type_of_catched_exceptions +ObjectInferTest.test_we_know_the_type_of_catched_multiple_excepts +ObjectInferTest.test_using_property_as_decorators +ObjectInferTest.test_using_property_as_decorators_and_passing_parameter + + +@clean projecttest.py +class ProjectTest +ProjectTest.setUp +ProjectTest._make_sample_project +ProjectTest.tearDown +ProjectTest.test_project_creation +ProjectTest.test_getting_project_file +ProjectTest.test_project_file_reading +ProjectTest.test_getting_not_existing_project_file +ProjectTest.test_writing_in_project_files +ProjectTest.test_creating_files +ProjectTest.test_creating_files_that_already_exist +ProjectTest.test_making_root_folder_if_it_does_not_exist +ProjectTest.test_failure_when_project_root_exists_and_is_a_file +ProjectTest.test_creating_folders +ProjectTest.test_making_folder_that_already_exists +ProjectTest.test_failing_if_creating_folder_while_file_already_exists +ProjectTest.test_creating_file_inside_folder +ProjectTest.test_failing_when_creating_file_inside_non_existent_folder +ProjectTest.test_nested_directories +ProjectTest.test_removing_files +ProjectTest.test_removing_files_invalidating_in_project_resource_pool +ProjectTest.test_removing_directories +ProjectTest.test_removing_non_existent_files +ProjectTest.test_removing_nested_files +ProjectTest.test_file_get_name +ProjectTest.test_folder_get_name +ProjectTest.test_file_get_path +ProjectTest.test_folder_get_path +ProjectTest.test_is_folder +ProjectTest.testget_children +ProjectTest.test_nonempty_get_children +ProjectTest.test_nonempty_get_children2 +ProjectTest.test_does_not_fail_for_permission_denied +ProjectTest.test_getting_files +ProjectTest.test_getting_folders +ProjectTest.test_nested_folder_get_files +ProjectTest.test_nested_folder_get_folders +ProjectTest.test_root_folder +ProjectTest.test_get_all_files +ProjectTest.test_get_all_files_after_changing +ProjectTest.test_multifile_get_all_files +ProjectTest.test_ignoring_dot_pyc_files_in_get_files +ProjectTest.test_folder_creating_files +ProjectTest.test_folder_creating_nested_files +ProjectTest.test_folder_creating_files2 +ProjectTest.test_folder_creating_nested_files2 +ProjectTest.test_folder_get_child +ProjectTest.test_folder_get_child_nested +ProjectTest.test_project_root_is_root_folder +ProjectTest.test_moving_files +ProjectTest.test_moving_folders +ProjectTest.test_moving_destination_folders +ProjectTest.test_moving_files_and_resource_objects +ProjectTest.test_file_encoding_reading +ProjectTest.test_file_encoding_writing +ProjectTest.test_using_utf8_when_writing_in_case_of_errors +ProjectTest.test_encoding_declaration_in_the_second_line +ProjectTest.test_not_an_encoding_declaration +ProjectTest.test_read_bytes +ProjectTest.test_file_with_unix_line_ending +ProjectTest.test_file_with_dos_line_ending +ProjectTest.test_file_with_mac_line_ending +ProjectTest.test_file_binary +ProjectTest.xxx_test_using_utf16 +ProjectTest.xxx_test_file_encoding_reading_for_notepad_styles +ProjectTest.test_using_project_get_file +ProjectTest.test_using_file_create +ProjectTest.test_using_folder_create +ProjectTest.test_exception_when_creating_twice +ProjectTest.test_exception_when_parent_does_not_exist +ProjectTest.test_simple_path_to_resource +ProjectTest.test_ignoring_symlinks_inside_project +ProjectTest.test_getting_empty_source_folders +ProjectTest.test_root_source_folder +ProjectTest.test_root_source_folder2 +ProjectTest.test_src_source_folder +ProjectTest.test_packages +ProjectTest.test_multi_source_folders +ProjectTest.test_multi_source_folders2 + +class ResourceObserverTest +ResourceObserverTest.setUp +ResourceObserverTest.tearDown +ResourceObserverTest.test_resource_change_observer +ResourceObserverTest.test_resource_change_observer_after_removal +ResourceObserverTest.test_resource_change_observer2 +ResourceObserverTest.test_resource_change_observer_for_folders +ResourceObserverTest.test_resource_change_observer_after_moving +ResourceObserverTest.test_revalidating_files +ResourceObserverTest.test_revalidating_files_and_no_changes2 +ResourceObserverTest.test_revalidating_folders +ResourceObserverTest.test_removing_and_adding_resources_to_filtered_observer +ResourceObserverTest.test_validation_and_changing_files +ResourceObserverTest.test_validation_and_changing_files2 +ResourceObserverTest.test_not_reporting_multiple_changes_to_folders +ResourceObserverTest._write_file +ResourceObserverTest.test_moving_and_being_interested_about_a_folder_and_a_child +ResourceObserverTest.test_contains_for_folders +ResourceObserverTest.test_validating_when_created +ResourceObserverTest.test_validating_twice_when_created +ResourceObserverTest.test_changes_and_adding_resources +ResourceObserverTest.test_validating_get_files_list +ResourceObserverTest.test_clear_observered_resources_for_filtered_observers + +class _MockChangeIndicator +_MockChangeIndicator.__init__ +_MockChangeIndicator.set_indicator +_MockChangeIndicator.get_indicator + +class _SampleObserver +_SampleObserver.__init__ +_SampleObserver.resource_changed +_SampleObserver.resource_moved +_SampleObserver.resource_created +_SampleObserver.resource_removed + +class OutOfProjectTest +OutOfProjectTest.setUp +OutOfProjectTest.tearDown +OutOfProjectTest.test_simple_out_of_project_file +OutOfProjectTest.test_simple_out_of_project_folder +OutOfProjectTest.test_using_absolute_path +OutOfProjectTest.test_folder_get_child +OutOfProjectTest.test_out_of_project_files_and_path_to_resource + +class _MockFSCommands +_MockFSCommands.__init__ +_MockFSCommands.create_file +_MockFSCommands.create_folder +_MockFSCommands.move +_MockFSCommands.remove +_MockFSCommands.read + +class _DeprecatedFSCommands +_DeprecatedFSCommands.__init__ +_DeprecatedFSCommands.create_file +_DeprecatedFSCommands.create_folder +_DeprecatedFSCommands.move +_DeprecatedFSCommands.remove + +class RopeFolderTest +RopeFolderTest.setUp +RopeFolderTest.tearDown +RopeFolderTest.test_none_project_rope_folder +RopeFolderTest.test_getting_project_rope_folder +RopeFolderTest.test_setting_ignored_resources +RopeFolderTest.test_ignored_folders +RopeFolderTest.test_ignored_resources_and_get_files +RopeFolderTest.test_ignored_resources_and_get_files2 +RopeFolderTest.test_setting_ignored_resources_patterns +RopeFolderTest.test_star_should_not_include_slashes +RopeFolderTest.test_normal_fscommands +RopeFolderTest.test_fscommands_and_ignored_resources +RopeFolderTest.test_deprecated_fscommands +RopeFolderTest.test_ignored_resources_and_prefixes +RopeFolderTest.test_loading_config_dot_py +RopeFolderTest.test_loading_pyproject +RopeFolderTest.test_loading_pyproject_empty_file +RopeFolderTest.test_loading_pyproject_no_tool_section +RopeFolderTest.test_loading_pyproject_no_tool_rope_section +RopeFolderTest.test_ignoring_syntax_errors +RopeFolderTest.test_compressed_history +RopeFolderTest.test_compressed_objectdb +RopeFolderTest.test_nested_dot_ropeproject_folder + + +@clean pycoretest.py +class PyCoreTest +PyCoreTest.setUp +PyCoreTest.tearDown +PyCoreTest.test_simple_module +PyCoreTest.test_nested_modules +PyCoreTest.test_package +PyCoreTest.test_simple_class +PyCoreTest.test_simple_function +PyCoreTest.test_class_methods +PyCoreTest.test_global_variable_without_type_annotation +PyCoreTest.test_global_variable_with_type_annotation +PyCoreTest.test_class_variables +PyCoreTest.test_class_attributes_set_in_init +PyCoreTest.test_class_attributes_set_in_init_overwriting_a_defined +PyCoreTest.test_classes_inside_other_classes +PyCoreTest.test_non_existent_module +PyCoreTest.test_imported_names +PyCoreTest.test_imported_as_names +PyCoreTest.test_get_string_module +PyCoreTest.test_get_string_module_with_extra_spaces +PyCoreTest.test_parameter_info_for_functions +PyCoreTest.xxx_test_not_found_module_is_module +PyCoreTest.test_mixing_scopes_and_objects_hierarchy +PyCoreTest.test_inheriting_base_class_attributes +PyCoreTest.test_inheriting_multiple_base_class_attributes +PyCoreTest.test_inherit_multiple_base_class_attrs_with_the_same_name +PyCoreTest.test_inheriting_unknown_base_class +PyCoreTest.test_module_creation +PyCoreTest.test_packaged_module_creation +PyCoreTest.test_packaged_module_creation_with_nested_src +PyCoreTest.test_package_creation +PyCoreTest.test_nested_package_creation +PyCoreTest.test_packaged_package_creation_with_nested_src +PyCoreTest.test_find_module +PyCoreTest.test_find_nested_module +PyCoreTest.test_find_multiple_module +PyCoreTest.test_find_module_packages +PyCoreTest.test_find_module_when_module_and_package_with_the_same_name +PyCoreTest.test_source_folders_preference +PyCoreTest.test_get_pyname_definition_location +PyCoreTest.test_get_pyname_definition_location_functions +PyCoreTest.test_get_pyname_definition_location_class +PyCoreTest.test_get_pyname_definition_location_local_variables +PyCoreTest.test_get_pyname_definition_location_reassigning +PyCoreTest.test_get_pyname_definition_location_importes +PyCoreTest.test_get_pyname_definition_location_imports +PyCoreTest.test_get_pyname_definition_location_parameters +PyCoreTest.test_module_get_resource +PyCoreTest.test_get_pyname_definition_location_class2 +PyCoreTest.test_import_not_found_module_get_definition_location +PyCoreTest.test_from_not_found_module_get_definition_location +PyCoreTest.test_from_package_import_module_get_definition_location +PyCoreTest.test_get_module_for_defined_pyobjects +PyCoreTest.test_get_definition_location_for_packages +PyCoreTest.test_get_definition_location_for_filtered_packages +PyCoreTest.test_out_of_project_modules +PyCoreTest.test_file_encoding_reading +PyCoreTest.test_global_keyword +PyCoreTest.test_not_leaking_for_vars_inside_parent_scope +PyCoreTest.test_not_leaking_for_vars_inside_parent_scope2 +PyCoreTest.test_variables_defined_in_excepts +PyCoreTest.test_not_leaking_tuple_assigned_names_inside_parent_scope +PyCoreTest.test_with_statement_variables +PyCoreTest.test_with_statement_variables_and_tuple_assignment +PyCoreTest.test_with_statement_variable_type +PyCoreTest.test_nested_with_statement_variable_type +PyCoreTest.test_with_statement_with_no_vars +PyCoreTest.test_with_statement +PyCoreTest.test_check_for_else_block +PyCoreTest.test_check_names_defined_in_whiles +PyCoreTest.test_get_definition_location_in_tuple_assnames +PyCoreTest.test_syntax_errors_in_code +PyCoreTest.test_holding_error_location_information +PyCoreTest.test_no_exceptions_on_module_encoding_problems +PyCoreTest.test_syntax_errors_when_cannot_decode_file2 +PyCoreTest.test_syntax_errors_when_null_bytes +PyCoreTest.test_syntax_errors_when_bad_strs +PyCoreTest.test_not_reaching_maximum_recursions_with_from_star_imports +PyCoreTest.test_not_reaching_maximum_recursions_when_importing_variables +PyCoreTest.test_not_reaching_maximum_recursions_when_importing_variables2 +PyCoreTest.test_pyobject_equality_should_compare_types + +class PyCoreInProjectsTest +PyCoreInProjectsTest.setUp +PyCoreInProjectsTest.tearDown +PyCoreInProjectsTest.test_simple_import +PyCoreInProjectsTest.test_from_import_class +PyCoreInProjectsTest.test_from_import_star +PyCoreInProjectsTest.test_from_import_star_overwriting +PyCoreInProjectsTest.test_from_import_star_not_imporing_underlined +PyCoreInProjectsTest.test_from_import_star_imports_in_functions +PyCoreInProjectsTest.test_from_package_import_mod +PyCoreInProjectsTest.xxx_test_from_package_import_star +PyCoreInProjectsTest.test_unknown_when_module_cannot_be_found +PyCoreInProjectsTest.test_from_import_function +PyCoreInProjectsTest.test_circular_imports +PyCoreInProjectsTest.test_circular_imports2 +PyCoreInProjectsTest.test_multi_dot_imports +PyCoreInProjectsTest.test_multi_dot_imports2 +PyCoreInProjectsTest.test_multi_dot_imports3 +PyCoreInProjectsTest.test_multi_dot_imports_as +PyCoreInProjectsTest.xxx_test_from_package_import_package +PyCoreInProjectsTest.test_invalidating_cache_after_resource_change +PyCoreInProjectsTest.test_invalidating_cache_after_resource_change_for_init_dot_pys +PyCoreInProjectsTest.test_invalidating_cache_after_rsrc_chng_for_nested_init_dot_pys +PyCoreInProjectsTest.test_from_import_nonexistent_module +PyCoreInProjectsTest.test_from_import_nonexistent_name +PyCoreInProjectsTest.test_not_considering_imported_names_as_sub_scopes +PyCoreInProjectsTest.test_not_considering_imported_modules_as_sub_scopes +PyCoreInProjectsTest.test_inheriting_dotted_base_class +PyCoreInProjectsTest.test_self_in_methods +PyCoreInProjectsTest.test_none_assignments_in_classes +PyCoreInProjectsTest.test_self_in_methods_with_decorators +PyCoreInProjectsTest.test_location_of_imports_when_importing +PyCoreInProjectsTest.test_nested_modules +PyCoreInProjectsTest.test_reading_init_dot_py +PyCoreInProjectsTest.test_relative_imports +PyCoreInProjectsTest.test_relative_froms +PyCoreInProjectsTest.test_relative_imports_for_string_modules +PyCoreInProjectsTest.test_relative_imports_for_string_scopes +PyCoreInProjectsTest.test_new_style_relative_imports1 +PyCoreInProjectsTest.test_new_style_relative_imports2 +PyCoreInProjectsTest.test_invalidating_cache_for_from_imports_after_resource_change +PyCoreInProjectsTest.test_invalidating_superclasses_after_change +PyCoreInProjectsTest.test_caching_pymodule_with_syntax_errors + +class TextChangeDetectorTest +TextChangeDetectorTest.test_trivial_case +TextChangeDetectorTest.test_one_line_change +TextChangeDetectorTest.test_line_expansion +TextChangeDetectorTest.test_line_removals +TextChangeDetectorTest.test_multi_line_checks +TextChangeDetectorTest.test_consume_change + +class PyCoreProjectConfigsTest +PyCoreProjectConfigsTest.setUp +PyCoreProjectConfigsTest.tearDown +PyCoreProjectConfigsTest.test_python_files_config +PyCoreProjectConfigsTest.test_ignore_bad_imports +PyCoreProjectConfigsTest.test_ignore_bad_imports_for_froms +PyCoreProjectConfigsTest.test_reporting_syntax_errors_with_force_errors +PyCoreProjectConfigsTest.test_reporting_syntax_errors_in_strings_with_force_errors +PyCoreProjectConfigsTest.test_not_raising_errors_for_strings_with_ignore_errors +PyCoreProjectConfigsTest.test_reporting_syntax_errors_with_force_errors_for_packages + + +@clean pyscopestest.py +class PyCoreScopesTest +PyCoreScopesTest.setUp +PyCoreScopesTest.tearDown +PyCoreScopesTest.test_simple_scope +PyCoreScopesTest.test_simple_function_scope +PyCoreScopesTest.test_classes_inside_function_scopes +PyCoreScopesTest.test_list_comprehension_scope_inside_assignment +PyCoreScopesTest.test_list_comprehension_scope +PyCoreScopesTest.test_set_comprehension_scope +PyCoreScopesTest.test_generator_comprehension_scope +PyCoreScopesTest.test_dict_comprehension_scope +PyCoreScopesTest.test_inline_assignment +PyCoreScopesTest.test_inline_assignment_in_comprehensions +PyCoreScopesTest.test_nested_comprehension +PyCoreScopesTest.test_simple_class_scope +PyCoreScopesTest.test_get_lineno +PyCoreScopesTest.test_scope_kind +PyCoreScopesTest.test_function_parameters_in_scope_names +PyCoreScopesTest.test_get_names_contains_only_names_defined_in_a_scope +PyCoreScopesTest.test_scope_lookup +PyCoreScopesTest.test_function_scopes +PyCoreScopesTest.test_function_scopes_classes +PyCoreScopesTest.test_function_getting_scope +PyCoreScopesTest.test_scopes_in_function_scopes +PyCoreScopesTest.test_for_variables_in_scopes +PyCoreScopesTest.test_assists_inside_fors +PyCoreScopesTest.test_first_parameter_of_a_method +PyCoreScopesTest.test_first_parameter_of_static_methods +PyCoreScopesTest.test_first_parameter_of_class_methods +PyCoreScopesTest.test_first_parameter_with_self_as_name_and_unknown_decorator +PyCoreScopesTest.test_inside_class_scope_attribute_lookup +PyCoreScopesTest.test_inside_class_scope_attribute_lookup2 +PyCoreScopesTest.test_get_inner_scope_for_staticmethods +PyCoreScopesTest.test_get_scope_for_offset_for_comprehension +PyCoreScopesTest.test_get_scope_for_offset_for_in_nested_comprehension +PyCoreScopesTest.test_get_scope_for_offset_for_scope_with_indent +PyCoreScopesTest.test_get_scope_for_offset_for_function_scope_and_async_with_statement +PyCoreScopesTest.test_getting_overwritten_scopes +PyCoreScopesTest.test_assigning_builtin_names +PyCoreScopesTest.test_get_inner_scope_and_logical_lines +PyCoreScopesTest.test_getting_defined_names_for_classes +PyCoreScopesTest.test_getting_defined_names_for_modules +PyCoreScopesTest.test_get_inner_scope_for_list_comprhension_with_many_targets +PyCoreScopesTest.test_get_inner_scope_for_generator +PyCoreScopesTest.test_get_inner_scope_for_set_comprehension +PyCoreScopesTest.test_get_inner_scope_for_dict_comprehension +PyCoreScopesTest.test_get_inner_scope_for_nested_list_comprhension +PyCoreScopesTest.test_get_scope_region +PyCoreScopesTest.test_only_get_inner_scope_region + + +@clean reprtest.py +project +mod +mod1 +test_repr_project +test_repr_file +test_repr_folder +test_repr_pyobjectsdef_pymodule +test_repr_pyobjectsdef_pymodule_without_associated_resource +test_repr_pyobjectsdef_pypackage +test_repr_pyobjectsdef_pypackage_without_associated_resource +test_repr_pyobjectsdef_pyfunction +test_repr_pyobjectsdef_pyfunction_without_associated_resource +test_repr_pyobjectsdef_pyclass +test_repr_pyobjectsdef_pyclass_without_associated_resource +test_repr_pyobjectsdef_pycomprehension +test_repr_pyobjectsdef_pycomprehension_without_associated_resource + +@clean runmodtest.py +class PythonFileRunnerTest +PythonFileRunnerTest.setUp +PythonFileRunnerTest.tearDown +PythonFileRunnerTest.make_sample_python_file +PythonFileRunnerTest.get_output_file_content +PythonFileRunnerTest.test_making_runner +PythonFileRunnerTest.test_passing_arguments +PythonFileRunnerTest.test_passing_arguments_with_spaces +PythonFileRunnerTest.test_killing_runner +PythonFileRunnerTest.test_running_nested_files +PythonFileRunnerTest.test_setting_process_input +PythonFileRunnerTest.test_setting_process_output +PythonFileRunnerTest.test_setting_pythonpath +PythonFileRunnerTest.test_making_runner_when_doi_is_disabled + + +@clean simplifytest.py +class SimplifyTest +SimplifyTest.test_trivial_case +SimplifyTest.test_empty_strs +SimplifyTest.test_blanking_strs +SimplifyTest.test_changing_to_double_quotes +SimplifyTest.test_changing_to_double_quotes2 +SimplifyTest.test_removing_comments +SimplifyTest.test_removing_comments_that_contain_strings +SimplifyTest.test_removing_strings_containing_comments +SimplifyTest.test_joining_implicit_continuations +SimplifyTest.test_joining_explicit_continuations +SimplifyTest.test_replacing_tabs +SimplifyTest.test_replacing_semicolons +SimplifyTest.test_simplifying_f_string +SimplifyTest.test_simplifying_f_string_containing_quotes +SimplifyTest.test_simplifying_uppercase_f_string_containing_quotes + + +@clean testutils.py +sample_project +create_module = generate.create_module +remove_project +remove_recursively +_remove_recursively +parse_version +only_for +only_for_versions_lower +only_for_versions_higher +skipNotPOSIX +time_limit + +@clean type_hinting_test.py +class AbstractHintingTest +AbstractHintingTest.setUp +AbstractHintingTest.tearDown +AbstractHintingTest._assist +AbstractHintingTest.assert_completion_in_result +AbstractHintingTest.assert_completion_not_in_result +AbstractHintingTest.run + +class DocstringParamHintingTest +DocstringParamHintingTest.test_hint_param +DocstringParamHintingTest.test_hierarchical_hint_param + +class DocstringReturnHintingTest +DocstringReturnHintingTest.test_hierarchical_hint_rtype + +class AbstractAssignmentHintingTest +AbstractAssignmentHintingTest._make_class_hint +AbstractAssignmentHintingTest._make_constructor_hint +AbstractAssignmentHintingTest.test_hint_attr +AbstractAssignmentHintingTest.test_hierarchical_hint_attr +AbstractAssignmentHintingTest.test_hint_defined_by_constructor +AbstractAssignmentHintingTest.test_hint_attr_redefined_by_constructor +AbstractAssignmentHintingTest.test_hierarchical_hint_attr_redefined_by_constructor +AbstractAssignmentHintingTest.test_hint_attr_for_pre_defined_type +AbstractAssignmentHintingTest.test_hint_attr_for_post_defined_type +AbstractAssignmentHintingTest.test_hint_parametrized_list +AbstractAssignmentHintingTest.test_hint_parametrized_tuple +AbstractAssignmentHintingTest.test_hint_parametrized_set +AbstractAssignmentHintingTest.test_hint_parametrized_iterable +AbstractAssignmentHintingTest.test_hint_parametrized_iterator +AbstractAssignmentHintingTest.test_hint_parametrized_dict_key +AbstractAssignmentHintingTest.test_hint_parametrized_dict_value +AbstractAssignmentHintingTest.test_hint_parametrized_nested_tuple_list +AbstractAssignmentHintingTest.test_hint_or +AbstractAssignmentHintingTest.test_hint_nonexistent +AbstractAssignmentHintingTest.test_hint_invalid_syntax + +class DocstringNoneAssignmentHintingTest +DocstringNoneAssignmentHintingTest._make_class_hint +DocstringNoneAssignmentHintingTest._make_constructor_hint + +class DocstringNotImplementedAssignmentHintingTest +DocstringNotImplementedAssignmentHintingTest._make_class_hint +DocstringNotImplementedAssignmentHintingTest._make_constructor_hint + +class PEP0484CommentNoneAssignmentHintingTest +class PEP0484CommentNotImplementedAssignmentHintingTest +class EvaluateTest +EvaluateTest.test_parser + +class RegressionHintingTest +RegressionHintingTest.test_hierarchical_hint_for_mutable_attr_type + + +@clean __init__.py +suite + +@path contrib +@clean autoimporttest.py +class AutoImportTest +AutoImportTest.setUp +AutoImportTest.tearDown +AutoImportTest.test_simple_case +AutoImportTest.test_update_resource +AutoImportTest.test_update_non_existent_module +AutoImportTest.test_module_with_syntax_errors +AutoImportTest.test_excluding_imported_names +AutoImportTest.test_get_modules +AutoImportTest.test_get_modules_inside_packages +AutoImportTest.test_trivial_insertion_line +AutoImportTest.test_insertion_line +AutoImportTest.test_insertion_line_with_pydocs +AutoImportTest.test_insertion_line_with_multiple_imports +AutoImportTest.test_insertion_line_with_blank_lines +AutoImportTest.test_empty_cache +AutoImportTest.test_not_caching_underlined_names +AutoImportTest.test_caching_underlined_names_passing_to_the_constructor +AutoImportTest.test_name_locations +AutoImportTest.test_name_locations_with_multiple_occurrences +AutoImportTest.test_handling_builtin_modules +AutoImportTest.test_search_submodule +AutoImportTest.test_search_module +AutoImportTest.test_search +AutoImportTest.test_generate_full_cache + +class AutoImportObservingTest +AutoImportObservingTest.setUp +AutoImportObservingTest.tearDown +AutoImportObservingTest.test_writing_files +AutoImportObservingTest.test_moving_files +AutoImportObservingTest.test_removing_files + + +@clean changestacktest.py +class ChangeStackTest +ChangeStackTest.setUp +ChangeStackTest.tearDown +ChangeStackTest.test_change_stack + + +@clean codeassisttest.py +class CodeAssistTest +CodeAssistTest.setUp +CodeAssistTest.tearDown +CodeAssistTest._assist +CodeAssistTest.test_simple_assist +CodeAssistTest.assert_completion_in_result +CodeAssistTest.assert_completion_not_in_result +CodeAssistTest.test_completing_global_variables +CodeAssistTest.test_not_proposing_unmatched_vars +CodeAssistTest.test_not_proposing_unmatched_vars_with_underlined_starting +CodeAssistTest.test_not_proposing_local_assigns_as_global_completions +CodeAssistTest.test_proposing_functions +CodeAssistTest.test_proposing_classes +CodeAssistTest.test_proposing_each_name_at_most_once +CodeAssistTest.test_throwing_exception_in_case_of_syntax_errors +CodeAssistTest.test_fixing_errors_with_maxfixes +CodeAssistTest.test_ignoring_errors_in_current_line +CodeAssistTest.test_not_reporting_variables_in_current_line +CodeAssistTest.test_completion_result +CodeAssistTest.test_completing_imported_names +CodeAssistTest.test_completing_imported_names_with_as +CodeAssistTest.test_not_completing_imported_names_with_as +CodeAssistTest.test_including_matching_builtins_types +CodeAssistTest.test_including_matching_builtins_functions +CodeAssistTest.test_builtin_instances +CodeAssistTest.test_including_keywords +CodeAssistTest.test_not_reporting_proposals_after_dot +CodeAssistTest.test_proposing_local_variables_in_functions +CodeAssistTest.test_local_variables_override_global_ones +CodeAssistTest.test_not_including_class_body_variables +CodeAssistTest.test_nested_functions +CodeAssistTest.test_scope_endpoint_selection +CodeAssistTest.test_scope_better_endpoint_selection +CodeAssistTest.test_imports_inside_function +CodeAssistTest.test_imports_inside_function_dont_mix_with_globals +CodeAssistTest.test_nested_classes_local_names +CodeAssistTest.test_nested_classes_global +CodeAssistTest.test_nested_classes_global_function +CodeAssistTest.test_proposing_function_parameters_in_functions +CodeAssistTest.test_proposing_function_keyword_parameters_in_functions +CodeAssistTest.test_not_proposing_unmatching_function_parameters_in_functions +CodeAssistTest.test_ignoring_current_statement +CodeAssistTest.test_ignoring_current_statement_brackets_continuation +CodeAssistTest.test_ignoring_current_statement_explicit_continuation +CodeAssistTest.test_ignor_current_statement_while_the_first_stmnt_of_the_block +CodeAssistTest.test_ignor_current_stmnt_while_current_line_ends_with_a_colon +CodeAssistTest.test_ignoring_string_contents +CodeAssistTest.test_ignoring_comment_contents +CodeAssistTest.test_ignoring_string_contents_backslash_plus_quotes +CodeAssistTest.test_ignoring_string_contents_backslash_plus_backslash +CodeAssistTest.test_not_proposing_later_defined_variables_in_current_block +CodeAssistTest.test_not_proposing_later_defined_variables_in_current_function +CodeAssistTest.test_ignoring_string_contents_with_triple_quotes +CodeAssistTest.test_ignoring_string_contents_with_triple_quotes_and_backslash +CodeAssistTest.test_ignor_str_contents_with_triple_quotes_and_double_backslash +CodeAssistTest.test_reporting_params_when_in_the_first_line_of_a_function +CodeAssistTest.test_code_assist_when_having_a_two_line_function_header +CodeAssistTest.test_code_assist_with_function_with_two_line_return +CodeAssistTest.test_get_definition_location +CodeAssistTest.test_get_definition_location_underlined_names +CodeAssistTest.test_get_definition_location_dotted_names_method +CodeAssistTest.test_get_definition_location_dotted_names_property +CodeAssistTest.test_get_definition_location_dotted_names_free_function +CodeAssistTest.test_get_definition_location_dotted_names_async_def +CodeAssistTest.test_get_definition_location_dotted_names_class +CodeAssistTest.test_get_definition_location_dotted_names_with_space +CodeAssistTest.test_get_definition_location_dotted_names_inline_body +CodeAssistTest.test_get_definition_location_dotted_names_inline_body_split_arg +CodeAssistTest.test_get_definition_location_dotted_module_names +CodeAssistTest.test_get_definition_location_for_nested_packages +CodeAssistTest.test_get_definition_location_unknown +CodeAssistTest.test_get_definition_location_dot_spaces +CodeAssistTest.test_get_definition_location_dot_line_break_inside_parens +CodeAssistTest.test_if_scopes_in_other_scopes_for_get_definition_location +CodeAssistTest.test_get_definition_location_false_triple_quoted_string +CodeAssistTest.test_code_assists_in_parens +CodeAssistTest.test_simple_type_inferencing +CodeAssistTest.test_proposals_sorter +CodeAssistTest.test_proposals_sorter_for_methods_and_attributes +CodeAssistTest.test_proposals_sorter_for_global_methods_and_funcs +CodeAssistTest.test_proposals_sorter_underlined_methods +CodeAssistTest.test_proposals_sorter_and_scope_prefs +CodeAssistTest.test_proposals_sorter_and_type_prefs +CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref +CodeAssistTest.test_get_pydoc_unicode +CodeAssistTest.test_get_pydoc_utf8_bytestring +CodeAssistTest.test_get_pydoc_for_functions +CodeAssistTest.test_get_pydoc_for_classes +CodeAssistTest.test_get_pydoc_for_classes_with_init +CodeAssistTest.test_get_pydoc_for_modules +CodeAssistTest.test_get_pydoc_for_builtins +CodeAssistTest.test_get_pydoc_for_methods_should_include_class_name +CodeAssistTest.test_get_pydoc_for_meths_should_inc_methods_from_super_classes +CodeAssistTest.test_get_pydoc_for_classes_should_name_super_classes +CodeAssistTest.test_get_pydoc_for_builtin_functions +CodeAssistTest.test_commenting_errors_before_offset +CodeAssistTest.test_proposing_variables_defined_till_the_end_of_scope +CodeAssistTest.test_completing_in_uncomplete_try_blocks +CodeAssistTest.test_completing_in_uncomplete_try_blocks_in_functions +CodeAssistTest.test_already_complete_try_blocks_with_finally +CodeAssistTest.test_already_complete_try_blocks_with_finally2 +CodeAssistTest.test_already_complete_try_blocks_with_except +CodeAssistTest.test_already_complete_try_blocks_with_except2 +CodeAssistTest.test_completing_ifs_in_uncomplete_try_blocks +CodeAssistTest.test_completing_ifs_in_uncomplete_try_blocks2 +CodeAssistTest.test_completing_excepts_in_uncomplete_try_blocks +CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing +CodeAssistTest.test_nested_blocks +CodeAssistTest.test_proposing_function_keywords_when_calling +CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions +CodeAssistTest.test_proposing_function_keywords_when_calling_extra_spaces +CodeAssistTest.test_proposing_function_keywords_when_calling_on_second_argument +CodeAssistTest.test_proposing_function_keywords_when_calling_not_proposing_args +CodeAssistTest.test_propos_function_kwrds_when_call_with_no_noth_after_parens +CodeAssistTest.test_propos_function_kwrds_when_call_with_no_noth_after_parens2 +CodeAssistTest.test_codeassists_before_opening_of_parens +CodeAssistTest.test_codeassist_before_single_line_indents +CodeAssistTest.test_codeassist_before_line_indents_in_a_blank_line +CodeAssistTest.test_simple_get_calltips +CodeAssistTest.test_get_calltips_for_classes +CodeAssistTest.test_get_calltips_for_objects_with_call +CodeAssistTest.test_get_calltips_and_including_module_name +CodeAssistTest.test_get_calltips_and_including_module_name_2 +CodeAssistTest.test_removing_self_parameter +CodeAssistTest.test_removing_self_parameter_and_more_than_one_parameter +CodeAssistTest.test_lambda_calltip +CodeAssistTest.test_keyword_before_parens +CodeAssistTest.TESTING PROPOSAL'S KINDS AND TYPES. +CodeAssistTest.test_local_variable_completion_proposal +CodeAssistTest.test_global_variable_completion_proposal +CodeAssistTest.test_builtin_variable_completion_proposal +CodeAssistTest.test_attribute_variable_completion_proposal +CodeAssistTest.test_local_class_completion_proposal +CodeAssistTest.test_global_class_completion_proposal +CodeAssistTest.test_builtin_class_completion_proposal +CodeAssistTest.test_attribute_class_completion_proposal +CodeAssistTest.test_local_function_completion_proposal +CodeAssistTest.test_global_function_completion_proposal +CodeAssistTest.test_builtin_function_completion_proposal +CodeAssistTest.test_attribute_function_completion_proposal +CodeAssistTest.test_local_module_completion_proposal +CodeAssistTest.test_global_module_completion_proposal +CodeAssistTest.test_attribute_module_completion_proposal +CodeAssistTest.test_builtin_exception_completion_proposal +CodeAssistTest.test_keyword_completion_proposal +CodeAssistTest.test_parameter_keyword_completion_proposal +CodeAssistTest.test_object_path_global +CodeAssistTest.test_object_path_attribute +CodeAssistTest.test_object_path_subclass +CodeAssistTest.test_object_path_method_parameter +CodeAssistTest.test_object_path_variable + +class CodeAssistInProjectsTest +CodeAssistInProjectsTest.setUp +CodeAssistInProjectsTest.tearDown +CodeAssistInProjectsTest._assist +CodeAssistInProjectsTest.assert_completion_in_result +CodeAssistInProjectsTest.assert_completion_not_in_result +CodeAssistInProjectsTest.test_simple_import +CodeAssistInProjectsTest.test_from_import_class +CodeAssistInProjectsTest.test_from_import_function +CodeAssistInProjectsTest.test_from_import_variable +CodeAssistInProjectsTest.test_from_imports_inside_functions +CodeAssistInProjectsTest.test_from_import_only_imports_imported +CodeAssistInProjectsTest.test_from_import_star +CodeAssistInProjectsTest.test_from_import_star2 +CodeAssistInProjectsTest.test_from_import_star_not_imporing_underlined +CodeAssistInProjectsTest.test_from_package_import_mod +CodeAssistInProjectsTest.test_completing_after_dot +CodeAssistInProjectsTest.test_completing_after_multiple_dots +CodeAssistInProjectsTest.test_completing_after_self_dot +CodeAssistInProjectsTest.test_result_start_offset_for_dotted_completions +CodeAssistInProjectsTest.test_backslash_after_dots +CodeAssistInProjectsTest.test_not_proposing_global_names_after_dot +CodeAssistInProjectsTest.test_assist_on_relative_imports +CodeAssistInProjectsTest.test_get_location_on_relative_imports +CodeAssistInProjectsTest.test_get_definition_location_for_builtins +CodeAssistInProjectsTest.test_get_doc_on_relative_imports +CodeAssistInProjectsTest.test_get_doc_on_from_import_module +CodeAssistInProjectsTest.test_fixing_errors_with_maxfixes_in_resources +CodeAssistInProjectsTest.test_completing_names_after_from_import +CodeAssistInProjectsTest.test_completing_names_after_from_import_and_sorted_proposals +CodeAssistInProjectsTest.test_completing_names_after_from_import2 +CodeAssistInProjectsTest.test_starting_expression + + +@clean finderrorstest.py +class FindErrorsTest +FindErrorsTest.setUp +FindErrorsTest.tearDown +FindErrorsTest.test_unresolved_variables +FindErrorsTest.test_defined_later +FindErrorsTest.test_ignoring_builtins +FindErrorsTest.test_ignoring_none +FindErrorsTest.test_bad_attributes + + +@clean findittest.py +class FindItTest +FindItTest.setUp +FindItTest.tearDown +FindItTest.test_finding_occurrences +FindItTest.test_finding_occurrences_in_more_than_one_module +FindItTest.test_finding_occurrences_matching_when_unsure +FindItTest.test_find_occurrences_resources_parameter +FindItTest.test_find_occurrences_and_class_hierarchies +FindItTest.test_trivial_find_implementations +FindItTest.test_find_implementations_and_not_returning_parents +FindItTest.test_find_implementations_real_implementation +FindItTest.test_find_implementations_real_implementation_simple +FindItTest.test_trivial_find_definition +FindItTest.test_find_definition_in_other_modules + + +@clean fixmodnamestest.py +class FixModuleNamesTest +FixModuleNamesTest.setUp +FixModuleNamesTest.tearDown +FixModuleNamesTest.test_simple_module_renaming +FixModuleNamesTest.test_packages_module_renaming +FixModuleNamesTest.test_fixing_contents +FixModuleNamesTest.test_handling_nested_modules + +_fixer + +@clean generatetest.py +class GenerateTest +GenerateTest.setUp +GenerateTest.tearDown +GenerateTest._get_generate +GenerateTest._get_generate_class +GenerateTest._get_generate_module +GenerateTest._get_generate_package +GenerateTest._get_generate_function +GenerateTest.test_getting_location +GenerateTest.test_generating_variable +GenerateTest.test_generating_variable_inserting_before_statement +GenerateTest.test_generating_variable_in_local_scopes +GenerateTest.test_generating_variable_in_other_modules +GenerateTest.test_generating_variable_in_classes +GenerateTest.test_generating_variable_in_classes_removing_pass +GenerateTest.test_generating_variable_in_packages +GenerateTest.test_generating_classes +GenerateTest.test_generating_classes_in_other_module +GenerateTest.test_generating_modules +GenerateTest.test_generating_packages +GenerateTest.test_generating_function +GenerateTest.test_generating_modules_with_empty_primary +GenerateTest.test_generating_variable_already_exists +GenerateTest.test_generating_variable_primary_cannot_be_determined +GenerateTest.test_generating_modules_when_already_exists +GenerateTest.test_generating_static_methods +GenerateTest.test_generating_methods +GenerateTest.test_generating_constructors +GenerateTest.test_generating_calls +GenerateTest.test_generating_calls_in_other_modules +GenerateTest.test_generating_function_handling_arguments +GenerateTest.test_generating_function_handling_keyword_xarguments +GenerateTest.test_generating_function_handling_arguments_better_naming +GenerateTest.test_generating_variable_in_other_modules2 +GenerateTest.test_generating_function_in_a_suite +GenerateTest.test_generating_function_in_a_suite_in_a_function +GenerateTest.test_create_generate_class_with_goal_resource +GenerateTest.test_create_generate_class_without_goal_resource + + +@clean __init__.py +suite + +@path autoimport +@clean conftest.py +project +mod1 +mod1_path +project_path +typing_path +build_env_path +build_path +compiled_lib + +@clean modeltest.py +class QueryTest +class NameModelTest +NameModelTest.test_name_objects +NameModelTest.test_query_strings + +class PackageModelTest +PackageModelTest.test_query_strings + + +@clean parsetest.py +test_typing_names +test_find_sys +test_find_underlined + +@clean utilstest.py +test_get_package_source +test_get_package_source_not_project +test_get_package_source_pytest +test_get_package_source_typing +test_get_modname_project_no_add +test_get_modname_single_file +test_get_modname_folder +test_get_package_tuple_sample +test_get_package_tuple_typing +test_get_package_tuple_compiled + + + +@path refactor +@clean __init__.py +class MethodObjectTest +MethodObjectTest.setUp +MethodObjectTest.tearDown +MethodObjectTest.test_empty_method +MethodObjectTest.test_trivial_return +MethodObjectTest.test_multi_line_header +MethodObjectTest.test_a_single_parameter +MethodObjectTest.test_self_parameter +MethodObjectTest.test_simple_using_passed_parameters +MethodObjectTest.test_self_keywords_and_args_parameters +MethodObjectTest.test_performing_on_not_a_function +MethodObjectTest.test_changing_the_module +MethodObjectTest.test_changing_the_module_and_class_methods + +class IntroduceFactoryTest +IntroduceFactoryTest.setUp +IntroduceFactoryTest.tearDown +IntroduceFactoryTest._introduce_factory +IntroduceFactoryTest.test_adding_the_method +IntroduceFactoryTest.test_changing_occurrences_in_the_main_module +IntroduceFactoryTest.test_changing_occurrences_with_arguments +IntroduceFactoryTest.test_changing_occurrences_in_other_modules +IntroduceFactoryTest.test_raising_exception_for_non_classes +IntroduceFactoryTest.test_undoing_introduce_factory +IntroduceFactoryTest.test_using_on_an_occurrence_outside_the_main_module +IntroduceFactoryTest.test_introduce_factory_in_nested_scopes +IntroduceFactoryTest.test_adding_factory_for_global_factories +IntroduceFactoryTest.test_get_name_for_factories +IntroduceFactoryTest.test_raising_exception_for_global_factory_for_nested_classes +IntroduceFactoryTest.test_changing_occurrences_in_the_main_module_for_global_factories +IntroduceFactoryTest.test_changing_occurrences_in_other_modules_for_global_factories +IntroduceFactoryTest.test_import_if_necessary_in_other_mods_for_global_factories +IntroduceFactoryTest.test_changing_occurrences_for_renamed_classes +IntroduceFactoryTest.test_changing_occurrs_in_the_same_module_with_conflict_ranges +IntroduceFactoryTest._transform_module_to_package +IntroduceFactoryTest.test_transform_module_to_package +IntroduceFactoryTest.test_transform_module_to_package_undoing +IntroduceFactoryTest.test_transform_module_to_package_with_relative_imports +IntroduceFactoryTest.test_resources_parameter + +class EncapsulateFieldTest +EncapsulateFieldTest.setUp +EncapsulateFieldTest.tearDown +EncapsulateFieldTest._encapsulate +EncapsulateFieldTest.test_adding_getters_and_setters +EncapsulateFieldTest.test_changing_getters_in_other_modules +EncapsulateFieldTest.test_changing_setters_in_other_modules +EncapsulateFieldTest.test_changing_getters_in_setters +EncapsulateFieldTest.test_appending_to_class_end +EncapsulateFieldTest.test_performing_in_other_modules +EncapsulateFieldTest.test_changing_main_module_occurrences +EncapsulateFieldTest.test_raising_exception_when_performed_on_non_attributes +EncapsulateFieldTest.test_raising_exception_on_tuple_assignments +EncapsulateFieldTest.test_raising_exception_on_tuple_assignments2 +EncapsulateFieldTest.test_tuple_assignments_and_function_calls +EncapsulateFieldTest.test_tuple_assignments +EncapsulateFieldTest.test_changing_augmented_assignments +EncapsulateFieldTest.test_changing_augmented_assignments2 +EncapsulateFieldTest.test_changing_occurrences_inside_the_class +EncapsulateFieldTest.test_getter_and_setter_parameters +EncapsulateFieldTest.test_using_resources_parameter + +class LocalToFieldTest +LocalToFieldTest.setUp +LocalToFieldTest.tearDown +LocalToFieldTest._perform_convert_local_variable_to_field +LocalToFieldTest.test_simple_local_to_field +LocalToFieldTest.test_raising_exception_when_performed_on_a_global_var +LocalToFieldTest.test_raising_exception_when_performed_on_field +LocalToFieldTest.test_raising_exception_when_performed_on_a_parameter +LocalToFieldTest.test_not_rais_exception_when_there_is_a_field_with_the_same_name +LocalToFieldTest.test_local_to_field_with_self_renamed + +class IntroduceParameterTest +IntroduceParameterTest.setUp +IntroduceParameterTest.tearDown +IntroduceParameterTest._introduce_parameter +IntroduceParameterTest.test_simple_case +IntroduceParameterTest.test_changing_function_body +IntroduceParameterTest.test_unknown_variables +IntroduceParameterTest.test_failing_when_not_inside +IntroduceParameterTest.test_attribute_accesses +IntroduceParameterTest.test_introducing_parameters_for_methods + +class _MockTaskObserver +class TaskHandleTest +TaskHandleTest.test_trivial_case +TaskHandleTest.test_stopping +TaskHandleTest.test_job_sets +TaskHandleTest.test_starting_and_finishing_jobs +TaskHandleTest.test_test_checking_status +TaskHandleTest.test_test_checking_status_when_starting +TaskHandleTest.test_calling_the_observer_after_stopping +TaskHandleTest.test_calling_the_observer_after_creating_job_sets +TaskHandleTest.test_calling_the_observer_when_starting_and_finishing_jobs +TaskHandleTest.test_job_set_get_percent_done +TaskHandleTest.test_getting_job_name (changed) + + +@clean change_signature_test.py +class ChangeSignatureTest +ChangeSignatureTest.setUp +ChangeSignatureTest.tearDown +ChangeSignatureTest.test_normalizing_parameters_for_trivial_case +ChangeSignatureTest.test_normalizing_parameters_for_trivial_case2 +ChangeSignatureTest.test_normalizing_parameters_for_unneeded_keyword +ChangeSignatureTest.test_normalizing_parameters_for_unneeded_keyword_for_methods +ChangeSignatureTest.test_normalizing_parameters_for_unsorted_keyword +ChangeSignatureTest.test_raising_exceptions_for_non_functions +ChangeSignatureTest.test_normalizing_parameters_for_args_parameter +ChangeSignatureTest.test_normalizing_parameters_for_args_parameter_and_keywords +ChangeSignatureTest.test_normalizing_functions_from_other_modules +ChangeSignatureTest.test_normalizing_parameters_for_keyword_parameters +ChangeSignatureTest.test_removing_arguments +ChangeSignatureTest.test_removing_arguments_with_multiple_args +ChangeSignatureTest.test_removing_arguments_passed_as_keywords +ChangeSignatureTest.test_removing_arguments_with_defaults +ChangeSignatureTest.test_removing_arguments_star_args +ChangeSignatureTest.test_removing_keyword_arg +ChangeSignatureTest.test_removing_keyword_arg2 +ChangeSignatureTest.xxx_test_removing_arguments_star_args2 +ChangeSignatureTest.xxx_test_removing_arguments_star_args3 +ChangeSignatureTest.test_adding_arguments_for_normal_args_changing_definition +ChangeSignatureTest.test_adding_arguments_for_normal_args_with_defaults +ChangeSignatureTest.test_adding_arguments_for_normal_args_changing_calls +ChangeSignatureTest.test_adding_arguments_for_norm_args_chang_calls_with_kwords +ChangeSignatureTest.test_adding_arguments_for_norm_args_chang_calls_with_no_value +ChangeSignatureTest.test_adding_duplicate_parameter_and_raising_exceptions +ChangeSignatureTest.test_inlining_default_arguments +ChangeSignatureTest.test_inlining_default_arguments2 +ChangeSignatureTest.test_preserving_args_and_keywords_order +ChangeSignatureTest.test_change_order_for_only_one_parameter +ChangeSignatureTest.test_change_order_for_two_parameter +ChangeSignatureTest.test_reordering_multi_line_function_headers +ChangeSignatureTest.test_changing_order_with_static_params +ChangeSignatureTest.test_doing_multiple_changes +ChangeSignatureTest.test_doing_multiple_changes2 +ChangeSignatureTest.test_changing_signature_in_subclasses +ChangeSignatureTest.test_differentiating_class_accesses_from_instance_accesses +ChangeSignatureTest.test_changing_signature_for_constructors +ChangeSignatureTest.test_changing_signature_for_constructors2 +ChangeSignatureTest.test_changing_signature_for_constructors_when_using_super +ChangeSignatureTest.test_redordering_arguments_reported_by_mft +ChangeSignatureTest.test_resources_parameter +ChangeSignatureTest.test_reordering_and_automatic_defaults + + +@clean extracttest.py +class ExtractMethodTest +ExtractMethodTest.setUp +ExtractMethodTest.tearDown +ExtractMethodTest.do_extract_method +ExtractMethodTest.do_extract_variable +ExtractMethodTest._convert_line_range_to_offset +ExtractMethodTest.test_simple_extract_function +ExtractMethodTest.test_simple_extract_function_one_line +ExtractMethodTest.test_extract_function_at_the_end_of_file +ExtractMethodTest.test_extract_function_after_scope +ExtractMethodTest.test_extract_function_containing_dict_generalized_unpacking +ExtractMethodTest.test_simple_extract_function_with_parameter +ExtractMethodTest.test_not_unread_variables_as_parameter +ExtractMethodTest.test_simple_extract_function_with_two_parameter +ExtractMethodTest.test_simple_extract_function_with_return_value +ExtractMethodTest.test_extract_function_with_multiple_return_values +ExtractMethodTest.test_simple_extract_method +ExtractMethodTest.test_extract_method_with_args_and_returns +ExtractMethodTest.test_extract_method_with_self_as_argument +ExtractMethodTest.test_extract_method_with_no_self_as_argument +ExtractMethodTest.test_extract_method_with_multiple_methods +ExtractMethodTest.test_extract_function_with_function_returns +ExtractMethodTest.test_simple_extract_global_function +ExtractMethodTest.test_extract_global_function_inside_ifs +ExtractMethodTest.test_extract_function_while_inner_function_reads +ExtractMethodTest.test_extract_method_bad_range +ExtractMethodTest.test_extract_method_bad_range2 +ExtractMethodTest.test_extract_method_containing_return +ExtractMethodTest.test_extract_method_containing_yield +ExtractMethodTest.test_extract_method_containing_uncomplete_lines +ExtractMethodTest.test_extract_method_containing_uncomplete_lines2 +ExtractMethodTest.test_extract_function_and_argument_as_paramenter +ExtractMethodTest.test_extract_function_and_end_as_the_start_of_a_line +ExtractMethodTest.test_extract_function_and_indented_blocks +ExtractMethodTest.test_extract_method_and_multi_line_headers +ExtractMethodTest.test_single_line_extract_function +ExtractMethodTest.test_single_line_extract_function2 +ExtractMethodTest.test_single_line_extract_method_and_logical_lines +ExtractMethodTest.test_single_line_extract_method_and_logical_lines2 +ExtractMethodTest.test_single_line_extract_method_with_large_multiline_expression +ExtractMethodTest.test_single_line_extract_method +ExtractMethodTest.test_single_line_extract_function_if_condition +ExtractMethodTest.test_unneeded_params +ExtractMethodTest.test_breaks_and_continues_inside_loops +ExtractMethodTest.test_breaks_and_continues_outside_loops +ExtractMethodTest.test_for_loop_variable_scope +ExtractMethodTest.test_for_loop_variable_scope_read_then_write +ExtractMethodTest.test_for_loop_variable_scope_write_then_read +ExtractMethodTest.test_for_loop_variable_scope_write_only +ExtractMethodTest.test_variable_writes_followed_by_variable_reads_after_extraction +ExtractMethodTest.test_var_writes_followed_by_var_reads_inside_extraction +ExtractMethodTest.test_extract_variable +ExtractMethodTest.test_extract_variable_f_string +ExtractMethodTest.test_extract_variable_multiple_lines +ExtractMethodTest.test_extract_variable_in_the_middle_of_statements +ExtractMethodTest.test_extract_variable_for_a_tuple +ExtractMethodTest.test_extract_variable_for_a_string +ExtractMethodTest.test_extract_variable_inside_ifs +ExtractMethodTest.test_extract_variable_inside_ifs_and_logical_lines +ExtractMethodTest.xxx_test_extract_variable_for_a_subexpression +ExtractMethodTest.test_extract_variable_starting_from_the_start_of_the_line +ExtractMethodTest.test_extract_variable_on_the_last_line_of_a_function +ExtractMethodTest.test_extract_variable_on_the_indented_function_statement +ExtractMethodTest.test_extract_method_on_the_last_line_of_a_function +ExtractMethodTest.test_raising_exception_when_on_incomplete_variables +ExtractMethodTest.test_raising_exception_when_on_incomplete_variables_on_end +ExtractMethodTest.test_raising_exception_on_bad_parens +ExtractMethodTest.test_raising_exception_on_bad_operators +ExtractMethodTest.xxx_test_raising_exception_on_function_parens +ExtractMethodTest.test_extract_method_and_extra_blank_lines +ExtractMethodTest.test_extract_method_f_string_extract_method +ExtractMethodTest.test_extract_method_f_string_extract_method_complex_expression +ExtractMethodTest.test_extract_method_f_string_false_comment +ExtractMethodTest.test_extract_method_f_string_false_format_value_in_regular_string +ExtractMethodTest.test_variable_writes_in_the_same_line_as_variable_read +ExtractMethodTest.test_variable_writes_in_the_same_line_as_variable_read2 +ExtractMethodTest.test_variable_writes_in_the_same_line_as_variable_read3 +ExtractMethodTest.test_variable_writes_only +ExtractMethodTest.test_variable_and_similar_expressions +ExtractMethodTest.test_definition_should_appear_before_the_first_use +ExtractMethodTest.test_extract_method_and_similar_expressions +ExtractMethodTest.test_simple_extract_method_and_similar_statements +ExtractMethodTest.test_extract_method_and_similar_statements2 +ExtractMethodTest.test_extract_method_and_similar_sttemnts_return_is_different +ExtractMethodTest.test_extract_method_and_similar_sttemnts_overlapping_regions +ExtractMethodTest.test_definition_should_appear_where_it_is_visible +ExtractMethodTest.test_extract_variable_and_similar_statements_in_classes +ExtractMethodTest.test_extract_method_in_staticmethods +ExtractMethodTest.test_extract_normal_method_with_staticmethods +ExtractMethodTest.test_extract_variable_with_no_new_lines_at_the_end +ExtractMethodTest.test_extract_method_containing_return_in_functions +ExtractMethodTest.test_extract_method_and_varying_first_parameter +ExtractMethodTest.test_extract_method_when_an_attribute_exists_in_function_scope +ExtractMethodTest.test_global_option_for_extract_method +ExtractMethodTest.test_global_extract_method +ExtractMethodTest.test_global_extract_method_with_multiple_methods +ExtractMethodTest.test_where_to_seach_when_extracting_global_names +ExtractMethodTest.test_extracting_pieces_with_distinct_temp_names +ExtractMethodTest.test_extract_methods_in_glob_funcs_should_be_glob +ExtractMethodTest.test_extract_methods_in_glob_funcs_should_be_glob_2 +ExtractMethodTest.test_extract_method_and_try_blocks +ExtractMethodTest.test_extract_method_and_augmentedj_assignment_in_try_block +ExtractMethodTest.test_extract_and_not_passing_global_functions +ExtractMethodTest.test_extracting_with_only_one_return +ExtractMethodTest.test_extracting_variable_and_implicit_continuations +ExtractMethodTest.test_extracting_method_and_implicit_continuations +ExtractMethodTest.test_passing_conditional_updated_vars_in_extracted +ExtractMethodTest.test_returning_conditional_updated_vars_in_extracted +ExtractMethodTest.test_extract_method_with_variables_possibly_written_to +ExtractMethodTest.test_extract_method_with_list_comprehension +ExtractMethodTest.test_extract_method_with_list_comprehension_in_class_method +ExtractMethodTest.test_extract_method_with_list_comprehension_and_iter +ExtractMethodTest.test_extract_method_with_list_comprehension_and_orelse +ExtractMethodTest.test_extract_method_with_list_comprehension_multiple_targets +ExtractMethodTest.test_extract_function_with_for_else_statemant +ExtractMethodTest.test_extract_function_with_for_else_statemant_more +ExtractMethodTest.test_extract_function_with_for_else_statemant_outside_loops +ExtractMethodTest.test_extract_function_with_inline_assignment_in_method +ExtractMethodTest.test_extract_function_statement_with_inline_assignment_in_condition +ExtractMethodTest.test_extract_function_expression_with_inline_assignment_in_condition +ExtractMethodTest.test_extract_function_expression_with_inline_assignment_complex +ExtractMethodTest.test_extract_function_expression_with_inline_assignment_in_inner_expression +ExtractMethodTest.test_extract_exec +ExtractMethodTest.test_extract_exec_statement +ExtractMethodTest.test_extract_async_function +ExtractMethodTest.test_extract_inner_async_function +ExtractMethodTest.test_extract_around_inner_async_function +ExtractMethodTest.test_extract_refactor_around_async_for_loop +ExtractMethodTest.test_extract_refactor_containing_async_for_loop_should_error_before_py38 +ExtractMethodTest.test_extract_refactor_containing_async_for_loop_is_supported_after_py38 +ExtractMethodTest.test_extract_await_expression +ExtractMethodTest.test_extract_to_staticmethod +ExtractMethodTest.test_extract_to_staticmethod_when_self_in_body +ExtractMethodTest.test_extract_from_function_to_staticmethod_raises_exception +ExtractMethodTest.test_extract_method_in_classmethods +ExtractMethodTest.test_extract_from_function_to_classmethod_raises_exception +ExtractMethodTest.test_extract_to_classmethod_when_self_in_body +ExtractMethodTest.test_extract_to_classmethod +ExtractMethodTest.test_extract_to_classmethod_when_name_starts_with_at_sign +ExtractMethodTest.test_extract_to_staticmethod_when_name_starts_with_dollar_sign +ExtractMethodTest.test_raises_exception_when_sign_in_name_and_kind_mismatch +ExtractMethodTest.test_extracting_from_static_with_function_arg +ExtractMethodTest.test_extract_with_list_comprehension +ExtractMethodTest.test_extract_with_generator +ExtractMethodTest.test_extract_with_generator_2 +ExtractMethodTest.test_extract_with_set_comprehension +ExtractMethodTest.test_extract_with_dict_comprehension +ExtractMethodTest.test_extract_function_expression_with_assignment_to_attribute +ExtractMethodTest.test_extract_function_expression_with_assignment_index +ExtractMethodTest.test_extraction_method_with_global_variable +ExtractMethodTest.test_extraction_method_with_global_variable_and_global_declaration +ExtractMethodTest.test_extraction_one_line_with_global_variable_read_only +ExtractMethodTest.test_extraction_one_line_with_global_variable +ExtractMethodTest.test_extraction_one_line_with_global_variable_has_postread +ExtractMethodTest.test_extract_method_with_nested_double_with_as +ExtractMethodTest.test_extract_method_with_double_with_as +ExtractMethodTest.test_extract_method_with_nested_double_with_as_and_misleading_comment +ExtractMethodTest.test_extract_method_async_with_simple +ExtractMethodTest.test_extract_method_containing_async_with +ExtractMethodTest.test_extract_method_containing_structural_pattern_match +ExtractMethodTest.test_extract_method_containing_structural_pattern_match_2 +ExtractMethodTest.test_extract_method_containing_structural_pattern_match_3 + + +@clean importutilstest.py +class ImportUtilsTest +ImportUtilsTest.setUp +ImportUtilsTest.tearDown +ImportUtilsTest.test_get_import_for_module +ImportUtilsTest.test_get_import_for_module_in_nested_modules +ImportUtilsTest.test_get_import_for_module_in_init_dot_py +ImportUtilsTest.test_get_from_import_for_module +ImportUtilsTest.test_get_from_import_for_module_in_nested_modules +ImportUtilsTest.test_get_from_import_for_module_in_init_dot_py +ImportUtilsTest.test_get_import_statements +ImportUtilsTest.test_get_import_statements_with_alias +ImportUtilsTest.test_get_import_statements_for_froms +ImportUtilsTest.test_get_multi_line_import_statements_for_froms +ImportUtilsTest.test_get_import_statements_for_from_star +ImportUtilsTest.test_get_import_statements_for_new_relatives +ImportUtilsTest.test_ignoring_indented_imports +ImportUtilsTest.test_import_get_names +ImportUtilsTest.test_import_get_names_with_alias +ImportUtilsTest.test_import_get_names_with_alias2 +ImportUtilsTest.test_empty_getting_used_imports +ImportUtilsTest.test_empty_getting_used_imports2 +ImportUtilsTest.test_simple_getting_used_imports +ImportUtilsTest.test_simple_getting_used_imports2 +ImportUtilsTest.test_getting_used_imports_for_nested_scopes +ImportUtilsTest.test_getting_used_imports_for_nested_scopes2 +ImportUtilsTest.test_empty_removing_unused_imports +ImportUtilsTest.test_simple_removing_unused_imports +ImportUtilsTest.test_simple_removing_unused_imports_for_froms +ImportUtilsTest.test_simple_removing_unused_imports_for_from_stars +ImportUtilsTest.test_simple_removing_unused_imports_for_nested_modules +ImportUtilsTest.test_removing_unused_imports_and_functions_of_the_same_name +ImportUtilsTest.test_removing_unused_imports_for_from_import_with_as +ImportUtilsTest.test_not_removing_imports_that_conflict_with_class_names +ImportUtilsTest.test_adding_imports +ImportUtilsTest.test_adding_imports_no_pull_to_top +ImportUtilsTest.test_adding_from_imports +ImportUtilsTest.test_adding_to_star_imports +ImportUtilsTest.test_adding_star_imports +ImportUtilsTest.test_adding_imports_and_preserving_spaces_after_imports +ImportUtilsTest.test_not_changing_the_format_of_unchanged_imports +ImportUtilsTest.test_not_changing_the_format_of_unchanged_imports2 +ImportUtilsTest.test_removing_unused_imports_and_reoccuring_names +ImportUtilsTest.test_removing_unused_imports_and_reoccuring_names2 +ImportUtilsTest.test_removing_unused_imports_and_common_packages +ImportUtilsTest.test_removing_unused_imports_and_common_packages_reversed +ImportUtilsTest.test_removing_unused_imports_and_common_packages2 +ImportUtilsTest.test_removing_unused_imports_and_froms +ImportUtilsTest.test_removing_unused_imports_and_froms2 +ImportUtilsTest.test_removing_unused_imports_and_froms3 +ImportUtilsTest.test_removing_unused_imports_and_froms4 +ImportUtilsTest.test_removing_unused_imports_and_getting_attributes +ImportUtilsTest.test_removing_unused_imports_function_parameters +ImportUtilsTest.test_trivial_expanding_star_imports +ImportUtilsTest.test_expanding_star_imports +ImportUtilsTest.test_removing_duplicate_imports +ImportUtilsTest.test_removing_duplicates_and_reoccuring_names +ImportUtilsTest.test_removing_duplicate_imports_for_froms +ImportUtilsTest.test_transforming_froms_to_normal_changing_imports +ImportUtilsTest.test_transforming_froms_to_normal_changing_occurrences +ImportUtilsTest.test_transforming_froms_to_normal_for_multi_imports +ImportUtilsTest.test_transform_froms_to_norm_for_multi_imports_inside_parens +ImportUtilsTest.test_transforming_froms_to_normal_from_stars +ImportUtilsTest.test_transforming_froms_to_normal_from_stars2 +ImportUtilsTest.test_transforming_froms_to_normal_from_with_alias +ImportUtilsTest.test_transforming_froms_to_normal_for_relatives +ImportUtilsTest.test_transforming_froms_to_normal_for_os_path +ImportUtilsTest.test_transform_relatives_imports_to_abs_imports_doing_nothing +ImportUtilsTest.test_transform_relatives_to_absolute_imports_for_normal_imports +ImportUtilsTest.test_transform_relatives_imports_to_absolute_imports_for_froms +ImportUtilsTest.test_transform_rel_imports_to_abs_imports_for_new_relatives +ImportUtilsTest.test_transform_relatives_to_absolute_imports_for_normal_imports2 +ImportUtilsTest.test_transform_relatives_to_absolute_imports_for_aliases +ImportUtilsTest.test_organizing_imports +ImportUtilsTest.test_organizing_imports_without_deduplication +ImportUtilsTest.test_splitting_imports +ImportUtilsTest.test_splitting_imports_no_pull_to_top +ImportUtilsTest.test_splitting_imports_with_filter +ImportUtilsTest.test_splitting_duplicate_imports +ImportUtilsTest.test_splitting_duplicate_imports2 +ImportUtilsTest.test_removing_self_imports +ImportUtilsTest.test_removing_self_imports2 +ImportUtilsTest.test_removing_self_imports_with_as +ImportUtilsTest.test_removing_self_imports_for_froms +ImportUtilsTest.test_removing_self_imports_for_froms_with_as +ImportUtilsTest.test_removing_self_imports_for_froms2 +ImportUtilsTest.test_removing_self_imports_for_froms3 +ImportUtilsTest.test_removing_self_imports_for_froms4 +ImportUtilsTest.test_removing_self_imports_with_no_dot_after_mod +ImportUtilsTest.test_removing_self_imports_with_no_dot_after_mod2 +ImportUtilsTest.test_removing_self_imports_for_from_import_star +ImportUtilsTest.test_not_removing_future_imports +ImportUtilsTest.test_sorting_empty_imports +ImportUtilsTest.test_sorting_one_import +ImportUtilsTest.test_sorting_imports_alphabetically +ImportUtilsTest.test_sorting_imports_purely_alphabetically +ImportUtilsTest.test_sorting_imports_and_froms +ImportUtilsTest.test_sorting_imports_and_standard_modules +ImportUtilsTest.test_sorting_imports_and_standard_modules2 +ImportUtilsTest.test_sorting_only_standard_modules +ImportUtilsTest.test_sorting_third_party +ImportUtilsTest.test_sorting_only_third_parties +ImportUtilsTest.test_simple_handling_long_imports +ImportUtilsTest.test_handling_long_imports_for_many_dots +ImportUtilsTest.test_handling_long_imports_for_their_length +ImportUtilsTest.test_handling_long_imports_for_many_dots2 +ImportUtilsTest.test_handling_long_imports_with_one_letter_last +ImportUtilsTest.test_empty_removing_unused_imports_and_eating_blank_lines +ImportUtilsTest.test_sorting_imports_moving_to_top +ImportUtilsTest.test_sorting_imports_moving_to_top2 +ImportUtilsTest.test_sorting_imports_no_pull_to_top +ImportUtilsTest.test_sorting_imports_moving_to_top_and_module_docs +ImportUtilsTest.test_sorting_imports_moving_to_top_and_module_docs2 +ImportUtilsTest.test_get_changed_source_preserves_blank_lines +ImportUtilsTest.test_sorting_future_imports +ImportUtilsTest.test_organizing_imports_all_star +ImportUtilsTest.test_organizing_imports_all_star_with_variables +ImportUtilsTest.test_organizing_imports_all_star_with_inline_if +ImportUtilsTest.test_organizing_imports_all_star_tolerates_non_list_of_str_1 +ImportUtilsTest.test_organizing_imports_all_star_assigned_name_alias +ImportUtilsTest.test_organizing_imports_all_star_imported_name_alias +ImportUtilsTest.test_organizing_imports_all_star_tolerates_non_list_of_str_2 +ImportUtilsTest.test_organizing_imports_all_star_plusjoin +ImportUtilsTest.test_organizing_imports_all_star_starjoin +ImportUtilsTest.test_organizing_imports_all_star_no_infinite_loop +ImportUtilsTest.test_organizing_imports_all_star_resolve_imported_name +ImportUtilsTest.test_organizing_imports_undefined_variable +ImportUtilsTest.test_organizing_imports_undefined_variable_with_imported_name +ImportUtilsTest.test_organizing_indirect_all_star_import +ImportUtilsTest.test_customized_import_organization +ImportUtilsTest.test_customized_import_organization2 +ImportUtilsTest.test_customized_import_organization3 +ImportUtilsTest.test_trivial_filtered_expand_stars +ImportUtilsTest._line_filter +ImportUtilsTest.test_filtered_expand_stars +ImportUtilsTest.test_filtered_relative_to_absolute +ImportUtilsTest.test_filtered_froms_to_normals +ImportUtilsTest.test_filtered_froms_to_normals2 +ImportUtilsTest.test_filtered_handle_long_imports +ImportUtilsTest.test_filtering_and_import_actions_with_more_than_one_phase +ImportUtilsTest.test_non_existent_module_and_used_imports + +class AddImportTest +AddImportTest.setUp +AddImportTest.tearDown +AddImportTest.test_normal_imports +AddImportTest.test_not_reimporting_a_name +AddImportTest.test_adding_import_when_siblings_are_imported +AddImportTest.test_adding_import_when_the_package_is_imported +AddImportTest.test_adding_import_for_modules_instead_of_names +AddImportTest.test_adding_import_for_modules_with_normal_duplicate_imports + + +@clean inlinetest.py +class InlineTest +InlineTest.setUp +InlineTest.tearDown +InlineTest._inline +InlineTest._inline2 +InlineTest.test_simple_case +InlineTest.test_empty_case +InlineTest.test_long_definition +InlineTest.test_explicit_continuation +InlineTest.test_implicit_continuation +InlineTest.test_inlining_at_the_end_of_input +InlineTest.test_on_classes +InlineTest.test_multiple_assignments +InlineTest.test_tuple_assignments +InlineTest.test_on_unknown_vars +InlineTest.test_attribute_inlining +InlineTest.test_attribute_inlining2 +InlineTest.test_a_function_with_no_occurrence +InlineTest.test_a_function_with_no_occurrence2 +InlineTest.test_replacing_calls_with_function_definition_in_other_modules +InlineTest.test_replacing_calls_with_function_definition_in_other_modules2 +InlineTest.test_replacing_calls_with_method_definition_in_other_modules +InlineTest.test_replacing_calls_with_function_definition_in_defining_module +InlineTest.test_replac_calls_with_function_definition_in_defining_module2 +InlineTest.test_replacing_calls_with_method_definition_in_defining_modules +InlineTest.test_parameters_with_the_same_name_as_passed +InlineTest.test_parameters_with_the_same_name_as_passed2 +InlineTest.test_simple_parameters_renaming +InlineTest.test_simple_parameters_renaming_for_multiple_params +InlineTest.test_parameters_renaming_for_passed_constants +InlineTest.test_parameters_renaming_for_passed_statements +InlineTest.test_simple_parameters_renam_for_multiple_params_using_keywords +InlineTest.test_simple_params_renam_for_multi_params_using_mixed_keywords +InlineTest.test_simple_putting_in_default_arguments +InlineTest.test_overriding_default_arguments +InlineTest.test_arguments_containing_comparisons +InlineTest.test_badly_formatted_text +InlineTest.test_passing_first_arguments_for_methods +InlineTest.test_passing_first_arguments_for_methods2 +InlineTest.test_passing_first_arguments_for_methods3 +InlineTest.test_inlining_staticmethods +InlineTest.test_static_methods2 +InlineTest.test_inlining_classmethods +InlineTest.test_inlining_classmethods2 +InlineTest.test_simple_return_values_and_inlining_functions +InlineTest.test_simple_return_values_and_inlining_lonely_functions +InlineTest.test_empty_returns_and_inlining_lonely_functions +InlineTest.test_multiple_returns +InlineTest.test_multiple_returns_and_not_using_the_value +InlineTest.test_raising_exception_for_list_arguments +InlineTest.test_raising_exception_for_list_keywods +InlineTest.test_function_parameters_and_returns_in_other_functions +InlineTest.test_function_references_other_than_call +InlineTest.test_function_referencing_itself +InlineTest.test_recursive_functions +InlineTest.xxx_test_inlining_function_default_parameters +InlineTest.test_simple_inlining_after_extra_indented_lines +InlineTest.test_inlining_a_function_with_pydoc +InlineTest.test_inlining_methods +InlineTest.test_simple_returns_with_backslashes +InlineTest.test_a_function_with_pass_body +InlineTest.test_inlining_the_last_method_of_a_class +InlineTest.test_adding_needed_imports_in_the_dest_module +InlineTest.test_adding_needed_imports_in_the_dest_module_removing_selfs +InlineTest.test_handling_relative_imports_when_inlining +InlineTest.test_adding_needed_imports_for_elements_in_source +InlineTest.test_relative_imports_and_changing_inlining_body +InlineTest.test_inlining_with_different_returns +InlineTest.test_not_removing_definition_for_variables +InlineTest.test_not_removing_definition_for_methods +InlineTest.test_only_current_for_methods +InlineTest.test_only_current_for_variables +InlineTest.test_inlining_one_line_functions +InlineTest.test_inlining_one_line_functions_with_breaks +InlineTest.test_inlining_one_line_functions_with_breaks2 +InlineTest.test_resources_parameter +InlineTest.test_inlining_parameters +InlineTest.test_inlining_function_with_line_breaks_in_args +InlineTest.test_inlining_variables_before_comparison +InlineTest.test_inlining_variables_in_other_modules +InlineTest.test_inlining_variables_and_back_importing +InlineTest.test_inlining_variables_and_importing_used_imports +InlineTest.test_inlining_variables_and_removing_old_froms +InlineTest.test_inlining_method_and_removing_old_froms +InlineTest.test_inlining_functions_in_other_modules_and_only_current +InlineTest.test_inlining_variables_in_other_modules_and_only_current +InlineTest.test_inlining_does_not_change_string_constants +InlineTest.test_inlining_does_change_string_constants_if_docs_is_set +InlineTest.test_inlining_into_format_string +InlineTest.test_inlining_into_format_string_containing_quotes +InlineTest.test_parameters_with_the_same_name_as_passed_with_type_hints +InlineTest.test_parameters_with_the_same_name_as_passed_as_kwargs_with_type_hints +InlineTest.test_simple_parameters_renaming_with_type_hints +InlineTest.test_simple_parameters_renaming_for_multiple_params_with_type_hints +InlineTest.test_parameters_renaming_for_passed_constants_with_type_hints +InlineTest.test_parameters_renaming_for_passed_statements_with_type_hints +InlineTest.test_simple_parameters_renaming_for_multiple_params_using_keywords_with_type_hints +InlineTest.test_simple_params_renaming_for_multi_params_using_mixed_keywords_with_type_hints +InlineTest.test_simple_putting_in_default_arguments_with_type_hints +InlineTest.test_overriding_default_arguments_with_type_hints + + +@clean movetest.py +class MoveRefactoringTest +MoveRefactoringTest.setUp +MoveRefactoringTest.tearDown +MoveRefactoringTest._move +MoveRefactoringTest.test_move_constant +MoveRefactoringTest.test_move_constant_2 +MoveRefactoringTest.test_move_constant_multiline +MoveRefactoringTest.test_move_constant_multiple_statements +MoveRefactoringTest.test_simple_moving +MoveRefactoringTest.test_moving_with_comment_prefix +MoveRefactoringTest.test_moving_with_comment_prefix_imports +MoveRefactoringTest.test_changing_other_modules_replacing_normal_imports +MoveRefactoringTest.test_changing_other_modules_adding_normal_imports +MoveRefactoringTest.test_adding_imports_prefer_from_module +MoveRefactoringTest.test_adding_imports_noprefer_from_module +MoveRefactoringTest.test_adding_imports_prefer_from_module_top_level_module +MoveRefactoringTest.test_changing_other_modules_removing_from_imports +MoveRefactoringTest.test_changing_source_module +MoveRefactoringTest.test_changing_destination_module +MoveRefactoringTest.test_folder_destination +MoveRefactoringTest.test_raising_exception_for_moving_non_global_elements +MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable +MoveRefactoringTest.test_raising_exception_for_mov_glob_elemnts_to_the_same_module +MoveRefactoringTest.test_moving_used_imports_to_destination_module +MoveRefactoringTest.test_moving_used_names_to_destination_module2 +MoveRefactoringTest.test_moving_used_underlined_names_to_destination_module +MoveRefactoringTest.test_moving_and_used_relative_imports +MoveRefactoringTest.test_moving_modules +MoveRefactoringTest.test_moving_modules_and_removing_out_of_date_imports +MoveRefactoringTest.test_moving_modules_and_removing_out_of_date_froms +MoveRefactoringTest.test_moving_modules_and_removing_out_of_date_froms2 +MoveRefactoringTest.test_moving_modules_and_relative_import +MoveRefactoringTest.test_moving_module_kwarg_same_name_as_old +MoveRefactoringTest.test_moving_packages +MoveRefactoringTest.test_moving_modules_with_self_imports +MoveRefactoringTest.test_moving_modules_with_from_imports +MoveRefactoringTest.test_moving_modules_with_from_import +MoveRefactoringTest.test_moving_modules_with_multi_from_imports +MoveRefactoringTest.test_moving_modules_with_from_and_normal_imports +MoveRefactoringTest.test_moving_modules_with_normal_and_from_imports +MoveRefactoringTest.test_moving_modules_from_import_variable +MoveRefactoringTest.test_moving_modules_normal_import +MoveRefactoringTest.test_moving_package_with_from_and_normal_imports +MoveRefactoringTest.test_moving_package_with_from_and_normal_imports2 +MoveRefactoringTest.test_moving_package_and_retaining_blank_lines +MoveRefactoringTest.test_moving_functions_to_imported_module +MoveRefactoringTest.test_moving_resources_using_move_module_refactoring +MoveRefactoringTest.test_moving_resources_using_move_module_for_packages +MoveRefactoringTest.test_moving_resources_using_move_module_for_init_dot_py +MoveRefactoringTest.test_moving_module_and_star_imports +MoveRefactoringTest.test_moving_module_and_not_removing_blanks_after_imports +MoveRefactoringTest.test_moving_module_refactoring_and_nonexistent_destinations +MoveRefactoringTest.test_moving_methods_choosing_the_correct_class +MoveRefactoringTest.test_moving_methods_getting_new_method_for_empty_methods +MoveRefactoringTest.test_moving_methods_getting_new_method_for_constant_methods +MoveRefactoringTest.test_moving_methods_getting_new_method_passing_simple_paremters +MoveRefactoringTest.test_moving_methods_getting_new_method_using_main_object +MoveRefactoringTest.test_moving_methods_getting_new_method_renaming_main_object +MoveRefactoringTest.test_moving_methods_gettin_new_method_with_keyword_arguments +MoveRefactoringTest.test_moving_methods_gettin_new_method_with_many_kinds_arguments +MoveRefactoringTest.test_moving_methods_getting_new_method_for_multi_line_methods +MoveRefactoringTest.test_moving_methods_getting_old_method_for_constant_methods +MoveRefactoringTest.test_moving_methods_getting_getting_changes_for_goal_class +MoveRefactoringTest.test_moving_methods_getting_getting_changes_for_goal_class2 +MoveRefactoringTest.test_moving_methods_and_nonexistent_attributes +MoveRefactoringTest.test_unknown_attribute_type +MoveRefactoringTest.test_moving_methods_and_moving_used_imports +MoveRefactoringTest.test_moving_methods_getting_getting_changes_for_goal_class3 +MoveRefactoringTest.test_moving_methods_and_source_class_with_parameters +MoveRefactoringTest.test_moving_globals_to_a_module_with_only_docstrings +MoveRefactoringTest.test_moving_globals_to_a_module_with_only_docstrings2 +MoveRefactoringTest.test_moving_a_global_when_it_is_used_after_a_multiline_str +MoveRefactoringTest.test_raising_an_exception_when_moving_non_package_folders +MoveRefactoringTest.test_moving_to_a_module_with_encoding_cookie +MoveRefactoringTest.test_moving_decorated_function +MoveRefactoringTest.test_moving_decorated_class + + +@clean multiprojecttest.py +class MultiProjectRefactoringTest +MultiProjectRefactoringTest.setUp +MultiProjectRefactoringTest.tearDown +MultiProjectRefactoringTest.test_trivial_rename +MultiProjectRefactoringTest.test_rename +MultiProjectRefactoringTest.test_move +MultiProjectRefactoringTest.test_rename_from_the_project_not_containing_the_change + + +@clean patchedasttest.py +class PatchedASTTest +PatchedASTTest.setUp +PatchedASTTest.tearDown +PatchedASTTest.assert_single_case_match_block +PatchedASTTest.test_bytes_string +PatchedASTTest.test_integer_literals_and_region +PatchedASTTest.test_negative_integer_literals_and_region +PatchedASTTest.test_scientific_integer_literals_and_region +PatchedASTTest.test_hex_integer_literals_and_region +PatchedASTTest.test_long_literals_and_region +PatchedASTTest.test_octal_integer_literals_and_region +PatchedASTTest.test_integer_literals_and_sorted_children +PatchedASTTest.test_ellipsis +PatchedASTTest.test_ass_name_node +PatchedASTTest.test_assign_node +PatchedASTTest.test_ann_assign_node_without_target +PatchedASTTest.test_ann_assign_node_with_target +PatchedASTTest.test_add_node +PatchedASTTest.test_lshift_node +PatchedASTTest.test_and_node +PatchedASTTest.test_matmult_node +PatchedASTTest.test_basic_closing_parens +PatchedASTTest.test_basic_opening_parens +PatchedASTTest.test_basic_opening_biway +PatchedASTTest.test_basic_opening_double +PatchedASTTest.test_handling_comments +PatchedASTTest.test_handling_parens_with_spaces +PatchedASTTest.test_handling_strings +PatchedASTTest.test_handling_implicit_string_concatenation +PatchedASTTest.test_handling_implicit_string_concatenation_line_breaks +PatchedASTTest.test_handling_explicit_string_concatenation_line_breaks +PatchedASTTest.test_not_concatenating_strings_on_separate_lines +PatchedASTTest.test_handling_raw_strings +PatchedASTTest.test_handling_format_strings_basic +PatchedASTTest.test_handling_format_strings_with_implicit_join +PatchedASTTest.test_handling_format_strings_with_format_spec +PatchedASTTest.test_handling_format_strings_with_inner_format_spec +PatchedASTTest.test_handling_format_strings_with_expression +PatchedASTTest.test_long_integer_literals +PatchedASTTest.test_complex_number_literals +PatchedASTTest.test_ass_attr_node +PatchedASTTest.test_ass_list_node +PatchedASTTest.test_ass_tuple +PatchedASTTest.test_ass_tuple2 +PatchedASTTest.test_assert +PatchedASTTest.test_assert2 +PatchedASTTest.test_aug_assign_node +PatchedASTTest.test_back_quotenode +PatchedASTTest.test_bitand +PatchedASTTest.test_bitor +PatchedASTTest.test_call_func +PatchedASTTest.test_call_func_and_keywords +PatchedASTTest.test_call_func_and_star_args +PatchedASTTest.test_call_func_and_star_argspython35 +PatchedASTTest.test_call_func_and_only_dstar_args +PatchedASTTest.test_call_func_and_only_dstar_args_python35 +PatchedASTTest.test_call_func_and_both_varargs_and_kwargs +PatchedASTTest.test_call_func_and_both_varargs_and_kwargs_python35 +PatchedASTTest.test_class_node +PatchedASTTest.test_class_with_no_bases +PatchedASTTest.test_simple_compare +PatchedASTTest.test_multiple_compare +PatchedASTTest.test_decorators_node +PatchedASTTest.test_decorators_for_classes +PatchedASTTest.test_both_varargs_and_kwargs +PatchedASTTest.test_function_node +PatchedASTTest.test_async_function_node +PatchedASTTest.test_function_node2 +PatchedASTTest.test_function_node_and_tuple_parameters +PatchedASTTest.test_dict_node +PatchedASTTest.test_dict_node_with_unpacking +PatchedASTTest.test_div_node +PatchedASTTest.test_simple_exec_node +PatchedASTTest.test_exec_node +PatchedASTTest.test_exec_node_with_parens +PatchedASTTest.test_for_node +PatchedASTTest.test_async_for_node +PatchedASTTest.test_named_expr_node +PatchedASTTest.test_normal_from_node +PatchedASTTest.test_from_node +PatchedASTTest.test_from_node_relative_import +PatchedASTTest.test_simple_gen_expr_node +PatchedASTTest.test_gen_expr_node_handling_surrounding_parens +PatchedASTTest.test_gen_expr_node2 +PatchedASTTest.test_get_attr_node +PatchedASTTest.test_global_node +PatchedASTTest.test_if_node +PatchedASTTest.test_if_node2 +PatchedASTTest.test_if_node3 +PatchedASTTest.test_import_node +PatchedASTTest.test_lambda_node +PatchedASTTest.test_list_node +PatchedASTTest.test_list_comp_node +PatchedASTTest.test_list_comp_node_with_multiple_comprehensions +PatchedASTTest.test_set_node +PatchedASTTest.test_set_comp_node +PatchedASTTest.test_dict_comp_node +PatchedASTTest.test_ext_slice_node +PatchedASTTest.test_simple_module_node +PatchedASTTest.test_module_node +PatchedASTTest.test_not_and_or_nodes +PatchedASTTest.test_print_node +PatchedASTTest.test_printnl_node +PatchedASTTest.test_raise_node_for_python2 +PatchedASTTest.test_raise_node_for_python3 +PatchedASTTest.test_return_node +PatchedASTTest.test_empty_return_node +PatchedASTTest.test_simple_slice_node +PatchedASTTest.test_slice_node2 +PatchedASTTest.test_simple_subscript +PatchedASTTest.test_tuple_node +PatchedASTTest.test_tuple_node2 +PatchedASTTest.test_tuple_with_complex_parentheses1 +PatchedASTTest.test_tuple_with_complex_parentheses2 +PatchedASTTest.test_tuple_with_complex_parentheses3 +PatchedASTTest.test_one_item_tuple_node +PatchedASTTest.test_empty_tuple_node +PatchedASTTest.test_empty_tuple_node2 +PatchedASTTest.test_empty_tuple_node3 +PatchedASTTest.test_yield_node +PatchedASTTest.test_yield_from_node +PatchedASTTest.test_while_node +PatchedASTTest.test_with_node +PatchedASTTest.test_async_with_node +PatchedASTTest.test_try_finally_node +PatchedASTTest.test_try_except_node +PatchedASTTest.test_try_except_node__with_as_syntax +PatchedASTTest.test_try_except_and_finally_node +PatchedASTTest.test_ignoring_comments +PatchedASTTest.test_simple_sliceobj +PatchedASTTest.test_ignoring_strings_that_start_with_a_char +PatchedASTTest.test_how_to_handle_old_not_equals +PatchedASTTest.test_semicolon +PatchedASTTest.test_if_exp_node +PatchedASTTest.test_delete_node +PatchedASTTest.test_starargs_before_keywords_legacy +PatchedASTTest.test_starargs_in_keywords_legacy +PatchedASTTest.test_starargs_after_keywords_legacy +PatchedASTTest.test_starargs_before_keywords +PatchedASTTest.test_starargs_in_keywords +PatchedASTTest.test_starargs_in_positional +PatchedASTTest.test_starargs_after_keywords +PatchedASTTest.test_await_node +PatchedASTTest.test_match_node_with_constant_match_value +PatchedASTTest.test_match_node_match_case_with_guard +PatchedASTTest.test_match_node_with_match_class +PatchedASTTest.test_match_node_with_wildcard +PatchedASTTest.test_match_node_with_match_as_capture_pattern +PatchedASTTest.test_match_node_with_match_as_capture_pattern_with_explicit_name +PatchedASTTest.test_match_node_with_match_class_simple_match_as_capture_pattern +PatchedASTTest.test_match_node_with_match_class_named_argument +PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name + +class _ResultChecker +_ResultChecker.__init__ +_ResultChecker.check_region +_ResultChecker._find_node +_ResultChecker.__call__ + +_ResultChecker.check_children + + +@clean renametest.py +class RenameRefactoringTest +RenameRefactoringTest.setUp +RenameRefactoringTest.tearDown +RenameRefactoringTest._local_rename +RenameRefactoringTest._rename +RenameRefactoringTest.test_local_variable_but_not_parameter +RenameRefactoringTest.test_simple_global_variable_renaming +RenameRefactoringTest.test_variable_renaming_only_in_its_scope +RenameRefactoringTest.test_not_renaming_dot_name +RenameRefactoringTest.test_renaming_multiple_names_in_the_same_line +RenameRefactoringTest.test_renaming_names_when_getting_some_attribute +RenameRefactoringTest.test_renaming_names_when_getting_some_attribute2 +RenameRefactoringTest.test_renaming_function_parameters1 +RenameRefactoringTest.test_renaming_function_parameters2 +RenameRefactoringTest.test_renaming_occurrences_inside_functions +RenameRefactoringTest.test_renaming_comprehension_loop_variables +RenameRefactoringTest.test_renaming_list_comprehension_loop_variables_in_assignment +RenameRefactoringTest.test_renaming_generator_comprehension_loop_variables +RenameRefactoringTest.test_renaming_comprehension_loop_variables_scope +RenameRefactoringTest.test_renaming_inline_assignment +RenameRefactoringTest.test_renaming_arguments_for_normal_args_changing_calls +RenameRefactoringTest.test_renaming_function_parameters_of_class_init +RenameRefactoringTest.test_rename_functions_parameters_and_occurences_in_other_modules +RenameRefactoringTest.test_renaming_with_backslash_continued_names +RenameRefactoringTest.test_renaming_occurrence_in_f_string +RenameRefactoringTest.test_renaming_occurrence_in_nested_f_string +RenameRefactoringTest.test_not_renaming_string_contents_in_f_string +RenameRefactoringTest.test_not_renaming_string_contents +RenameRefactoringTest.test_not_renaming_comment_contents +RenameRefactoringTest.test_renaming_all_occurrences_in_containing_scope +RenameRefactoringTest.test_renaming_a_variable_with_arguement_name +RenameRefactoringTest.test_renaming_an_arguement_with_variable_name +RenameRefactoringTest.test_renaming_function_with_local_variable_name +RenameRefactoringTest.test_renaming_functions +RenameRefactoringTest.test_renaming_async_function +RenameRefactoringTest.test_renaming_await +RenameRefactoringTest.test_renaming_functions_across_modules +RenameRefactoringTest.test_renaming_functions_across_modules_from_import +RenameRefactoringTest.test_renaming_functions_from_another_module +RenameRefactoringTest.test_applying_all_changes_together +RenameRefactoringTest.test_renaming_modules +RenameRefactoringTest.test_renaming_modules_aliased +RenameRefactoringTest.test_renaming_packages +RenameRefactoringTest.test_module_dependencies +RenameRefactoringTest.test_renaming_class_attributes +RenameRefactoringTest.test_renaming_class_attributes2 +RenameRefactoringTest.test_renaming_methods_in_subclasses +RenameRefactoringTest.test_renaming_methods_in_sibling_classes +RenameRefactoringTest.test_not_renaming_methods_in_hierarchies +RenameRefactoringTest.test_undoing_refactorings +RenameRefactoringTest.test_undoing_renaming_modules +RenameRefactoringTest.test_rename_in_module_renaming_one_letter_names_for_expressions +RenameRefactoringTest.test_renaming_for_loop_variable +RenameRefactoringTest.test_renaming_async_for_loop_variable +RenameRefactoringTest.test_renaming_async_with_context_manager +RenameRefactoringTest.test_renaming_async_with_as_variable +RenameRefactoringTest.test_renaming_parameters +RenameRefactoringTest.test_renaming_assigned_parameters +RenameRefactoringTest.test_renaming_parameters_not_renaming_others +RenameRefactoringTest.test_renaming_parameters_not_renaming_others2 +RenameRefactoringTest.test_renaming_parameters_with_multiple_params +RenameRefactoringTest.test_renaming_parameters_with_multiple_params2 +RenameRefactoringTest.test_renaming_parameters_on_calls +RenameRefactoringTest.test_renaming_parameters_spaces_before_call +RenameRefactoringTest.test_renaming_parameter_like_objects_after_keywords +RenameRefactoringTest.test_renaming_variables_in_init_dot_pys +RenameRefactoringTest.test_renaming_variables_in_init_dot_pys2 +RenameRefactoringTest.test_renaming_variables_in_init_dot_pys3 +RenameRefactoringTest.test_renaming_resources_using_rename_module_refactoring +RenameRefactoringTest.test_renam_resources_using_rename_module_refactor_for_packages +RenameRefactoringTest.test_renam_resources_use_rename_module_refactor_for_init_dot_py +RenameRefactoringTest.test_renaming_global_variables +RenameRefactoringTest.test_renaming_global_variables2 +RenameRefactoringTest.test_renaming_when_unsure +RenameRefactoringTest._true +RenameRefactoringTest.test_renaming_when_unsure_with_confirmation +RenameRefactoringTest.test_renaming_when_unsure_not_renaming_knowns +RenameRefactoringTest.test_renaming_in_strings_and_comments +RenameRefactoringTest.test_not_renaming_in_strings_and_comments_where_not_visible +RenameRefactoringTest.test_not_renaming_all_text_occurrences_in_strings_and_comments +RenameRefactoringTest.test_renaming_occurrences_in_overwritten_scopes +RenameRefactoringTest.test_renaming_occurrences_in_overwritten_scopes2 +RenameRefactoringTest.test_renaming_in_generalized_dict_unpacking +RenameRefactoringTest.test_dos_line_ending_and_renaming +RenameRefactoringTest.test_multi_byte_strs_and_renaming +RenameRefactoringTest.test_resources_parameter +RenameRefactoringTest.test_resources_parameter_not_changing_defining_module +RenameRefactoringTest.xxx_test_with_statement_variables_should_not_leak +RenameRefactoringTest.test_rename_in_list_comprehension +RenameRefactoringTest.test_renaming_modules_aliased_with_dots +RenameRefactoringTest.test_renaming_modules_aliased_many_dots + +class ChangeOccurrencesTest +ChangeOccurrencesTest.setUp +ChangeOccurrencesTest.tearDown +ChangeOccurrencesTest.test_simple_case +ChangeOccurrencesTest.test_only_performing_inside_scopes +ChangeOccurrencesTest.test_only_performing_on_calls +ChangeOccurrencesTest.test_only_performing_on_reads + +class ImplicitInterfacesTest +ImplicitInterfacesTest.setUp +ImplicitInterfacesTest.tearDown +ImplicitInterfacesTest._rename +ImplicitInterfacesTest.test_performing_rename_on_parameters + + +@clean restructuretest.py +class RestructureTest +RestructureTest.setUp +RestructureTest.tearDown +RestructureTest.test_trivial_case +RestructureTest.test_replacing_simple_patterns +RestructureTest.test_replacing_patterns_with_normal_names +RestructureTest.test_replacing_patterns_with_any_names +RestructureTest.test_replacing_patterns_with_any_names2 +RestructureTest.test_replacing_patterns_with_checks +RestructureTest.test_replacing_assignments_with_sets +RestructureTest.test_replacing_sets_with_assignments +RestructureTest.test_using_make_checks +RestructureTest.test_using_make_checking_builtin_types +RestructureTest.test_auto_indentation_when_no_indentation +RestructureTest.test_auto_indentation +RestructureTest.test_auto_indentation_and_not_indenting_blanks +RestructureTest.test_importing_names +RestructureTest.test_not_importing_names_when_there_are_no_changes +RestructureTest.test_handling_containing_matches +RestructureTest.test_handling_overlapping_matches +RestructureTest.test_preventing_stack_overflow_when_matching +RestructureTest.test_performing_a_restructuring_to_all_modules +RestructureTest.test_performing_a_restructuring_to_selected_modules +RestructureTest.test_unsure_argument_of_default_wildcard +RestructureTest.test_statement_after_string_and_column +RestructureTest.test_yield_from + + +@clean similarfindertest.py +class SimilarFinderTest +SimilarFinderTest.setUp +SimilarFinderTest.tearDown +SimilarFinderTest._create_finder +SimilarFinderTest.test_trivial_case +SimilarFinderTest.test_constant_integer +SimilarFinderTest.test_bool_is_not_similar_to_integer +SimilarFinderTest.test_simple_addition +SimilarFinderTest.test_simple_addition2 +SimilarFinderTest.test_simple_assign_statements +SimilarFinderTest.test_simple_multiline_statements +SimilarFinderTest.test_multiple_matches +SimilarFinderTest.test_multiple_matches2 +SimilarFinderTest.test_restricting_the_region_to_search +SimilarFinderTest.test_matching_basic_patterns +SimilarFinderTest.test_match_get_ast +SimilarFinderTest.test_match_get_ast_for_statements +SimilarFinderTest.test_matching_multiple_patterns +SimilarFinderTest.test_matching_any_patterns +SimilarFinderTest.test_matching_any_patterns_repeating +SimilarFinderTest.test_matching_any_patterns_not_matching_different_nodes +SimilarFinderTest.test_matching_normal_names_and_assname +SimilarFinderTest.test_matching_normal_names_and_assname2 +SimilarFinderTest.test_matching_normal_names_and_attributes +SimilarFinderTest.test_functions_not_matching_when_only_first_parameters +SimilarFinderTest.test_matching_nested_try_finally +SimilarFinderTest.test_matching_dicts_inside_functions + +class CheckingFinderTest +CheckingFinderTest.setUp +CheckingFinderTest.tearDown +CheckingFinderTest.test_trivial_case +CheckingFinderTest.test_simple_finding +CheckingFinderTest.test_not_matching_when_the_name_does_not_match +CheckingFinderTest.test_not_matching_unknowns_finding +CheckingFinderTest.test_finding_and_matching_pyobjects +CheckingFinderTest.test_finding_and_matching_types +CheckingFinderTest.test_checking_the_type_of_an_ass_name_node +CheckingFinderTest.test_checking_instance_of_an_ass_name_node +CheckingFinderTest.test_checking_equality_of_imported_pynames + +class TemplateTest +TemplateTest.test_simple_templates +TemplateTest.test_ignoring_matches_in_comments +TemplateTest.test_ignoring_matches_in_strings +TemplateTest.test_simple_substitution +TemplateTest.test_substituting_multiple_names + + +@clean suitestest.py +class SuiteTest +SuiteTest.setUp +SuiteTest.tearDown +SuiteTest.test_trivial_case +SuiteTest.test_simple_ifs +SuiteTest.test_simple_else +SuiteTest.test_for +SuiteTest.test_while +SuiteTest.test_with +SuiteTest.test_try_finally +SuiteTest.test_try_except +SuiteTest.test_try_except_finally +SuiteTest.test_local_start_and_end +SuiteTest.test_find_suite +SuiteTest.test_find_suite_for_ifs +SuiteTest.test_find_suite_for_between_suites +SuiteTest.test_simple_find_visible +SuiteTest.test_simple_find_visible_ifs +SuiteTest.test_simple_find_visible_for_else +SuiteTest.test_simple_find_visible_for_different_suites +SuiteTest.test_not_always_selecting_scope_start +SuiteTest.test_ignoring_functions +SuiteTest.test_ignoring_classes +SuiteTest.test_match_case + +source_suite_tree + +@clean usefunctiontest.py +class UseFunctionTest +UseFunctionTest.setUp +UseFunctionTest.tearDown +UseFunctionTest.test_simple_case +UseFunctionTest.test_simple_function +UseFunctionTest.test_simple_function2 +UseFunctionTest.test_functions_with_multiple_statements +UseFunctionTest.test_returning +UseFunctionTest.test_returning_a_single_expression +UseFunctionTest.test_occurrences_in_other_modules +UseFunctionTest.test_when_performing_on_non_functions +UseFunctionTest.test_differing_in_the_inner_temp_names +UseFunctionTest.xxx_test_being_a_bit_more_intelligent_when_returning_assigneds +UseFunctionTest.test_exception_when_performing_a_function_with_yield +UseFunctionTest.test_exception_when_performing_a_function_two_returns +UseFunctionTest.test_exception_when_returns_is_not_the_last_statement + + + + + + +Recent files + + + + + + + + +Recent code +--- Old/closed PRs +=== PR #5: (closed) Remove python2 code +=== PR #540: (closed) closed: ekr-clean-pyflakes + +--- To do: create new issues +--- Possible bugs (new rope issues?) +--- possible bug in AbstractClass.get_name + + +--- class hierarch for _PyModule + + + + + +--- possible bug in utils.py: resolve_type + + + +=== PR/issue: xxx Fix pylint errors +=== PR/issue: fix minor flake8 errors +--- flake8 minor errors + +=== PR/issue: xxx Full coverage +=== PR/issue: xxx Remove @deprecated +=== PR/issue: xxx Remove only_for decorator + +Found 38:only_for +--- 2.x + + + + + + + + + + + + + + + + + + + +--- 3.x + + + + + + + + + + + + + + + + + + + + + + +=== PR/Issue: xxx Use f-strings +Found 49:".*{} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +=== PR #539: ekr-dummy-classes +=== PR #528: ekr-walk-special cases +--- self.module: None vs. "" +--- recent + + + + + +Found 7:def get_module + + + + + + + + +Found 4:def get_pymodule + + + + + +Found 9:def get_object + + + + + + + + + + + +--- traces + + + +------ testing sequence + + + + + + + + + +Results + +Found 8:ImportFrom + + + + + + +Found 23:PyModule + + + + + + + + + + + + + + + + +Found 8:PyPackage + + + + + + + + + + +diff master..HEAD (ekr-walk-special-case) +diff: rope/base/ast.py +diff: Changed +diff: walk +Old:walk + + + + +diff: rope/base/pyobjectsdef.py +diff: Changed +diff: _ScopeVisitor._ImportFrom (trace) +Old:_ScopeVisitor._ImportFrom (trace) + + + + + + + +diff master..HEAD (ekr-reorg) +--- Deleted +Deleted: rope/base/ast.py +Deleted: rope/base/pynamesdef.py + +--- New (rewritten) +diff: rope/base/astutils.py +diff: Changed +diff: rope/base/astutils.py:HEAD +Old:rope/base/astutils.py:HEAD + + +diff: _NodeNameCollector._Tuple +Old:_NodeNameCollector._Tuple + + +diff: _NodeNameCollector._Slice +Old:_NodeNameCollector._Slice + + + + + +--- Changed docstrings +diff: rope/base/oi/type_hinting/providers/composite.py +diff: Changed +diff: AssignmentProvider.__call__ +Old:AssignmentProvider.__call__ + + + + +diff: rope/base/oi/type_hinting/providers/docstrings.py +diff: Changed +diff: AssignmentProvider.__call__ +Old:AssignmentProvider.__call__ + + + + +diff: rope/base/oi/type_hinting/providers/inheritance.py +diff: Changed +diff: AssignmentProvider.__call__ +Old:AssignmentProvider.__call__ + + + + +diff: rope/base/oi/type_hinting/providers/interfaces.py +diff: Changed +diff: ITypeHintingFactory.make_assignment_provider +Old:ITypeHintingFactory.make_assignment_provider + + + + +diff: rope/base/oi/type_hinting/providers/pep0484_type_comments.py +diff: Changed +diff: AssignmentProvider.__call__ +Old:AssignmentProvider.__call__ + + + + +diff: rope/base/oi/type_hinting/utils.py +diff: Changed +diff: path_relative_to_project_root +Old:path_relative_to_project_root + + +diff: relative +Old:relative + + + + + +--- Cleaned imports +diff: rope/base/pycore.py +diff: Changed +diff: rope/base/pycore.py:HEAD +Old:rope/base/pycore.py:HEAD + + + + + +--- Major changes +diff: rope/base/pynames.py +diff: Changed +diff: rope/base/pynames.py:HEAD +Old:rope/base/pynames.py:HEAD + + +diff: AssignedName.__init__ +Old:AssignedName.__init__ + + +diff: ParameterName.__init__ +Old:ParameterName.__init__ + + + + + +--- Changed imports & qualifiers +diff: rope/base/arguments.py +diff: Changed +diff: rope/base/arguments.py:HEAD +Old:rope/base/arguments.py:HEAD + + + + +diff: rope/base/evaluate.py +diff: Changed +diff: rope/base/evaluate.py:HEAD +Old:rope/base/evaluate.py:HEAD + + +diff: eval_node2 +Old:eval_node2 + + +diff: eval_str2 +Old:eval_str2 + + +diff: ScopeNameFinder.get_primary_and_pyname_at +Old:ScopeNameFinder.get_primary_and_pyname_at + + +diff: ScopeNameFinder._find_module +Old:ScopeNameFinder._find_module + + +diff: StatementEvaluator._Attribute +Old:StatementEvaluator._Attribute + + +diff: StatementEvaluator._Call +Old:StatementEvaluator._Call + + +diff: StatementEvaluator._Str +Old:StatementEvaluator._Str + + +diff: StatementEvaluator._get_builtin_name +Old:StatementEvaluator._get_builtin_name + + +diff: StatementEvaluator._BinOp +Old:StatementEvaluator._BinOp + + +diff: StatementEvaluator._BoolOp +Old:StatementEvaluator._BoolOp + + +diff: StatementEvaluator._UnaryOp +Old:StatementEvaluator._UnaryOp + + +diff: StatementEvaluator._Dict +Old:StatementEvaluator._Dict + + +diff: StatementEvaluator._List +Old:StatementEvaluator._List + + +diff: StatementEvaluator._ListComp +Old:StatementEvaluator._ListComp + + +diff: StatementEvaluator._GeneratorExp +Old:StatementEvaluator._GeneratorExp + + +diff: StatementEvaluator._Tuple +Old:StatementEvaluator._Tuple + + +diff: StatementEvaluator._call_function +Old:StatementEvaluator._call_function + + +diff: StatementEvaluator._Lambda +Old:StatementEvaluator._Lambda + + +diff: _get_evaluated_names +Old:_get_evaluated_names + + + + +diff: rope/base/oi/soa.py +diff: Changed +diff: rope/base/oi/soa.py:HEAD +Old:rope/base/oi/soa.py:HEAD + + +diff: _analyze_node +Old:_analyze_node + + +diff: SOAVisitor._Call +Old:SOAVisitor._Call + + +diff: SOAVisitor._AnnAssign +Old:SOAVisitor._AnnAssign + + +diff: SOAVisitor._Assign +Old:SOAVisitor._Assign + + +diff: SOAVisitor._evaluate_assign_value +Old:SOAVisitor._evaluate_assign_value + + +diff: class _SOAAssignVisitor +Old:class _SOAAssignVisitor + + +diff: _SOAAssignVisitor._added +Old:_SOAAssignVisitor._added + + + + +diff: rope/base/oi/soi.py +diff: Changed +diff: rope/base/oi/soi.py:HEAD +Old:rope/base/oi/soi.py:HEAD + + +diff: _infer_assignment & helpers +Old:_infer_assignment & helpers + + +diff: _follow_pyname +Old:_follow_pyname + + + + +diff: rope/base/pyobjects.py +diff: Changed +diff: rope/base/pyobjects.py:HEAD +Old:rope/base/pyobjects.py:HEAD + + +diff: PyDefinedObject.get_doc (changed) +Old:PyDefinedObject.get_doc (changed) + + +diff: PyDefinedObject._create_structural_attributes +Old:PyDefinedObject._create_structural_attributes + + + + +diff: rope/base/pyobjectsdef.py +diff: Changed +diff: << imports: pyobjectsdef >> +Old:<< imports: pyobjectsdef >> + + +diff: PyModule.__init__ +Old:PyModule.__init__ + + +diff: PyModule._init_source +Old:PyModule._init_source + + +diff: PyPackage.__init__ +Old:PyPackage.__init__ + + +diff: _AnnAssignVisitor._AnnAssign +Old:_AnnAssignVisitor._AnnAssign + + +diff: _AnnAssignVisitor._Tuple +Old:_AnnAssignVisitor._Tuple + + +diff: _ExpressionVisitor._NamedExpr +Old:_ExpressionVisitor._NamedExpr + + +diff: _AssignVisitor._Assign +Old:_AssignVisitor._Assign + + +diff: _AssignVisitor._Tuple +Old:_AssignVisitor._Tuple + + +diff: _ScopeVisitor._Assign +Old:_ScopeVisitor._Assign + + +diff: _ScopeVisitor._AnnAssign +Old:_ScopeVisitor._AnnAssign + + +diff: _ScopeVisitor._For +Old:_ScopeVisitor._For + + +diff: _ScopeVisitor._update_evaluated +Old:_ScopeVisitor._update_evaluated + + +diff: _ScopeVisitor._With +Old:_ScopeVisitor._With + + +diff: _ScopeVisitor._excepthandler +Old:_ScopeVisitor._excepthandler + + +diff: _ComprehensionVisitor._comprehension +Old:_ComprehensionVisitor._comprehension + + +diff: _ClassVisitor._FunctionDef +Old:_ClassVisitor._FunctionDef + + +diff: _ClassInitVisitor._Tuple +Old:_ClassInitVisitor._Tuple + + + + +diff: rope/base/pyscopes.py +diff: Changed +diff: rope/base/pyscopes.py:HEAD +Old:rope/base/pyscopes.py:HEAD + + +diff: ComprehensionScope._visit_comprehension +Old:ComprehensionScope._visit_comprehension + + +diff: FunctionScope._visit_function +Old:FunctionScope._visit_function + + + + +diff: rope/contrib/codeassist.py +diff: Changed +diff: rope/contrib/codeassist.py:HEAD +Old:rope/contrib/codeassist.py:HEAD + + +diff: get_canonical_path +Old:get_canonical_path + + + + +diff: rope/contrib/finderrors.py +diff: Changed +diff: rope/contrib/finderrors.py:HEAD +Old:rope/contrib/finderrors.py:HEAD + + +diff: find_errors +Old:find_errors + + +diff: _BadAccessFinder._Attribute +Old:_BadAccessFinder._Attribute + + + + +diff: rope/contrib/generate.py +diff: Changed +diff: rope/contrib/generate.py:HEAD +Old:rope/contrib/generate.py:HEAD + + + + +diff: rope/refactor/extract.py +diff: Changed +diff: rope/refactor/extract.py:HEAD +Old:rope/refactor/extract.py:HEAD + + +diff: _ExtractMethodParts._create_info_collector +Old:_ExtractMethodParts._create_info_collector + + +diff: _ExtractMethodParts._get_globals_in_body +Old:_ExtractMethodParts._get_globals_in_body + + +diff: _FunctionInformationCollector._FunctionDef +Old:_FunctionInformationCollector._FunctionDef + + +diff: _FunctionInformationCollector._MatchAs +Old:_FunctionInformationCollector._MatchAs + + +diff: _FunctionInformationCollector._Assign +Old:_FunctionInformationCollector._Assign + + +diff: _FunctionInformationCollector._AugAssign +Old:_FunctionInformationCollector._AugAssign + + +diff: _FunctionInformationCollector._comp_exp +Old:_FunctionInformationCollector._comp_exp + + +diff: _FunctionInformationCollector._For +Old:_FunctionInformationCollector._For + + +diff: _FunctionInformationCollector._handle_conditional_node +Old:_FunctionInformationCollector._handle_conditional_node + + +diff: _VariableReadsAndWritesFinder._FunctionDef +Old:_VariableReadsAndWritesFinder._FunctionDef + + +diff: _VariableReadsAndWritesFinder.find_reads_and_writes +Old:_VariableReadsAndWritesFinder.find_reads_and_writes + + +diff: _VariableReadsAndWritesFinder.find_reads_for_one_liners +Old:_VariableReadsAndWritesFinder.find_reads_for_one_liners + + +diff: _BaseErrorFinder.has_errors +Old:_BaseErrorFinder.has_errors + + +diff: _UnmatchedBreakOrContinueFinder.loop_encountered +Old:_UnmatchedBreakOrContinueFinder.loop_encountered + + + + +diff: rope/refactor/importutils/module_imports.py +diff: Changed +diff: rope/refactor/importutils/module_imports.py:HEAD +Old:rope/refactor/importutils/module_imports.py:HEAD + + +diff: ModuleImports._get_unbound_names +Old:ModuleImports._get_unbound_names + + +diff: ModuleImports._get_all_star_list +Old:ModuleImports._get_all_star_list + + +diff: _UnboundNameFinder._visit_child_scope +Old:_UnboundNameFinder._visit_child_scope + + +diff: _UnboundNameFinder._Attribute +Old:_UnboundNameFinder._Attribute + + + + +diff: rope/refactor/patchedast.py +diff: Changed +diff: rope/refactor/patchedast.py:HEAD +Old:rope/refactor/patchedast.py:HEAD + + +diff: get_patched_ast +Old:get_patched_ast + + +diff: patch_ast +Old:patch_ast + + +diff: _PatchingASTWalker.__call__ +Old:_PatchingASTWalker.__call__ + + +diff: _PatchingASTWalker._handle (changed) +Old:_PatchingASTWalker._handle (changed) + + +diff: _Source.consume (changed) +Old:_Source.consume (changed) + + + + +diff: rope/refactor/restructure.py +diff: Changed +diff: rope/refactor/restructure.py:HEAD +Old:rope/refactor/restructure.py:HEAD + + +diff: _ChangeComputer._get_nearest_roots +Old:_ChangeComputer._get_nearest_roots + + + + +diff: rope/refactor/similarfinder.py +diff: Changed +diff: rope/refactor/similarfinder.py:HEAD +Old:rope/refactor/similarfinder.py:HEAD + + +diff: RawSimilarFinder.__init__ +Old:RawSimilarFinder.__init__ + + +diff: RawSimilarFinder._create_pattern +Old:RawSimilarFinder._create_pattern + + +diff: _ASTMatcher.find_matches +Old:_ASTMatcher.find_matches + + +diff: _ASTMatcher._check_statements +Old:_ASTMatcher._check_statements + + +diff: _ASTMatcher._get_children +Old:_ASTMatcher._get_children + + + + + +diff: rope/refactor/suites.py +diff: Changed +diff: rope/refactor/suites.py:HEAD +Old:rope/refactor/suites.py:HEAD + + +diff: Suite.get_children +Old:Suite.get_children + + + + +diff: rope/refactor/usefunction.py +diff: Changed +diff: rope/refactor/usefunction.py:HEAD +Old:rope/refactor/usefunction.py:HEAD + + +diff: _ReturnOrYieldFinder.start_walking +Old:_ReturnOrYieldFinder.start_walking + + + + +diff: rope/refactor/wildcards.py +diff: Changed +diff: rope/refactor/wildcards.py:HEAD +Old:rope/refactor/wildcards.py:HEAD + + + + +diff: ropetest/contrib/autoimport/utilstest.py +diff: Changed +diff: ropetest/contrib/autoimport/utilstest.py:HEAD +Old:ropetest/contrib/autoimport/utilstest.py:HEAD + + + + +diff: ropetest/pycoretest.py +diff: Changed +diff: ropetest/pycoretest.py:HEAD +Old:ropetest/pycoretest.py:HEAD + + + + + +=== PR xxx: ekr-clean-imports +diff master..HEAD (ekr-clean-pyflakes) +unused as e: +diff: rope/refactor/patchedast.py +diff: Changed +diff: _Source.consume (changed) +Old:_Source.consume (changed) + + + + + +Good changes +diff: rope/base/ast.py +diff: Changed +diff: rope/base/ast.py:HEAD +Old:rope/base/ast.py:HEAD + + + + +diff: rope/base/fscommands.py +diff: Changed +diff: rope/base/fscommands.py:HEAD +Old:rope/base/fscommands.py:HEAD + + + + +diff: rope/base/oi/soa.py +diff: Changed +diff: _analyze_node +Old:_analyze_node + + + + +diff: rope/base/oi/type_hinting/evaluate.py +diff: Changed +diff: rope/base/oi/type_hinting/evaluate.py:HEAD +Old:rope/base/oi/type_hinting/evaluate.py:HEAD + + +diff: eval_str2 +Old:eval_str2 + + +diff: ScopeNameFinder._is_defined_in_class_body +Old:ScopeNameFinder._is_defined_in_class_body + + +diff: ScopeNameFinder._is_function_name_in_function_header +Old:ScopeNameFinder._is_function_name_in_function_header + + +diff: ScopeNameFinder.get_primary_and_pyname_at +Old:ScopeNameFinder.get_primary_and_pyname_at + + +diff: ScopeNameFinder.get_enclosing_function +Old:ScopeNameFinder.get_enclosing_function + + + + +diff: rope/base/oi/type_hinting/providers/pep0484_type_comments.py +diff: Changed +diff: rope/base/oi/type_hinting/providers/pep0484_type_comments.py:HEAD +Old:rope/base/oi/type_hinting/providers/pep0484_type_comments.py:HEAD + + + + +diff: rope/base/oi/type_hinting/utils.py +diff: Changed +diff: rope/base/oi/type_hinting/utils.py:HEAD +Old:rope/base/oi/type_hinting/utils.py:HEAD + + + + +diff: rope/base/pycore.py +diff: Changed +diff: rope/base/pycore.py:HEAD +Old:rope/base/pycore.py:HEAD + + + + +diff: rope/base/pyobjectsdef.py +diff: Changed +diff: << imports: pyobjectsdef >> +Old:<< imports: pyobjectsdef >> + + +diff: _ScopeVisitor._For +Old:_ScopeVisitor._For + + + + +diff: rope/refactor/suites.py +diff: Changed +diff: rope/refactor/suites.py:HEAD +Old:rope/refactor/suites.py:HEAD + + + + + +Good and bad changes +diff: ropetest/advanced_oi_test.py +diff: Changed +diff: ropetest/advanced_oi_test.py:HEAD +Old:ropetest/advanced_oi_test.py:HEAD + + +diff: NewStaticOITest.test_validation_problems_for_changing_builtin_types +Old:NewStaticOITest.test_validation_problems_for_changing_builtin_types + + +diff: NewStaticOITest.test_set_comprehension +Old:NewStaticOITest.test_set_comprehension + + + + + +Bad changes +diff: rope/contrib/autoimport/__init__.py +diff: Changed +diff: rope/contrib/autoimport/__init__.py:HEAD +Old:rope/contrib/autoimport/__init__.py:HEAD + + + + +diff: rope/refactor/__init__.py +diff: Changed +diff: rope/refactor/__init__.py:HEAD +Old:rope/refactor/__init__.py:HEAD + + + + +diff: rope/refactor/inline.py +diff: Changed +diff: rope/refactor/inline.py:HEAD +Old:rope/refactor/inline.py:HEAD + + + + +diff: ropetest/builtinstest.py +diff: Changed +diff: BuiltinTypesTest.test_wrong_arguments_to_zip_function +Old:BuiltinTypesTest.test_wrong_arguments_to_zip_function + + + + +diff: ropetest/codeanalyzetest.py +diff: Changed +diff: WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line +Old:WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line + + +diff: ScopeNameFinderTest.test_relative_modules_after_from_statements2 +Old:ScopeNameFinderTest.test_relative_modules_after_from_statements2 + + + + + +Bad unittest changes +diff: ropetest/contrib/autoimport/utilstest.py +diff: Changed +diff: ropetest/contrib/autoimport/utilstest.py:HEAD +Old:ropetest/contrib/autoimport/utilstest.py:HEAD + + +diff: test_get_package_tuple_compiled +Old:test_get_package_tuple_compiled + + + + +diff: ropetest/contrib/codeassisttest.py +diff: Changed +diff: CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref +Old:CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref + + +diff: CodeAssistTest.test_commenting_errors_before_offset +Old:CodeAssistTest.test_commenting_errors_before_offset + + +diff: CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing +Old:CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing + + +diff: CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions +Old:CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions + + +diff: CodeAssistInProjectsTest.setUp +Old:CodeAssistInProjectsTest.setUp + + + + +diff: ropetest/contrib/fixmodnamestest.py +diff: Changed +diff: FixModuleNamesTest.test_handling_nested_modules +Old:FixModuleNamesTest.test_handling_nested_modules + + + + +diff: ropetest/historytest.py +diff: Changed +diff: SavingHistoryTest.test_writing_and_reading_history +Old:SavingHistoryTest.test_writing_and_reading_history + + +diff: SavingHistoryTest.test_writing_and_reading_history2 +Old:SavingHistoryTest.test_writing_and_reading_history2 + + + + +diff: ropetest/objectinfertest.py +diff: Changed +diff: ObjectInferTest.test_empty_tuples +Old:ObjectInferTest.test_empty_tuples + + + + +diff: ropetest/projecttest.py +diff: Changed +diff: ropetest/projecttest.py:HEAD +Old:ropetest/projecttest.py:HEAD + + +diff: ResourceObserverTest.test_revalidating_folders +Old:ResourceObserverTest.test_revalidating_folders + + +diff: ResourceObserverTest.test_changes_and_adding_resources +Old:ResourceObserverTest.test_changes_and_adding_resources + + +diff: ResourceObserverTest.test_validating_get_files_list +Old:ResourceObserverTest.test_validating_get_files_list + + +diff: RopeFolderTest.test_ignored_resources_and_get_files2 +Old:RopeFolderTest.test_ignored_resources_and_get_files2 + + +diff: RopeFolderTest.test_ignoring_syntax_errors +Old:RopeFolderTest.test_ignoring_syntax_errors + + + + +diff: ropetest/pycoretest.py +diff: Changed +diff: PyCoreTest.test_nested_modules +Old:PyCoreTest.test_nested_modules + + +diff: PyCoreTest.test_package +Old:PyCoreTest.test_package + + +diff: PyCoreTest.test_class_variables +Old:PyCoreTest.test_class_variables + + +diff: PyCoreTest.test_class_attributes_set_in_init +Old:PyCoreTest.test_class_attributes_set_in_init + + +diff: PyCoreTest.test_get_string_module_with_extra_spaces +Old:PyCoreTest.test_get_string_module_with_extra_spaces + + +diff: PyCoreTest.test_packaged_module_creation +Old:PyCoreTest.test_packaged_module_creation + + + + +diff: ropetest/pyscopestest.py +diff: Changed +diff: PyCoreScopesTest.test_classes_inside_function_scopes +Old:PyCoreScopesTest.test_classes_inside_function_scopes + + +diff: PyCoreScopesTest.test_getting_defined_names_for_classes +Old:PyCoreScopesTest.test_getting_defined_names_for_classes + + + + +diff: ropetest/refactor/__init__.py +diff: Changed +diff: ropetest/refactor/__init__.py:HEAD +Old:ropetest/refactor/__init__.py:HEAD + + + + +diff: ropetest/refactor/importutilstest.py +diff: Changed +diff: ImportUtilsTest.setUp +Old:ImportUtilsTest.setUp + + + + +diff: ropetest/refactor/movetest.py +diff: Changed +diff: MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable +Old:MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable + + + + +diff: ropetest/refactor/patchedasttest.py +diff: Changed +diff: PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name +Old:PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name + + + + +diff: ropetest/testutils.py +diff: Changed +diff: ropetest/testutils.py:HEAD +Old:ropetest/testutils.py:HEAD + + +diff: remove_recursively +Old:remove_recursively + + + + + +Weird change: diff: setup.py + +COPY: diff master..HEAD (ekr-clean-pyflakes) +unused as e: +diff: rope/refactor/patchedast.py +diff: Changed +diff: _Source.consume (changed) +Old:_Source.consume (changed) +_Source.consume (changed) + + + + +Good changes +diff: rope/base/ast.py +diff: Changed +diff: rope/base/ast.py:HEAD +Old:rope/base/ast.py:HEAD +@clean ast.py +parse +walk +get_child_nodes +call_for_nodes +get_children + + + + +diff: rope/base/fscommands.py +diff: Changed +diff: rope/base/fscommands.py:HEAD +Old:rope/base/fscommands.py:HEAD +@clean fscommands.py +create_fscommands +class FileSystemCommands +FileSystemCommands.create_file +FileSystemCommands.create_folder +FileSystemCommands.move +FileSystemCommands.remove +FileSystemCommands.write +FileSystemCommands.read + +class SubversionCommands +SubversionCommands.__init__ +SubversionCommands.create_file +SubversionCommands.create_folder +SubversionCommands.move +SubversionCommands.remove +SubversionCommands.write +SubversionCommands.read + +class MercurialCommands +MercurialCommands.__init__ +MercurialCommands._import_mercurial +MercurialCommands.create_file +MercurialCommands.create_folder +MercurialCommands.move +MercurialCommands.remove +MercurialCommands.write +MercurialCommands.read + +class GITCommands +GITCommands.__init__ +GITCommands.create_file +GITCommands.create_folder +GITCommands.move +GITCommands.remove +GITCommands.write +GITCommands.read +GITCommands._do +GITCommands._in_dir + +class DarcsCommands +DarcsCommands.__init__ +DarcsCommands.create_file +DarcsCommands.create_folder +DarcsCommands.move +DarcsCommands.remove +DarcsCommands.read +DarcsCommands.write +DarcsCommands._do + +_execute +unicode_to_file_data +file_data_to_unicode +_decode_data +read_str_coding +_find_coding + + + + +diff: rope/base/oi/soa.py +diff: Changed +diff: _analyze_node +Old:_analyze_node +_analyze_node + + + +diff: rope/base/oi/type_hinting/evaluate.py +diff: Changed +diff: rope/base/oi/type_hinting/evaluate.py:HEAD +Old:rope/base/oi/type_hinting/evaluate.py:HEAD +@clean evaluate.py +eval_location +eval_location2 +eval_node +eval_node2 +eval_str +eval_str2 +class ScopeNameFinder +ScopeNameFinder.__init__ +ScopeNameFinder._is_defined_in_class_body +ScopeNameFinder._is_function_name_in_function_header +ScopeNameFinder.get_pyname_at +ScopeNameFinder.get_primary_and_pyname_at +ScopeNameFinder.get_enclosing_function +ScopeNameFinder._find_module + +class StatementEvaluator +StatementEvaluator.__init__ +StatementEvaluator._Name +StatementEvaluator._Attribute +StatementEvaluator._Call +StatementEvaluator._Str +StatementEvaluator._Num +StatementEvaluator._Constant +StatementEvaluator._get_builtin_name +StatementEvaluator._BinOp +StatementEvaluator._BoolOp +StatementEvaluator._Repr +StatementEvaluator._UnaryOp +StatementEvaluator._Compare +StatementEvaluator._Dict +StatementEvaluator._List +StatementEvaluator._ListComp +StatementEvaluator._GeneratorExp +StatementEvaluator._what_does_comprehension_hold +StatementEvaluator._make_comprehension_scope +StatementEvaluator._Tuple +StatementEvaluator._get_object_for_node +StatementEvaluator._get_primary_and_object_for_node +StatementEvaluator._Subscript +StatementEvaluator._Slice +StatementEvaluator._call_function +StatementEvaluator._Lambda + +_get_evaluated_names + + +diff: eval_str2 +Old:eval_str2 + + +diff: ScopeNameFinder._is_defined_in_class_body +Old:ScopeNameFinder._is_defined_in_class_body + + +diff: ScopeNameFinder._is_function_name_in_function_header +Old:ScopeNameFinder._is_function_name_in_function_header + + +diff: ScopeNameFinder.get_primary_and_pyname_at +Old:ScopeNameFinder.get_primary_and_pyname_at + + +diff: ScopeNameFinder.get_enclosing_function +Old:ScopeNameFinder.get_enclosing_function + + + + +diff: rope/base/oi/type_hinting/providers/pep0484_type_comments.py +diff: Changed +diff: rope/base/oi/type_hinting/providers/pep0484_type_comments.py:HEAD +Old:rope/base/oi/type_hinting/providers/pep0484_type_comments.py:HEAD +@clean pep0484_type_comments.py +class AssignmentProvider +AssignmentProvider.__init__ +AssignmentProvider.PEP0484_TYPE_COMMENT_PATTERNS = (re.compile(r"type:/s*([^/n]+)"),) +AssignmentProvider.__call__ +AssignmentProvider._search_type_in_type_comment + + + + + +diff: rope/base/oi/type_hinting/utils.py +diff: Changed +diff: rope/base/oi/type_hinting/utils.py:HEAD +Old:rope/base/oi/type_hinting/utils.py:HEAD +@clean libutils.py +path_to_resource +path_relative_to_project_root +relative +report_change +analyze_module +analyze_modules +get_string_module +get_string_scope +is_python_file +modname + + + + +diff: rope/base/pycore.py +diff: Changed +diff: rope/base/pycore.py:HEAD +Old:rope/base/pycore.py:HEAD +@clean pycore.py +class PyCore +PyCore.__init__ +PyCore._init_python_files +PyCore._init_resource_observer +PyCore._init_automatic_soa +PyCore.automatic_soa +PyCore._file_changed_for_soa +PyCore.is_python_file +PyCore.get_module +PyCore._builtin_submodules +PyCore.builtin_module +PyCore.get_relative_module +PyCore.get_string_module +PyCore.get_string_scope +PyCore._invalidate_resource_cache +PyCore.get_python_path_folders +PyCore.find_module +PyCore.find_relative_module +PyCore.get_source_folders +PyCore.resource_to_pyobject (unique) +PyCore.get_python_files +PyCore._is_package +PyCore._find_source_folders +PyCore.run_module +PyCore.analyze_module +PyCore.get_classes +PyCore.__str__ +PyCore.modname +PyCore.extension_modules + +class _ModuleCache +_ModuleCache.__init__ +_ModuleCache._invalidate_resource +_ModuleCache.get_pymodule +_ModuleCache.forget_all_data +_ModuleCache.__str__ + +class _ExtensionCache +_ExtensionCache.__init__ +_ExtensionCache.get_pymodule + +perform_soa_on_changed_scopes +class _TextChangeDetector +_TextChangeDetector.__init__ +_TextChangeDetector._set_diffs +_TextChangeDetector.is_changed +_TextChangeDetector.consume_changes +_TextChangeDetector._get_changed + + + + + +diff: rope/base/pyobjectsdef.py +diff: Changed +diff: << imports: pyobjectsdef >> +Old:<< imports: pyobjectsdef >> +<< imports: pyobjectsdef >> + +diff: _ScopeVisitor._For +Old:_ScopeVisitor._For +_ScopeVisitor._For + + + +diff: rope/refactor/suites.py +diff: Changed +diff: rope/refactor/suites.py:HEAD +Old:rope/refactor/suites.py:HEAD +@clean suites.py +find_visible +find_visible_for_suite +valid + +ast_suite_tree +class Suite +Suite.__init__ +Suite.get_start +Suite.get_children +Suite.local_start +Suite.local_end +Suite.find_suite +Suite._get_level + +class _SuiteWalker +_SuiteWalker.__init__ +_SuiteWalker._If +_SuiteWalker._For +_SuiteWalker._While +_SuiteWalker._With +_SuiteWalker._AsyncWith +_SuiteWalker._Match +_SuiteWalker._TryFinally +_SuiteWalker._Try +_SuiteWalker._TryExcept +_SuiteWalker._add_if_like_node +_SuiteWalker._FunctionDef +_SuiteWalker._AsyncFunctionDef +_SuiteWalker._ClassDef + + + + + + +Good and bad changes +diff: ropetest/advanced_oi_test.py +diff: Changed +diff: ropetest/advanced_oi_test.py:HEAD +Old:ropetest/advanced_oi_test.py:HEAD +@clean advanced_oi_test.py +class DynamicOITest +DynamicOITest.setUp +DynamicOITest.tearDown +DynamicOITest.test_simple_dti +DynamicOITest.test_module_dti +DynamicOITest.test_class_from_another_module_dti +DynamicOITest.test_class_dti +DynamicOITest.test_instance_dti +DynamicOITest.test_method_dti +DynamicOITest.test_function_argument_dti +DynamicOITest.test_classes_with_the_same_name +DynamicOITest.test_nested_classes +DynamicOITest.test_function_argument_dti2 +DynamicOITest.test_dti_and_concluded_data_invalidation +DynamicOITest.test_list_objects_and_dynamicoi +DynamicOITest.test_for_loops_and_dynamicoi +DynamicOITest.test_dict_objects_and_dynamicoi +DynamicOITest.test_dict_keys_and_dynamicoi +DynamicOITest.test_dict_keys_and_dynamicoi2 +DynamicOITest.test_strs_and_dynamicoi +DynamicOITest.test_textual_transformations +DynamicOITest.test_arguments_with_keywords +DynamicOITest.test_a_function_with_different_returns +DynamicOITest.test_a_function_with_different_returns2 +DynamicOITest.test_ignoring_star_args +DynamicOITest.test_ignoring_double_star_args +DynamicOITest.test_invalidating_data_after_changing +DynamicOITest.test_invalidating_data_after_moving + +class NewStaticOITest +NewStaticOITest.setUp +NewStaticOITest.tearDown +NewStaticOITest.test_static_oi_for_simple_function_calls +NewStaticOITest.test_static_oi_not_failing_when_callin_callables +NewStaticOITest.test_static_oi_for_nested_calls +NewStaticOITest.test_static_oi_class_methods +NewStaticOITest.test_static_oi_preventing_soi_maximum_recursion_exceptions +NewStaticOITest.test_static_oi_for_infer_return_typs_from_funcs_based_on_params +NewStaticOITest.test_a_function_with_different_returns +NewStaticOITest.test_not_reporting_out_of_date_information +NewStaticOITest.test_invalidating_concluded_data_in_a_function +NewStaticOITest.test_handling_generator_functions_for_strs +NewStaticOITest.xxx_test_handl_generator_functions_when_unknown_type_is_yielded +NewStaticOITest.test_static_oi_for_lists_depending_on_append_function +NewStaticOITest.test_static_oi_for_lists_per_object_for_get_item +NewStaticOITest.test_static_oi_for_lists_per_object_for_fields +NewStaticOITest.test_static_oi_for_lists_per_object_for_set_item +NewStaticOITest.test_static_oi_for_lists_per_object_for_extending_lists +NewStaticOITest.test_static_oi_for_lists_per_object_for_iters +NewStaticOITest.test_static_oi_for_dicts_depending_on_append_function +NewStaticOITest.test_static_oi_for_dicts_depending_on_for_loops +NewStaticOITest.test_static_oi_for_dicts_depending_on_update +NewStaticOITest.test_static_oi_for_dicts_depending_on_update_on_seqs +NewStaticOITest.test_static_oi_for_sets_per_object_for_set_item +NewStaticOITest.test_properties_and_calling_get_property +NewStaticOITest.test_soi_on_constructors +NewStaticOITest.test_soi_on_literal_assignment +NewStaticOITest.test_soi_on_typed_assignment +NewStaticOITest.test_not_saving_unknown_function_returns +NewStaticOITest.test_using_the_best_callinfo +NewStaticOITest.test_call_function_and_parameters +NewStaticOITest.test_report_change_in_libutils +NewStaticOITest.test_report_libutils_and_analyze_all_modules +NewStaticOITest.test_validation_problems_for_objectdb_retrievals +NewStaticOITest.test_validation_problems_for_changing_builtin_types +NewStaticOITest.test_always_returning_containing_class_for_selfs +NewStaticOITest.test_following_function_calls_when_asked_to +NewStaticOITest.test_set_comprehension + + + +diff: NewStaticOITest.test_validation_problems_for_changing_builtin_types +Old:NewStaticOITest.test_validation_problems_for_changing_builtin_types + + +diff: NewStaticOITest.test_set_comprehension +Old:NewStaticOITest.test_set_comprehension + + + + + +Bad changes +diff: rope/contrib/autoimport/__init__.py +diff: Changed +diff: rope/contrib/autoimport/__init__.py:HEAD +Old:rope/contrib/autoimport/__init__.py:HEAD +@clean __init__.py + + + +diff: rope/refactor/__init__.py +diff: Changed +diff: rope/refactor/__init__.py:HEAD +Old:rope/refactor/__init__.py:HEAD + + + + +diff: rope/refactor/inline.py +diff: Changed +diff: rope/refactor/inline.py:HEAD +Old:rope/refactor/inline.py:HEAD +@clean inline.py +unique_prefix +create_inline +class _Inliner +_Inliner.__init__ +_Inliner.get_changes +_Inliner.get_kind + +class InlineMethod +InlineMethod.__init__ +InlineMethod._init_imports +InlineMethod._get_scope_range +InlineMethod.get_changes +InlineMethod._get_removed_range +InlineMethod._defining_file_changes +InlineMethod._get_method_replacement +InlineMethod._is_the_last_method_of_a_class +InlineMethod.get_kind + +class InlineVariable +InlineVariable.__init__ +InlineVariable._check_exceptional_conditions +InlineVariable.get_changes +InlineVariable._change_main_module +InlineVariable._init_imports +InlineVariable._change_module +InlineVariable.check_aim + +InlineVariable.get_kind + +class InlineParameter +InlineParameter.__init__ +InlineParameter._function_location +InlineParameter.get_changes +InlineParameter.get_kind + +_join_lines +class _DefinitionGenerator +_DefinitionGenerator.__init__ +_DefinitionGenerator._get_definition_info +_DefinitionGenerator._get_definition_params +_DefinitionGenerator.get_function_name +_DefinitionGenerator.get_definition +_DefinitionGenerator._calculate_header +_DefinitionGenerator._calculate_definition +_DefinitionGenerator._replace_returns_with +_DefinitionGenerator._check_nothing_after_return +_DefinitionGenerator._get_return_pattern +_DefinitionGenerator.named_pattern + + +class _InlineFunctionCallsForModuleHandle +_InlineFunctionCallsForModuleHandle.__init__ +_InlineFunctionCallsForModuleHandle.occurred_inside_skip +_InlineFunctionCallsForModuleHandle.occurred_outside_skip +_InlineFunctionCallsForModuleHandle._find_end_parens +_InlineFunctionCallsForModuleHandle.pymodule +_InlineFunctionCallsForModuleHandle.source +_InlineFunctionCallsForModuleHandle.lines + +_inline_variable +_getvardef +_assigned_lineno +_add_imports +_get_pyname +_remove_from + + + + +diff: ropetest/builtinstest.py +diff: Changed +diff: BuiltinTypesTest.test_wrong_arguments_to_zip_function +Old:BuiltinTypesTest.test_wrong_arguments_to_zip_function +BuiltinTypesTest.test_wrong_arguments_to_zip_function + + + +diff: ropetest/codeanalyzetest.py +diff: Changed +diff: WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line +Old:WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line +WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line + +diff: ScopeNameFinderTest.test_relative_modules_after_from_statements2 +Old:ScopeNameFinderTest.test_relative_modules_after_from_statements2 +ScopeNameFinderTest.test_relative_modules_after_from_statements2 + + + + +Bad unittest changes +diff: ropetest/contrib/autoimport/utilstest.py +diff: Changed +diff: ropetest/contrib/autoimport/utilstest.py:HEAD +Old:ropetest/contrib/autoimport/utilstest.py:HEAD +@clean utilstest.py +test_get_package_source +test_get_package_source_not_project +test_get_package_source_pytest +test_get_package_source_typing +test_get_modname_project_no_add +test_get_modname_single_file +test_get_modname_folder +test_get_package_tuple_sample +test_get_package_tuple_typing +test_get_package_tuple_compiled + + +diff: test_get_package_tuple_compiled +Old:test_get_package_tuple_compiled + + + + +diff: ropetest/contrib/codeassisttest.py +diff: Changed +diff: CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref +Old:CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref +CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref + +diff: CodeAssistTest.test_commenting_errors_before_offset +Old:CodeAssistTest.test_commenting_errors_before_offset +CodeAssistTest.test_commenting_errors_before_offset + +diff: CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing +Old:CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing +CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing + +diff: CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions +Old:CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions +CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions + +diff: CodeAssistInProjectsTest.setUp +Old:CodeAssistInProjectsTest.setUp +CodeAssistInProjectsTest.setUp + + + +diff: ropetest/contrib/fixmodnamestest.py +diff: Changed +diff: FixModuleNamesTest.test_handling_nested_modules +Old:FixModuleNamesTest.test_handling_nested_modules +FixModuleNamesTest.test_handling_nested_modules + + + +diff: ropetest/historytest.py +diff: Changed +diff: SavingHistoryTest.test_writing_and_reading_history +Old:SavingHistoryTest.test_writing_and_reading_history +SavingHistoryTest.test_writing_and_reading_history + +diff: SavingHistoryTest.test_writing_and_reading_history2 +Old:SavingHistoryTest.test_writing_and_reading_history2 +SavingHistoryTest.test_writing_and_reading_history2 + + + +diff: ropetest/objectinfertest.py +diff: Changed +diff: ObjectInferTest.test_empty_tuples +Old:ObjectInferTest.test_empty_tuples +ObjectInferTest.test_empty_tuples + + + +diff: ropetest/projecttest.py +diff: Changed +diff: ropetest/projecttest.py:HEAD +Old:ropetest/projecttest.py:HEAD +@clean projecttest.py +class ProjectTest +ProjectTest.setUp +ProjectTest._make_sample_project +ProjectTest.tearDown +ProjectTest.test_project_creation +ProjectTest.test_getting_project_file +ProjectTest.test_project_file_reading +ProjectTest.test_getting_not_existing_project_file +ProjectTest.test_writing_in_project_files +ProjectTest.test_creating_files +ProjectTest.test_creating_files_that_already_exist +ProjectTest.test_making_root_folder_if_it_does_not_exist +ProjectTest.test_failure_when_project_root_exists_and_is_a_file +ProjectTest.test_creating_folders +ProjectTest.test_making_folder_that_already_exists +ProjectTest.test_failing_if_creating_folder_while_file_already_exists +ProjectTest.test_creating_file_inside_folder +ProjectTest.test_failing_when_creating_file_inside_non_existent_folder +ProjectTest.test_nested_directories +ProjectTest.test_removing_files +ProjectTest.test_removing_files_invalidating_in_project_resource_pool +ProjectTest.test_removing_directories +ProjectTest.test_removing_non_existent_files +ProjectTest.test_removing_nested_files +ProjectTest.test_file_get_name +ProjectTest.test_folder_get_name +ProjectTest.test_file_get_path +ProjectTest.test_folder_get_path +ProjectTest.test_is_folder +ProjectTest.testget_children +ProjectTest.test_nonempty_get_children +ProjectTest.test_nonempty_get_children2 +ProjectTest.test_does_not_fail_for_permission_denied +ProjectTest.test_getting_files +ProjectTest.test_getting_folders +ProjectTest.test_nested_folder_get_files +ProjectTest.test_nested_folder_get_folders +ProjectTest.test_root_folder +ProjectTest.test_get_all_files +ProjectTest.test_get_all_files_after_changing +ProjectTest.test_multifile_get_all_files +ProjectTest.test_ignoring_dot_pyc_files_in_get_files +ProjectTest.test_folder_creating_files +ProjectTest.test_folder_creating_nested_files +ProjectTest.test_folder_creating_files2 +ProjectTest.test_folder_creating_nested_files2 +ProjectTest.test_folder_get_child +ProjectTest.test_folder_get_child_nested +ProjectTest.test_project_root_is_root_folder +ProjectTest.test_moving_files +ProjectTest.test_moving_folders +ProjectTest.test_moving_destination_folders +ProjectTest.test_moving_files_and_resource_objects +ProjectTest.test_file_encoding_reading +ProjectTest.test_file_encoding_writing +ProjectTest.test_using_utf8_when_writing_in_case_of_errors +ProjectTest.test_encoding_declaration_in_the_second_line +ProjectTest.test_not_an_encoding_declaration +ProjectTest.test_read_bytes +ProjectTest.test_file_with_unix_line_ending +ProjectTest.test_file_with_dos_line_ending +ProjectTest.test_file_with_mac_line_ending +ProjectTest.test_file_binary +ProjectTest.xxx_test_using_utf16 +ProjectTest.xxx_test_file_encoding_reading_for_notepad_styles +ProjectTest.test_using_project_get_file +ProjectTest.test_using_file_create +ProjectTest.test_using_folder_create +ProjectTest.test_exception_when_creating_twice +ProjectTest.test_exception_when_parent_does_not_exist +ProjectTest.test_simple_path_to_resource +ProjectTest.test_ignoring_symlinks_inside_project +ProjectTest.test_getting_empty_source_folders +ProjectTest.test_root_source_folder +ProjectTest.test_root_source_folder2 +ProjectTest.test_src_source_folder +ProjectTest.test_packages +ProjectTest.test_multi_source_folders +ProjectTest.test_multi_source_folders2 + +class ResourceObserverTest +ResourceObserverTest.setUp +ResourceObserverTest.tearDown +ResourceObserverTest.test_resource_change_observer +ResourceObserverTest.test_resource_change_observer_after_removal +ResourceObserverTest.test_resource_change_observer2 +ResourceObserverTest.test_resource_change_observer_for_folders +ResourceObserverTest.test_resource_change_observer_after_moving +ResourceObserverTest.test_revalidating_files +ResourceObserverTest.test_revalidating_files_and_no_changes2 +ResourceObserverTest.test_revalidating_folders +ResourceObserverTest.test_removing_and_adding_resources_to_filtered_observer +ResourceObserverTest.test_validation_and_changing_files +ResourceObserverTest.test_validation_and_changing_files2 +ResourceObserverTest.test_not_reporting_multiple_changes_to_folders +ResourceObserverTest._write_file +ResourceObserverTest.test_moving_and_being_interested_about_a_folder_and_a_child +ResourceObserverTest.test_contains_for_folders +ResourceObserverTest.test_validating_when_created +ResourceObserverTest.test_validating_twice_when_created +ResourceObserverTest.test_changes_and_adding_resources +ResourceObserverTest.test_validating_get_files_list +ResourceObserverTest.test_clear_observered_resources_for_filtered_observers + +class _MockChangeIndicator +_MockChangeIndicator.__init__ +_MockChangeIndicator.set_indicator +_MockChangeIndicator.get_indicator + +class _SampleObserver +_SampleObserver.__init__ +_SampleObserver.resource_changed +_SampleObserver.resource_moved +_SampleObserver.resource_created +_SampleObserver.resource_removed + +class OutOfProjectTest +OutOfProjectTest.setUp +OutOfProjectTest.tearDown +OutOfProjectTest.test_simple_out_of_project_file +OutOfProjectTest.test_simple_out_of_project_folder +OutOfProjectTest.test_using_absolute_path +OutOfProjectTest.test_folder_get_child +OutOfProjectTest.test_out_of_project_files_and_path_to_resource + +class _MockFSCommands +_MockFSCommands.__init__ +_MockFSCommands.create_file +_MockFSCommands.create_folder +_MockFSCommands.move +_MockFSCommands.remove +_MockFSCommands.read + +class _DeprecatedFSCommands +_DeprecatedFSCommands.__init__ +_DeprecatedFSCommands.create_file +_DeprecatedFSCommands.create_folder +_DeprecatedFSCommands.move +_DeprecatedFSCommands.remove + +class RopeFolderTest +RopeFolderTest.setUp +RopeFolderTest.tearDown +RopeFolderTest.test_none_project_rope_folder +RopeFolderTest.test_getting_project_rope_folder +RopeFolderTest.test_setting_ignored_resources +RopeFolderTest.test_ignored_folders +RopeFolderTest.test_ignored_resources_and_get_files +RopeFolderTest.test_ignored_resources_and_get_files2 +RopeFolderTest.test_setting_ignored_resources_patterns +RopeFolderTest.test_star_should_not_include_slashes +RopeFolderTest.test_normal_fscommands +RopeFolderTest.test_fscommands_and_ignored_resources +RopeFolderTest.test_deprecated_fscommands +RopeFolderTest.test_ignored_resources_and_prefixes +RopeFolderTest.test_loading_config_dot_py +RopeFolderTest.test_loading_pyproject +RopeFolderTest.test_loading_pyproject_empty_file +RopeFolderTest.test_loading_pyproject_no_tool_section +RopeFolderTest.test_loading_pyproject_no_tool_rope_section +RopeFolderTest.test_ignoring_syntax_errors +RopeFolderTest.test_compressed_history +RopeFolderTest.test_compressed_objectdb +RopeFolderTest.test_nested_dot_ropeproject_folder + + + +diff: ResourceObserverTest.test_revalidating_folders +Old:ResourceObserverTest.test_revalidating_folders + + +diff: ResourceObserverTest.test_changes_and_adding_resources +Old:ResourceObserverTest.test_changes_and_adding_resources + + +diff: ResourceObserverTest.test_validating_get_files_list +Old:ResourceObserverTest.test_validating_get_files_list + + +diff: RopeFolderTest.test_ignored_resources_and_get_files2 +Old:RopeFolderTest.test_ignored_resources_and_get_files2 + + +diff: RopeFolderTest.test_ignoring_syntax_errors +Old:RopeFolderTest.test_ignoring_syntax_errors + + + + +diff: ropetest/pycoretest.py +diff: Changed +diff: PyCoreTest.test_nested_modules +Old:PyCoreTest.test_nested_modules +PyCoreTest.test_nested_modules + +diff: PyCoreTest.test_package +Old:PyCoreTest.test_package +PyCoreTest.test_package + +diff: PyCoreTest.test_class_variables +Old:PyCoreTest.test_class_variables +PyCoreTest.test_class_variables + +diff: PyCoreTest.test_class_attributes_set_in_init +Old:PyCoreTest.test_class_attributes_set_in_init +PyCoreTest.test_class_attributes_set_in_init + +diff: PyCoreTest.test_get_string_module_with_extra_spaces +Old:PyCoreTest.test_get_string_module_with_extra_spaces +PyCoreTest.test_get_string_module_with_extra_spaces + +diff: PyCoreTest.test_packaged_module_creation +Old:PyCoreTest.test_packaged_module_creation +PyCoreTest.test_packaged_module_creation + + + +diff: ropetest/pyscopestest.py +diff: Changed +diff: PyCoreScopesTest.test_classes_inside_function_scopes +Old:PyCoreScopesTest.test_classes_inside_function_scopes +PyCoreScopesTest.test_classes_inside_function_scopes + +diff: PyCoreScopesTest.test_getting_defined_names_for_classes +Old:PyCoreScopesTest.test_getting_defined_names_for_classes +PyCoreScopesTest.test_getting_defined_names_for_classes + + + +diff: ropetest/refactor/__init__.py +diff: Changed +diff: ropetest/refactor/__init__.py:HEAD +Old:ropetest/refactor/__init__.py:HEAD + + + + +diff: ropetest/refactor/importutilstest.py +diff: Changed +diff: ImportUtilsTest.setUp +Old:ImportUtilsTest.setUp +ImportUtilsTest.setUp + + + +diff: ropetest/refactor/movetest.py +diff: Changed +diff: MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable +Old:MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable +MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable + + + +diff: ropetest/refactor/patchedasttest.py +diff: Changed +diff: PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name +Old:PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name +PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name + + + +diff: ropetest/testutils.py +diff: Changed +diff: ropetest/testutils.py:HEAD +Old:ropetest/testutils.py:HEAD +@clean testutils.py +sample_project +create_module = generate.create_module +remove_project +remove_recursively +_remove_recursively +parse_version +only_for +only_for_versions_lower +only_for_versions_higher +skipNotPOSIX +time_limit + + +diff: remove_recursively +Old:remove_recursively + + + + + +Weird change: diff: setup.py + +Found 6:ast_arg_type (same as ast.arg) + + + + + + + + +Found 23:pycompat + + + + + + + + + + + + + + + + + + + + + + + + + +'''Recursively import all python files in a directory and clean the result.''' +@tabwidth -4 # For a better match. +g.cls() +dir_ = r'C:\Repos\ekr-rope\rope\base\ast.py' +c.recursiveImport( + add_context=True, # Override setting only if True/False + add_file_context=False, # Override setting only if True/False + dir_=dir_, + kind = '@clean', # '@auto', '@clean', '@nosent','@file', + add_path = True, + recursive = True, + safe_at_file = False, + theTypes = ['.py'], + # ['.ts', '.js', '.json'] # ['.html', '.js', '.json', '.py', '.rs', '.svg', '.ts', '.tsx'] + verbose = False, +) +if 1: + last = c.lastTopLevel() + # for p in last.self_and_subtree(): + # p.expand() + # c.expandAllSubheads() + c.redraw(last) +print('Done') +@path C:/Repos/ekr-rope/docs/ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- +import rope + +project = "rope" +copyright = "2022, Rope Contributors" +author = "Rope Contributors" + +# The full version, including alpha/beta/rc tags +version = release = rope.VERSION + + +# -- General configuration --------------------------------------------------- + +pygments_style = "sphinx" +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.autosectionlabel", + "sphinx.ext.autosummary", + "sphinx_autodoc_typehints", + "pytoolconfig.documentation", + "sphinx_rtd_theme", +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_rtd_theme" + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +# Make sure the target is unique +autosectionlabel_prefix_document = True +@language python +@tabwidth -4 + +def _new_list(self, args): + return _create_builtin(args, get_list) + + +@abstractmethod +def is_stopped(self) -> bool: + pass + + +@abstractmethod +def get_jobsets(self) -> Sequence[BaseJobSet]: + pass + + +def create_jobset( + self, name: str = "JobSet", count: Optional[int] = None +) -> BaseJobSet: + pass + + +def _inform_observers(self) -> None: + pass + + + +class TaskHandle(BaseTaskHandle): + @others + +def __init__(self, name="Task", interrupts=True): + """Construct a TaskHandle + + If `interrupts` is `False` the task won't be interrupted by + calling `TaskHandle.stop()`. + + """ + self.name = name + self.interrupts = interrupts + self.stopped = False + self.job_sets = [] + self.observers = [] + + +def stop(self): + """Interrupts the refactoring""" + if self.interrupts: + self.stopped = True + self._inform_observers() + + +def current_jobset(self): + """Return the current `JobSet`""" + if self.job_sets: + return self.job_sets[-1] + + +def add_observer(self, observer): + """Register an observer for this task handle + + The observer is notified whenever the task is stopped or + a job gets finished. + + """ + self.observers.append(observer) + + +def is_stopped(self): + return self.stopped + + +def _list_add(self, context): + if self.holding is not None: + return + holding = context.get_argument("value") + if holding is not None and holding != pyobjects.get_unknown(): + context.save_per_name(holding) + + +def get_jobsets(self): + return self.job_sets + + +def create_jobset(self, name="JobSet", count=None): + result = JobSet(self, name=name, count=count) + self.job_sets.append(result) + self._inform_observers() + return result + + +def _inform_observers(self): + for observer in list(self.observers): + observer() + + + +class JobSet(BaseJobSet): + @others + +def __init__(self, handle, name, count): + self.handle = handle + self.name = name + self.count = count + self.done = 0 + self.job_name = None + + +def started_job(self, name): + self.check_status() + self.job_name = name + self.handle._inform_observers() + + +def finished_job(self): + self.check_status() + self.done += 1 + self.handle._inform_observers() + self.job_name = None + + +def check_status(self): + if self.handle.is_stopped(): + raise exceptions.InterruptedTaskError() + + +@utils.deprecated("Just use JobSet.job_name attribute/property instead") +def get_active_job_name(self): + return self.job_name + + +def get_percent_done(self): + if self.count is not None and self.count > 0: + percent = self.done * 100 // self.count + return min(percent, 100) + + +def _self_set(self, context): + if self.holding is not None: + return + iterable = context.get_pyname("iterable") + holding = _infer_sequence_for_pyname(iterable) + if holding is not None and holding != pyobjects.get_unknown(): + context.save_per_name(holding) + + +@utils.deprecated("Just use JobSet.name attribute/property instead") +def get_name(self): + return self.name + + +def increment(self): + self.count += 1 + + + +class NullTaskHandle(BaseTaskHandle): + @others + +def __init__(self): + pass + + +def is_stopped(self): + return False + + +def stop(self): + pass + + +def create_jobset(self, *args, **kwds): + return NullJobSet() + + +def get_jobsets(self): + return [] + + +def add_observer(self, observer): + pass + + +def current_jobset(self) -> None: + """Return the current `JobSet`""" + return None + + + +def _list_get(self, context): + if self.holding is not None: + args = context.get_arguments(["self", "key"]) + if ( + len(args) > 1 + and args[1] is not None + and args[1].get_type() == builtins["slice"].get_object() + ): + return get_list(self.holding) + return self.holding + return context.get_per_name() + + +class NullJobSet(BaseJobSet): + @others + +def __init__(self, *args): + pass + + +def started_job(self, name): + pass + + +def finished_job(self): + pass + + +def check_status(self): + pass + + +@utils.deprecated("Just use JobSet.job_name attribute/property instead") +def get_active_job_name(self): + pass + + +def get_percent_done(self): + pass + + +@utils.deprecated("Just use JobSet.name attribute/property instead") +def get_name(self): + pass + + +def increment(self): + pass + +@path C:/Repos/ekr-rope/rope/base/ +import bisect +import keyword + +import rope.base.simplify + +MINIMAL_LEN_FOR_AS = 5 + + +@others +@language python +@tabwidth -4 + +def _iterator_get(self, context): + return get_iterator(self._list_get(context)) + + +def get_name_at(resource, offset): + source_code = resource.read() + word_finder = Worder(source_code) + return word_finder.get_word_at(offset) + + + +class Worder: + """A class for finding boundaries of words and expressions + + Note that in these methods, offset should be the index of the + character not the index of the character after it. + + Some of the methods here doesn't exactly do what their name might lead you + to think they do, these probably should be fixed. Refer to + ropetest/codeanalyzetest.py for what these methods returns. Note that + codeanalyzetest.py documents the current behavior, rather than what they + should've been. + """ + + @others + +def __init__(self, code, handle_ignores=False): + simplified = rope.base.simplify.real_code(code) + self.code_finder = _RealFinder(simplified, code) + self.handle_ignores = handle_ignores + self.code = code + + +def _init_ignores(self): + ignores = rope.base.simplify.ignored_regions(self.code) + self.dumb_finder = _RealFinder(self.code, self.code) + self.starts = [ignored[0] for ignored in ignores] + self.ends = [ignored[1] for ignored in ignores] + + +def _context_call(self, name, offset): + if self.handle_ignores: + if not hasattr(self, "starts"): + self._init_ignores() + start = bisect.bisect(self.starts, offset) + if start > 0 and offset < self.ends[start - 1]: + return getattr(self.dumb_finder, name)(offset) + return getattr(self.code_finder, name)(offset) + + +def get_primary_at(self, offset): + return self._context_call("get_primary_at", offset) + + +def get_word_at(self, offset): + return self._context_call("get_word_at", offset) + + +def get_primary_range(self, offset): + return self._context_call("get_primary_range", offset) + + +def get_splitted_primary_before(self, offset): + return self._context_call("get_splitted_primary_before", offset) + + +def get_word_range(self, offset): + return self._context_call("get_word_range", offset) + + +def _self_get(self, context): + return get_list(self._list_get(context)) + + + +def is_function_keyword_parameter(self, offset): + return self.code_finder.is_function_keyword_parameter(offset) + + +def is_a_class_or_function_name_in_header(self, offset): + return self.code_finder.is_a_class_or_function_name_in_header(offset) + + +def is_from_statement_module(self, offset): + return self.code_finder.is_from_statement_module(offset) + + +def is_from_aliased(self, offset): + return self.code_finder.is_from_aliased(offset) + + +def is_import_statement_aliased_module(self, offset): + return self.code_finder.is_import_statement_aliased_module(offset) + + +def find_parens_start_from_inside(self, offset): + return self.code_finder.find_parens_start_from_inside(offset) + + +def is_a_name_after_from_import(self, offset): + return self.code_finder.is_a_name_after_from_import(offset) + + +def is_from_statement(self, offset): + return self.code_finder.is_from_statement(offset) + + +def get_from_aliased(self, offset): + return self.code_finder.get_from_aliased(offset) + + +def is_import_statement(self, offset): + return self.code_finder.is_import_statement(offset) + + +get_list = _create_builtin_getter(List) +get_list_type = _create_builtin_type_getter(List) + + + +def is_assigned_here(self, offset): + return self.code_finder.is_assigned_here(offset) + + +def is_a_function_being_called(self, offset): + return self.code_finder.is_a_function_being_called(offset) + + +def get_word_parens_range(self, offset): + return self.code_finder.get_word_parens_range(offset) + + +def is_name_assigned_in_class_body(self, offset): + return self.code_finder.is_name_assigned_in_class_body(offset) + + +def is_on_function_call_keyword(self, offset): + return self.code_finder.is_on_function_call_keyword(offset) + + +def _find_parens_start(self, offset): + return self.code_finder._find_parens_start(offset) + + +def get_parameters(self, first, last): + return self.code_finder.get_parameters(first, last) + + +def get_from_module(self, offset): + return self.code_finder.get_from_module(offset) + + +def is_assigned_in_a_tuple_assignment(self, offset): + return self.code_finder.is_assigned_in_a_tuple_assignment(offset) + + +def get_assignment_type(self, offset): + return self.code_finder.get_assignment_type(offset) + + +class Dict(BuiltinClass): + @others + +def get_function_and_args_in_header(self, offset): + return self.code_finder.get_function_and_args_in_header(offset) + + +def get_lambda_and_args(self, offset): + return self.code_finder.get_lambda_and_args(offset) + + +def find_function_offset(self, offset): + return self.code_finder.find_function_offset(offset) + + + +class _RealFinder: + @others + +def __init__(self, code, raw): + self.code = code + self.raw = raw + + +def _find_word_start(self, offset): + current_offset = offset + while current_offset >= 0 and self._is_id_char(current_offset): + current_offset -= 1 + return current_offset + 1 + + +def _find_word_end(self, offset): + while offset + 1 < len(self.code) and self._is_id_char(offset + 1): + offset += 1 + return offset + + +def _find_last_non_space_char(self, offset): + while offset >= 0 and self.code[offset].isspace(): + if self.code[offset] == "\n": + return offset + offset -= 1 + return max(-1, offset) + + +def get_word_at(self, offset): + offset = self._get_fixed_offset(offset) + return self.raw[self._find_word_start(offset) : self._find_word_end(offset) + 1] + + +def _get_fixed_offset(self, offset): + if offset >= len(self.code): + return offset - 1 + if not self._is_id_char(offset): + if offset > 0 and self._is_id_char(offset - 1): + return offset - 1 + if offset < len(self.code) - 1 and self._is_id_char(offset + 1): + return offset + 1 + return offset + + +def __init__(self, keys=None, values=None): + self.keys = keys + self.values = values + collector = _AttributeCollector(dict) + collector("__new__", function=self._new_dict, parent=self) + collector("__setitem__", function=self._dict_add, parent=self) + collector("popitem", function=self._item_get, parent=self) + collector("pop", function=self._value_get, parent=self) + collector("get", function=self._key_get, parent=self) + collector("keys", function=self._key_list, parent=self) + collector("values", function=self._value_list, parent=self) + collector("items", function=self._item_list, parent=self) + collector("copy", function=self._self_get, parent=self) + collector("__getitem__", function=self._value_get, parent=self) + collector("__iter__", function=self._key_iter, parent=self) + collector("update", function=self._self_set, parent=self) + super().__init__(dict, collector.attributes) + + +def _is_id_char(self, offset): + return self.code[offset].isalnum() or self.code[offset] == "_" + + +def _find_string_start(self, offset): + kind = self.code[offset] + try: + return self.code.rindex(kind, 0, offset) + except ValueError: + return 0 + + +def _find_parens_start(self, offset): + offset = self._find_last_non_space_char(offset - 1) + while offset >= 0 and self.code[offset] not in "[({": + if self.code[offset] not in ":,": + offset = self._find_primary_start(offset) + offset = self._find_last_non_space_char(offset - 1) + return offset + + +def _find_atom_start(self, offset): + old_offset = offset + if self.code[offset] == "\n": + return offset + 1 + if self.code[offset].isspace(): + offset = self._find_last_non_space_char(offset) + if self.code[offset] in "'\"": + return self._find_string_start(offset) + if self.code[offset] in ")]}": + return self._find_parens_start(offset) + if self._is_id_char(offset): + return self._find_word_start(offset) + return old_offset + + +def _find_primary_without_dot_start(self, offset): + """It tries to find the undotted primary start + + It is different from `self._get_atom_start()` in that it + follows function calls, too; such as in ``f(x)``. + + """ + last_atom = offset + offset = self._find_last_non_space_char(last_atom) + while offset > 0 and self.code[offset] in ")]": + last_atom = self._find_parens_start(offset) + offset = self._find_last_non_space_char(last_atom - 1) + if offset >= 0 and (self.code[offset] in "\"'})]" or self._is_id_char(offset)): + atom_start = self._find_atom_start(offset) + if not keyword.iskeyword(self.code[atom_start : offset + 1]) or ( + offset + 1 < len(self.code) and self._is_id_char(offset + 1) + ): + return atom_start + return last_atom + + +def _find_primary_start(self, offset): + if offset >= len(self.code): + offset = len(self.code) - 1 + if self.code[offset] != ".": + offset = self._find_primary_without_dot_start(offset) + else: + offset = offset + 1 + while offset > 0: + prev = self._find_last_non_space_char(offset - 1) + if offset <= 0 or self.code[prev] != ".": + break + + # Check if relative import + # XXX: Looks like a hack... + prev_word_end = self._find_last_non_space_char(prev - 1) + if self.code[prev_word_end - 3 : prev_word_end + 1] == "from": + offset = prev + break + + offset = self._find_primary_without_dot_start(prev - 1) + if not self._is_id_char(offset): + break + + return offset + + +def get_primary_at(self, offset): + offset = self._get_fixed_offset(offset) + start, end = self.get_primary_range(offset) + return self.raw[start:end].strip() + + +def get_splitted_primary_before(self, offset): + """returns expression, starting, starting_offset + + This function is used in `rope.codeassist.assist` function. + """ + if offset == 0: + return ("", "", 0) + end = offset - 1 + word_start = self._find_atom_start(end) + real_start = self._find_primary_start(end) + if self.code[word_start:offset].strip() == "": + word_start = end + if self.code[end].isspace(): + word_start = end + if self.code[real_start:word_start].strip() == "": + real_start = word_start + if real_start == word_start == end and not self._is_id_char(end): + return ("", "", offset) + if real_start == word_start: + return ("", self.raw[word_start:offset], word_start) + else: + if self.code[end] == ".": + return (self.raw[real_start:end], "", offset) + last_dot_position = word_start + if self.code[word_start] != ".": + last_dot_position = self._find_last_non_space_char(word_start - 1) + last_char_position = self._find_last_non_space_char(last_dot_position - 1) + if self.code[word_start].isspace(): + word_start = offset + return ( + self.raw[real_start : last_char_position + 1], + self.raw[word_start:offset], + word_start, + ) + + +def _get_line_start(self, offset): + try: + return self.code.rindex("\n", 0, offset + 1) + except ValueError: + return 0 + + +def _get_line_end(self, offset): + try: + return self.code.index("\n", offset) + except ValueError: + return len(self.code) + + +def _new_dict(self, args): + def do_create(holding=None): + if holding is None: + return get_dict() + type = holding.get_type() + if isinstance(type, Tuple) and len(type.get_holding_objects()) == 2: + return get_dict(*type.get_holding_objects()) + + return _create_builtin(args, do_create) + + +def is_name_assigned_in_class_body(self, offset): + word_start = self._find_word_start(offset - 1) + word_end = self._find_word_end(offset) + 1 + if "." in self.code[word_start:word_end]: + return False + line_start = self._get_line_start(word_start) + line = self.code[line_start:word_start].strip() + return not line and self.get_assignment_type(offset) == "=" + + +def is_a_class_or_function_name_in_header(self, offset): + word_start = self._find_word_start(offset - 1) + line_start = self._get_line_start(word_start) + prev_word = self.code[line_start:word_start].strip() + return prev_word in ["def", "class"] + + +def _find_first_non_space_char(self, offset): + if offset >= len(self.code): + return len(self.code) + while offset < len(self.code) and self.code[offset].isspace(): + if self.code[offset] == "\n": + return offset + offset += 1 + return offset + + +def is_a_function_being_called(self, offset): + word_end = self._find_word_end(offset) + 1 + next_char = self._find_first_non_space_char(word_end) + return ( + next_char < len(self.code) + and self.code[next_char] == "(" + and not self.is_a_class_or_function_name_in_header(offset) + ) + + +def _find_import_end(self, start): + return self._get_line_end(start) + + +def is_import_statement(self, offset): + try: + last_import = self.code.rindex("import ", 0, offset) + except ValueError: + return False + line_start = self._get_line_start(last_import) + return ( + self._find_import_end(last_import + 7) >= offset + and self._find_word_start(line_start) == last_import + ) + + +def is_from_statement(self, offset): + try: + last_from = self.code.rindex("from ", 0, offset) + from_import = self.code.index(" import ", last_from) + from_names = from_import + 8 + except ValueError: + return False + from_names = self._find_first_non_space_char(from_names) + return self._find_import_end(from_names) >= offset + + +def is_from_statement_module(self, offset): + if offset >= len(self.code) - 1: + return False + stmt_start = self._find_primary_start(offset) + line_start = self._get_line_start(stmt_start) + prev_word = self.code[line_start:stmt_start].strip() + return prev_word == "from" + + +def is_import_statement_aliased_module(self, offset): + if not self.is_import_statement(offset): + return False + try: + line_start = self._get_line_start(offset) + import_idx = self.code.rindex("import", line_start, offset) + imported_names = import_idx + 7 + except ValueError: + return False + # Check if the offset is within the imported names + if ( + imported_names - 1 > offset + or self._find_import_end(imported_names) < offset + ): + return False + try: + end = self._find_import_main_part_end(offset) + if not self._has_enough_len_for_as(end): + return False + as_end = min(self._find_word_end(end + 1), len(self.code)) + as_start = self._find_word_start(as_end) + return self.code[as_start : as_end + 1] == "as" + except ValueError: + return False + + +def _has_enough_len_for_as(self, end): + return len(self.code) > end + MINIMAL_LEN_FOR_AS + + +@path C:/Repos/ekr-rope/docs/ +# The default ``config.py`` +# flake8: noqa + + +@others +@language python +@tabwidth -4 + +def _dict_add(self, context): + if self.keys is not None: + return + key, value = context.get_arguments(["self", "key", "value"])[1:] + if key is not None and key != pyobjects.get_unknown(): + context.save_per_name(get_tuple(key, value)) + + +def _find_import_main_part_end(self, offset): + end = self._find_word_end(offset) + while len(self.code) > end + 2 and self.code[end + 1] == ".": + end = self._find_word_end(end + 2) + return end + + +def is_a_name_after_from_import(self, offset): + try: + if len(self.code) > offset and self.code[offset] == "\n": + line_start = self._get_line_start(offset - 1) + else: + line_start = self._get_line_start(offset) + last_from = self.code.rindex("from ", line_start, offset) + from_import = self.code.index(" import ", last_from) + from_names = from_import + 8 + except ValueError: + return False + if from_names - 1 > offset: + return False + return self._find_import_end(from_names) >= offset + + +def get_from_module(self, offset): + try: + last_from = self.code.rindex("from ", 0, offset) + import_offset = self.code.index(" import ", last_from) + end = self._find_last_non_space_char(import_offset) + return self.get_primary_at(end) + except ValueError: + pass + + +def is_from_aliased(self, offset): + if not self.is_a_name_after_from_import(offset): + return False + try: + end = self._find_word_end(offset) + as_end = min(self._find_word_end(end + 1), len(self.code)) + as_start = self._find_word_start(as_end) + return self.code[as_start : as_end + 1] == "as" + except ValueError: + return False + + +def get_from_aliased(self, offset): + try: + end = self._find_word_end(offset) + as_ = self._find_word_end(end + 1) + alias = self._find_word_end(as_ + 1) + start = self._find_word_start(alias) + return self.raw[start : alias + 1] + except ValueError: + pass + + +def is_function_keyword_parameter(self, offset): + word_end = self._find_word_end(offset) + if word_end + 1 == len(self.code): + return False + next_char = self._find_first_non_space_char(word_end + 1) + equals = self.code[next_char : next_char + 2] + if equals == "==" or not equals.startswith("="): + return False + word_start = self._find_word_start(offset) + prev_char = self._find_last_non_space_char(word_start - 1) + return prev_char - 1 >= 0 and self.code[prev_char] in ",(" + + +def is_on_function_call_keyword(self, offset): + stop = self._get_line_start(offset) + if self._is_id_char(offset): + offset = self._find_word_start(offset) - 1 + offset = self._find_last_non_space_char(offset) + if offset <= stop or self.code[offset] not in "(,": + return False + parens_start = self.find_parens_start_from_inside(offset) + return stop < parens_start + + +def find_parens_start_from_inside(self, offset): + stop = self._get_line_start(offset) + while offset > stop: + if self.code[offset] == "(": + break + if self.code[offset] != ",": + offset = self._find_primary_start(offset) + offset -= 1 + return max(stop, offset) + + +def is_assigned_here(self, offset): + return self.get_assignment_type(offset) is not None + + +def get_assignment_type(self, offset): + # XXX: does not handle tuple assignments + word_end = self._find_word_end(offset) + next_char = self._find_first_non_space_char(word_end + 1) + single = self.code[next_char : next_char + 1] + double = self.code[next_char : next_char + 2] + triple = self.code[next_char : next_char + 3] + if double not in ("==", "<=", ">=", "!="): + for op in [single, double, triple]: + if op.endswith("="): + return op + + +def _item_get(self, context): + if self.keys is not None: + return get_tuple(self.keys, self.values) + item = context.get_per_name() + if item is None or not isinstance(item.get_type(), Tuple): + return get_tuple(self.keys, self.values) + return item + + +def get_primary_range(self, offset): + start = self._find_primary_start(offset) + end = self._find_word_end(offset) + 1 + return (start, end) + + +def get_word_range(self, offset): + offset = max(0, offset) + start = self._find_word_start(offset) + end = self._find_word_end(offset) + 1 + return (start, end) + + +def get_word_parens_range(self, offset, opening="(", closing=")"): + end = self._find_word_end(offset) + start_parens = self.code.index(opening, end) + index = start_parens + open_count = 0 + while index < len(self.code): + if self.code[index] == opening: + open_count += 1 + if self.code[index] == closing: + open_count -= 1 + if open_count == 0: + return (start_parens, index + 1) + index += 1 + return (start_parens, index) + + +def get_parameters(self, first, last): + keywords = [] + args = [] + current = self._find_last_non_space_char(last - 1) + while current > first: + primary_start = current + current = self._find_primary_start(current) + while current != first and ( + self.code[current] not in "=," or self.code[current - 1] in "=!<>" + ): + current = self._find_last_non_space_char(current - 1) + primary = self.raw[current + 1 : primary_start + 1].strip() + if self.code[current] == "=": + primary_start = current - 1 + current -= 1 + while current != first and self.code[current] not in ",": + current = self._find_last_non_space_char(current - 1) + param_name = self.raw[current + 1 : primary_start + 1].strip() + keywords.append((self.__strip_type_hint(param_name), primary)) + else: + args.append(self.__strip_type_hint(primary)) + current = self._find_last_non_space_char(current - 1) + args.reverse() + keywords.reverse() + return args, keywords + + +def __strip_type_hint(self, name): + return name.split(":", 1)[0] + + +def is_assigned_in_a_tuple_assignment(self, offset): + start = self._get_line_start(offset) + end = self._get_line_end(offset) + primary_start = self._find_primary_start(offset) + primary_end = self._find_word_end(offset) + + prev_char_offset = self._find_last_non_space_char(primary_start - 1) + next_char_offset = self._find_first_non_space_char(primary_end + 1) + next_char = prev_char = "" + if prev_char_offset >= start: + prev_char = self.code[prev_char_offset] + if next_char_offset < end: + next_char = self.code[next_char_offset] + try: + equals_offset = self.code.index("=", start, end) + except ValueError: + return False + if prev_char not in "(," and next_char not in ",)": + return False + parens_start = self.find_parens_start_from_inside(offset) + # XXX: only handling (x, y) = value + return offset < equals_offset and self.code[start:parens_start].strip() == "" + + +def get_function_and_args_in_header(self, offset): + offset = self.find_function_offset(offset) + lparens, rparens = self.get_word_parens_range(offset) + return self.raw[offset : rparens + 1] + + +def find_function_offset(self, offset, definition="def "): + while True: + offset = self.code.index(definition, offset) + if offset == 0 or not self._is_id_char(offset - 1): + break + offset += 1 + def_ = offset + 4 + return self._find_first_non_space_char(def_) + + +def get_lambda_and_args(self, offset): + offset = self.find_function_offset(offset, definition="lambda ") + lparens, rparens = self.get_word_parens_range(offset, opening=" ", closing=":") + return self.raw[offset : rparens + 1] + +@path C:/Repos/ekr-rope/rope/base/ +"""Base rope package + +This package contains rope core modules that are used by other modules +and packages. + +""" + +__all__ = ["project", "libutils", "exceptions"] +@language python +@tabwidth -4 + +def _value_get(self, context): + item = self._item_get(context).get_type() + return item.get_holding_objects()[1] + + + +@path C:/Repos/ekr-rope/rope/base/oi/ +import base64 +import hashlib +import hmac + +try: + import cPickle as pickle +except ImportError: + import pickle +import marshal +import os +import socket +import subprocess +import sys +import tempfile +import threading + + +@others +@language python +@tabwidth -4 + +def _compat_compare_digest(a, b): + """Implementation of hmac.compare_digest for python < 2.7.7. + + This function uses an approach designed to prevent timing analysis by + avoiding content-based short circuiting behaviour, making it appropriate + for cryptography. + """ + if len(a) != len(b): + return False + # Computes the bitwise difference of all characters in the two strings + # before returning whether or not they are equal. + difference = 0 + for (a_char, b_char) in zip(a, b): + difference |= ord(a_char) ^ ord(b_char) + return difference == 0 + + + +try: + from hmac import compare_digest +except ImportError: + compare_digest = _compat_compare_digest + + + +class PythonFileRunner: + """A class for running python project files""" + + @others + +def __init__( + self, pycore, file_, args=None, stdin=None, stdout=None, analyze_data=None +): + self.pycore = pycore + self.file = file_ + self.analyze_data = analyze_data + self.observers = [] + self.args = args + self.stdin = stdin + self.stdout = stdout + + +def run(self): + """Execute the process""" + env = dict(os.environ) + file_path = self.file.real_path + path_folders = ( + self.pycore.project.get_source_folders() + + self.pycore.project.get_python_path_folders() + ) + env["PYTHONPATH"] = os.pathsep.join(folder.real_path for folder in path_folders) + runmod_path = self.pycore.project.find_module("rope.base.oi.runmod").real_path + self.receiver = None + self._init_data_receiving() + send_info = "-" + if self.receiver: + send_info = self.receiver.get_send_info() + args = [ + sys.executable, + runmod_path, + send_info, + self.pycore.project.address, + self.file.real_path, + ] + if self.analyze_data is None: + del args[1:4] + if self.args is not None: + args.extend(self.args) + self.process = subprocess.Popen( + executable=sys.executable, + args=args, + env=env, + cwd=os.path.split(file_path)[0], + stdin=self.stdin, + stdout=self.stdout, + stderr=self.stdout, + close_fds=os.name != "nt", + ) + + +def _init_data_receiving(self): + if self.analyze_data is None: + return + # Disabling FIFO data transfer due to blocking when running + # unittests in the GUI. + # XXX: Handle FIFO data transfer for `rope.ui.testview` + if True or os.name == "nt": + self.receiver = _SocketReceiver() + else: + self.receiver = _FIFOReceiver() + self.receiving_thread = threading.Thread(target=self._receive_information) + self.receiving_thread.setDaemon(True) + self.receiving_thread.start() + + +def _receive_information(self): + # temp = open('/dev/shm/info', 'wb') + for data in self.receiver.receive_data(): + self.analyze_data(data) + # temp.write(str(data) + '\n') + # temp.close() + for observer in self.observers: + observer() + + +def wait_process(self): + """Wait for the process to finish""" + self.process.wait() + if self.analyze_data: + self.receiving_thread.join() + + +def _key_get(self, context): + item = self._item_get(context).get_type() + return item.get_holding_objects()[0] + + +def kill_process(self): + """Stop the process""" + if self.process.poll() is not None: + return + try: + if hasattr(self.process, "terminate"): + self.process.terminate() + elif os.name != "nt": + os.kill(self.process.pid, 9) + else: + import ctypes + + handle = int(self.process._handle) + ctypes.windll.kernel32.TerminateProcess(handle, -1) + except OSError: + pass + + +def add_finishing_observer(self, observer): + """Notify this observer when execution finishes""" + self.observers.append(observer) + + + +class _MessageReceiver: + def receive_data(self): + pass + + def get_send_info(self): + pass + + + +class _SocketReceiver(_MessageReceiver): + @others + +def __init__(self): + self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.data_port = 3037 + self.key = os.urandom(32) + + while self.data_port < 4000: + try: + self.server_socket.bind(("localhost", self.data_port)) + break + except OSError: + self.data_port += 1 + self.server_socket.listen(1) + + +def get_send_info(self): + return "%d:%s" % (self.data_port, base64.b64encode(self.key).decode("utf-8")) + + +def receive_data(self): + conn, addr = self.server_socket.accept() + self.server_socket.close() + my_file = conn.makefile("rb") + while True: + # Received messages must meet the following criteria: + # 1. Must be contained on a single line. + # 2. Must be prefixed with a base64 encoded sha256 message digest + # of the base64 encoded pickle data. + # 3. Message digest must be computed using the correct key. + # + # Any messages received that do not meet these criteria will never + # be unpickled and will be dropped silently. + try: + buf = my_file.readline() + if len(buf) == 0: + break + + try: + digest_end = buf.index(b":") + buf_digest = base64.b64decode(buf[:digest_end]) + buf_data = buf[digest_end + 1 : -1] + decoded_buf_data = base64.b64decode(buf_data) + except: + # Corrupted data; the payload cannot be trusted and just has + # to be dropped. See CVE-2014-3539. + continue + + digest = hmac.new(self.key, buf_data, hashlib.sha256).digest() + if not compare_digest(buf_digest, digest): + # Signature mismatch; the payload cannot be trusted and just + # has to be dropped. See CVE-2014-3539. + continue + + yield pickle.loads(decoded_buf_data) + except EOFError: + break + my_file.close() + conn.close() + + + +class _FIFOReceiver(_MessageReceiver): + @others + +def __init__(self): + # XXX: this is insecure and might cause race conditions + self.file_name = self._get_file_name() + os.mkfifo(self.file_name) + + +def _get_file_name(self): + prefix = tempfile.gettempdir() + "/__rope_" + i = 0 + while os.path.exists(prefix + str(i).rjust(4, "0")): + i += 1 + return prefix + str(i).rjust(4, "0") + + +def _value_list(self, context): + return get_list(self._value_get(context)) + + +def get_send_info(self): + return self.file_name + + +def receive_data(self): + my_file = open(self.file_name, "rb") + while True: + try: + yield marshal.load(my_file) + except EOFError: + break + my_file.close() + os.remove(self.file_name) + +@path C:/Repos/ekr-rope/rope/base/oi/ +from rope.base.oi import objectdb + + +@others +@language python +@tabwidth -4 + +class MemoryDB(objectdb.FileDict): + @others + +def __init__(self, project, persist=None): + self.project = project + self._persist = persist + self.files = self + self._load_files() + self.project.data_files.add_write_hook(self.write) + + +def _load_files(self): + self._files = {} + if self.persist: + result = self.project.data_files.read_data( + "objectdb", compress=self.compress, import_=True + ) + if result is not None: + self._files = result + + +def keys(self): + return self._files.keys() + + +def __iter__(self): + yield from self._files + + +def __len__(self): + return len(self._files) + + +def __setitem__(self): + raise NotImplementedError() + + +def _key_list(self, context): + return get_list(self._key_get(context)) + + +def __contains__(self, key): + return key in self._files + + +def __getitem__(self, key): + return FileInfo(self._files[key]) + + +def create(self, path): + self._files[path] = {} + + +def rename(self, file, newfile): + if file not in self._files: + return + self._files[newfile] = self._files[file] + del self[file] + + +def __delitem__(self, file): + del self._files[file] + + +def write(self): + if self.persist: + self.project.data_files.write_data("objectdb", self._files, self.compress) + + +@property +def compress(self): + return self.project.prefs.get("compress_objectdb", False) + + +@property +def persist(self): + if self._persist is not None: + return self._persist + else: + return self.project.prefs.get("save_objectdb", False) + + + +class FileInfo(objectdb.FileInfo): + @others + +def __init__(self, scopes): + self.scopes = scopes + + +def _item_list(self, context): + return get_list(self._item_get(context)) + + +def create_scope(self, key): + self.scopes[key] = ScopeInfo() + + +def keys(self): + return self.scopes.keys() + + +def __contains__(self, key): + return key in self.scopes + + +def __getitem__(self, key): + return self.scopes[key] + + +def __delitem__(self, key): + del self.scopes[key] + + +def __iter__(self): + yield from self.scopes + + +def __len__(self): + return len(self.scopes) + + +def __setitem__(self): + raise NotImplementedError() + + + +class ScopeInfo(objectdb.ScopeInfo): + @others + +def __init__(self): + self.call_info = {} + self.per_name = {} + + +def _value_iter(self, context): + return get_iterator(self._value_get(context)) + + +def get_per_name(self, name): + return self.per_name.get(name, None) + + +def save_per_name(self, name, value): + self.per_name[name] = value + + +def get_returned(self, parameters): + return self.call_info.get(parameters, None) + + +def get_call_infos(self): + for args, returned in self.call_info.items(): + yield objectdb.CallInfo(args, returned) + + +def add_call(self, parameters, returned): + self.call_info[parameters] = returned + + +def __getstate__(self): + return (self.call_info, self.per_name) + + +def __setstate__(self, data): + self.call_info, self.per_name = data + +@path C:/Repos/ekr-rope/rope/base/oi/ +@others +@language python +@tabwidth -4 + +class ObjectDB: + @others + +def __init__(self, db, validation): + self.db = db + self.validation = validation + self.observers = [] + self.files = db.files + + +def _key_iter(self, context): + return get_iterator(self._key_get(context)) + + +def validate_files(self): + for file in list(self.files): + if not self.validation.is_file_valid(file): + del self.files[file] + self._file_removed(file) + + +def validate_file(self, file): + if file not in self.files: + return + for key in list(self.files[file]): + if not self.validation.is_scope_valid(file, key): + del self.files[file][key] + + +def file_moved(self, file, newfile): + if file not in self.files: + return + self.files.rename(file, newfile) + self._file_removed(file) + self._file_added(newfile) + + +def get_files(self): + return self.files.keys() + + +def get_returned(self, path, key, args): + scope_info = self._get_scope_info(path, key, readonly=True) + result = scope_info.get_returned(args) + if self.validation.is_value_valid(result): + return result + + +def get_pername(self, path, key, name): + scope_info = self._get_scope_info(path, key, readonly=True) + result = scope_info.get_per_name(name) + if self.validation.is_value_valid(result): + return result + + +def get_callinfos(self, path, key): + scope_info = self._get_scope_info(path, key, readonly=True) + return scope_info.get_call_infos() + + +def add_callinfo(self, path, key, args, returned): + scope_info = self._get_scope_info(path, key, readonly=False) + old_returned = scope_info.get_returned(args) + if self.validation.is_more_valid(returned, old_returned): + scope_info.add_call(args, returned) + + +def add_pername(self, path, key, name, value): + scope_info = self._get_scope_info(path, key, readonly=False) + old_value = scope_info.get_per_name(name) + if self.validation.is_more_valid(value, old_value): + scope_info.save_per_name(name, value) + + +def add_file_list_observer(self, observer): + self.observers.append(observer) + + +def _item_iter(self, context): + return get_iterator(self._item_get(context)) + + +def write(self): + self.db.write() + + +def _get_scope_info(self, path, key, readonly=True): + if path not in self.files: + if readonly: + return _NullScopeInfo() + self.files.create(path) + self._file_added(path) + if key not in self.files[path]: + if readonly: + return _NullScopeInfo() + self.files[path].create_scope(key) + result = self.files[path][key] + if isinstance(result, dict): + print(self.files, self.files[path], self.files[path][key]) + return result + + +def _file_removed(self, path): + for observer in self.observers: + observer.removed(path) + + +def _file_added(self, path): + for observer in self.observers: + observer.added(path) + + +def __str__(self): + scope_count = 0 + for file_dict in self.files.values(): + scope_count += len(file_dict) + return "ObjectDB holds {} file and {} scope infos".format( + len(self.files), + scope_count, + ) + + + +class _NullScopeInfo: + @others + +def __init__(self, error_on_write=True): + self.error_on_write = error_on_write + + +def get_per_name(self, name): + pass + + +def save_per_name(self, name, value): + if self.error_on_write: + raise NotImplementedError() + + +def get_returned(self, parameters): + pass + + +def set_prefs(prefs): + """This function is called before opening the project""" + + # Specify which files and folders to ignore in the project. + # Changes to ignored resources are not added to the history and + # VCSs. Also they are not returned in `Project.get_files()`. + # Note that ``?`` and ``*`` match all characters but slashes. + # "*.pyc": matches "test.pyc" and "pkg/test.pyc" + # "mod*.pyc": matches "test/mod1.pyc" but not "mod/1.pyc" + # ".svn": matches "pkg/.svn" and all of its children + # "build/*.o": matches "build/lib.o" but not "build/sub/lib.o" + # "build//*.o": matches "build/lib.o" and "build/sub/lib.o" + # + # prefs["ignored_resources"] = [ + # "*.pyc", + # "*~", + # ".ropeproject", + # ".hg", + # ".svn", + # "_svn", + # ".git", + # ".tox", + # ".venv", + # "venv", + # ".mypy_cache", + # ".pytest_cache", + # ] + + # Specifies which files should be considered python files. It is + # useful when you have scripts inside your project. Only files + # ending with ``.py`` are considered to be python files by + # default. + # + # prefs["python_files"] = ["*.py"] + + # Custom source folders: By default rope searches the project + # for finding source folders (folders that should be searched + # for finding modules). You can add paths to that list. Note + # that rope guesses project source folders correctly most of the + # time; use this if you have any problems. + # The folders should be relative to project root and use "/" for + # separating folders regardless of the platform rope is running on. + # "src/my_source_folder" for instance. + # + # prefs.add("source_folders", "src") + + # You can extend python path for looking up modules + # + # prefs.add("python_path", "~/python/") + + # Should rope save object information or not. + # + # prefs["save_objectdb"] = True + # prefs["compress_objectdb"] = False + + # If `True`, rope analyzes each module when it is being saved. + # + # prefs["automatic_soa"] = True + # + # The depth of calls to follow in static object analysis + # + # prefs["soa_followed_calls"] = 0 + + # If `False` when running modules or unit tests "dynamic object + # analysis" is turned off. This makes them much faster. + # + # prefs["perform_doa"] = True + + # Rope can check the validity of its object DB when running. + # + # prefs["validate_objectdb"] = True + + # How many undos to hold? + # + # prefs["max_history_items"] = 32 + + # Shows whether to save history across sessions. + # + # prefs["save_history"] = True + # prefs["compress_history"] = False + + # Set the number spaces used for indenting. According to + # :PEP:`8`, it is best to use 4 spaces. Since most of rope's + # unit-tests use 4 spaces it is more reliable, too. + # + # prefs["indent_size"] = 4 + + # Builtin and c-extension modules that are allowed to be imported + # and inspected by rope. + # + # prefs["extension_modules"] = [] + + # Add all standard c-extensions to extension_modules list. + # + # prefs["import_dynload_stdmods"] = True + + # If `True` modules with syntax errors are considered to be empty. + # The default value is `False`; When `False` syntax errors raise + # `rope.base.exceptions.ModuleSyntaxError` exception. + # + # prefs["ignore_syntax_errors"] = False + + # If `True`, rope ignores unresolvable imports. Otherwise, they + # appear in the importing namespace. + # + # prefs["ignore_bad_imports"] = False + + # If `True`, rope will insert new module imports as + # `from <package> import <module>` by default. + # + # prefs["prefer_module_from_imports"] = False + + # If `True`, rope will transform a comma list of imports into + # multiple separate import statements when organizing + # imports. + # + # prefs["split_imports"] = False + + # If `True`, rope will remove all top-level import statements and + # reinsert them at the top of the module when making changes. + # + # prefs["pull_imports_to_top"] = True + + # If `True`, rope will sort imports alphabetically by module name instead + # of alphabetically by import statement, with from imports after normal + # imports. + # + # prefs["sort_imports_alphabetically"] = False + + # Location of implementation of + # rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general + # case, you don't have to change this value, unless you're an rope expert. + # Change this value to inject you own implementations of interfaces + # listed in module rope.base.oi.type_hinting.providers.interfaces + # For example, you can add you own providers for Django Models, or disable + # the search type-hinting in a class hierarchy, etc. + # + # prefs[ + # "type_hinting_factory" + # ] = "rope.base.oi.type_hinting.factory.default_type_hinting_factory" + + + +def _self_get(self, context): + item = self._item_get(context).get_type() + key, value = item.get_holding_objects()[:2] + return get_dict(key, value) + + +def get_call_infos(self): + return [] + + +def add_call(self, parameters, returned): + if self.error_on_write: + raise NotImplementedError() + + + +class FileInfo(dict): + def create_scope(self, key): + pass + + + +class FileDict(dict): + def create(self, key): + pass + + def rename(self, key, new_key): + pass + + + +class ScopeInfo: + @others + +def get_per_name(self, name): + pass + + +def save_per_name(self, name, value): + pass + + +def get_returned(self, parameters): + pass + + +def get_call_infos(self): + pass + + +def add_call(self, parameters, returned): + pass + + + +def _self_set(self, context): + if self.keys is not None: + return + new_dict = context.get_pynames(["self", "d"])[1] + if new_dict and isinstance(new_dict.get_object().get_type(), Dict): + args = arguments.ObjectArguments([new_dict]) + items = ( + new_dict.get_object()["popitem"].get_object().get_returned_object(args) + ) + context.save_per_name(items) + else: + holding = _infer_sequence_for_pyname(new_dict) + if holding is not None and isinstance(holding.get_type(), Tuple): + context.save_per_name(holding) + + + +class CallInfo: + @others + +def __init__(self, args, returned): + self.args = args + self.returned = returned + + +def get_parameters(self): + return self.args + + +def get_returned(self): + return self.returned + + + +class FileListObserver: + def added(self, path): + pass + + def removed(self, path): + pass + +@path C:/Repos/ekr-rope/rope/base/oi/ +import warnings + +from rope.base import exceptions, resourceobserver +from rope.base.oi import objectdb, memorydb, transform + + +@others +@language python +@tabwidth -4 + +class ObjectInfoManager: + """Stores object information + + It uses an instance of `objectdb.ObjectDB` for storing + information. + + """ + + @others + +def __init__(self, project): + self.project = project + self.to_textual = transform.PyObjectToTextual(project) + self.to_pyobject = transform.TextualToPyObject(project) + self.doi_to_pyobject = transform.DOITextualToPyObject(project) + self._init_objectdb() + if project.prefs.get("validate_objectdb", False): + self._init_validation() + + +def _init_objectdb(self): + dbtype = self.project.get_prefs().get("objectdb_type", None) + persist = None + if dbtype is not None: + warnings.warn( + '"objectdb_type" project config is deprecated;\n' + 'Use "save_objectdb" instead in your project ' + 'config file.\n(".ropeproject/config.py" by default)\n', + DeprecationWarning, + ) + if dbtype != "memory" and self.project.ropefolder is not None: + persist = True + self.validation = TextualValidation(self.to_pyobject) + db = memorydb.MemoryDB(self.project, persist=persist) + self.objectdb = objectdb.ObjectDB(db, self.validation) + + +def _init_validation(self): + self.objectdb.validate_files() + observer = resourceobserver.ResourceObserver( + changed=self._resource_changed, + moved=self._resource_moved, + removed=self._resource_moved, + ) + files = [] + for path in self.objectdb.get_files(): + resource = self.to_pyobject.path_to_resource(path) + if resource is not None and resource.project == self.project: + files.append(resource) + self.observer = resourceobserver.FilteredResourceObserver(observer, files) + self.objectdb.add_file_list_observer(_FileListObserver(self)) + self.project.add_observer(self.observer) + + +get_dict = _create_builtin_getter(Dict) +get_dict_type = _create_builtin_type_getter(Dict) + + + +def _resource_changed(self, resource): + try: + self.objectdb.validate_file(self.to_textual.resource_to_path(resource)) + except exceptions.ModuleSyntaxError: + pass + + +def _resource_moved(self, resource, new_resource=None): + self.observer.remove_resource(resource) + if new_resource is not None: + old = self.to_textual.resource_to_path(resource) + new = self.to_textual.resource_to_path(new_resource) + self.objectdb.file_moved(old, new) + self.observer.add_resource(new_resource) + + +def get_returned(self, pyobject, args): + result = self.get_exact_returned(pyobject, args) + if result is not None: + return result + path, key = self._get_scope(pyobject) + if path is None: + return None + for call_info in self.objectdb.get_callinfos(path, key): + returned = call_info.get_returned() + if returned and returned[0] not in ("unknown", "none"): + result = returned + break + if result is None: + result = returned + if result is not None: + return self.to_pyobject(result) + + +def get_exact_returned(self, pyobject, args): + path, key = self._get_scope(pyobject) + if path is not None: + returned = self.objectdb.get_returned( + path, key, self._args_to_textual(pyobject, args) + ) + if returned is not None: + return self.to_pyobject(returned) + + +def _args_to_textual(self, pyfunction, args): + parameters = list(pyfunction.get_param_names(special_args=False)) + arguments = args.get_arguments(parameters)[: len(parameters)] + textual_args = tuple(self.to_textual(arg) for arg in arguments) + return textual_args + + +def get_parameter_objects(self, pyobject): + path, key = self._get_scope(pyobject) + if path is None: + return None + arg_count = len(pyobject.get_param_names(special_args=False)) + unknowns = arg_count + parameters = [None] * arg_count + for call_info in self.objectdb.get_callinfos(path, key): + args = call_info.get_parameters() + for index, arg in enumerate(args[:arg_count]): + old = parameters[index] + if self.validation.is_more_valid(arg, old): + parameters[index] = arg + if self.validation.is_value_valid(arg): + unknowns -= 1 + if unknowns == 0: + break + if unknowns < arg_count: + return [self.to_pyobject(parameter) for parameter in parameters] + + +def get_passed_objects(self, pyfunction, parameter_index): + path, key = self._get_scope(pyfunction) + if path is None: + return [] + result = [] + for call_info in self.objectdb.get_callinfos(path, key): + args = call_info.get_parameters() + if len(args) > parameter_index: + parameter = self.to_pyobject(args[parameter_index]) + if parameter is not None: + result.append(parameter) + return result + + +def doa_data_received(self, data): + def doi_to_normal(textual): + pyobject = self.doi_to_pyobject(textual) + return self.to_textual(pyobject) + + function = doi_to_normal(data[0]) + args = tuple(doi_to_normal(textual) for textual in data[1]) + returned = doi_to_normal(data[2]) + if function[0] == "defined" and len(function) == 3: + self._save_data(function, args, returned) + + +def function_called(self, pyfunction, params, returned=None): + function_text = self.to_textual(pyfunction) + params_text = tuple(self.to_textual(param) for param in params) + returned_text = ("unknown",) + if returned is not None: + returned_text = self.to_textual(returned) + self._save_data(function_text, params_text, returned_text) + + +def save_per_name(self, scope, name, data): + path, key = self._get_scope(scope.pyobject) + if path is not None: + self.objectdb.add_pername(path, key, name, self.to_textual(data)) + + +class Tuple(BuiltinClass): + @others + +def get_per_name(self, scope, name): + path, key = self._get_scope(scope.pyobject) + if path is not None: + result = self.objectdb.get_pername(path, key, name) + if result is not None: + return self.to_pyobject(result) + + +def _save_data(self, function, args, returned=("unknown",)): + self.objectdb.add_callinfo(function[1], function[2], args, returned) + + +def _get_scope(self, pyobject): + resource = pyobject.get_module().get_resource() + if resource is None: + return None, None + textual = self.to_textual(pyobject) + if textual[0] == "defined": + path = textual[1] + if len(textual) == 3: + key = textual[2] + else: + key = "" + return path, key + return None, None + + +def sync(self): + self.objectdb.sync() + + +def __str__(self): + return str(self.objectdb) + + + +class TextualValidation: + @others + +def __init__(self, to_pyobject): + self.to_pyobject = to_pyobject + + +def is_value_valid(self, value): + # ???: Should none and unknown be considered valid? + if value is None or value[0] in ("none", "unknown"): + return False + return self.to_pyobject(value) is not None + + +def is_more_valid(self, new, old): + if old is None: + return True + return new[0] not in ("unknown", "none") + + +def is_file_valid(self, path): + return self.to_pyobject.path_to_resource(path) is not None + + +def __init__(self, *objects): + self.objects = objects + first = None + if objects: + first = objects[0] + attributes = { + "__getitem__": BuiltinName( + BuiltinFunction(first) + ), # TODO: add slice support + "__getslice__": BuiltinName(BuiltinFunction(pyobjects.PyObject(self))), + "__new__": BuiltinName(BuiltinFunction(function=self._new_tuple)), + "__iter__": BuiltinName(BuiltinFunction(get_iterator(first))), + } + super().__init__(tuple, attributes) + + +def is_scope_valid(self, path, key): + if key == "": + textual = ("defined", path) + else: + textual = ("defined", path, key) + return self.to_pyobject(textual) is not None + + + +class _FileListObserver: + @others + +def __init__(self, object_info): + self.object_info = object_info + self.observer = self.object_info.observer + self.to_pyobject = self.object_info.to_pyobject + + +def removed(self, path): + resource = self.to_pyobject.path_to_resource(path) + if resource is not None: + self.observer.remove_resource(resource) + + +def added(self, path): + resource = self.to_pyobject.path_to_resource(path) + if resource is not None: + self.observer.add_resource(resource) + +@path C:/Repos/ekr-rope/rope/base/oi/ +@others +if __name__ == "__main__": + __rope_start_everything() +@language python +@tabwidth -4 + +def __rope_start_everything(): + import os + import sys + import socket + + try: + import cPickle as pickle + except ImportError: + import pickle + import marshal + import inspect + import types + import threading + import base64 + import hashlib + import hmac + + @others + send_info = sys.argv[1] + project_root = sys.argv[2] + file_to_run = sys.argv[3] + run_globals = globals() + run_globals.update( + {"__name__": "__main__", "__builtins__": __builtins__, "__file__": file_to_run} + ) + + if send_info != "-": + data_sender = _FunctionCallDataSender(send_info, project_root) + del sys.argv[1:4] + with open(file_to_run) as f: + code = compile(f.read(), file_to_run, 'exec') + exec(code, run_globals) + if send_info != "-": + data_sender.close() + +class _MessageSender: + def send_data(self, data): + pass + + +class _SocketSender(_MessageSender): + def __init__(self, port, key): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(("127.0.0.1", port)) + self.my_file = s.makefile("wb") + self.key = base64.b64decode(key) + + def send_data(self, data): + if not self.my_file.closed: + pickled_data = base64.b64encode( + pickle.dumps(data, pickle.HIGHEST_PROTOCOL) + ) + dgst = hmac.new(self.key, pickled_data, hashlib.sha256).digest() + self.my_file.write(base64.b64encode(dgst) + b":" + pickled_data + b"\n") + + def close(self): + self.my_file.close() + + +class _FileSender(_MessageSender): + def __init__(self, file_name): + self.my_file = open(file_name, "wb") + + def send_data(self, data): + if not self.my_file.closed: + marshal.dump(data, self.my_file) + + def close(self): + self.my_file.close() + + +def get_holding_objects(self): + return self.objects + + +def _cached(func): + cache = {} + + def newfunc(self, arg): + if arg in cache: + return cache[arg] + result = func(self, arg) + cache[arg] = result + return result + + return newfunc + + +class _FunctionCallDataSender: + def __init__(self, send_info, project_root): + self.project_root = project_root + if send_info[0].isdigit(): + port, key = send_info.split(":", 1) + self.sender = _SocketSender(int(port), key) + else: + self.sender = _FileSender(send_info) + + @others + sys.settrace(global_trace) + threading.settrace(global_trace) + + def on_function_call(self, frame, event, arg): + if event != "return": + return + args = [] + returned = ("unknown",) + code = frame.f_code + for argname in code.co_varnames[: code.co_argcount]: + try: + argvalue = self._object_to_persisted_form(frame.f_locals[argname]) + args.append(argvalue) + except (TypeError, AttributeError): + args.append(("unknown",)) + try: + returned = self._object_to_persisted_form(arg) + except (TypeError, AttributeError): + pass + try: + data = ( + self._object_to_persisted_form(frame.f_code), + tuple(args), + returned, + ) + self.sender.send_data(data) + except (TypeError): + pass + return self.on_function_call + + def _is_an_interesting_call(self, frame): + # if frame.f_code.co_name in ['?', '<module>']: + # return False + # return not frame.f_back or + # not self._is_code_inside_project(frame.f_back.f_code) + if not self._is_code_inside_project(frame.f_code) and ( + not frame.f_back + or not self._is_code_inside_project(frame.f_back.f_code) + ): + return False + return True + + def _is_code_inside_project(self, code): + source = self._path(code.co_filename) + return ( + source is not None + and os.path.exists(source) + and _realpath(source).startswith(self.project_root) + ) + + @_cached + def _get_persisted_code(self, object_): + source = self._path(object_.co_filename) + if not os.path.exists(source): + raise TypeError("no source") + return ("defined", _realpath(source), str(object_.co_firstlineno)) + + @_cached + def _get_persisted_class(self, object_): + try: + return ( + "defined", + _realpath(inspect.getsourcefile(object_)), + object_.__name__, + ) + except (TypeError, AttributeError): + return ("unknown",) + + def _get_persisted_builtin(self, object_): + if isinstance(object_, str): + return ("builtin", "str") + if isinstance(object_, list): + holding = None + if len(object_) > 0: + holding = object_[0] + return ("builtin", "list", self._object_to_persisted_form(holding)) + if isinstance(object_, dict): + keys = None + values = None + if len(object_) > 0: + # @todo - fix it properly, why is __locals__ being + # duplicated ? + keys = [key for key in object_.keys() if key != "__locals__"][0] + values = object_[keys] + return ( + "builtin", + "dict", + self._object_to_persisted_form(keys), + self._object_to_persisted_form(values), + ) + if isinstance(object_, tuple): + objects = [] + if len(object_) < 3: + for holding in object_: + objects.append(self._object_to_persisted_form(holding)) + else: + objects.append(self._object_to_persisted_form(object_[0])) + return tuple(["builtin", "tuple"] + objects) + if isinstance(object_, set): + holding = None + if len(object_) > 0: + for o in object_: + holding = o + break + return ("builtin", "set", self._object_to_persisted_form(holding)) + return ("unknown",) + + def _object_to_persisted_form(self, object_): + if object_ is None: + return ("none",) + if isinstance(object_, types.CodeType): + return self._get_persisted_code(object_) + if isinstance(object_, types.FunctionType): + return self._get_persisted_code(object_.__code__) + if isinstance(object_, types.MethodType): + return self._get_persisted_code(object_.__func__.__code__) + if isinstance(object_, types.ModuleType): + return self._get_persisted_module(object_) + if isinstance(object_, (str, list, dict, tuple, set)): + return self._get_persisted_builtin(object_) + if isinstance(object_, type): + return self._get_persisted_class(object_) + return ("instance", self._get_persisted_class(type(object_))) + + @_cached + def _get_persisted_module(self, object_): + path = self._path(object_.__file__) + if path and os.path.exists(path): + return ("defined", _realpath(path)) + return ("unknown",) + + def _path(self, path): + if path.endswith(".pyc"): + path = path[:-1] + if path.endswith(".py"): + return path + + def close(self): + self.sender.close() + sys.settrace(None) + + +def global_trace(frame, event, arg): + # HACK: Ignoring out->in calls + # This might lose some information + if self._is_an_interesting_call(frame): + return self.on_function_call + + +def _realpath(path): + return os.path.realpath(os.path.abspath(os.path.expanduser(path))) + + +@path C:/Repos/ekr-rope/rope/base/oi/ +import rope.base.ast +import rope.base.oi.soi +import rope.base.pynames +from rope.base import pyobjects, evaluate, astutils, arguments + + +@others +@language python +@tabwidth -4 + +def analyze_module(pycore, pymodule, should_analyze, search_subscopes, followed_calls): + """Analyze `pymodule` for static object inference + + Analyzes scopes for collecting object information. The analysis + starts from inner scopes. + + """ + _analyze_node(pycore, pymodule, should_analyze, search_subscopes, followed_calls) + + + +def _analyze_node(pycore, pydefined, should_analyze, search_subscopes, followed_calls): + if search_subscopes(pydefined): + for scope in pydefined.get_scope().get_scopes(): + _analyze_node( + pycore, scope.pyobject, should_analyze, search_subscopes, followed_calls + ) + if should_analyze(pydefined): + new_followed_calls = max(0, followed_calls - 1) + return_true = lambda pydefined: True + return_false = lambda pydefined: False + + def _follow(pyfunction): + _analyze_node( + pycore, pyfunction, return_true, return_false, new_followed_calls + ) + + if not followed_calls: + _follow = None + visitor = SOAVisitor(pycore, pydefined, _follow) + for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): + rope.base.ast.walk(child, visitor) + + + +class SOAVisitor: + @others + +def __init__(self, pycore, pydefined, follow_callback=None): + self.pycore = pycore + self.pymodule = pydefined.get_module() + self.scope = pydefined.get_scope() + self.follow = follow_callback + + +def _FunctionDef(self, node): + pass + + +def _new_tuple(self, args): + return _create_builtin(args, get_tuple) + + + +def _ClassDef(self, node): + pass + + +def _Call(self, node): + for child in rope.base.ast.get_child_nodes(node): + rope.base.ast.walk(child, self) + primary, pyname = evaluate.eval_node2(self.scope, node.func) + if pyname is None: + return + pyfunction = pyname.get_object() + if isinstance(pyfunction, pyobjects.AbstractFunction): + args = arguments.create_arguments(primary, pyfunction, node, self.scope) + elif isinstance(pyfunction, pyobjects.PyClass): + pyclass = pyfunction + if "__init__" in pyfunction: + pyfunction = pyfunction["__init__"].get_object() + pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass)) + args = self._args_with_self(primary, pyname, pyfunction, node) + elif "__call__" in pyfunction: + pyfunction = pyfunction["__call__"].get_object() + args = self._args_with_self(primary, pyname, pyfunction, node) + else: + return + self._call(pyfunction, args) + + +def _args_with_self(self, primary, self_pyname, pyfunction, node): + base_args = arguments.create_arguments(primary, pyfunction, node, self.scope) + return arguments.MixedArguments(self_pyname, base_args, self.scope) + + +def _call(self, pyfunction, args): + if isinstance(pyfunction, pyobjects.PyFunction): + if self.follow is not None: + before = self._parameter_objects(pyfunction) + self.pycore.object_info.function_called( + pyfunction, args.get_arguments(pyfunction.get_param_names()) + ) + pyfunction._set_parameter_pyobjects(None) + if self.follow is not None: + after = self._parameter_objects(pyfunction) + if after != before: + self.follow(pyfunction) + # XXX: Maybe we should not call every builtin function + if isinstance(pyfunction, rope.base.builtins.BuiltinFunction): + pyfunction.get_returned_object(args) + + +def _parameter_objects(self, pyfunction): + return [ + pyfunction.get_parameter(i) + for i in range(len(pyfunction.get_param_names(False))) + ] + + +def _AnnAssign(self, node): + for child in rope.base.ast.get_child_nodes(node): + rope.base.ast.walk(child, self) + visitor = _SOAAssignVisitor() + nodes = [] + + rope.base.ast.walk(node.target, visitor) + nodes.extend(visitor.nodes) + + self._evaluate_assign_value(node, nodes, type_hint=node.annotation) + + +def _Assign(self, node): + for child in rope.base.ast.get_child_nodes(node): + rope.base.ast.walk(child, self) + visitor = _SOAAssignVisitor() + nodes = [] + for child in node.targets: + rope.base.ast.walk(child, visitor) + nodes.extend(visitor.nodes) + self._evaluate_assign_value(node, nodes) + + +def _evaluate_assign_value(self, node, nodes, type_hint=False): + for subscript, levels in nodes: + instance = evaluate.eval_node(self.scope, subscript.value) + args_pynames = [evaluate.eval_node(self.scope, subscript.slice)] + value = rope.base.oi.soi._infer_assignment( + rope.base.pynames.AssignmentValue( + node.value, levels, type_hint=type_hint + ), + self.pymodule, + ) + args_pynames.append(rope.base.pynames.UnboundName(value)) + if instance is not None and value is not None: + pyobject = instance.get_object() + if "__setitem__" in pyobject: + pyfunction = pyobject["__setitem__"].get_object() + args = arguments.ObjectArguments([instance] + args_pynames) + self._call(pyfunction, args) + # IDEA: handle `__setslice__`, too + + + +class _SOAAssignVisitor(astutils._NodeNameCollector): + @others + +def __init__(self): + super().__init__() + self.nodes = [] + + +get_tuple = _create_builtin_getter(Tuple) +get_tuple_type = _create_builtin_type_getter(Tuple) + + + +def _added(self, node, levels): + if isinstance(node, rope.base.ast.Subscript) and isinstance( + node.slice, (rope.base.ast.Index, rope.base.ast.expr) + ): + self.nodes.append((node, levels)) + +@path C:/Repos/ekr-rope/rope/base/oi/ +"""A module for inferring objects + +For more information see the documentation in `rope.base.oi` +package. + +""" +import rope.base.builtins +import rope.base.pynames +import rope.base.pyobjects +from rope.base import evaluate, utils, arguments +from rope.base.oi.type_hinting.factory import get_type_hinting_factory + + +_ignore_inferred = utils.ignore_exception(rope.base.pyobjects.IsBeingInferredError) + + +@others +@language python +@tabwidth -4 + +@_ignore_inferred +def infer_returned_object(pyfunction, args): + """Infer the `PyObject` this `PyFunction` returns after calling""" + object_info = pyfunction.pycore.object_info + result = object_info.get_exact_returned(pyfunction, args) + if result is not None: + return result + result = _infer_returned(pyfunction, args) + if result is not None: + if args and pyfunction.get_module().get_resource() is not None: + params = args.get_arguments(pyfunction.get_param_names(special_args=False)) + object_info.function_called(pyfunction, params, result) + return result + result = object_info.get_returned(pyfunction, args) + if result is not None: + return result + hint_return = get_type_hinting_factory( + pyfunction.pycore.project + ).make_return_provider() + type_ = hint_return(pyfunction) + if type_ is not None: + return rope.base.pyobjects.PyObject(type_) + + + +@_ignore_inferred +def infer_parameter_objects(pyfunction): + """Infer the `PyObject` of parameters of this `PyFunction`""" + object_info = pyfunction.pycore.object_info + result = object_info.get_parameter_objects(pyfunction) + if result is None: + result = _parameter_objects(pyfunction) + _handle_first_parameter(pyfunction, result) + return result + + + +def _handle_first_parameter(pyobject, parameters): + kind = pyobject.get_kind() + if parameters is None or kind not in ["method", "classmethod"]: + pass + if not parameters: + if not pyobject.get_param_names(special_args=False): + return + parameters.append(rope.base.pyobjects.get_unknown()) + if kind == "method": + parameters[0] = rope.base.pyobjects.PyObject(pyobject.parent) + if kind == "classmethod": + parameters[0] = pyobject.parent + + + +@_ignore_inferred +def infer_assigned_object(pyname): + if not pyname.assignments: + return + for assignment in reversed(pyname.assignments): + result = _infer_assignment(assignment, pyname.module) + if ( + isinstance(result, rope.base.builtins.BuiltinUnknown) + and result.get_name() == "NotImplementedType" + ): + break + elif result == rope.base.pyobjects.get_unknown(): + break + elif result is not None: + return result + + hint_assignment = get_type_hinting_factory( + pyname.module.pycore.project + ).make_assignment_provider() + hinting_result = hint_assignment(pyname) + if hinting_result is not None: + return rope.base.pyobjects.PyObject(hinting_result) + return result + + + +def get_passed_objects(pyfunction, parameter_index): + object_info = pyfunction.pycore.object_info + result = object_info.get_passed_objects(pyfunction, parameter_index) + if not result: + statically_inferred = _parameter_objects(pyfunction) + if len(statically_inferred) > parameter_index: + result.append(statically_inferred[parameter_index]) + return result + + + +def _infer_returned(pyobject, args): + if args: + # HACK: Setting parameter objects manually + # This is not thread safe and might cause problems if `args` + # does not come from a good call site + pyobject.get_scope().invalidate_data() + pyobject._set_parameter_pyobjects( + args.get_arguments(pyobject.get_param_names(special_args=False)) + ) + scope = pyobject.get_scope() + if not scope._get_returned_asts(): + return + maxtries = 3 + for returned_node in reversed(scope._get_returned_asts()[-maxtries:]): + try: + resulting_pyname = evaluate.eval_node(scope, returned_node) + if resulting_pyname is None: + continue + pyobject = resulting_pyname.get_object() + if pyobject == rope.base.pyobjects.get_unknown(): + continue + if not scope._is_generator(): + return pyobject + else: + return rope.base.builtins.get_generator(pyobject) + except rope.base.pyobjects.IsBeingInferredError: + pass + + + +def _parameter_objects(pyobject): + result = [] + params = pyobject.get_param_names(special_args=False) + hint_param = get_type_hinting_factory(pyobject.pycore.project).make_param_provider() + for name in params: + type_ = hint_param(pyobject, name) + if type_ is not None: + result.append(rope.base.pyobjects.PyObject(type_)) + else: + result.append(rope.base.pyobjects.get_unknown()) + return result + + + +class Set(BuiltinClass): + @others + +# handling `rope.base.pynames.AssignmentValue` + + +@_ignore_inferred +def _infer_assignment(assignment, pymodule): + result = _follow_pyname(assignment, pymodule) + if result is None: + return None + pyname, pyobject = result + pyobject = _follow_evaluations(assignment, pyname, pyobject) + if pyobject is None: + return None + return _follow_levels(assignment, pyobject) + + + +def _follow_levels(assignment, pyobject): + for index in assignment.levels: + if isinstance(pyobject.get_type(), rope.base.builtins.Tuple): + holdings = pyobject.get_type().get_holding_objects() + if holdings: + pyobject = holdings[min(len(holdings) - 1, index)] + else: + pyobject = None + elif isinstance(pyobject.get_type(), rope.base.builtins.List): + pyobject = pyobject.get_type().holding + else: + pyobject = None + if pyobject is None: + break + return pyobject + + + +@_ignore_inferred +def _follow_pyname(assignment, pymodule, lineno=None): + assign_node = assignment.type_hint or assignment.ast_node + if lineno is None: + lineno = _get_lineno_for_node(assign_node) + holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) + pyname = evaluate.eval_node(holding_scope, assign_node) + if pyname is not None: + result = pyname.get_object() + if ( + isinstance(result.get_type(), rope.base.builtins.Property) + and holding_scope.get_kind() == "Class" + ): + arg = rope.base.pynames.UnboundName( + rope.base.pyobjects.PyObject(holding_scope.pyobject) + ) + return pyname, result.get_type().get_property_object( + arguments.ObjectArguments([arg]) + ) + return pyname, result + + + +@_ignore_inferred +def _follow_evaluations(assignment, pyname, pyobject): + new_pyname = pyname + tokens = assignment.evaluation.split(".") + for token in tokens: + call = token.endswith("()") + if call: + token = token[:-2] + if token: + pyname = new_pyname + new_pyname = _get_attribute(pyobject, token) + if new_pyname is not None: + pyobject = new_pyname.get_object() + if pyobject is not None and call: + if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): + args = arguments.ObjectArguments([pyname]) + pyobject = pyobject.get_returned_object(args) + else: + pyobject = None + if pyobject is None: + break + if pyobject is not None and assignment.assign_type: + return rope.base.pyobjects.PyObject(pyobject) + return pyobject + + + +def _get_lineno_for_node(assign_node): + if hasattr(assign_node, "lineno") and assign_node.lineno is not None: + return assign_node.lineno + return 1 + + + +def _get_attribute(pyobject, name): + if pyobject is not None and name in pyobject: + return pyobject[name] + +@path C:/Repos/ekr-rope/rope/base/oi/ +"""Provides classes for persisting `PyObject`""" +import os +import re + +import rope.base.builtins +from rope.base import exceptions + + +@others +@language python +@tabwidth -4 + +class PyObjectToTextual: + """For transforming `PyObject` to textual form + + This can be used for storing `PyObjects` in files. Use + `TextualToPyObject` for converting back. + + """ + + @others + +def __init__(self, project): + self.project = project + + +def transform(self, pyobject): + """Transform a `PyObject` to textual form""" + if pyobject is None: + return ("none",) + object_type = type(pyobject) + try: + method = getattr(self, object_type.__name__ + "_to_textual") + return method(pyobject) + except AttributeError: + return ("unknown",) + + +def __init__(self, holding=None): + self.holding = holding + collector = _AttributeCollector(set) + collector("__new__", function=self._new_set) + + self_methods = [ + "copy", + "difference", + "intersection", + "symmetric_difference", + "union", + ] + for method in self_methods: + collector(method, function=self._self_get, parent=self) + collector("add", function=self._set_add, parent=self) + collector("update", function=self._self_set, parent=self) + collector("update", function=self._self_set, parent=self) + collector("symmetric_difference_update", function=self._self_set, parent=self) + collector("difference_update", function=self._self_set, parent=self) + + collector("pop", function=self._set_get, parent=self) + collector("__iter__", function=self._iterator_get, parent=self) + super().__init__(set, collector.attributes) + + +def __call__(self, pyobject): + return self.transform(pyobject) + + +def PyObject_to_textual(self, pyobject): + if isinstance(pyobject.get_type(), rope.base.pyobjects.AbstractClass): + result = self.transform(pyobject.get_type()) + if result[0] == "defined": + return ("instance", result) + return result + return ("unknown",) + + +def PyFunction_to_textual(self, pyobject): + return self._defined_to_textual(pyobject) + + +def PyClass_to_textual(self, pyobject): + return self._defined_to_textual(pyobject) + + +def _defined_to_textual(self, pyobject): + address = [] + while pyobject.parent is not None: + address.insert(0, pyobject.get_name()) + pyobject = pyobject.parent + return ( + "defined", + self._get_pymodule_path(pyobject.get_module()), + ".".join(address), + ) + + +def PyModule_to_textual(self, pyobject): + return ("defined", self._get_pymodule_path(pyobject)) + + +def PyPackage_to_textual(self, pyobject): + return ("defined", self._get_pymodule_path(pyobject)) + + +def List_to_textual(self, pyobject): + return ("builtin", "list", self.transform(pyobject.holding)) + + +def Dict_to_textual(self, pyobject): + return ( + "builtin", + "dict", + self.transform(pyobject.keys), + self.transform(pyobject.values), + ) + + +def Tuple_to_textual(self, pyobject): + objects = [ + self.transform(holding) for holding in pyobject.get_holding_objects() + ] + return tuple(["builtin", "tuple"] + objects) + + +def project_opened(project): + """This function is called after opening the project""" + # Do whatever you like here! + +def _new_set(self, args): + return _create_builtin(args, get_set) + + +def Set_to_textual(self, pyobject): + return ("builtin", "set", self.transform(pyobject.holding)) + + +def Iterator_to_textual(self, pyobject): + return ("builtin", "iter", self.transform(pyobject.holding)) + + +def Generator_to_textual(self, pyobject): + return ("builtin", "generator", self.transform(pyobject.holding)) + + +def Str_to_textual(self, pyobject): + return ("builtin", "str") + + +def File_to_textual(self, pyobject): + return ("builtin", "file") + + +def BuiltinFunction_to_textual(self, pyobject): + return ("builtin", "function", pyobject.get_name()) + + +def _get_pymodule_path(self, pymodule): + return self.resource_to_path(pymodule.get_resource()) + + +def resource_to_path(self, resource): + if resource.project == self.project: + return resource.path + else: + return resource.real_path + + + +class TextualToPyObject: + """For transforming textual form to `PyObject`""" + + @others + +def __init__(self, project, allow_in_project_absolutes=False): + self.project = project + + +def _set_add(self, context): + if self.holding is not None: + return + holding = context.get_arguments(["self", "value"])[1] + if holding is not None and holding != pyobjects.get_unknown(): + context.save_per_name(holding) + + +def __call__(self, textual): + return self.transform(textual) + + +def transform(self, textual): + """Transform an object from textual form to `PyObject`""" + if textual is None: + return None + type = textual[0] + try: + method = getattr(self, type + "_to_pyobject") + return method(textual) + except AttributeError: + return None + + +def builtin_to_pyobject(self, textual): + method = getattr(self, "builtin_%s_to_pyobject" % textual[1], None) + if method is not None: + return method(textual) + + +def builtin_str_to_pyobject(self, textual): + return rope.base.builtins.get_str() + + +def builtin_list_to_pyobject(self, textual): + holding = self.transform(textual[2]) + return rope.base.builtins.get_list(holding) + + +def builtin_dict_to_pyobject(self, textual): + keys = self.transform(textual[2]) + values = self.transform(textual[3]) + return rope.base.builtins.get_dict(keys, values) + + +def builtin_tuple_to_pyobject(self, textual): + objects = [self.transform(holding) for holding in textual[2:]] + return rope.base.builtins.get_tuple(*objects) + + +def builtin_set_to_pyobject(self, textual): + holding = self.transform(textual[2]) + return rope.base.builtins.get_set(holding) + + +def builtin_iter_to_pyobject(self, textual): + holding = self.transform(textual[2]) + return rope.base.builtins.get_iterator(holding) + + +def builtin_generator_to_pyobject(self, textual): + holding = self.transform(textual[2]) + return rope.base.builtins.get_generator(holding) + + +def _self_set(self, context): + if self.holding is not None: + return + iterable = context.get_pyname("iterable") + holding = _infer_sequence_for_pyname(iterable) + if holding is not None and holding != pyobjects.get_unknown(): + context.save_per_name(holding) + + +def builtin_file_to_pyobject(self, textual): + return rope.base.builtins.get_file() + + +def builtin_function_to_pyobject(self, textual): + if textual[2] in rope.base.builtins.builtins: + return rope.base.builtins.builtins[textual[2]].get_object() + + +def unknown_to_pyobject(self, textual): + return None + + +def none_to_pyobject(self, textual): + return None + + +def _module_to_pyobject(self, textual): + path = textual[1] + return self._get_pymodule(path) + + +def _hierarchical_defined_to_pyobject(self, textual): + path = textual[1] + names = textual[2].split(".") + pymodule = self._get_pymodule(path) + pyobject = pymodule + for name in names: + if pyobject is None: + return None + if isinstance(pyobject, rope.base.pyobjects.PyDefinedObject): + try: + pyobject = pyobject.get_scope()[name].get_object() + except exceptions.NameNotFoundError: + return None + else: + return None + return pyobject + + +def defined_to_pyobject(self, textual): + if len(textual) == 2 or textual[2] == "": + return self._module_to_pyobject(textual) + else: + return self._hierarchical_defined_to_pyobject(textual) + + +def instance_to_pyobject(self, textual): + type = self.transform(textual[1]) + if type is not None: + return rope.base.pyobjects.PyObject(type) + + +def _get_pymodule(self, path): + resource = self.path_to_resource(path) + if resource is not None: + return self.project.get_pymodule(resource) + + +def path_to_resource(self, path): + try: + root = self.project.address + if not os.path.isabs(path): + return self.project.get_resource(path) + if path == root or path.startswith(root + os.sep): + # INFO: This is a project file; should not be absolute + return None + import rope.base.project + + return rope.base.project.get_no_project().get_resource(path) + except exceptions.ResourceNotFoundError: + return None + + + +def _set_get(self, context): + if self.holding is not None: + return self.holding + return context.get_per_name() + + +class DOITextualToPyObject(TextualToPyObject): + """For transforming textual form to `PyObject` + + The textual form DOI uses is different from rope's standard + textual form. The reason is that we cannot find the needed + information by analyzing live objects. This class can be + used to transform DOI textual form to `PyObject` and later + we can convert it to standard textual form using + `TextualToPyObject` class. + + """ + + @others + +def _function_to_pyobject(self, textual): + path = textual[1] + lineno = int(textual[2]) + pymodule = self._get_pymodule(path) + if pymodule is not None: + scope = pymodule.get_scope() + inner_scope = scope.get_inner_scope_for_line(lineno) + return inner_scope.pyobject + + +def _class_to_pyobject(self, textual): + path, name = textual[1:] + pymodule = self._get_pymodule(path) + if pymodule is None: + return None + module_scope = pymodule.get_scope() + suspected = None + if name in module_scope.get_names(): + suspected = module_scope[name].get_object() + if suspected is not None and isinstance(suspected, rope.base.pyobjects.PyClass): + return suspected + else: + lineno = self._find_occurrence(name, pymodule.get_resource().read()) + if lineno is not None: + inner_scope = module_scope.get_inner_scope_for_line(lineno) + return inner_scope.pyobject + + +def defined_to_pyobject(self, textual): + if len(textual) == 2: + return self._module_to_pyobject(textual) + else: + if textual[2].isdigit(): + result = self._function_to_pyobject(textual) + else: + result = self._class_to_pyobject(textual) + if not isinstance(result, rope.base.pyobjects.PyModule): + return result + + +def _find_occurrence(self, name, source): + pattern = re.compile(r"^\s*class\s*" + name + r"\b") + lines = source.split("\n") + for i in range(len(lines)): + if pattern.match(lines[i]): + return i + 1 + + +def path_to_resource(self, path): + import rope.base.libutils + + relpath = rope.base.libutils.path_relative_to_project_root(self.project, path) + if relpath is not None: + path = relpath + return super().path_to_resource(path) + +@path C:/Repos/ekr-rope/rope/base/oi/ +<< docstring: oi/__init__ >> +@language python +@tabwidth -4 + + +@path C:/Repos/ekr-rope/rope/base/ +@nopyflakes +# Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm +# and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py +import re +from rope.base.oi.type_hinting import utils +from rope.base import utils as base_utils + + +@others +evaluate = Evaluator() +@language python +@tabwidth -4 + +class SymbolBase: + + name = None # node/token type name + + @others + +def _iterator_get(self, context): + return get_iterator(self._set_get(context)) + + +def __init__(self): + self.value = None # used by name and literals + self.first = None + self.second = None + self.third = None # used by tree nodes + + +def nud(self, parser): + raise SyntaxError("Syntax error (%r)." % self.name) + + +def led(self, left, parser): + raise SyntaxError("Unknown operator (%r)." % self.name) + + +def evaluate(self, pyobject): + raise NotImplementedError(self.name, self) + + +def __repr__(self): + if self.name == "(name)": + return "({} {})".format(self.name[1:-1], self.value) + out = [repr(self.name), self.first, self.second, self.third] + out = [str(i) for i in out if i] + return "(" + " ".join(out) + ")" + + + +class SymbolTable: + @others + multi = staticmethod(multi) # Just for code checker + + + +def multi(func): + def _inner(self, names, *a, **kw): + for name in names.split(): + func(self, name, *a, **kw) + + return _inner + + +def __init__(self): + self.symbol_table = {} + + +def get(self, name, default=None): + return self.symbol_table.get(name, default) + + +def __getitem__(self, name): + return self.symbol_table[name] + + +def _self_get(self, context): + return get_list(self._set_get(context)) + + + +def __iter__(self): + return iter(self.symbol_table) + + +def symbol(self, name, bp=0): + try: + s = self.symbol_table[name] + except KeyError: + + @others + s = S + s.__name__ = "symbol-" + name # for debugging + s.name = name + s.lbp = bp + self.symbol_table[name] = s + else: + s.lbp = max(bp, s.lbp) + return s + + +class S(SymbolBase): + pass + + +@multi +def infix(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def led(self, left, parser): + self.first = left + self.second = parser.expression(bp) + return self + + +@multi +def infix_r(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def led(self, left, parser): + self.first = left + self.second = parser.expression(bp - 0.1) + return self + + +def ternary(self, name, name2, bp): + symbol = self.symbol(name, bp) + symbol2 = self.symbol(name2) + + @method(symbol) + def led(self, left, parser): + self.first = left + self.second = parser.expression(symbol2.lbp) + parser.advance(symbol2.name) + self.third = parser.expression(symbol2.lbp + 0.1) + return self + + +@multi +def prefix(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def nud(self, parser): + self.first = parser.expression(bp) + return self + + +@multi +def postfix(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def led(self, left, parser): + self.first = left + return self + + +symbol_table = SymbolTable() + + + +class Lexer: + + _token_pattern = re.compile( + r""" + \s* + (?: + ( + [,()\[\]|] + | -> + | (?<=\s)(?:or)\b + ) # operator + | ([a-zA-Z](?:\w|\.)*) # name + ) + """, + re.U | re.S | re.X, + ) + + @others + +get_set = _create_builtin_getter(Set) +get_set_type = _create_builtin_type_getter(Set) + + + +def __init__(self, symbol_table): + self.symbol_table = symbol_table + + +def tokenize(self, program): + for name, value in self._tokenize_expr(program): + symbol = symbol_table.get(value) + if symbol: + s = symbol() + elif name == "(name)": + symbol = symbol_table[name] + s = symbol() + s.value = value + else: + raise SyntaxError( + "Unknown operator ({}). Possible operators are {!r}".format( + value, list(self.symbol_table) + ) + ) + + yield s + + +def _tokenize_expr(self, program): + if isinstance(program, bytes): + program = program.decode("utf-8") + # import pprint; pprint.pprint(self._token_pattern.findall(program)) + for operator, name in self._token_pattern.findall(program): + if operator: + yield "(operator)", operator + elif name: + yield "(name)", name + else: + raise SyntaxError + yield "(end)", "(end)" + + + +class Parser: + + token = None + next = None + + @others + +def __init__(self, lexer): + self.lexer = lexer + + +def parse(self, program): + generator = self.lexer.tokenize(program) + self.next = generator.__next__ + self.token = self.next() + return self.expression() + + +def expression(self, rbp=0): + t = self.token + self.token = self.next() + left = t.nud(self) + while rbp < self.token.lbp: + t = self.token + self.token = self.next() + left = t.led(left, self) + return left + + +def advance(self, name=None): + if name and self.token.name != name: + raise SyntaxError(f"Expected {name!r} but found {self.token.name!r}") + self.token = self.next() + + + +def method(s): + assert issubclass(s, SymbolBase) + + @others + return bind + + + +def bind(fn): + setattr(s, fn.__name__, fn) + return fn + + +class Str(BuiltinClass): + @others + +symbol, infix, infix_r, prefix, postfix, ternary = ( + symbol_table.symbol, + symbol_table.infix, + symbol_table.infix_r, + symbol_table.prefix, + symbol_table.postfix, + symbol_table.ternary, +) + +symbol("(", 270) +symbol(")") +symbol("[", 250) # Parameters +symbol("]") +symbol("->", 230) +infix("|", 170) +infix("or", 170) +symbol(",") + +symbol("(name)") +symbol("(end)") + + + +@method(symbol("(name)")) +def nud(self, parser): + return self + + + +@method(symbol("(name)")) +def evaluate(self, pyobject): + return utils.resolve_type(self.value, pyobject) + + + +# Parametrized objects +@method(symbol("[")) +def led(self, left, parser): + self.first = left + self.second = [] + if parser.token.name != "]": + while 1: + if parser.token.name == "]": + break + self.second.append(parser.expression()) + if parser.token.name != ",": + break + parser.advance(",") + parser.advance("]") + return self + + + +@method(symbol("[")) +def evaluate(self, pyobject): + return utils.parametrize_type( + self.first.evaluate(pyobject), *[i.evaluate(pyobject) for i in self.second] + ) + + + +# Anonymous Function Calls +@method(symbol("(")) +def nud(self, parser): + self.second = [] + if parser.token.name != ")": + while 1: + self.second.append(parser.expression()) + if parser.token.name != ",": + break + parser.advance(",") + parser.advance(")") + parser.advance("->") + self.third = parser.expression(symbol("->").lbp + 0.1) + return self + + + +# Function Calls +@method(symbol("(")) +def led(self, left, parser): + self.first = left + self.second = [] + if parser.token.name != ")": + while 1: + self.second.append(parser.expression()) + if parser.token.name != ",": + break + parser.advance(",") + parser.advance(")") + parser.advance("->") + self.third = parser.expression(symbol("->").lbp + 0.1) + return self + + + +@method(symbol("(")) +def evaluate(self, pyobject): + # TODO: Implement me + raise NotImplementedError + + + +@method(symbol("or")) +@method(symbol("|")) +def evaluate(self, pyobject): + # TODO: Implement me + raise NotImplementedError + + + +class Compiler: + + parser_factory = Parser + lexer_factory = Lexer + symbol_table = symbol_table + + @others + +def __init__(self): + self_object = pyobjects.PyObject(self) + collector = _AttributeCollector(str) + collector("__iter__", get_iterator(self_object), check_existence=False) + + self_methods = [ + "__getitem__", + "capitalize", + "center", + "encode", + "expandtabs", + "join", + "ljust", + "lower", + "lstrip", + "replace", + "rjust", + "rstrip", + "strip", + "swapcase", + "title", + "translate", + "upper", + "zfill", + ] + for method in self_methods: + collector(method, self_object, parent=self) + + py2_self_methods = ["__getslice__", "decode"] + for method in py2_self_methods: + try: + collector(method, self_object) + except AttributeError: + pass + + for method in ["rsplit", "split", "splitlines"]: + collector(method, get_list(self_object), parent=self) + + super().__init__(str, collector.attributes) + + +def _make_parser(self): + return self.parser_factory(self.lexer_factory(self.symbol_table)) + + +@base_utils.cached(500) +def __call__(self, program): + """ + :type program: str + :rtype: rope.base.oi.type_hinting.evaluate.SymbolBase + """ + return self._make_parser().parse(program) + + + +compile = Compiler() + + + +class Evaluator: + + compile = compile + + @others + +def __call__(self, program, pyobject): + """Evaluates the program string or AST + + :type program: str or rope.base.oi.type_hinting.evaluate.SymbolBase + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + ast = self.compile(program) if isinstance(program, str) else program + return ast.evaluate(pyobject) + + + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/ +from rope.base.oi.type_hinting import interfaces +from rope.base.oi.type_hinting.providers import ( + composite, + inheritance, + docstrings, + numpydocstrings, + pep0484_type_comments, +) +from rope.base.oi.type_hinting.resolvers import composite as composite_resolvers, types +from rope.base import utils + + +@others +get_type_hinting_factory = TypeHintingFactoryAccessor() +@language python +@tabwidth -4 + +class TypeHintingFactory(interfaces.ITypeHintingFactory): + @others + +@utils.saveit +def make_param_provider(self): + providers = [ + docstrings.ParamProvider( + docstrings.DocstringParamParser(), self.make_resolver() + ), + docstrings.ParamProvider( + numpydocstrings.NumPyDocstringParamParser(), self.make_resolver() + ), + ] + return inheritance.ParamProvider(composite.ParamProvider(*providers)) + + +@utils.saveit +def make_return_provider(self): + providers = [ + docstrings.ReturnProvider( + docstrings.DocstringReturnParser(), self.make_resolver() + ), + ] + return inheritance.ReturnProvider(composite.ReturnProvider(*providers)) + + +@utils.saveit +def make_assignment_provider(self): + providers = [ + pep0484_type_comments.AssignmentProvider(self.make_resolver()), + docstrings.AssignmentProvider( + docstrings.DocstringParamParser(), self.make_resolver() + ), + docstrings.AssignmentProvider( + numpydocstrings.NumPyDocstringParamParser(), self.make_resolver() + ), + ] + return inheritance.AssignmentProvider(composite.AssignmentProvider(*providers)) + + +def get_doc(self): + return str.__doc__ + + + +@utils.saveit +def make_resolver(self): + """ + :rtype: rope.base.oi.type_hinting.resolvers.interfaces.IResolver + """ + resolvers = [ + types.Resolver(), + ] + return composite_resolvers.Resolver(*resolvers) + + + +default_type_hinting_factory = TypeHintingFactory() + + + +class TypeHintingFactoryAccessor: + @others + +def __call__(self, project): + """ + :type project: rope.base.project.Project + :rtype: rope.base.oi.type_hinting.interfaces.ITypeHintingFactory + """ + factory_location = project.get_prefs().get( + "type_hinting_factory", + "rope.base.oi.type_hinting.factory.default_type_hinting_factory", + ) + return self._get_factory(factory_location) + + +@utils.cached(10) +def _get_factory(self, factory_location): + """ + :type factory_location: str + :rtype: rope.base.oi.type_hinting.interfaces.ITypeHintingFactory + """ + return utils.resolve(factory_location) + + + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/ +@others +@language python +@tabwidth -4 + +class ITypeHintingFactory: + @others + +def make_param_provider(self): + """ + :rtype: rope.base.oi.type_hinting.providers.interfaces.IParamProvider + """ + raise NotImplementedError + + +def make_return_provider(self): + """ + :rtype: rope.base.oi.type_hinting.providers.interfaces.IReturnProvider + """ + raise NotImplementedError + + +def make_assignment_provider(self): + """ + :rtype: rope.base.oi.type_hinting.providers.interfaces.IAssignmentProvider + """ + raise NotImplementedError + + +get_str = _create_builtin_getter(Str) +get_str_type = _create_builtin_type_getter(Str) + + + +def make_resolver(self): + """ + :rtype: rope.base.oi.type_hinting.resolvers.interfaces.IResolver + """ + raise NotImplementedError + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/ +import logging + +try: + from typing import Union, Optional +except ImportError: + pass +import rope.base.utils as base_utils +from rope.base import evaluate +from rope.base.exceptions import AttributeNotFoundError +from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject + + +@others +parametrize_type = ParametrizeType() +@language python +@tabwidth -4 + +def get_super_func(pyfunc): + + if not isinstance(pyfunc.parent, PyClass): + return + + for cls in get_mro(pyfunc.parent)[1:]: + try: + superfunc = cls.get_attribute(pyfunc.get_name()).get_object() + except AttributeNotFoundError: + pass + else: + if isinstance(superfunc, PyFunction): + return superfunc + + + +def get_super_assignment(pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :type: rope.base.pynamesdef.AssignedName + """ + try: + pyclass, attr_name = get_class_with_attr_name(pyname) + except TypeError: + return + else: + for super_pyclass in get_mro(pyclass)[1:]: + if attr_name in super_pyclass: + return super_pyclass[attr_name] + + + +def get_class_with_attr_name(pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :return: rope.base.pyobjectsdef.PyClass, str + :rtype: tuple + """ + lineno = get_lineno_for_node(pyname.assignments[0].ast_node) + holding_scope = pyname.module.get_scope().get_inner_scope_for_line(lineno) + pyobject = holding_scope.pyobject + if isinstance(pyobject, PyClass): + pyclass = pyobject + elif isinstance(pyobject, PyFunction) and isinstance(pyobject.parent, PyClass): + pyclass = pyobject.parent + else: + return + for name, attr in pyclass.get_attributes().items(): + if attr is pyname: + return (pyclass, name) + + + +def get_lineno_for_node(assign_node): + if hasattr(assign_node, "lineno") and assign_node.lineno is not None: + return assign_node.lineno + return 1 + + + +def get_mro(pyclass): + # FIXME: to use real mro() result + class_list = [pyclass] + for cls in class_list: + for super_cls in cls.get_superclasses(): + if isinstance(super_cls, PyClass) and super_cls not in class_list: + class_list.append(super_cls) + return class_list + + + +def resolve_type(type_name, pyobject): + # type: (str, Union[PyDefinedObject, PyObject]) -> Optional[PyDefinedObject, PyObject] + """ + Find proper type object from its name. + """ + deprecated_aliases = {"collections": "collections.abc"} + ret_type = None + logging.debug("Looking for %s", type_name) + if "." not in type_name: + try: + ret_type = ( + pyobject.get_module().get_scope().get_name(type_name).get_object() + ) + except AttributeNotFoundError: + logging.exception("Cannot resolve type %s", type_name) + else: + mod_name, attr_name = type_name.rsplit(".", 1) + try: + mod_finder = evaluate.ScopeNameFinder(pyobject.get_module()) + mod = mod_finder._find_module(mod_name).get_object() + ret_type = mod.get_attribute(attr_name).get_object() + except AttributeNotFoundError: + if mod_name in deprecated_aliases: + try: + logging.debug( + "Looking for %s in %s", attr_name, deprecated_aliases[mod_name] + ) + mod = mod_finder._find_module( + deprecated_aliases[mod_name] + ).get_object() + ret_type = mod.get_attribute(attr_name).get_object() + except AttributeNotFoundError: + logging.exception( + "Cannot resolve type %s in %s", attr_name, dir(mod) + ) + logging.debug("ret_type = %s", ret_type) + return ret_type + + + +class ParametrizeType: + + _supported_mapping = { + "builtins.list": "rope.base.builtins.get_list", + "builtins.tuple": "rope.base.builtins.get_tuple", + "builtins.set": "rope.base.builtins.get_set", + "builtins.dict": "rope.base.builtins.get_dict", + "_collections_abc.Iterable": "rope.base.builtins.get_iterator", + "_collections_abc.Iterator": "rope.base.builtins.get_iterator", + "collections.abc.Iterable": "rope.base.builtins.get_iterator", # Python3.3 + "collections.abc.Iterator": "rope.base.builtins.get_iterator", # Python3.3 + } + + @others + +def __call__(self, pyobject, *args, **kwargs): + """ + :type pyobject: rope.base.pyobjects.PyObject + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + type_factory = self._get_type_factory(pyobject) + if type_factory: + parametrized_type = type_factory(*args, **kwargs) + if parametrized_type: + return parametrized_type + return pyobject + + +class BuiltinName(pynames.PyName): + @others + +def _get_type_factory(self, pyobject): + type_str = "{}.{}".format( + pyobject.get_module().get_name(), + pyobject.get_name(), + ) + if type_str in self._supported_mapping: + return base_utils.resolve(self._supported_mapping[type_str]) + + + + + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ +from rope.base.oi.type_hinting.providers import interfaces + + +@others +@language python +@tabwidth -4 + +class ParamProvider(interfaces.IParamProvider): + @others + +def __init__(self, *delegates): + """ + :type delegates: list[rope.base.oi.type_hinting.providers.interfaces.IParamProvider] + """ + self._delegates = delegates + + +def __call__(self, pyfunc, param_name): + """ + :type pyfunc: rope.base.pyobjectsdef.PyFunction + :type param_name: str + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + for delegate in self._delegates: + result = delegate(pyfunc, param_name) + if result: + return result + + + +class ReturnProvider(interfaces.IReturnProvider): + @others + +def __init__(self, *delegates): + """ + :type delegates: list[rope.base.oi.type_hinting.providers.interfaces.IReturnProvider] + """ + self._delegates = delegates + + +def __call__(self, pyfunc): + """ + :type pyfunc: rope.base.pyobjectsdef.PyFunction + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + for delegate in self._delegates: + result = delegate(pyfunc) + if result: + return result + + + +def __init__(self, pyobject): + self.pyobject = pyobject + + +class AssignmentProvider(interfaces.IAssignmentProvider): + @others + +def __init__(self, *delegates): + """ + :type delegates: list[rope.base.oi.type_hinting.providers.interfaces.IAssignmentProvider] + """ + self._delegates = delegates + + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + for delegate in self._delegates: + result = delegate(pyname) + if result: + return result + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ +""" +Hinting the type using docstring of class/function. + +It's an irreplaceable thing if you are using Dependency Injection with passive class: +http://www.martinfowler.com/articles/injection.html + +Some code extracted (or based on code) from: +https://github.com/davidhalter/jedi/blob/b489019f5bd5750051122b94cc767df47751ecb7/jedi/evaluate/docstrings.py +Thanks to @davidhalter for this utils under MIT License. + +Similar solutions: + + - https://www.jetbrains.com/pycharm/help/type-hinting-in-pycharm.html + - https://www.python.org/dev/peps/pep-0484/#type-comments + - http://www.pydev.org/manual_adv_type_hints.html + - https://jedi.readthedocs.org/en/latest/docs/features.html#type-hinting + +Discussions: + + - https://groups.google.com/d/topic/rope-dev/JlAzmZ83K1M/discussion + - https://groups.google.com/d/topic/rope-dev/LCFNN98vckI/discussion + +""" +import re + +from rope.base.oi.type_hinting import utils +from rope.base.oi.type_hinting.providers import interfaces + + +@others +@language python +@tabwidth -4 + +class ParamProvider(interfaces.IParamProvider): + @others + +def __init__(self, docstring_parser, resolver): + """ + :type docstring_parser: rope.base.oi.type_hinting.providers.docstrings.IParamParser + :type resolver: rope.base.oi.type_hinting.resolvers.interfaces.IResolver + """ + self._parse_docstring = docstring_parser + self._resolve = resolver + + +def __call__(self, pyfunc, param_name): + """ + :type pyfunc: rope.base.pyobjectsdef.PyFunction + :type param_name: str + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + type_strs = self._parse_docstring(pyfunc.get_doc(), param_name) + if type_strs: + return self._resolve(type_strs[0], pyfunc) + + + +class ReturnProvider(interfaces.IReturnProvider): + @others + +def __init__(self, docstring_parser, resolver): + """ + :type docstring_parser: rope.base.oi.type_hinting.providers.docstrings.IReturnParser + :type resolver: rope.base.oi.type_hinting.resolvers.interfaces.IResolver + """ + self._parse_docstring = docstring_parser + self._resolve = resolver + + +def __call__(self, pyfunc): + """ + :type pyfunc: rope.base.pyobjectsdef.PyFunction + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + type_strs = self._parse_docstring(pyfunc.get_doc()) + if type_strs: + return self._resolve(type_strs[0], pyfunc) + + + +def get_object(self): + return self.pyobject + + +class AssignmentProvider(interfaces.IAssignmentProvider): + @others + +def __init__(self, docstring_parser, resolver): + """ + :type docstring_parser: rope.base.oi.type_hinting.providers.docstrings.IParamParser + :type resolver: rope.base.oi.type_hinting.resolvers.interfaces.IResolver + """ + self._parse_docstring = docstring_parser + self._resolve = resolver + + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + try: + pyclass, attr_name = utils.get_class_with_attr_name(pyname) + except TypeError: + return + else: + type_strs = self._parse_docstring(pyclass.get_doc(), attr_name) + if type_strs: + return self._resolve(type_strs[0], pyclass) + + + +class IParamParser: + def __call__(self, docstring, param_name): + """ + :type docstring: str + :type param_name: str + """ + + + +class IReturnParser: + def __call__(self, docstring): + """ + :type docstring: str + """ + + + +class DocstringParamParser(IParamParser): + + DOCSTRING_PARAM_PATTERNS = [ + r"\s*:type\s+%s:\s*([^\n]+)", # Sphinx + r"\s*:param\s+(\w+)\s+%s:[^\n]+", # Sphinx param with type + r"\s*@type\s+%s:\s*([^\n]+)", # Epydoc + ] + + @others + +def __init__(self): + self._strip_rst_role = RSTRoleStrip() + + +def __call__(self, docstring, param_name): + """Search `docstring` for type(-s) of `param_name`. + + >>> DocstringParamParser()(':type param: int', 'param') + ['int'] + >>> DocstringParamParser()('@type param: int', 'param') + ['int'] + >>> DocstringParamParser()(':type param: :class:`threading.Thread`', 'param') + ['threading.Thread'] + >>> bool(DocstringParamParser()('no document', 'param')) + False + >>> DocstringParamParser()(':param int param: some description', 'param') + ['int'] + """ + if not docstring: + return [] + patterns = [ + re.compile(p % re.escape(param_name)) for p in self.DOCSTRING_PARAM_PATTERNS + ] + for pattern in patterns: + match = pattern.search(docstring) + if match: + return [self._strip_rst_role(match.group(1))] + + return [] + + + +class DocstringReturnParser(IReturnParser): + + DOCSTRING_RETURN_PATTERNS = [ + re.compile(r"\s*:rtype:\s*([^\n]+)", re.M), # Sphinx + re.compile(r"\s*@rtype:\s*([^\n]+)", re.M), # Epydoc + ] + + @others + +def __init__(self): + self._strip_rst_role = RSTRoleStrip() + + +def get_definition_location(self): + return (None, None) + + + +def __call__(self, docstring): + if not docstring: + return [] + for p in self.DOCSTRING_RETURN_PATTERNS: + match = p.search(docstring) + if match: + return [self._strip_rst_role(match.group(1))] + return [] + + + +class RSTRoleStrip: + + RST_ROLE_PATTERN = re.compile(r":[^`]+:`([^`]+)`") + + @others + +def __call__(self, type_str): + """ + Strip off the part looks like a ReST role in `type_str`. + + >>> RSTRoleStrip()(':class:`ClassName`') # strip off :class: + 'ClassName' + >>> RSTRoleStrip()(':py:obj:`module.Object`') # works with domain + 'module.Object' + >>> RSTRoleStrip()('ClassName') # do nothing when not ReST role + 'ClassName' + + See also: + http://sphinx-doc.org/domains.html#cross-referencing-python-objects + + """ + match = self.RST_ROLE_PATTERN.match(type_str) + if match: + return match.group(1) + else: + return type_str + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ +from rope.base.oi.type_hinting import utils +from rope.base.oi.type_hinting.providers import interfaces + + +@others +@language python +@tabwidth -4 + +class ParamProvider(interfaces.IParamProvider): + @others + +def __init__(self, delegate): + """ + :type delegate: rope.base.oi.type_hinting.providers.interfaces.IParamProvider + """ + self._delegate = delegate + + +def __call__(self, pyfunc, param_name): + """ + :type pyfunc: rope.base.pyobjectsdef.PyFunction + :type param_name: str + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + superfunc = pyfunc + while superfunc: + result = self._delegate(superfunc, param_name) + if result: + return result + superfunc = utils.get_super_func(superfunc) + + + +class ReturnProvider(interfaces.IReturnProvider): + @others + +def __init__(self, delegate): + """ + :type delegate: rope.base.oi.type_hinting.providers.interfaces.IReturnProvider + """ + self._delegate = delegate + + +def __call__(self, pyfunc): + """ + :type pyfunc: rope.base.pyobjectsdef.PyFunction + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + superfunc = pyfunc + while superfunc: + result = self._delegate(superfunc) + if result: + return result + superfunc = utils.get_super_func(superfunc) + + + +class Iterator(pyobjects.AbstractClass): + @others + +class AssignmentProvider(interfaces.IAssignmentProvider): + @others + +def __init__(self, delegate): + """ + :type delegate: rope.base.oi.type_hinting.providers.interfaces.IAssignmentProvider + """ + self._delegate = delegate + + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + super_pyname = pyname + while super_pyname: + result = self._delegate(super_pyname) + if result: + return result + super_pyname = utils.get_super_assignment(super_pyname) + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ +@others +@language python +@tabwidth -4 + +class IParamProvider: + @others + +def __call__(self, pyfunc, param_name): + """ + :type pyfunc: rope.base.pyobjectsdef.PyFunction + :type param_name: str + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + raise NotImplementedError + + + +class IReturnProvider: + """ + :type resolve: rope.base.oi.type_hinting.resolvers.interfaces.IResolver + """ + + resolve = None + + @others + +def __call__(self, pyfunc): + """ + :type pyfunc: rope.base.pyobjectsdef.PyFunction + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + raise NotImplementedError + + + +class IAssignmentProvider: + """ + :type resolve: rope.base.oi.type_hinting.resolvers.interfaces.IResolver + """ + + resolve = None + + @others + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + raise NotImplementedError + +def __init__(self, holding=None): + super().__init__() + self.holding = holding + self.attributes = { + "next": BuiltinName(BuiltinFunction(self.holding)), + "__iter__": BuiltinName(BuiltinFunction(self)), + } + + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ +@nopyflakes +""" +Some code extracted (or based on code) from: +https://github.com/davidhalter/jedi/blob/b489019f5bd5750051122b94cc767df47751ecb7/jedi/evaluate/docstrings.py +Thanks to @davidhalter for this utils under MIT License. +""" +import re +from ast import literal_eval +from rope.base.oi.type_hinting.providers import docstrings + +try: + from numpydoc.docscrape import NumpyDocString +except ImportError: + NumpyDocString = None + + +@others +if not NumpyDocString: + NumPyDocstringParamParser = _DummyParamParser +@language python +@tabwidth -4 + +class NumPyDocstringParamParser(docstrings.IParamParser): + @others + +def __call__(self, docstring, param_name): + """Search `docstring` (in numpydoc format) for type(-s) of `param_name`.""" + if not docstring: + return [] + params = NumpyDocString(docstring)._parsed_data["Parameters"] + for p_name, p_type, p_descr in params: + if p_name == param_name: + m = re.match("([^,]+(,[^,]+)*?)(,[ ]*optional)?$", p_type) + if m: + p_type = m.group(1) + + if p_type.startswith("{"): + types = {type(x).__name__ for x in literal_eval(p_type)} + return list(types) + else: + return [p_type] + return [] + + + +class _DummyParamParser(docstrings.IParamParser): + def __call__(self, docstring, param_name): + return [] + + + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ +import re +from rope.base.oi.type_hinting import utils +from rope.base.oi.type_hinting.providers import interfaces + + +@others +@language python +@tabwidth -4 + +class AssignmentProvider(interfaces.IAssignmentProvider): + @others + +def __init__(self, resolver): + """ + :type resolver: rope.base.oi.type_hinting.resolvers.interfaces.IResolver + """ + self._resolve = resolver + + +PEP0484_TYPE_COMMENT_PATTERNS = (re.compile(r"type:\s*([^\n]+)"),) + + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + from rope.base.oi.soi import _get_lineno_for_node + + lineno = _get_lineno_for_node(pyname.assignments[0].ast_node) + holding_scope = pyname.module.get_scope().get_inner_scope_for_line(lineno) + line = holding_scope._get_global_scope()._scope_finder.lines.get_line(lineno) + if "#" in line: + type_strs = self._search_type_in_type_comment(line.split("#", 1)[1]) + if type_strs: + return self._resolve(type_strs[0], holding_scope.pyobject) + + +def _search_type_in_type_comment(self, code): + """For more info see: + https://www.python.org/dev/peps/pep-0484/#type-comments + + >>> AssignmentProvider()._search_type_in_type_comment('type: int') + ['int'] + """ + for p in self.PEP0484_TYPE_COMMENT_PATTERNS: + match = p.search(code) + if match: + return [match.group(1)] + +def get_attributes(self): + return self.attributes + + + + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/resolvers/ +from rope.base.oi.type_hinting.resolvers import interfaces + + +@others +@language python +@tabwidth -4 + +class Resolver(interfaces.IResolver): + @others + +def __init__(self, *delegates): + """ + :type delegates: list[rope.base.oi.type_hinting.resolvers.interfaces.IResolver] + """ + self._delegates = delegates + + +def __call__(self, hint, pyobject): + """ + :param hint: For example "List[int]" or "(Foo, Bar) -> Baz" or simple "Foo" + :type hint: str + :type pyobject: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + for delegate in self._delegates: + result = delegate(hint, pyobject) + if result: + return result + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/resolvers/ +class IResolver: + def __call__(self, hint, pyobject): + """ + :param hint: For example "List[int]" or "(Foo, Bar) -> Baz" or simple "Foo" + :type hint: str + :type pyobject: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + raise NotImplementedError +@language python +@tabwidth -4 + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/resolvers/ +from rope.base.oi.type_hinting import evaluate +from rope.base.oi.type_hinting.resolvers import interfaces + + +@others +@language python +@tabwidth -4 + +class Resolver(interfaces.IResolver): + @others + +def __call__(self, hint, pyobject): + """ + :param hint: For example "List[int]" or "(Foo, Bar) -> Baz" or simple "Foo" + :type hint: str + :type pyobject: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + try: + return evaluate.evaluate(hint, pyobject) + except (Exception): + pass + +def get_returned_object(self, args): + return self.holding + + + + + +@path C:/Repos/ekr-rope/rope/base/utils/ +# this snippet was taken from this link +# http://code.activestate.com/recipes/576694/ + +try: + from collections.abc import MutableSet +except ImportError: + from collections import MutableSet + + +@others +@language python +@tabwidth -4 + +class OrderedSet(MutableSet): + @others + +def __init__(self, iterable=None): + self.end = end = [] + end += [None, end, end] # sentinel + # node for doubly linked list + self.map = {} # key --> [key, prev, next] + if iterable is not None: + self |= iterable + + +def __len__(self): + return len(self.map) + + +def __contains__(self, key): + return key in self.map + + +def add(self, key): + if key not in self.map: + end = self.end + curr = end[1] + curr[2] = end[1] = self.map[key] = [key, curr, end] + + +def intersection(self, set_b): + return OrderedSet([item for item in self if item in set_b]) + + +def discard(self, key): + if key in self.map: + key, prev, next = self.map.pop(key) + prev[2] = next + next[1] = prev + + +get_iterator = _create_builtin_getter(Iterator) + + + +def __iter__(self): + end = self.end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + +def __reversed__(self): + end = self.end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] + + +def pop(self, last=True): + if not self: + raise KeyError("set is empty") + key = self.end[1][0] if last else self.end[2][0] + self.discard(key) + return key + + +def __repr__(self): + if not self: + return "{}()".format(self.__class__.__name__) + return "{}({!r})".format(self.__class__.__name__, list(self)) + + +def __eq__(self, other): + if isinstance(other, OrderedSet): + return len(self) == len(other) and list(self) == list(other) + return set(self) == set(other) + +@path C:/Repos/ekr-rope/rope/base/utils/ +import sys +import warnings + + +@others +@language python +@tabwidth -4 + + +class Generator(pyobjects.AbstractClass): + @others + +def saveit(func): + """A decorator that caches the return value of a function""" + + name = "_" + func.__name__ + + @others + return _wrapper + + + +def _wrapper(self, *args, **kwds): + if not hasattr(self, name): + setattr(self, name, func(self, *args, **kwds)) + return getattr(self, name) + + +cacheit = saveit + + + +def prevent_recursion(default): + """A decorator that returns the return value of `default` in recursions""" + + @others + return decorator + + + +def decorator(func): + name = "_calling_%s_" % func.__name__ + + def newfunc(self, *args, **kwds): + if getattr(self, name, False): + return default() + setattr(self, name, True) + try: + return func(self, *args, **kwds) + finally: + setattr(self, name, False) + + return newfunc + + +def ignore_exception(exception_class): + """A decorator that ignores `exception_class` exceptions""" + + @others + return _decorator + + + +def _decorator(func): + def newfunc(*args, **kwds): + try: + return func(*args, **kwds) + except exception_class: + pass + + return newfunc + + +def deprecated(message=None): + """A decorator for deprecated functions""" + + @others + return _decorator + + + +def _decorator(func, message=message): + if message is None: + message = "%s is deprecated" % func.__name__ + + def newfunc(*args, **kwds): + warnings.warn(message, DeprecationWarning, stacklevel=2) + return func(*args, **kwds) + + return newfunc + + +def cached(size): + """A caching decorator based on parameter objects""" + + @others + return decorator + + + +def __init__(self, holding=None): + super().__init__() + self.holding = holding + self.attributes = { + "next": BuiltinName(BuiltinFunction(self.holding)), + "__iter__": BuiltinName(BuiltinFunction(get_iterator(self.holding))), + "close": BuiltinName(BuiltinFunction()), + "send": BuiltinName(BuiltinFunction()), + "throw": BuiltinName(BuiltinFunction()), + } + + +def decorator(func): + cached_func = _Cached(func, size) + return lambda *a, **kw: cached_func(*a, **kw) + + +class _Cached: + @others + +def __init__(self, func, count): + self.func = func + self.cache = [] + self.count = count + + +def __call__(self, *args, **kwds): + key = (args, kwds) + for cached_key, cached_result in self.cache: + if cached_key == key: + return cached_result + result = self.func(*args, **kwds) + self.cache.append((key, result)) + if len(self.cache) > self.count: + del self.cache[0] + return result + + + +def resolve(str_or_obj): + """Returns object from string""" + if not isinstance(str_or_obj, str): + return str_or_obj + if "." not in str_or_obj: + str_or_obj += "." + mod_name, obj_name = str_or_obj.rsplit(".", 1) + __import__(mod_name) + mod = sys.modules[mod_name] + return getattr(mod, obj_name) if obj_name else mod + + + +def guess_def_lineno(module, node): + """Find the line number for a function or class definition. + + `node` may be either an ast.FunctionDef, ast.AsyncFunctionDef, or ast.ClassDef + + Python 3.8 simply provides this to us, but in earlier versions the ast + node.lineno points to the first decorator rather than the actual + definition, so we try our best to find where the definitions are. + + This is to workaround bpo-33211 (https://bugs.python.org/issue33211) + """ + + @others + if sys.version_info >= (3, 8) or not hasattr(node, "body"): + return node.lineno + + possible_def_line = ( + node.body[0].lineno if is_inline_body() else node.body[0].lineno - 1 + ) + return module.logical_lines.logical_line_in(possible_def_line)[0] + +def is_inline_body(): + # class Foo(object): + # def inline_body(): pass + # ^ ^--- body_col_offset + # `--- indent_col_offset + # def not_inline_body(): + # pass + # ^--- body_col_offset == indent_col_offset + line = module.lines.get_line(node.body[0].lineno) + indent_col_offset = len(line) - len(line.lstrip()) + body_col_offset = node.body[0].col_offset + return indent_col_offset < body_col_offset + + + +@path C:/Repos/ekr-rope/rope/contrib/ +"""For performing many refactorings as a single command + +`changestack` module can be used to perform many refactorings on top +of each other as one bigger command. It can be used like:: + + stack = ChangeStack(project, 'my big command') + + #.. + stack.push(refactoring1.get_changes()) + #.. + stack.push(refactoring2.get_changes()) + #.. + stack.push(refactoringX.get_changes()) + + stack.pop_all() + changes = stack.merged() + +Now `changes` can be previewed or performed as before. +""" + +from rope.base import change + + +@others +@language python +@tabwidth -4 + +class ChangeStack: + @others + +def get_attributes(self): + return self.attributes + + +def __init__(self, project, description="merged changes"): + self.project = project + self.description = description + self.stack = [] + + +def push(self, changes): + self.stack.append(changes) + self.project.do(changes) + + +def pop_all(self): + for i in range(len(self.stack)): + self.project.history.undo(drop=True) + + +def merged(self): + result = change.ChangeSet(self.description) + for changes in self.stack: + for c in self._basic_changes(changes): + result.add_change(c) + return result + + +def _basic_changes(self, changes): + if isinstance(changes, change.ChangeSet): + for child in changes.changes: + yield from self._basic_changes(child) + else: + yield changes + +@path C:/Repos/ekr-rope/rope/contrib/ +import keyword +import sys +import warnings + +import rope.base.codeanalyze +import rope.base.evaluate +from rope.base import builtins +from rope.base import exceptions +from rope.base import libutils +from rope.base import pynames +from rope.base import pynamesdef +from rope.base import pyobjects +from rope.base import pyobjectsdef +from rope.base import pyscopes +from rope.base import worder +from rope.contrib import fixsyntax +from rope.refactor import functionutils + + +@others +@language python +@tabwidth -4 + +def code_assist( + project, + source_code, + offset, + resource=None, + templates=None, + maxfixes=1, + later_locals=True, +): + """Return python code completions as a list of `CodeAssistProposal` + + `resource` is a `rope.base.resources.Resource` object. If + provided, relative imports are handled. + + `maxfixes` is the maximum number of errors to fix if the code has + errors in it. + + If `later_locals` is `False` names defined in this scope and after + this line is ignored. + + """ + if templates is not None: + warnings.warn( + "Codeassist no longer supports templates", DeprecationWarning, stacklevel=2 + ) + assist = _PythonCodeAssist( + project, + source_code, + offset, + resource=resource, + maxfixes=maxfixes, + later_locals=later_locals, + ) + return assist() + + + +def starting_offset(source_code, offset): + """Return the offset in which the completion should be inserted + + Usually code assist proposals should be inserted like:: + + completion = proposal.name + result = (source_code[:starting_offset] + + completion + source_code[offset:]) + + Where starting_offset is the offset returned by this function. + + """ + word_finder = worder.Worder(source_code, True) + expression, starting, starting_offset = word_finder.get_splitted_primary_before( + offset + ) + return starting_offset + + + +def get_doc(project, source_code, offset, resource=None, maxfixes=1): + """Get the pydoc""" + fixer = fixsyntax.FixSyntax(project, source_code, resource, maxfixes) + pyname = fixer.pyname_at(offset) + if pyname is None: + return None + pyobject = pyname.get_object() + return PyDocExtractor().get_doc(pyobject) + + + +def get_calltip( + project, + source_code, + offset, + resource=None, + maxfixes=1, + ignore_unknown=False, + remove_self=False, +): + """Get the calltip of a function + + The format of the returned string is + ``module_name.holding_scope_names.function_name(arguments)``. For + classes `__init__()` and for normal objects `__call__()` function + is used. + + Note that the offset is on the function itself *not* after the its + open parenthesis. (Actually it used to be the other way but it + was easily confused when string literals were involved. So I + decided it is better for it not to try to be too clever when it + cannot be clever enough). You can use a simple search like:: + + offset = source_code.rindex('(', 0, offset) - 1 + + to handle simple situations. + + If `ignore_unknown` is `True`, `None` is returned for functions + without source-code like builtins and extensions. + + If `remove_self` is `True`, the first parameter whose name is self + will be removed for methods. + """ + fixer = fixsyntax.FixSyntax(project, source_code, resource, maxfixes) + pyname = fixer.pyname_at(offset) + if pyname is None: + return None + pyobject = pyname.get_object() + return PyDocExtractor().get_calltip(pyobject, ignore_unknown, remove_self) + + + +def get_returned_object(self, args): + return self.holding + + + +def get_definition_location(project, source_code, offset, resource=None, maxfixes=1): + """Return the definition location of the python name at `offset` + + Return a (`rope.base.resources.Resource`, lineno) tuple. If no + `resource` is given and the definition is inside the same module, + the first element of the returned tuple would be `None`. If the + location cannot be determined ``(None, None)`` is returned. + + """ + fixer = fixsyntax.FixSyntax(project, source_code, resource, maxfixes) + pyname = fixer.pyname_at(offset) + if pyname is not None: + module, lineno = pyname.get_definition_location() + if module is not None: + return module.get_module().get_resource(), lineno + return (None, None) + + + +def find_occurrences(*args, **kwds): + import rope.contrib.findit + + warnings.warn( + "Use `rope.contrib.findit.find_occurrences()` instead", + DeprecationWarning, + stacklevel=2, + ) + return rope.contrib.findit.find_occurrences(*args, **kwds) + + + +def get_canonical_path(project, resource, offset): + """Get the canonical path to an object. + + Given the offset of the object, this returns a list of + (name, name_type) tuples representing the canonical path to the + object. For example, the 'x' in the following code: + + class Foo(object): + def bar(self): + class Qux(object): + def mux(self, x): + pass + + we will return: + + [('Foo', 'CLASS'), ('bar', 'FUNCTION'), ('Qux', 'CLASS'), + ('mux', 'FUNCTION'), ('x', 'PARAMETER')] + + `resource` is a `rope.base.resources.Resource` object. + + `offset` is the offset of the pyname you want the path to. + + """ + # Retrieve the PyName. + pymod = project.get_pymodule(resource) + pyname = rope.base.evaluate.eval_location(pymod, offset) + + # Now get the location of the definition and its containing scope. + defmod, lineno = pyname.get_definition_location() + if not defmod: + return None + scope = defmod.get_scope().get_inner_scope_for_line(lineno) + + # Start with the name of the object we're interested in. + names = [] + if isinstance(pyname, pynamesdef.ParameterName): + names = [(worder.get_name_at(pymod.get_resource(), offset), "PARAMETER")] + elif isinstance(pyname, pynamesdef.AssignedName): + names = [(worder.get_name_at(pymod.get_resource(), offset), "VARIABLE")] + + # Collect scope names. + while scope.parent: + if isinstance(scope, pyscopes.FunctionScope): + scope_type = "FUNCTION" + elif isinstance(scope, pyscopes.ClassScope): + scope_type = "CLASS" + else: + scope_type = None + names.append((scope.pyobject.get_name(), scope_type)) + scope = scope.parent + + names.append((defmod.get_resource().real_path, "MODULE")) + names.reverse() + return names + + + +class CompletionProposal: + """A completion proposal + + The `scope` instance variable shows where proposed name came from + and can be 'global', 'local', 'builtin', 'attribute', 'keyword', + 'imported', 'parameter_keyword'. + + The `type` instance variable shows the approximate type of the + proposed object and can be 'instance', 'class', 'function', 'module', + and `None`. + + All possible relations between proposal's `scope` and `type` are shown + in the table below (different scopes in rows and types in columns): + + | instance | class | function | module | None + local | + | + | + | + | + global | + | + | + | + | + builtin | + | + | + | | + attribute | + | + | + | + | + imported | + | + | + | + | + keyword | | | | | + + parameter_keyword | | | | | + + + """ + + @others + +def __init__(self, name, scope, pyname=None): + self.name = name + self.pyname = pyname + self.scope = self._get_scope(scope) + + +def __str__(self): + return "{} ({}, {})".format(self.name, self.scope, self.type) + + +def __repr__(self): + return str(self) + + +@property +def parameters(self): + """The names of the parameters the function takes. + + Returns None if this completion is not a function. + """ + pyname = self.pyname + if isinstance(pyname, pynames.ImportedName): + pyname = pyname._get_imported_pyname() + if isinstance(pyname, pynames.DefinedName): + pyobject = pyname.get_object() + if isinstance(pyobject, pyobjects.AbstractFunction): + return pyobject.get_param_names() + + +@property +def type(self): + pyname = self.pyname + if isinstance(pyname, builtins.BuiltinName): + pyobject = pyname.get_object() + if isinstance(pyobject, builtins.BuiltinFunction): + return "function" + elif isinstance(pyobject, builtins.BuiltinClass): + return "class" + elif isinstance(pyobject, builtins.BuiltinObject) or isinstance( + pyobject, builtins.BuiltinName + ): + return "instance" + elif isinstance(pyname, pynames.ImportedModule): + return "module" + elif isinstance(pyname, pynames.ImportedName) or isinstance( + pyname, pynames.DefinedName + ): + pyobject = pyname.get_object() + if isinstance(pyobject, pyobjects.AbstractFunction): + return "function" + if isinstance(pyobject, pyobjects.AbstractClass): + return "class" + return "instance" + + +def _get_scope(self, scope): + if isinstance(self.pyname, builtins.BuiltinName): + return "builtin" + if isinstance(self.pyname, pynames.ImportedModule) or isinstance( + self.pyname, pynames.ImportedName + ): + return "imported" + return scope + + +get_generator = _create_builtin_getter(Generator) + + + +def get_doc(self): + """Get the proposed object's docstring. + + Returns None if it can not be get. + """ + if not self.pyname: + return None + pyobject = self.pyname.get_object() + if not hasattr(pyobject, "get_doc"): + return None + return self.pyname.get_object().get_doc() + + +@property +def kind(self): + warnings.warn( + "the proposal's `kind` property is deprecated, " "use `scope` instead" + ) + return self.scope + + + +# leaved for backward compatibility +CodeAssistProposal = CompletionProposal + + + +class NamedParamProposal(CompletionProposal): + """A parameter keyword completion proposal + + Holds reference to ``_function`` -- the function which + parameter ``name`` belongs to. This allows to determine + default value for this parameter. + """ + + @others + +def __init__(self, name, function): + self.argname = name + name = "%s=" % name + super().__init__(name, "parameter_keyword") + self._function = function + + +def get_default(self): + """Get a string representation of a param's default value. + + Returns None if there is no default value for this param. + """ + definfo = functionutils.DefinitionInfo.read(self._function) + for arg, default in definfo.args_with_defaults: + if self.argname == arg: + return default + return None + + + +def sorted_proposals(proposals, scopepref=None, typepref=None): + """Sort a list of proposals + + Return a sorted list of the given `CodeAssistProposal`. + + `scopepref` can be a list of proposal scopes. Defaults to + ``['parameter_keyword', 'local', 'global', 'imported', + 'attribute', 'builtin', 'keyword']``. + + `typepref` can be a list of proposal types. Defaults to + ``['class', 'function', 'instance', 'module', None]``. + (`None` stands for completions with no type like keywords.) + """ + sorter = _ProposalSorter(proposals, scopepref, typepref) + return sorter.get_sorted_proposal_list() + + + +def starting_expression(source_code, offset): + """Return the expression to complete""" + word_finder = worder.Worder(source_code, True) + expression, starting, starting_offset = word_finder.get_splitted_primary_before( + offset + ) + if expression: + return expression + "." + starting + return starting + + + +def default_templates(): + warnings.warn( + "default_templates() is deprecated.", DeprecationWarning, stacklevel=2 + ) + return {} + + + +class _PythonCodeAssist: + @others + +class File(BuiltinClass): + @others + +def __init__( + self, project, source_code, offset, resource=None, maxfixes=1, later_locals=True +): + self.project = project + self.code = source_code + self.resource = resource + self.maxfixes = maxfixes + self.later_locals = later_locals + self.word_finder = worder.Worder(source_code, True) + ( + self.expression, + self.starting, + self.offset, + ) = self.word_finder.get_splitted_primary_before(offset) + + +keywords = keyword.kwlist + + +def _find_starting_offset(self, source_code, offset): + current_offset = offset - 1 + while current_offset >= 0 and ( + source_code[current_offset].isalnum() or source_code[current_offset] in "_" + ): + current_offset -= 1 + return current_offset + 1 + + +def _matching_keywords(self, starting): + return [ + CompletionProposal(kw, "keyword") + for kw in self.keywords + if kw.startswith(starting) + ] + + +def __call__(self): + if self.offset > len(self.code): + return [] + completions = list(self._code_completions().values()) + if self.expression.strip() == "" and self.starting.strip() != "": + completions.extend(self._matching_keywords(self.starting)) + return completions + + +def _dotted_completions(self, module_scope, holding_scope): + result = {} + found_pyname = rope.base.evaluate.eval_str(holding_scope, self.expression) + if found_pyname is not None: + element = found_pyname.get_object() + compl_scope = "attribute" + if isinstance(element, (pyobjectsdef.PyModule, pyobjectsdef.PyPackage)): + compl_scope = "imported" + for name, pyname in element.get_attributes().items(): + if name.startswith(self.starting): + result[name] = CompletionProposal(name, compl_scope, pyname) + return result + + +def _undotted_completions(self, scope, result, lineno=None): + if scope.parent is not None: + self._undotted_completions(scope.parent, result) + if lineno is None: + names = scope.get_propagated_names() + else: + names = scope.get_names() + for name, pyname in names.items(): + if name.startswith(self.starting): + compl_scope = "local" + if scope.get_kind() == "Module": + compl_scope = "global" + if ( + lineno is None + or self.later_locals + or not self._is_defined_after(scope, pyname, lineno) + ): + result[name] = CompletionProposal(name, compl_scope, pyname) + + +def _from_import_completions(self, pymodule): + module_name = self.word_finder.get_from_module(self.offset) + if module_name is None: + return {} + pymodule = self._find_module(pymodule, module_name) + result = {} + for name in pymodule: + if name.startswith(self.starting): + result[name] = CompletionProposal( + name, scope="global", pyname=pymodule[name] + ) + return result + + +def _find_module(self, pymodule, module_name): + dots = 0 + while module_name[dots] == ".": + dots += 1 + pyname = pynames.ImportedModule(pymodule, module_name[dots:], dots) + return pyname.get_object() + + +def _is_defined_after(self, scope, pyname, lineno): + location = pyname.get_definition_location() + if location is not None and location[1] is not None: + if ( + location[0] == scope.pyobject.get_module() + and lineno <= location[1] <= scope.get_end() + ): + return True + + +def __init__(self, filename=None, mode="r", *args): + self.filename = filename + self.mode = mode + self.args = args + str_object = get_str() + str_list = get_list(get_str()) + attributes = {} + + def add(name, returned=None, function=None): + builtin = getattr(io.TextIOBase, name, None) + attributes[name] = BuiltinName( + BuiltinFunction(returned=returned, function=function, builtin=builtin) + ) + + add("__iter__", get_iterator(str_object)) + add("__enter__", returned=pyobjects.PyObject(self)) + for method in ["next", "read", "readline", "readlines"]: + add(method, str_list) + for method in [ + "close", + "flush", + "lineno", + "isatty", + "seek", + "tell", + "truncate", + "write", + "writelines", + ]: + add(method) + super().__init__(open, attributes) + + + +def _code_completions(self): + lineno = self.code.count("\n", 0, self.offset) + 1 + fixer = fixsyntax.FixSyntax( + self.project, self.code, self.resource, self.maxfixes + ) + pymodule = fixer.get_pymodule() + module_scope = pymodule.get_scope() + code = pymodule.source_code + lines = code.split("\n") + result = {} + start = fixsyntax._logical_start(lines, lineno) + indents = fixsyntax._get_line_indents(lines[start - 1]) + inner_scope = module_scope.get_inner_scope_for_line(start, indents) + if self.word_finder.is_a_name_after_from_import(self.offset): + return self._from_import_completions(pymodule) + if self.expression.strip() != "": + result.update(self._dotted_completions(module_scope, inner_scope)) + else: + result.update(self._keyword_parameters(module_scope.pyobject, inner_scope)) + self._undotted_completions(inner_scope, result, lineno=lineno) + return result + + +def _keyword_parameters(self, pymodule, scope): + offset = self.offset + if offset == 0: + return {} + word_finder = worder.Worder(self.code, True) + if word_finder.is_on_function_call_keyword(offset - 1): + function_parens = word_finder.find_parens_start_from_inside(offset - 1) + primary = word_finder.get_primary_at(function_parens - 1) + try: + function_pyname = rope.base.evaluate.eval_str(scope, primary) + except exceptions.BadIdentifierError: + return {} + if function_pyname is not None: + pyobject = function_pyname.get_object() + if isinstance(pyobject, pyobjects.AbstractFunction): + pass + elif ( + isinstance(pyobject, pyobjects.AbstractClass) + and "__init__" in pyobject + ): + pyobject = pyobject["__init__"].get_object() + elif "__call__" in pyobject: + pyobject = pyobject["__call__"].get_object() + if isinstance(pyobject, pyobjects.AbstractFunction): + param_names = [] + param_names.extend(pyobject.get_param_names(special_args=False)) + result = {} + for name in param_names: + if name.startswith(self.starting): + result[name + "="] = NamedParamProposal(name, pyobject) + return result + return {} + + + +class _ProposalSorter: + """Sort a list of code assist proposals""" + + @others + +def __init__(self, code_assist_proposals, scopepref=None, typepref=None): + self.proposals = code_assist_proposals + if scopepref is None: + scopepref = [ + "parameter_keyword", + "local", + "global", + "imported", + "attribute", + "builtin", + "keyword", + ] + self.scopepref = scopepref + if typepref is None: + typepref = ["class", "function", "instance", "module", None] + self.typerank = {type: index for index, type in enumerate(typepref)} + + +def get_sorted_proposal_list(self): + """Return a list of `CodeAssistProposal`""" + proposals = {} + for proposal in self.proposals: + proposals.setdefault(proposal.scope, []).append(proposal) + result = [] + for scope in self.scopepref: + scope_proposals = proposals.get(scope, []) + scope_proposals = [ + proposal + for proposal in scope_proposals + if proposal.type in self.typerank + ] + scope_proposals.sort(key=self._proposal_key) + result.extend(scope_proposals) + return result + + +def _proposal_key(self, proposal1): + def _underline_count(name): + return sum(1 for c in name if c == "_") + + return ( + self.typerank.get(proposal1.type, 100), + _underline_count(proposal1.name), + proposal1.name, + ) + # if proposal1.type != proposal2.type: + # return cmp(self.typerank.get(proposal1.type, 100), + # self.typerank.get(proposal2.type, 100)) + # return self._compare_underlined_names(proposal1.name, + # proposal2.name) + + + +class PyDocExtractor: + @others + +def get_doc(self, pyobject): + if isinstance(pyobject, pyobjects.AbstractFunction): + return self._get_function_docstring(pyobject) + elif isinstance(pyobject, pyobjects.AbstractClass): + return self._get_class_docstring(pyobject) + elif isinstance(pyobject, pyobjects.AbstractModule): + return self._trim_docstring(pyobject.get_doc()) + return None + + +def get_calltip(self, pyobject, ignore_unknown=False, remove_self=False): + try: + if isinstance(pyobject, pyobjects.AbstractClass): + pyobject = pyobject["__init__"].get_object() + if not isinstance(pyobject, pyobjects.AbstractFunction): + pyobject = pyobject["__call__"].get_object() + except exceptions.AttributeNotFoundError: + return None + if ignore_unknown and not isinstance(pyobject, pyobjects.PyFunction): + return + if isinstance(pyobject, pyobjects.AbstractFunction): + result = self._get_function_signature(pyobject, add_module=True) + if remove_self and self._is_method(pyobject): + return result.replace("(self)", "()").replace("(self, ", "(") + return result + + +def _get_class_docstring(self, pyclass): + contents = self._trim_docstring(pyclass.get_doc(), 2) + supers = [super.get_name() for super in pyclass.get_superclasses()] + doc = ( + "class {}({}):\n\n".format(pyclass.get_name(), ", ".join(supers)) + contents + ) + + if "__init__" in pyclass: + init = pyclass["__init__"].get_object() + if isinstance(init, pyobjects.AbstractFunction): + doc += "\n\n" + self._get_single_function_docstring(init) + return doc + + +get_file = _create_builtin_getter(File) +get_file_type = _create_builtin_type_getter(File) + + + +def _get_function_docstring(self, pyfunction): + functions = [pyfunction] + if self._is_method(pyfunction): + functions.extend( + self._get_super_methods(pyfunction.parent, pyfunction.get_name()) + ) + return "\n\n".join( + [self._get_single_function_docstring(function) for function in functions] + ) + + +def _is_method(self, pyfunction): + return isinstance(pyfunction, pyobjects.PyFunction) and isinstance( + pyfunction.parent, pyobjects.PyClass + ) + + +def _get_single_function_docstring(self, pyfunction): + signature = self._get_function_signature(pyfunction) + docs = self._trim_docstring(pyfunction.get_doc(), indents=2) + return signature + ":\n\n" + docs + + +def _get_super_methods(self, pyclass, name): + result = [] + for super_class in pyclass.get_superclasses(): + if name in super_class: + function = super_class[name].get_object() + if isinstance(function, pyobjects.AbstractFunction): + result.append(function) + result.extend(self._get_super_methods(super_class, name)) + return result + + +def _get_function_signature(self, pyfunction, add_module=False): + location = self._location(pyfunction, add_module) + if isinstance(pyfunction, pyobjects.PyFunction): + info = functionutils.DefinitionInfo.read(pyfunction) + return location + info.to_string() + else: + return "{}({})".format( + location + pyfunction.get_name(), + ", ".join(pyfunction.get_param_names()), + ) + + +def _location(self, pyobject, add_module=False): + location = [] + parent = pyobject.parent + while parent and not isinstance(parent, pyobjects.AbstractModule): + location.append(parent.get_name()) + location.append(".") + parent = parent.parent + if add_module: + if isinstance(pyobject, pyobjects.PyFunction): + location.insert(0, self._get_module(pyobject)) + if isinstance(parent, builtins.BuiltinModule): + location.insert(0, parent.get_name() + ".") + return "".join(location) + + +def _get_module(self, pyfunction): + module = pyfunction.get_module() + if module is not None: + resource = module.get_resource() + if resource is not None: + return libutils.modname(resource) + "." + return "" + + +def _trim_docstring(self, docstring, indents=0): + """The sample code from :PEP:`257`""" + if not docstring: + return "" + # Convert tabs to spaces (following normal Python rules) + # and split into a list of lines: + lines = docstring.expandtabs().splitlines() + # Determine minimum indentation (first line doesn't count): + indent = sys.maxsize + for line in lines[1:]: + stripped = line.lstrip() + if stripped: + indent = min(indent, len(line) - len(stripped)) + # Remove indentation (first line is special): + trimmed = [lines[0].strip()] + if indent < sys.maxsize: + for line in lines[1:]: + trimmed.append(line[indent:].rstrip()) + # Strip off trailing and leading blank lines: + while trimmed and not trimmed[-1]: + trimmed.pop() + while trimmed and not trimmed[0]: + trimmed.pop(0) + # Return a single string: + return "\n".join(" " * indents + line for line in trimmed) + + + +# Deprecated classes + + + +class TemplateProposal(CodeAssistProposal): + def __init__(self, name, template): + warnings.warn( + "TemplateProposal is deprecated.", DeprecationWarning, stacklevel=2 + ) + super().__init__(name, "template") + self.template = template + + + +class Property(BuiltinClass): + @others + +class Template: + @others + +def __init__(self, template): + self.template = template + warnings.warn("Template is deprecated.", DeprecationWarning, stacklevel=2) + + +def variables(self): + return [] + + +def substitute(self, mapping): + return self.template + + +def get_cursor_location(self, mapping): + return len(self.template) + +@path C:/Repos/ekr-rope/rope/contrib/ +"""Finding bad name and attribute accesses + +`find_errors` function can be used to find possible bad name and +attribute accesses. As an example:: + + errors = find_errors(project, project.get_resource('mod.py')) + for error in errors: + print('%s: %s' % (error.lineno, error.error)) + +prints possible errors for ``mod.py`` file. + +TODO: + +* use task handles +* reporting names at most once +* attributes of extension modules that don't appear in + extension_modules project config can be ignored +* not calling `PyScope.get_inner_scope_for_line()` if it is a + bottleneck; needs profiling +* not reporting occurrences where rope cannot infer the object +* rope saves multiple objects for some of the names in its objectdb + use all of them not to give false positives +* ... ;-) + +""" +from rope.base import ast, evaluate, pyobjects + + +@others +@language python +@tabwidth -4 + +def find_errors(project, resource): + """Find possible bad name and attribute accesses + + It returns a list of `Error`. + """ + pymodule = project.get_pymodule(resource) + finder = _BadAccessFinder(pymodule) + ast.walk(pymodule.get_ast(), finder) + return finder.errors + + + +class _BadAccessFinder: + @others + +def __init__(self, pymodule): + self.pymodule = pymodule + self.scope = pymodule.get_scope() + self.errors = [] + + +def _Name(self, node): + if isinstance(node.ctx, (ast.Store, ast.Param)): + return + scope = self.scope.get_inner_scope_for_line(node.lineno) + pyname = scope.lookup(node.id) + if pyname is None: + self._add_error(node, "Unresolved variable") + elif self._is_defined_after(scope, pyname, node.lineno): + self._add_error(node, "Defined later") + + +def __init__(self, fget=None, fset=None, fdel=None, fdoc=None): + self._fget = fget + self._fdoc = fdoc + attributes = { + "fget": BuiltinName(BuiltinFunction()), + "fset": BuiltinName(pynames.UnboundName()), + "fdel": BuiltinName(pynames.UnboundName()), + "__new__": BuiltinName(BuiltinFunction(function=_property_function)), + } + super().__init__(property, attributes) + + +def _Attribute(self, node): + if not isinstance(node.ctx, ast.Store): + scope = self.scope.get_inner_scope_for_line(node.lineno) + pyname = evaluate.eval_node(scope, node.value) + if pyname is not None and pyname.get_object() != pyobjects.get_unknown(): + if node.attr not in pyname.get_object(): + self._add_error(node, "Unresolved attribute") + ast.walk(node.value, self) + + +def _add_error(self, node, msg): + if isinstance(node, ast.Attribute): + name = node.attr + else: + name = node.id + if name != "None": + error = Error(node.lineno, msg + " " + name) + self.errors.append(error) + + +def _is_defined_after(self, scope, pyname, lineno): + location = pyname.get_definition_location() + if location is not None and location[1] is not None: + if ( + location[0] == self.pymodule + and lineno <= location[1] <= scope.get_end() + ): + return True + + + +class Error: + def __init__(self, lineno, error): + self.lineno = lineno + self.error = error + + def __str__(self): + return "{}: {}".format(self.lineno, self.error) + +@path C:/Repos/ekr-rope/rope/contrib/ +import rope.base.codeanalyze +import rope.base.evaluate +import rope.base.pyobjects +from rope.base import taskhandle, exceptions, worder +from rope.contrib import fixsyntax +from rope.refactor import occurrences + + +@others +@language python +@tabwidth -4 + +def find_occurrences( + project, + resource, + offset, + unsure=False, + resources=None, + in_hierarchy=False, + task_handle=taskhandle.NullTaskHandle(), +): + """Return a list of `Location` + + If `unsure` is `True`, possible matches are returned, too. You + can use `Location.unsure` to see which are unsure occurrences. + `resources` can be a list of `rope.base.resource.File` that + should be searched for occurrences; if `None` all python files + in the project are searched. + + """ + name = worder.get_name_at(resource, offset) + this_pymodule = project.get_pymodule(resource) + primary, pyname = rope.base.evaluate.eval_location2(this_pymodule, offset) + + @others + finder = occurrences.create_finder( + project, + name, + pyname, + unsure=is_match, + in_hierarchy=in_hierarchy, + instance=primary, + ) + if resources is None: + resources = project.get_python_files() + job_set = task_handle.create_jobset("Finding Occurrences", count=len(resources)) + return _find_locations(finder, resources, job_set) + + + +def is_match(occurrence): + return unsure + + +def find_implementations( + project, resource, offset, resources=None, task_handle=taskhandle.NullTaskHandle() +): + """Find the places a given method is overridden. + + Finds the places a method is implemented. Returns a list of + `Location`. + """ + name = worder.get_name_at(resource, offset) + this_pymodule = project.get_pymodule(resource) + pyname = rope.base.evaluate.eval_location(this_pymodule, offset) + if pyname is not None: + pyobject = pyname.get_object() + if ( + not isinstance(pyobject, rope.base.pyobjects.PyFunction) + or pyobject.get_kind() != "method" + ): + raise exceptions.BadIdentifierError("Not a method!") + else: + raise exceptions.BadIdentifierError("Cannot resolve the identifier!") + + @others + filters = [is_defined, not_self, occurrences.InHierarchyFilter(pyname, True)] + finder = occurrences.Finder(project, name, filters=filters) + if resources is None: + resources = project.get_python_files() + job_set = task_handle.create_jobset("Finding Implementations", count=len(resources)) + return _find_locations(finder, resources, job_set) + + + +def is_defined(occurrence): + if not occurrence.is_defined(): + return False + + +def not_self(occurrence): + if occurrence.get_pyname().get_object() == pyname.get_object(): + return False + + +@path C:/Repos/ekr-rope/rope/ +"""rope, a python refactoring library""" + +from pkg_resources import get_distribution, DistributionNotFound + +try: + VERSION = get_distribution("rope").version +except DistributionNotFound: + + def get_fallback_version(): + import re + import pathlib + + pyproject = ( + pathlib.Path(__file__).resolve().parent.parent / "pyproject.toml" + ).read_text() + version = re.search("version.*=.*'(.*)'", pyproject) + return version.group(1) if version else None + + VERSION = get_fallback_version() + + +INFO = __doc__ +COPYRIGHT = """\ +Copyright (C) 2021-2022 Lie Ryan +Copyright (C) 2019-2021 Matej Cepl +Copyright (C) 2015-2018 Nicholas Smith +Copyright (C) 2014-2015 Matej Cepl +Copyright (C) 2006-2012 Ali Gholami Rudi +Copyright (C) 2009-2012 Anton Gritsay + +This program is free software: you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation, either +version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this program. If not, see +<https://www.gnu.org/licenses/>.""" +@language python +@tabwidth -4 + +def get_property_object(self, args): + if isinstance(self._fget, pyobjects.AbstractFunction): + return self._fget.get_returned_object(args) + + + +def find_definition(project, code, offset, resource=None, maxfixes=1): + """Return the definition location of the python name at `offset` + + A `Location` object is returned if the definition location can be + determined, otherwise ``None`` is returned. + """ + fixer = fixsyntax.FixSyntax(project, code, resource, maxfixes) + pyname = fixer.pyname_at(offset) + if pyname is not None: + module, lineno = pyname.get_definition_location() + name = rope.base.worder.Worder(code).get_word_at(offset) + if lineno is not None: + start = module.lines.get_line_start(lineno) + + def check_offset(occurrence): + if occurrence.offset < start: + return False + + pyname_filter = occurrences.PyNameFilter(pyname) + finder = occurrences.Finder(project, name, [check_offset, pyname_filter]) + for occurrence in finder.find_occurrences(pymodule=module): + return Location(occurrence) + + + +class Location: + def __init__(self, occurrence): + self.resource = occurrence.resource + self.region = occurrence.get_word_range() + self.offset = self.region[0] + self.unsure = occurrence.is_unsure() + self.lineno = occurrence.lineno + + + +def _find_locations(finder, resources, job_set): + result = [] + for resource in resources: + job_set.started_job(resource.path) + for occurrence in finder.find_occurrences(resource): + result.append(Location(occurrence)) + job_set.finished_job() + return result + +@path C:/Repos/ekr-rope/rope/contrib/ +"""Fix the name of modules + +This module is useful when you want to rename many of the modules in +your project. That can happen specially when you want to change their +naming style. + +For instance:: + + fixer = FixModuleNames(project) + changes = fixer.get_changes(fixer=str.lower) + project.do(changes) + +Here it renames all modules and packages to use lower-cased chars. +You can tell it to use any other style by using the ``fixer`` +argument. + +""" +from rope.base import taskhandle +from rope.contrib import changestack +from rope.refactor import rename + + +@others +@language python +@tabwidth -4 + +class FixModuleNames: + @others + +def __init__(self, project): + self.project = project + + +def get_changes(self, fixer=str.lower, task_handle=taskhandle.NullTaskHandle()): + """Fix module names + + `fixer` is a function that takes and returns a `str`. Given + the name of a module, it should return the fixed name. + + """ + stack = changestack.ChangeStack(self.project, "Fixing module names") + jobset = task_handle.create_jobset( + "Fixing module names", self._count_fixes(fixer) + 1 + ) + try: + while True: + for resource in self._tobe_fixed(fixer): + jobset.started_job(resource.path) + renamer = rename.Rename(self.project, resource) + changes = renamer.get_changes(fixer(self._name(resource))) + stack.push(changes) + jobset.finished_job() + break + else: + break + finally: + jobset.started_job("Reverting to original state") + stack.pop_all() + jobset.finished_job() + return stack.merged() + + +def _count_fixes(self, fixer): + return len(list(self._tobe_fixed(fixer))) + + +def _tobe_fixed(self, fixer): + for resource in self.project.get_python_files(): + modname = self._name(resource) + if modname != fixer(modname): + yield resource + + +def _name(self, resource): + modname = resource.name.rsplit(".", 1)[0] + if modname == "__init__": + modname = resource.parent.name + return modname + +def _property_function(args): + parameters = args.get_arguments(["fget", "fset", "fdel", "fdoc"]) + return pyobjects.PyObject(Property(parameters[0])) + + + +@path C:/Repos/ekr-rope/rope/contrib/ +import rope.base.codeanalyze +import rope.base.evaluate +from rope.base import exceptions +from rope.base import libutils +from rope.base import utils +from rope.base import worder +from rope.base.codeanalyze import ArrayLinesAdapter, LogicalLineFinder + + +@others +@language python +@tabwidth -4 + +class Lambda(pyobjects.AbstractFunction): + @others + +def __init__(self, node, scope): + super().__init__() + self.node = node + self.arguments = node.args + self.scope = scope + + +def get_returned_object(self, args): + result = rope.base.evaluate.eval_node(self.scope, self.node.body) + if result is not None: + return result.get_object() + else: + return pyobjects.get_unknown() + + +def get_module(self): + return self.parent.get_module() + + +def get_scope(self): + return self.scope + + +def get_kind(self): + return "lambda" + + +def get_ast(self): + return self.node + + +def get_attributes(self): + return {} + + + +def get_name(self): + return "lambda" + + +def get_param_names(self, special_args=True): + result = [ + node.arg for node in self.arguments.args if isinstance(node, ast.arg) + ] + if self.arguments.vararg: + result.append("*" + self.arguments.vararg.arg) + if self.arguments.kwarg: + result.append("**" + self.arguments.kwarg.arg) + return result + + +@property +def parent(self): + return self.scope.pyobject + + + +class BuiltinObject(BuiltinClass): + def __init__(self): + super().__init__(object, {}) + + + +class BuiltinType(BuiltinClass): + def __init__(self): + super().__init__(type, {}) + + + +def _infer_sequence_for_pyname(pyname): + if pyname is None: + return None + seq = pyname.get_object() + args = arguments.ObjectArguments([pyname]) + if "__iter__" in seq: + obj = seq["__iter__"].get_object() + if not isinstance(obj, pyobjects.AbstractFunction): + return None + iter = obj.get_returned_object(args) + if iter is not None and "next" in iter: + holding = iter["next"].get_object().get_returned_object(args) + return holding + + + +def _create_builtin(args, creator): + passed = args.get_pynames(["sequence"])[0] + if passed is None: + holding = None + else: + holding = _infer_sequence_for_pyname(passed) + if holding is not None: + return creator(holding) + else: + return creator() + + + +def _open_function(args): + return _create_builtin(args, get_file) + + + +def _range_function(args): + return get_list() + + + +def _reversed_function(args): + return _create_builtin(args, get_iterator) + + + +@path C:/Repos/ekr-rope/rope/base/ +import rope.base.evaluate +from rope.base import ast + + +@others +@language python +@tabwidth -4 + +def _sorted_function(args): + return _create_builtin(args, get_list) + + + +def _super_function(args): + passed_class, passed_self = args.get_arguments(["type", "self"]) + if passed_self is None: + return passed_class + else: + # pyclass = passed_self.get_type() + pyclass = passed_class + if isinstance(pyclass, pyobjects.AbstractClass): + supers = pyclass.get_superclasses() + if supers: + return pyobjects.PyObject(supers[0]) + return passed_self + + + +def _zip_function(args): + args = args.get_pynames(["sequence"]) + objects = [] + for seq in args: + if seq is None: + holding = None + else: + holding = _infer_sequence_for_pyname(seq) + objects.append(holding) + tuple = get_tuple(*objects) + return get_list(tuple) + + + +def _enumerate_function(args): + passed = args.get_pynames(["sequence"])[0] + if passed is None: + holding = None + else: + holding = _infer_sequence_for_pyname(passed) + tuple = get_tuple(None, holding) + return get_iterator(tuple) + + + +def _iter_function(args): + passed = args.get_pynames(["sequence"])[0] + if passed is None: + holding = None + else: + holding = _infer_sequence_for_pyname(passed) + return get_iterator(holding) + + + +def _input_function(args): + return get_str() + + + +@path C:/Repos/ekr-rope/rope/base/ +import datetime +import difflib +import os +import time +from typing import Union + +import rope.base.fscommands +from rope.base import exceptions, taskhandle, utils +from rope.base.fscommands import FileContent + + +@others +@language python +@tabwidth -4 + +class Change: + """The base class for changes + + Rope refactorings return `Change` objects. They can be previewed, + committed or undone. + """ + + @others + +def do(self, job_set=None): + """Perform the change + + .. note:: Do use this directly. Use `Project.do()` instead. + """ + + +def undo(self, job_set=None): + """Perform the change + + .. note:: Do use this directly. Use `History.undo()` instead. + """ + + +class Arguments: + """A class for evaluating parameters passed to a function + + You can use the `create_arguments` factory. It handles implicit + first arguments. + + """ + + @others + +def get_description(self): + """Return the description of this change + + This can be used for previewing the changes. + """ + return str(self) + + +def get_changed_resources(self): + """Return the list of resources that will be changed""" + return [] + + +@property +@utils.saveit +def _operations(self): + return _ResourceOperations(self.resource.project) + + + +class ChangeSet(Change): + """A collection of `Change` objects + + This class holds a collection of changes. This class provides + these fields: + + * `changes`: the list of changes + * `description`: the goal of these changes + """ + + @others + +def __init__(self, description, timestamp=None): + self.changes = [] + self.description = description + self.time = timestamp + + +def do(self, job_set=taskhandle.NullJobSet()): + try: + done = [] + for change in self.changes: + change.do(job_set) + done.append(change) + self.time = time.time() + except Exception: + for change in done: + change.undo() + raise + + +def undo(self, job_set=taskhandle.NullJobSet()): + try: + done = [] + for change in reversed(self.changes): + change.undo(job_set) + done.append(change) + except Exception: + for change in done: + change.do() + raise + + +def add_change(self, change): + self.changes.append(change) + + +def get_description(self): + result = [str(self) + ":\n\n\n"] + for change in self.changes: + result.append(change.get_description()) + result.append("\n") + return "".join(result) + + +def __str__(self): + if self.time is not None: + date = datetime.datetime.fromtimestamp(self.time) + if date.date() == datetime.date.today(): + string_date = "today" + elif date.date() == (datetime.date.today() - datetime.timedelta(1)): + string_date = "yesterday" + elif date.year == datetime.date.today().year: + string_date = date.strftime("%b %d") + else: + string_date = date.strftime("%d %b, %Y") + string_time = date.strftime("%H:%M:%S") + string_time = "{} {} ".format(string_date, string_time) + return self.description + " - " + string_time + return self.description + + +def __init__(self, args, scope): + self.args = args + self.scope = scope + self.instance = None + + +def get_changed_resources(self): + result = set() + for change in self.changes: + result.update(change.get_changed_resources()) + return result + + + +def _handle_job_set(function): + """A decorator for handling `taskhandle.JobSet` + + A decorator for handling `taskhandle.JobSet` for `do` and `undo` + methods of `Change`. + """ + + @others + return call + + + +def call(self, job_set=taskhandle.NullJobSet()): + job_set.started_job(str(self)) + function(self) + job_set.finished_job() + + +class ChangeContents(Change): + """A class to change the contents of a file + + Fields: + + * `resource`: The `rope.base.resources.File` to change + * `new_contents`: What to write in the file + """ + + @others + +def __init__(self, resource, new_contents, old_contents=None): + self.resource = resource + # IDEA: Only saving diffs; possible problems when undo/redoing + self.new_contents = new_contents + self.old_contents = old_contents + + +@_handle_job_set +def do(self): + if self.old_contents is None: + self.old_contents = self.resource.read() + self._operations.write_file(self.resource, self.new_contents) + + +@_handle_job_set +def undo(self): + if self.old_contents is None: + raise exceptions.HistoryError("Undoing a change that is not performed yet!") + self._operations.write_file(self.resource, self.old_contents) + + +def __str__(self): + return "Change <%s>" % self.resource.path + + +def get_description(self): + new = self.new_contents + old = self.old_contents + if old is None: + if self.resource.exists(): + old = self.resource.read() + else: + old = "" + result = difflib.unified_diff( + old.splitlines(True), + new.splitlines(True), + "a/" + self.resource.path, + "b/" + self.resource.path, + ) + return "".join(list(result)) + + +def get_changed_resources(self): + return [self.resource] + + + +def get_arguments(self, parameters): + result = [] + for pyname in self.get_pynames(parameters): + if pyname is None: + result.append(None) + else: + result.append(pyname.get_object()) + return result + + +class MoveResource(Change): + """Move a resource to a new location + + Fields: + + * `resource`: The `rope.base.resources.Resource` to move + * `new_resource`: The destination for move; It is the moved + resource not the folder containing that resource. + """ + + @others + +def __init__(self, resource, new_location, exact=False): + self.project = resource.project + self.resource = resource + if not exact: + new_location = _get_destination_for_move(resource, new_location) + if resource.is_folder(): + self.new_resource = self.project.get_folder(new_location) + else: + self.new_resource = self.project.get_file(new_location) + + +@_handle_job_set +def do(self): + self._operations.move(self.resource, self.new_resource) + + +@_handle_job_set +def undo(self): + self._operations.move(self.new_resource, self.resource) + + +def __str__(self): + return "Move <%s>" % self.resource.path + + +def get_description(self): + return "rename from {}\nrename to {}".format( + self.resource.path, + self.new_resource.path, + ) + + +def get_changed_resources(self): + return [self.resource, self.new_resource] + + + +class CreateResource(Change): + """A class to create a resource + + Fields: + + * `resource`: The resource to create + """ + + @others + +def __init__(self, resource): + self.resource = resource + + +@_handle_job_set +def do(self): + self._operations.create(self.resource) + + +def get_pynames(self, parameters): + result = [None] * max(len(parameters), len(self.args)) + for index, arg in enumerate(self.args): + if isinstance(arg, ast.keyword) and arg.arg in parameters: + result[parameters.index(arg.arg)] = self._evaluate(arg.value) + else: + result[index] = self._evaluate(arg) + return result + + +@_handle_job_set +def undo(self): + self._operations.remove(self.resource) + + +def __str__(self): + return "Create Resource <%s>" % (self.resource.path) + + +def get_description(self): + return "new file %s" % (self.resource.path) + + +def get_changed_resources(self): + return [self.resource] + + +def _get_child_path(self, parent, name): + if parent.path == "": + return name + else: + return parent.path + "/" + name + + + +class CreateFolder(CreateResource): + """A class to create a folder + + See docs for `CreateResource`. + """ + + @others + +def __init__(self, parent, name): + resource = parent.project.get_folder(self._get_child_path(parent, name)) + super().__init__(resource) + + + +class CreateFile(CreateResource): + """A class to create a file + + See docs for `CreateResource`. + """ + + @others + +def __init__(self, parent, name): + resource = parent.project.get_file(self._get_child_path(parent, name)) + super().__init__(resource) + + + +class RemoveResource(Change): + """A class to remove a resource + + Fields: + + * `resource`: The resource to be removed + """ + + @others + +def get_instance_pyname(self): + if self.args: + return self._evaluate(self.args[0]) + + +def __init__(self, resource): + self.resource = resource + + +@_handle_job_set +def do(self): + self._operations.remove(self.resource) + + +# TODO: Undoing remove operations +@_handle_job_set +def undo(self): + raise NotImplementedError("Undoing `RemoveResource` is not implemented yet.") + + +def __str__(self): + return "Remove <%s>" % (self.resource.path) + + +def get_changed_resources(self): + return [self.resource] + + + +def count_changes(change): + """Counts the number of basic changes a `Change` will make""" + if isinstance(change, ChangeSet): + result = 0 + for child in change.changes: + result += count_changes(child) + return result + return 1 + + + +def create_job_set(task_handle, change): + return task_handle.create_jobset(str(change), count_changes(change)) + + + +class _ResourceOperations: + @others + +def __init__(self, project): + self.project = project + self.fscommands = project.fscommands + self.direct_commands = rope.base.fscommands.FileSystemCommands() + + +def _get_fscommands(self, resource): + if self.project.is_ignored(resource): + return self.direct_commands + return self.fscommands + + +def _evaluate(self, ast_node): + return rope.base.evaluate.eval_node(self.scope, ast_node) + + + +def write_file(self, resource, contents: Union[str, FileContent]): + data: FileContent + if not isinstance(contents, bytes): + data = rope.base.fscommands.unicode_to_file_data( + contents, + newlines=resource.newlines, + ) + else: + data = contents + fscommands = self._get_fscommands(resource) + fscommands.write(resource.real_path, data) + for observer in list(self.project.observers): + observer.resource_changed(resource) + + +def move(self, resource, new_resource): + fscommands = self._get_fscommands(resource) + fscommands.move(resource.real_path, new_resource.real_path) + for observer in list(self.project.observers): + observer.resource_moved(resource, new_resource) + + +def create(self, resource): + if resource.is_folder(): + self._create_resource(resource.path, kind="folder") + else: + self._create_resource(resource.path) + for observer in list(self.project.observers): + observer.resource_created(resource) + + +def remove(self, resource): + fscommands = self._get_fscommands(resource) + fscommands.remove(resource.real_path) + for observer in list(self.project.observers): + observer.resource_removed(resource) + + +def _create_resource(self, file_name, kind="file"): + resource_path = self.project._get_resource_path(file_name) + if os.path.exists(resource_path): + raise exceptions.RopeError("Resource <%s> already exists" % resource_path) + resource = self.project.get_file(file_name) + if not resource.parent.exists(): + raise exceptions.ResourceNotFoundError( + "Parent folder of <%s> does not exist" % resource.path + ) + fscommands = self._get_fscommands(resource) + try: + if kind == "file": + fscommands.create_file(resource_path) + else: + fscommands.create_folder(resource_path) + except OSError as e: + raise exceptions.RopeError(e) + + + +def _get_destination_for_move(resource, destination): + dest_path = resource.project._get_resource_path(destination) + if os.path.isdir(dest_path): + if destination != "": + return destination + "/" + resource.name + else: + return resource.name + return destination + + + +class ChangeToData: + @others + +def convertChangeSet(self, change): + description = change.description + changes = [self(child) for child in change.changes] + return (description, changes, change.time) + + +def convertChangeContents(self, change): + return (change.resource.path, change.new_contents, change.old_contents) + + +def convertMoveResource(self, change): + return (change.resource.path, change.new_resource.path) + + +def create_arguments(primary, pyfunction, call_node, scope): + """A factory for creating `Arguments`""" + args = list(call_node.args) + args.extend(call_node.keywords) + called = call_node.func + # XXX: Handle constructors + if _is_method_call(primary, pyfunction) and isinstance(called, ast.Attribute): + args.insert(0, called.value) + return Arguments(args, scope) + + + +def convertCreateResource(self, change): + return (change.resource.path, change.resource.is_folder()) + + +def convertRemoveResource(self, change): + return (change.resource.path, change.resource.is_folder()) + + +def __call__(self, change): + change_type = type(change) + if change_type in (CreateFolder, CreateFile): + change_type = CreateResource + method = getattr(self, "convert" + change_type.__name__) + return (change_type.__name__, method(change)) + + + +class DataToChange: + @others + +def __init__(self, project): + self.project = project + + +def makeChangeSet(self, description, changes, time=None): + result = ChangeSet(description, time) + for child in changes: + result.add_change(self(child)) + return result + + +def makeChangeContents(self, path, new_contents, old_contents): + resource = self.project.get_file(path) + return ChangeContents(resource, new_contents, old_contents) + + +def makeMoveResource(self, old_path, new_path): + resource = self.project.get_file(old_path) + return MoveResource(resource, new_path, exact=True) + + +def makeCreateResource(self, path, is_folder): + if is_folder: + resource = self.project.get_folder(path) + else: + resource = self.project.get_file(path) + return CreateResource(resource) + + +def makeRemoveResource(self, path, is_folder): + if is_folder: + resource = self.project.get_folder(path) + else: + resource = self.project.get_file(path) + return RemoveResource(resource) + + +class ObjectArguments: + @others + +def __call__(self, data): + method = getattr(self, "make" + data[0]) + return method(*data[1]) + +@path C:/Repos/ekr-rope/rope/base/ +import bisect +import re +import token +import tokenize + + +@others +@language python +@tabwidth -4 + +class ChangeCollector: + @others + +def __init__(self, text): + self.text = text + self.changes = [] + + +def add_change(self, start, end, new_text=None): + if new_text is None: + new_text = self.text[start:end] + self.changes.append((start, end, new_text)) + + +def get_changed(self): + if not self.changes: + return None + + self.changes.sort(key=lambda x: x[:2]) + pieces = [] + last_changed = 0 + for change in self.changes: + start, end, text = change + pieces.append(self.text[last_changed:start] + text) + last_changed = end + if last_changed < len(self.text): + pieces.append(self.text[last_changed:]) + result = "".join(pieces) + if result != self.text: + return result + + + +class SourceLinesAdapter: + """Adapts source to Lines interface + + Note: The creation of this class is expensive. + """ + + @others + +def __init__(self, source_code): + self.code = source_code + self.starts = None + self._initialize_line_starts() + + +def _initialize_line_starts(self): + self.starts = [] + self.starts.append(0) + try: + i = 0 + while True: + i = self.code.index("\n", i) + 1 + self.starts.append(i) + except ValueError: + pass + self.starts.append(len(self.code) + 1) + + +def get_line(self, lineno): + return self.code[self.starts[lineno - 1] : self.starts[lineno] - 1] + + +def __init__(self, pynames): + self.pynames = pynames + + +def length(self): + return len(self.starts) - 1 + + +def get_line_number(self, offset): + return bisect.bisect(self.starts, offset) + + +def get_line_start(self, lineno): + return self.starts[lineno - 1] + + +def get_line_end(self, lineno): + return self.starts[lineno] - 1 + + + +class ArrayLinesAdapter: + @others + +def __init__(self, lines): + self.lines = lines + + +def get_line(self, line_number): + return self.lines[line_number - 1] + + +def length(self): + return len(self.lines) + + + +class LinesToReadline: + @others + +def __init__(self, lines, start): + self.lines = lines + self.current = start + + +def get_arguments(self, parameters): + result = [] + for pyname in self.pynames: + if pyname is None: + result.append(None) + else: + result.append(pyname.get_object()) + return result + + +def readline(self): + if self.current <= self.lines.length(): + self.current += 1 + return self.lines.get_line(self.current - 1) + "\n" + return "" + + +def __call__(self): + return self.readline() + + + +class _CustomGenerator: + @others + +def __init__(self, lines): + self.lines = lines + self.in_string = "" + self.open_count = 0 + self.continuation = False + + +def __call__(self): + size = self.lines.length() + result = [] + i = 1 + while i <= size: + while i <= size and not self.lines.get_line(i).strip(): + i += 1 + if i <= size: + start = i + while True: + line = self.lines.get_line(i) + self._analyze_line(line) + if ( + not (self.continuation or self.open_count or self.in_string) + or i == size + ): + break + i += 1 + result.append((start, i)) + i += 1 + return result + + +# Matches all backslashes before the token, to detect escaped quotes +_main_tokens = re.compile(r'(\\*)((\'\'\'|"""|\'|")|#|\[|\]|\{|\}|\(|\))') + + +def _analyze_line(self, line): + token = None + for match in self._main_tokens.finditer(line): + prefix = match.group(1) + token = match.group(2) + # Skip any tokens which are escaped + if len(prefix) % 2 == 1: + continue + if token in ["'''", '"""', "'", '"']: + if not self.in_string: + self.in_string = token + elif self.in_string == token or ( + self.in_string in ['"', "'"] and token == 3 * self.in_string + ): + self.in_string = "" + if self.in_string: + continue + if token == "#": + break + if token in "([{": + self.open_count += 1 + elif token in ")]}": + self.open_count -= 1 + if line and token != "#" and line.endswith("\\"): + self.continuation = True + else: + self.continuation = False + + + +def custom_generator(lines): + return _CustomGenerator(lines)() + + + +class LogicalLineFinder: + @others + +def __init__(self, lines): + self.lines = lines + + +def get_pynames(self, parameters): + return self.pynames + + +def logical_line_in(self, line_number): + indents = count_line_indents(self.lines.get_line(line_number)) + tries = 0 + while True: + block_start = get_block_start(self.lines, line_number, indents) + try: + return self._block_logical_line(block_start, line_number) + except IndentationError as e: + tries += 1 + if tries == 5: + raise e + lineno = e.lineno + block_start - 1 + indents = count_line_indents(self.lines.get_line(lineno)) + + +def generate_starts(self, start_line=1, end_line=None): + for start, end in self.generate_regions(start_line, end_line): + yield start + + +def generate_regions(self, start_line=1, end_line=None): + # XXX: `block_start` should be at a better position! + block_start = 1 + readline = LinesToReadline(self.lines, block_start) + try: + for start, end in self._logical_lines(readline): + real_start = start + block_start - 1 + real_start = self._first_non_blank(real_start) + if end_line is not None and real_start >= end_line: + break + real_end = end + block_start - 1 + if real_start >= start_line: + yield (real_start, real_end) + except tokenize.TokenError: + pass + + +def _block_logical_line(self, block_start, line_number): + readline = LinesToReadline(self.lines, block_start) + shifted = line_number - block_start + 1 + region = self._calculate_logical(readline, shifted) + start = self._first_non_blank(region[0] + block_start - 1) + if region[1] is None: + end = self.lines.length() + else: + end = region[1] + block_start - 1 + return start, end + + +def _calculate_logical(self, readline, line_number): + last_end = 1 + try: + for start, end in self._logical_lines(readline): + if line_number <= end: + return (start, end) + last_end = end + 1 + except tokenize.TokenError as e: + current = e.args[1][0] + return (last_end, max(last_end, current - 1)) + return (last_end, None) + + +def _logical_lines(self, readline): + last_end = 1 + for current_token in tokenize.generate_tokens(readline): + current = current_token[2][0] + if current_token[0] == token.NEWLINE: + yield (last_end, current) + last_end = current + 1 + + +def _first_non_blank(self, line_number): + current = line_number + while current < self.lines.length(): + line = self.lines.get_line(current).strip() + if line and not line.startswith("#"): + return current + current += 1 + return current + + + +def tokenizer_generator(lines): + return LogicalLineFinder(lines).generate_regions() + + + +class CachingLogicalLineFinder: + @others + +def __init__(self, lines, generate=custom_generator): + self.lines = lines + self._generate = generate + + +def get_instance_pyname(self): + return self.pynames[0] + + + +_starts = None + + +@property +def starts(self): + if self._starts is None: + self._init_logicals() + return self._starts + + +_ends = None + + +@property +def ends(self): + if self._ends is None: + self._init_logicals() + return self._ends + + +def _init_logicals(self): + """Should initialize _starts and _ends attributes""" + size = self.lines.length() + 1 + self._starts = [None] * size + self._ends = [None] * size + for start, end in self._generate(self.lines): + self._starts[start] = True + self._ends[end] = True + + +def logical_line_in(self, line_number): + start = line_number + while start > 0 and not self.starts[start]: + start -= 1 + if start == 0: + try: + start = self.starts.index(True, line_number) + except ValueError: + return (line_number, line_number) + return (start, self.ends.index(True, start)) + + +def generate_starts(self, start_line=1, end_line=None): + if end_line is None: + end_line = self.lines.length() + for index in range(start_line, end_line): + if self.starts[index]: + yield index + + + +def get_block_start(lines, lineno, maximum_indents=80): + """Approximate block start""" + pattern = get_block_start_patterns() + for i in range(lineno, 0, -1): + match = pattern.search(lines.get_line(i)) + if ( + match is not None + and count_line_indents(lines.get_line(i)) <= maximum_indents + ): + striped = match.string.lstrip() + # Maybe we're in a list comprehension or generator expression + if i > 1 and striped.startswith("if") or striped.startswith("for"): + bracs = 0 + for j in range(i, min(i + 5, lines.length() + 1)): + for c in lines.get_line(j): + if c == "#": + break + if c in "[(": + bracs += 1 + if c in ")]": + bracs -= 1 + if bracs < 0: + break + if bracs < 0: + break + if bracs < 0: + continue + return i + return 1 + + + +_block_start_pattern = None + + + +def get_block_start_patterns(): + global _block_start_pattern + if not _block_start_pattern: + pattern = ( + "^\\s*(((def|class|if|elif|except|for|while|with)\\s)|" + "((try|else|finally|except)\\s*:))" + ) + _block_start_pattern = re.compile(pattern, re.M) + return _block_start_pattern + + + +class MixedArguments: + @others + +def count_line_indents(line): + indents = 0 + for char in line: + if char == " ": + indents += 1 + elif char == "\t": + indents += 8 + else: + return indents + return 0 + + + +def get_string_pattern_with_prefix(prefix, prefix_group_name=None): + longstr = r'"""(\\.|"(?!"")|\\\n|[^"\\])*"""' + shortstr = r'"(\\.|\\\n|[^"\\\n])*"' + if prefix_group_name is not None: + pattern = "(?P<%s>%%s)(%%s)" % prefix_group_name + else: + pattern = "%s(%s)" + return pattern % ( + prefix, + "|".join( + [ + longstr, + longstr.replace('"', "'"), + shortstr, + shortstr.replace('"', "'"), + ] + ), + ) + + + +def get_string_pattern(): + prefix = r"(?<![fF])(\b[uUbB]?[rR]?)?" + return get_string_pattern_with_prefix(prefix) + + + +def get_formatted_string_pattern(): + prefix = r"(\b[rR]?[fF]|[fF][rR]?)" + return get_string_pattern_with_prefix(prefix) + + + +def get_any_string_pattern(): + prefix = r"[bBfFrRuU]{,4}" + return get_string_pattern_with_prefix( + prefix, + prefix_group_name="prefix", + ) + + + +def get_comment_pattern(): + return r"#[^\n]*" + +@path C:/Repos/ekr-rope/rope/base/ +from operator import itemgetter +from typing import Optional, Tuple + +import rope.base.builtins +import rope.base.pynames +import rope.base.pyobjects +from rope.base import ( + ast, + astutils, + exceptions, + pyobjects, + pyobjectsdef, + arguments, + worder, +) + + +BadIdentifierError = exceptions.BadIdentifierError + + +@others +@language python +@tabwidth -4 + +def eval_location(pymodule, offset): + """Find the pyname at the offset""" + return eval_location2(pymodule, offset)[1] + + + +def eval_location2(pymodule, offset): + """Find the primary and pyname at offset""" + pyname_finder = ScopeNameFinder(pymodule) + return pyname_finder.get_primary_and_pyname_at(offset) + + + +def eval_node(scope, node): + """Evaluate a `ast.AST` node and return a PyName + + Return `None` if the expression cannot be evaluated. + """ + return eval_node2(scope, node)[1] + + + +def __init__(self, pyname, arguments, scope): + """`argumens` is an instance of `Arguments`""" + self.pyname = pyname + self.args = arguments + + +def eval_node2(scope, node): + evaluator = StatementEvaluator(scope) + ast.walk(node, evaluator) + return evaluator.old_result, evaluator.result + + + +def eval_str(holding_scope, name): + return eval_str2(holding_scope, name)[1] + + + +def eval_str2(holding_scope, name): + try: + # parenthesizing for handling cases like 'a_var.\nattr' + node = ast.parse("(%s)" % name) + except SyntaxError: + raise BadIdentifierError("Not a resolvable python identifier selected.") + return eval_node2(holding_scope, node) + + + +class ScopeNameFinder: + @others + +def __init__(self, pymodule): + self.module_scope = pymodule.get_scope() + self.lines = pymodule.lines + self.worder = worder.Worder(pymodule.source_code, True) + + +def _is_defined_in_class_body(self, holding_scope, offset, lineno): + if ( + lineno == holding_scope.get_start() + and holding_scope.parent is not None + and holding_scope.parent.get_kind() == "Class" + and self.worder.is_a_class_or_function_name_in_header(offset) + ): + return True + if ( + lineno != holding_scope.get_start() + and holding_scope.get_kind() == "Class" + and self.worder.is_name_assigned_in_class_body(offset) + ): + return True + return False + + +def _is_function_name_in_function_header(self, scope, offset, lineno): + return ( + scope.get_start() <= lineno <= scope.get_body_start() + and scope.get_kind() == "Function" + and self.worder.is_a_class_or_function_name_in_header(offset) + ) + + +def get_pyname_at(self, offset): + return self.get_primary_and_pyname_at(offset)[1] + + +def get_primary_and_pyname_at( + self, + offset: int, +) -> Tuple[Optional[rope.base.pynames.PyName], Optional[rope.base.pynames.PyName]]: + lineno = self.lines.get_line_number(offset) + holding_scope = self.module_scope.get_inner_scope_for_offset(offset) + # function keyword parameter + if self.worder.is_function_keyword_parameter(offset): + keyword_name = self.worder.get_word_at(offset) + pyobject = self.get_enclosing_function(offset) + if isinstance(pyobject, pyobjectsdef.PyFunction): + parameter_name = pyobject.get_parameters().get(keyword_name, None) + return (None, parameter_name) + elif isinstance(pyobject, pyobjects.AbstractFunction): + parameter_name = rope.base.pynames.ParameterName() + return (None, parameter_name) + # class body + if self._is_defined_in_class_body(holding_scope, offset, lineno): + class_scope = holding_scope + if lineno == holding_scope.get_start(): + class_scope = holding_scope.parent + name = self.worder.get_primary_at(offset).strip() + try: + return (None, class_scope.pyobject[name]) + except rope.base.exceptions.AttributeNotFoundError: + return (None, None) + # function header + if self._is_function_name_in_function_header(holding_scope, offset, lineno): + name = self.worder.get_primary_at(offset).strip() + return (None, holding_scope.parent[name]) + # module in a from statement or an imported name that is aliased + if self.worder.is_from_statement_module( + offset + ) or self.worder.is_import_statement_aliased_module(offset): + module = self.worder.get_primary_at(offset) + module_pyname = self._find_module(module) + return (None, module_pyname) + if self.worder.is_from_aliased(offset): + name = self.worder.get_from_aliased(offset) + else: + name = self.worder.get_primary_at(offset) + return eval_str2(holding_scope, name) + + +def get_enclosing_function(self, offset): + function_parens = self.worder.find_parens_start_from_inside(offset) + try: + function_pyname = self.get_pyname_at(function_parens - 1) + except BadIdentifierError: + function_pyname = None + if function_pyname is not None: + pyobject = function_pyname.get_object() + if isinstance(pyobject, pyobjects.AbstractFunction): + return pyobject + elif ( + isinstance(pyobject, pyobjects.AbstractClass) and "__init__" in pyobject + ): + return pyobject["__init__"].get_object() + elif "__call__" in pyobject: + return pyobject["__call__"].get_object() + return None + + +def get_pynames(self, parameters): + return [self.pyname] + self.args.get_pynames(parameters[1:]) + + +def _find_module(self, module_name): + dots = 0 + while module_name[dots] == ".": + dots += 1 + return rope.base.pynames.ImportedModule( + self.module_scope.pyobject, module_name[dots:], dots + ) + + + +class StatementEvaluator: + @others + +def __init__(self, scope): + self.scope = scope + self.result = None + self.old_result = None + + +def _Name(self, node): + self.result = self.scope.lookup(node.id) + + +def _Attribute(self, node): + pyname = eval_node(self.scope, node.value) + if pyname is None: + pyname = rope.base.pynames.UnboundName() + self.old_result = pyname + if pyname.get_object() != rope.base.pyobjects.get_unknown(): + try: + self.result = pyname.get_object()[node.attr] + except exceptions.AttributeNotFoundError: + self.result = None + + +def _Call(self, node): + primary, pyobject = self._get_primary_and_object_for_node(node.func) + if pyobject is None: + return + + def _get_returned(pyobject): + args = arguments.create_arguments(primary, pyobject, node, self.scope) + return pyobject.get_returned_object(args) + + if isinstance(pyobject, rope.base.pyobjects.AbstractClass): + result = None + if "__new__" in pyobject: + new_function = pyobject["__new__"].get_object() + result = _get_returned(new_function) + if result is None or result == rope.base.pyobjects.get_unknown(): + result = rope.base.pyobjects.PyObject(pyobject) + self.result = rope.base.pynames.UnboundName(pyobject=result) + return + + pyfunction = None + if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): + pyfunction = pyobject + elif "__call__" in pyobject: + pyfunction = pyobject["__call__"].get_object() + if pyfunction is not None: + self.result = rope.base.pynames.UnboundName( + pyobject=_get_returned(pyfunction) + ) + + +def _Str(self, node): + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_str() + ) + + +def _Num(self, node): + type_name = type(node.n).__name__ + self.result = self._get_builtin_name(type_name) + + +def _Constant(self, node): + type_name = type(node.n).__name__ + try: + self.result = self._get_builtin_name(type_name) + except exceptions.AttributeNotFoundError: + # XXX: Right way to fix this is to add missing NoneType to builtins? + pass + + +def _get_builtin_name(self, type_name): + pytype = rope.base.builtins.builtins[type_name].get_object() + return rope.base.pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) + + +def get_arguments(self, parameters): + result = [] + for pyname in self.get_pynames(parameters): + if pyname is None: + result.append(None) + else: + result.append(pyname.get_object()) + return result + + +def _BinOp(self, node): + self.result = rope.base.pynames.UnboundName( + self._get_object_for_node(node.left) + ) + + +def _BoolOp(self, node): + pyobject = self._get_object_for_node(node.values[0]) + if pyobject is None: + pyobject = self._get_object_for_node(node.values[1]) + self.result = rope.base.pynames.UnboundName(pyobject) + + +def _Repr(self, node): + self.result = self._get_builtin_name("str") + + +def _UnaryOp(self, node): + self.result = rope.base.pynames.UnboundName( + self._get_object_for_node(node.operand) + ) + + +def _Compare(self, node): + self.result = self._get_builtin_name("bool") + + +def _Dict(self, node): + keys = None + values = None + if node.keys and node.keys[0]: + keys, values = next( + iter(filter(itemgetter(0), zip(node.keys, node.values))), (None, None) + ) + if keys: + keys = self._get_object_for_node(keys) + if values: + values = self._get_object_for_node(values) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_dict(keys, values) + ) + + +def _List(self, node): + holding = None + if node.elts: + holding = self._get_object_for_node(node.elts[0]) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_list(holding) + ) + + +def _ListComp(self, node): + pyobject = self._what_does_comprehension_hold(node) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_list(pyobject) + ) + + +def _GeneratorExp(self, node): + pyobject = self._what_does_comprehension_hold(node) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_iterator(pyobject) + ) + + +def _what_does_comprehension_hold(self, node): + scope = self._make_comprehension_scope(node) + pyname = eval_node(scope, node.elt) + return pyname.get_object() if pyname is not None else None + + +def get_instance_pyname(self): + return self.pyname + + + +def _make_comprehension_scope(self, node): + scope = self.scope + module = scope.pyobject.get_module() + names = {} + for comp in node.generators: + new_names = _get_evaluated_names( + comp.target, comp.iter, module, ".__iter__().next()", node.lineno + ) + names.update(new_names) + return rope.base.pyscopes.TemporaryScope(scope.pycore, scope, names) + + +def _Tuple(self, node): + objects = [] + if len(node.elts) < 4: + for stmt in node.elts: + pyobject = self._get_object_for_node(stmt) + objects.append(pyobject) + else: + objects.append(self._get_object_for_node(node.elts[0])) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_tuple(*objects) + ) + + +def _get_object_for_node(self, stmt): + pyname = eval_node(self.scope, stmt) + pyobject = None + if pyname is not None: + pyobject = pyname.get_object() + return pyobject + + +def _get_primary_and_object_for_node(self, stmt): + primary, pyname = eval_node2(self.scope, stmt) + pyobject = None + if pyname is not None: + pyobject = pyname.get_object() + return primary, pyobject + + +def _Subscript(self, node): + if isinstance(node.slice, ast.Index): + self._call_function(node.value, "__getitem__", [node.slice.value]) + elif isinstance(node.slice, ast.Slice): + self._call_function(node.value, "__getitem__", [node.slice]) + elif isinstance(node.slice, ast.expr): + self._call_function(node.value, "__getitem__", [node.value]) + + +def _Slice(self, node): + self.result = self._get_builtin_name("slice") + + +def _call_function(self, node, function_name, other_args=None): + pyname = eval_node(self.scope, node) + if pyname is not None: + pyobject = pyname.get_object() + else: + return + if function_name in pyobject: + called = pyobject[function_name].get_object() + if not called or not isinstance(called, pyobjects.AbstractFunction): + return + args = [node] + if other_args: + args += other_args + arguments_ = arguments.Arguments(args, self.scope) + self.result = rope.base.pynames.UnboundName( + pyobject=called.get_returned_object(arguments_) + ) + + +def _Lambda(self, node): + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.Lambda(node, self.scope) + ) + + + +def _get_evaluated_names(targets, assigned, module, evaluation, lineno): + result = {} + for name, levels in astutils.get_name_levels(targets): + assignment = rope.base.pynames.AssignmentValue(assigned, levels, evaluation) + # XXX: this module should not access `rope.base.pynamesdef`! + pyname = rope.base.pynamesdef.AssignedName(lineno, module) + pyname.assignments.append(assignment) + result[name] = pyname + return result + +@path C:/Repos/ekr-rope/rope/base/ +@others +@language python +@tabwidth -4 + +def _is_method_call(primary, pyfunction): + if primary is None: + return False + pyobject = primary.get_object() + if ( + isinstance(pyobject.get_type(), rope.base.pyobjects.PyClass) + and isinstance(pyfunction, rope.base.pyobjects.PyFunction) + and isinstance(pyfunction.parent, rope.base.pyobjects.PyClass) + ): + return True + if isinstance( + pyobject.get_type(), rope.base.pyobjects.AbstractClass + ) and isinstance(pyfunction, rope.base.builtins.BuiltinFunction): + return True + return False + +class RopeError(Exception): + """Base exception for rope""" + + + +class ResourceNotFoundError(RopeError): + """Resource not found exception""" + + + +class RefactoringError(RopeError): + """Errors for performing a refactoring""" + + + +class InterruptedTaskError(RopeError): + """The task has been interrupted""" + + + +class HistoryError(RopeError): + """Errors for history undo/redo operations""" + + + +class ModuleNotFoundError(RopeError): + """Module not found exception""" + + + +class AttributeNotFoundError(RopeError): + """Attribute not found exception""" + + + +class NameNotFoundError(RopeError): + """Name not found exception""" + + + +class BadIdentifierError(RopeError): + """The name cannot be resolved""" + + + +class ModuleSyntaxError(RopeError): + """Module has syntax errors + + The `filename` and `lineno` fields indicate where the error has + occurred. + + """ + + @others + +def __init__(self, filename, lineno, message): + self.filename = filename + self.lineno = lineno + self.message_ = message + super().__init__( + "Syntax error in file <{}> line <{}>: {}".format(filename, lineno, message) + ) + + + +class ModuleDecodeError(RopeError): + """Cannot decode module""" + + def __init__(self, filename, message): + self.filename = filename + self.message_ = message + super().__init__("Cannot decode file <{}>: {}".format(filename, message)) + +@path C:/Repos/ekr-rope/rope/base/ +"""Project file system commands. + +This modules implements file system operations used by rope. Different +version control systems can be supported by implementing the interface +provided by `FileSystemCommands` class. See `SubversionCommands` and +`MercurialCommands` for example. + +""" +import re +import os +import shutil +import subprocess +import typing + + +FileContent = typing.NewType("FileContent", bytes) + + +@others +@language python +@tabwidth -4 + +def create_fscommands(root): + dirlist = os.listdir(root) + commands = { + ".hg": MercurialCommands, + ".svn": SubversionCommands, + ".git": GITCommands, + "_svn": SubversionCommands, + "_darcs": DarcsCommands, + } + for key in commands: + if key in dirlist: + try: + return commands[key](root) + except (ImportError, OSError): + pass + return FileSystemCommands() + + + +class FileSystemCommands: + @others + +def create_file(self, path): + open(path, "w").close() + + +def create_folder(self, path): + os.mkdir(path) + + +def move(self, path, new_location): + shutil.move(path, new_location) + + +def remove(self, path): + if os.path.isfile(path): + os.remove(path) + else: + shutil.rmtree(path) + + +def write(self, path, data): + file_ = open(path, "wb") + try: + file_.write(data) + finally: + file_.close() + + +def read(self, path): + with open(path, "rb") as handle: + return handle.read() + + + +class SubversionCommands: + @others + +def __init__(self, *args): + self.normal_actions = FileSystemCommands() + import pysvn + + self.client = pysvn.Client() + + +def create_file(self, path): + self.normal_actions.create_file(path) + self.client.add(path, force=True) + + +def create_folder(self, path): + self.normal_actions.create_folder(path) + self.client.add(path, force=True) + + +def move(self, path, new_location): + self.client.move(path, new_location, force=True) + + +def remove(self, path): + self.client.remove(path, force=True) + + +def write(self, path, data): + self.normal_actions.write(path, data) + + +def read(self, path): + return self.normal_actions.read(path) + + + +class MercurialCommands: + @others + +def __init__(self, root): + self.hg = self._import_mercurial() + self.normal_actions = FileSystemCommands() + try: + self.ui = self.hg.ui.ui( + verbose=False, + debug=False, + quiet=True, + interactive=False, + traceback=False, + report_untrusted=False, + ) + except: + self.ui = self.hg.ui.ui() + self.ui.setconfig("ui", "interactive", "no") + self.ui.setconfig("ui", "debug", "no") + self.ui.setconfig("ui", "traceback", "no") + self.ui.setconfig("ui", "verbose", "no") + self.ui.setconfig("ui", "report_untrusted", "no") + self.ui.setconfig("ui", "quiet", "yes") + + self.repo = self.hg.hg.repository(self.ui, root) + + +def _import_mercurial(self): + import mercurial.commands + import mercurial.hg + import mercurial.ui + + return mercurial + + +def create_file(self, path): + self.normal_actions.create_file(path) + self.hg.commands.add(self.ui, self.repo, path) + + +def create_folder(self, path): + self.normal_actions.create_folder(path) + + +def move(self, path, new_location): + self.hg.commands.rename(self.ui, self.repo, path, new_location, after=False) + + +def remove(self, path): + self.hg.commands.remove(self.ui, self.repo, path) + + +def write(self, path, data): + self.normal_actions.write(path, data) + + +def read(self, path): + return self.normal_actions.read(path) + + + +class GITCommands: + @others + +def __init__(self, root): + self.root = root + self._do(["version"]) + self.normal_actions = FileSystemCommands() + + + +def create_file(self, path): + self.normal_actions.create_file(path) + self._do(["add", self._in_dir(path)]) + + +def create_folder(self, path): + self.normal_actions.create_folder(path) + + +def move(self, path, new_location): + self._do(["mv", self._in_dir(path), self._in_dir(new_location)]) + + +def remove(self, path): + self._do(["rm", self._in_dir(path)]) + + +def write(self, path, data): + # XXX: should we use ``git add``? + self.normal_actions.write(path, data) + + +def read(self, path): + return self.normal_actions.read(path) + + +def _do(self, args): + _execute(["git"] + args, cwd=self.root) + + +def _in_dir(self, path): + if path.startswith(self.root): + return path[len(self.root) + 1 :] + return self.root + + + +class DarcsCommands: + @others + +def __init__(self, root): + self.root = root + self.normal_actions = FileSystemCommands() + + +def create_file(self, path): + self.normal_actions.create_file(path) + self._do(["add", path]) + + +def create_folder(self, path): + self.normal_actions.create_folder(path) + self._do(["add", path]) + + +def move(self, path, new_location): + self._do(["mv", path, new_location]) + + +def remove(self, path): + self.normal_actions.remove(path) + + +def read(self, path): + return self.normal_actions.read(path) + + +def write(self, path, data): + self.normal_actions.write(path, data) + + +def _do(self, args): + _execute(["darcs"] + args, cwd=self.root) + + + +def _execute(args, cwd=None): + process = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE) + process.wait() + return process.returncode + + + +def unicode_to_file_data(contents: str, encoding=None, newlines=None) -> FileContent: + assert isinstance(contents, str) + if newlines and newlines != "\n": + contents = contents.replace("\n", newlines) + if encoding is None: + encoding = read_str_coding(contents) + if encoding is not None: + return FileContent(contents.encode(encoding)) + try: + return FileContent(contents.encode()) + except UnicodeEncodeError: + return FileContent(contents.encode("utf-8")) + + + +def file_data_to_unicode(data, encoding=None): + result = _decode_data(data, encoding) + newline = "\n" + if "\r\n" in result: + result = result.replace("\r\n", "\n") + newline = "\r\n" + if "\r" in result: + result = result.replace("\r", "\n") + newline = "\r" + return result, newline + + + +def _decode_data(data, encoding): + if isinstance(data, str): + return data + if encoding is None: + encoding = read_str_coding(data) + if encoding is None: + # there is no encoding tip, we need to guess. + # PEP263 says that "encoding not explicitly defined" means it is ascii, + # but we will use utf8 instead since utf8 fully covers ascii and btw is + # the only non-latin sane encoding. + encoding = "utf-8" + try: + return data.decode(encoding) + except (UnicodeError, LookupError): + # fallback to latin1: it should never fail + return data.decode("latin1") + + + +def read_str_coding(source): + # as defined by PEP-263 (https://www.python.org/dev/peps/pep-0263/) + CODING_LINE_PATTERN = b"^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)" + + if type(source) == bytes: + newline = b"\n" + CODING_LINE_PATTERN = re.compile(CODING_LINE_PATTERN) + else: + newline = "\n" + CODING_LINE_PATTERN = re.compile(CODING_LINE_PATTERN.decode("ascii")) + for line in source.split(newline, 2)[:2]: + if re.match(CODING_LINE_PATTERN, line): + return _find_coding(line) + else: + return + + + +def _find_coding(text): + if isinstance(text, str): + text = text.encode("utf-8") + coding = b"coding" + to_chr = chr + try: + start = text.index(coding) + len(coding) + if text[start] not in b"=:": + return + start += 1 + while start < len(text) and to_chr(text[start]).isspace(): + start += 1 + end = start + while end < len(text): + c = text[end] + if not to_chr(c).isalnum() and c not in b"-_": + break + end += 1 + result = text[start:end] + if isinstance(result, bytes): + result = result.decode("utf-8") + return result + except ValueError: + pass + +@path C:/Repos/ekr-rope/rope/base/ +@nopyflakes +from rope.base import exceptions, change, taskhandle + + +@others +@language python +@tabwidth -4 + +class History: + """A class that holds project history""" + + @others + +def __init__(self, project, maxundos=None): + self.project = project + self._undo_list = [] + self._redo_list = [] + self._maxundos = maxundos + self._load_history() + self.project.data_files.add_write_hook(self.write) + self.current_change = None + + +def _load_history(self): + if self.save: + result = self.project.data_files.read_data( + "history", compress=self.compress, import_=True + ) + if result is not None: + to_change = change.DataToChange(self.project) + for data in result[0]: + self._undo_list.append(to_change(data)) + for data in result[1]: + self._redo_list.append(to_change(data)) + + +def do(self, changes, task_handle=taskhandle.NullTaskHandle()): + """Perform the change and add it to the `self.undo_list` + + Note that uninteresting changes (changes to ignored files) + will not be appended to `self.undo_list`. + + """ + try: + self.current_change = changes + changes.do(change.create_job_set(task_handle, changes)) + finally: + self.current_change = None + if self._is_change_interesting(changes): + self.undo_list.append(changes) + self._remove_extra_items() + del self.redo_list[:] + + +def _remove_extra_items(self): + if len(self.undo_list) > self.max_undos: + del self.undo_list[0 : len(self.undo_list) - self.max_undos] + + +def _is_change_interesting(self, changes): + for resource in changes.get_changed_resources(): + if not self.project.is_ignored(resource): + return True + return False + + +def undo(self, change=None, drop=False, task_handle=taskhandle.NullTaskHandle()): + """Redo done changes from the history + + When `change` is `None`, the last done change will be undone. + If change is not `None` it should be an item from + `self.undo_list`; this change and all changes that depend on + it will be undone. In both cases the list of undone changes + will be returned. + + If `drop` is `True`, the undone change will not be appended to + the redo list. + + """ + if not self._undo_list: + raise exceptions.HistoryError("Undo list is empty") + if change is None: + change = self.undo_list[-1] + dependencies = self._find_dependencies(self.undo_list, change) + self._move_front(self.undo_list, dependencies) + self._perform_undos(len(dependencies), task_handle) + result = self.redo_list[-len(dependencies) :] + if drop: + del self.redo_list[-len(dependencies) :] + return result + + +def redo(self, change=None, task_handle=taskhandle.NullTaskHandle()): + """Redo undone changes from the history + + When `change` is `None`, the last undone change will be + redone. If change is not `None` it should be an item from + `self.redo_list`; this change and all changes that depend on + it will be redone. In both cases the list of redone changes + will be returned. + + """ + if not self.redo_list: + raise exceptions.HistoryError("Redo list is empty") + if change is None: + change = self.redo_list[-1] + dependencies = self._find_dependencies(self.redo_list, change) + self._move_front(self.redo_list, dependencies) + self._perform_redos(len(dependencies), task_handle) + return self.undo_list[-len(dependencies) :] + + +def _move_front(self, change_list, changes): + for change in changes: + change_list.remove(change) + change_list.append(change) + + +def _find_dependencies(self, change_list, change): + index = change_list.index(change) + return _FindChangeDependencies(change_list[index:])() + + +def _perform_undos(self, count, task_handle): + for i in range(count): + self.current_change = self.undo_list[-1] + try: + job_set = change.create_job_set(task_handle, self.current_change) + self.current_change.undo(job_set) + finally: + self.current_change = None + self.redo_list.append(self.undo_list.pop()) + + +def _perform_redos(self, count, task_handle): + for i in range(count): + self.current_change = self.redo_list[-1] + try: + job_set = change.create_job_set(task_handle, self.current_change) + self.current_change.do(job_set) + finally: + self.current_change = None + self.undo_list.append(self.redo_list.pop()) + + +def contents_before_current_change(self, file): + if self.current_change is None: + return None + result = self._search_for_change_contents([self.current_change], file) + if result is not None: + return result + if file.exists() and not file.is_folder(): + return file.read() + else: + return None + + +def _search_for_change_contents(self, change_list, file): + for change_ in reversed(change_list): + if isinstance(change_, change.ChangeSet): + result = self._search_for_change_contents(change_.changes, file) + if result is not None: + return result + if isinstance(change_, change.ChangeContents) and change_.resource == file: + return change_.old_contents + + +def write(self): + if self.save: + data = [] + to_data = change.ChangeToData() + self._remove_extra_items() + data.append([to_data(change_) for change_ in self.undo_list]) + data.append([to_data(change_) for change_ in self.redo_list]) + self.project.data_files.write_data("history", data, compress=self.compress) + + +def get_file_undo_list(self, resource): + return [ + change + for change in self.undo_list + if resource in change.get_changed_resources() + ] + + +def __str__(self): + return "History holds %s changes in memory" % ( + len(self.undo_list) + len(self.redo_list) + ) + + +undo_list = property(lambda self: self._undo_list) +redo_list = property(lambda self: self._redo_list) + + +@property +def tobe_undone(self): + """The last done change if available, `None` otherwise""" + if self.undo_list: + return self.undo_list[-1] + + +@property +def tobe_redone(self): + """The last undone change if available, `None` otherwise""" + if self.redo_list: + return self.redo_list[-1] + + +@property +def max_undos(self): + if self._maxundos is None: + return self.project.prefs.get("max_history_items", 100) + else: + return self._maxundos + + +@property +def save(self): + return self.project.prefs.get("save_history", False) + + +@property +def compress(self): + return self.project.prefs.get("compress_history", False) + + +def clear(self): + """Forget all undo and redo information""" + del self.undo_list[:] + del self.redo_list[:] + + + +class _FindChangeDependencies: + @others + +def __init__(self, change_list): + self.change = change_list[0] + self.change_list = change_list + self.changed_resources = set(self.change.get_changed_resources()) + + +def __call__(self): + result = [self.change] + for change in self.change_list[1:]: + if self._depends_on(change, result): + result.append(change) + self.changed_resources.update(change.get_changed_resources()) + return result + + +def _depends_on(self, changes, result): + for resource in changes.get_changed_resources(): + if resource is None: + continue + if resource in self.changed_resources: + return True + for changed in self.changed_resources: + if resource.is_folder() and resource.contains(changed): + return True + if changed.is_folder() and changed.contains(resource): + return True + return False + +@path C:/Repos/ekr-rope/rope/base/ +"""A few useful functions for using rope as a library""" +import os.path + +import rope.base.project +import rope.base.pycore +from rope.base import pyobjectsdef +from rope.base import utils +from rope.base import taskhandle + + +@others +@language python +@tabwidth -4 + +def path_to_resource(project, path, type=None): + """Get the resource at path + + You only need to specify `type` if `path` does not exist. It can + be either 'file' or 'folder'. If the type is `None` it is assumed + that the resource already exists. + + Note that this function uses `Project.get_resource()`, + `Project.get_file()`, and `Project.get_folder()` methods. + + """ + project_path = path_relative_to_project_root(project, path) + if project_path is None: + project_path = rope.base.project._realpath(path) + project = rope.base.project.get_no_project() + if type is None: + return project.get_resource(project_path) + if type == "file": + return project.get_file(project_path) + if type == "folder": + return project.get_folder(project_path) + return None + + + +def path_relative_to_project_root(project, path): + return relative(project.address, path) + + + +@utils.deprecated() +def relative(root, path): + root = rope.base.project._realpath(root).replace(os.path.sep, "/") + path = rope.base.project._realpath(path).replace(os.path.sep, "/") + if path == root: + return "" + if path.startswith(root + "/"): + return path[len(root) + 1 :] + + + +def report_change(project, path, old_content): + """Report that the contents of file at `path` was changed + + The new contents of file is retrieved by reading the file. + + """ + resource = path_to_resource(project, path) + if resource is None: + return + for observer in list(project.observers): + observer.resource_changed(resource) + if project.pycore.automatic_soa: + rope.base.pycore.perform_soa_on_changed_scopes(project, resource, old_content) + + + +def analyze_module(project, resource): + """Perform static object analysis on a python file in the project + + Note that this might be really time consuming. + """ + project.pycore.analyze_module(resource) + + + +def analyze_modules(project, task_handle=taskhandle.NullTaskHandle()): + """Perform static object analysis on all python files in the project + + Note that this might be really time consuming. + """ + resources = project.get_python_files() + job_set = task_handle.create_jobset("Analyzing Modules", len(resources)) + for resource in resources: + job_set.started_job(resource.path) + analyze_module(project, resource) + job_set.finished_job() + + + +def get_string_module(project, code, resource=None, force_errors=False): + """Returns a `PyObject` object for the given code + + If `force_errors` is `True`, `exceptions.ModuleSyntaxError` is + raised if module has syntax errors. This overrides + ``ignore_syntax_errors`` project config. + + """ + return pyobjectsdef.PyModule( + project.pycore, code, resource, force_errors=force_errors + ) + + + +def get_string_scope(project, code, resource=None): + """Returns a `Scope` object for the given code""" + return get_string_module(project, code, resource).get_scope() + + + +def is_python_file(project, resource): + return project.pycore.is_python_file(resource) + + + +def modname(resource): + if resource.is_folder(): + module_name = resource.name + source_folder = resource.parent + elif resource.name == "__init__.py": + module_name = resource.parent.name + source_folder = resource.parent.parent + else: + module_name = resource.name[:-3] + source_folder = resource.parent + + while source_folder != source_folder.parent and source_folder.has_child( + "__init__.py" + ): + module_name = source_folder.name + "." + module_name + source_folder = source_folder.parent + + return module_name + +@path C:/Repos/ekr-rope/rope/base/ +"""Rope preferences.""" +from dataclasses import asdict, dataclass +from textwrap import dedent +from typing import Any, Callable, Dict, List, Optional, Tuple + +from packaging.requirements import Requirement +from pytoolconfig import PyToolConfig, UniversalKey, field +from pytoolconfig.sources import Source +from rope.base.resources import Folder + + +@others +@language python +@tabwidth -4 + +@dataclass +class Prefs: + """Class to store rope preferences.""" + + ignored_resources: List[str] = field( + default_factory=lambda: [ + "*.pyc", + "*~", + ".ropeproject", + ".hg", + ".svn", + "_svn", + ".git", + ".tox", + ".venv", + "venv", + ".mypy_cache", + ".pytest_cache", + ], + description=dedent(""" + Specify which files and folders to ignore in the project. + Changes to ignored resources are not added to the history and + VCSs. Also they are not returned in `Project.get_files()`. + Note that ``?`` and ``*`` match all characters but slashes. + '*.pyc': matches 'test.pyc' and 'pkg/test.pyc' + 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc' + '.svn': matches 'pkg/.svn' and all of its children + 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o' + 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o' + """), + ) + python_files: List[str] = field( + default_factory=lambda: ["*.py"], + description=dedent(""" + Specifies which files should be considered python files. It is + useful when you have scripts inside your project. Only files + ending with ``.py`` are considered to be python files by + default. + """), + ) + source_folders: List[str] = field( + description=dedent(""" + Custom source folders: By default rope searches the project + for finding source folders (folders that should be searched + for finding modules). You can add paths to that list. Note + that rope guesses project source folders correctly most of the + time; use this if you have any problems. + The folders should be relative to project root and use '/' for + separating folders regardless of the platform rope is running on. + 'src/my_source_folder' for instance. + """), + default_factory=lambda: [], + ) + python_path: List[str] = field( + default_factory=lambda: [], + description="You can extend python path for looking up modules.", + ) + save_objectdb: bool = field( + default=False, description="Should rope save object information or not." + ) + compress_objectdb: bool = False + automatic_soa: bool = field( + True, "If `True`, rope analyzes each module when it is being saved." + ) + soa_followed_calls: int = field( + default=0, description="The depth of calls to follow in static object analysis" + ) + perform_doa: bool = field( + default=True, + description=dedent(""" + If `False` when running modules or unit tests 'dynamic object analysis' is turned off. + This makes them much faster. + """), + ) + validate_objectdb: bool = field( + default=False, + description="Rope can check the validity of its object DB when running.", + ) + + max_history_items: int = field(default=32, description="How many undos to hold?") + save_history: bool = field( + default=True, description="Shows whether to save history across sessions." + ) + compress_history: bool = False + + indent_size: int = field( + default=4, + description=dedent(""" + Set the number spaces used for indenting. According to + :PEP:`8`, it is best to use 4 spaces. Since most of rope's + unit-tests use 4 spaces it is more reliable, too. + """), + ) + + extension_modules: List[str] = field( + default_factory=list, + description=""" +Builtin and c-extension modules that are allowed to be imported and inspected by rope. + """, + ) + + import_dynload_stdmods: bool = field( + default=True, + description="Add all standard c-extensions to extension_modules list.", + ) + ignore_syntax_errors: bool = field( + default=False, + description=dedent(""" + If `True` modules with syntax errors are considered to be empty. + The default value is `False`; When `False` syntax errors raise + `rope.base.exceptions.ModuleSyntaxError` exception. + """), + ) + + ignore_bad_imports: bool = field( + default=False, + description=dedent(""" + If `True`, rope ignores unresolvable imports. Otherwise, they + appear in the importing namespace. + """), + ) + + prefer_module_from_imports: bool = field( + default=False, + description=dedent(""" + If `True`, rope will insert new module imports as `from <package> import <module>`by default. + """), + ) + + split_imports: bool = field( + default=False, + description=dedent(""" + If `True`, rope will transform a comma list of imports into + multiple separate import statements when organizing + imports. + """), + ) + + pull_imports_to_top: bool = field( + default=True, + description=dedent(""" + If `True`, rope will remove all top-level import statements and + reinsert them at the top of the module when making changes. + """), + ) + + sort_imports_alphabetically: bool = field( + default=False, + description=dedent(""" + If `True`, rope will sort imports alphabetically by module name instead + of alphabetically by import statement, with from imports after normal + imports. + """), + ) + type_hinting_factory: str = field( + "rope.base.oi.type_hinting.factory.default_type_hinting_factory", + description=dedent(""" + Location of implementation of + rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general + case, you don't have to change this value, unless you're an rope expert. + Change this value to inject you own implementations of interfaces + listed in module rope.base.oi.type_hinting.providers.interfaces + For example, you can add you own providers for Django Models, or disable + the search type-hinting in a class hierarchy, etc. + """), + ) + project_opened: Optional[Callable] = field( + None, + description=dedent(""" + This function is called after opening the project. + Can only be set in config.py. + """), + ) + py_version: Optional[Tuple[int, int]] = field( + default=None, + description="Minimum python version to target", + universal_config=UniversalKey.min_py_version, + ) + dependencies: Optional[List[Requirement]] = field( + default=None, universal_config=UniversalKey.dependencies + ) + callbacks: Dict[str, Callable[[Any], None]] = field( + default_factory=lambda: {}, + description=dedent(""" + Callbacks run when configuration values are changed. + Can only be set in config.py. + """), + ) + + @others + +def set(self, key: str, value: Any): + """Set the value of `key` preference to `value`.""" + if key in self.callbacks: + self.callbacks[key](value) + else: + setattr(self, key, value) + + +def add(self, key: str, value: Any): + """Add an entry to a list preference + + Add `value` to the list of entries for the `key` preference. + + """ + if getattr(self, key) is None: + self[key] = [] + getattr(self, key).append(value) + + +def get(self, key: str, default: Any = None): + """Get the value of the key preference""" + return getattr(self, key, default) + + +def add_callback(self, key: str, callback: Callable): + """Add `key` preference with `callback` function + + Whenever `key` is set the callback is called with the + given `value` as parameter. + + """ + self.callbacks[key] = callback + + +def __setitem__(self, key: str, value: Any): + self.set(key, value) + + +def __getitem__(self, key: str): + return self.get(key) + + + +class _RopeConfigSource(Source): + """Custom source for rope config.py files.""" + + name: str = "config.py" + run_globals: Dict + + @others + +def __init__(self, ropefolder: Folder): + self.ropefolder = ropefolder + self.run_globals = {} + + +def _read(self) -> bool: + if self.ropefolder is None or not self.ropefolder.has_child("config.py"): + return False + config = self.ropefolder.get_child("config.py") + self.run_globals.update( + { + "__name__": "__main__", + "__builtins__": __builtins__, + "__file__": config.real_path, + } + ) + with open(config.real_path) as f: + code = compile(f.read(),config.real_path, 'exec') + exec(code, self.run_globals) + return True + + +def parse(self) -> Optional[Dict]: + prefs = Prefs() + if not self._read(): + return None + if "set_prefs" in self.run_globals: + self.run_globals["set_prefs"](prefs) + if "project_opened" in self.run_globals: + prefs["project_opened"] = self.run_globals["project_opened"] + return asdict(prefs) + + + +def get_config(root: Folder, ropefolder: Folder) -> PyToolConfig: + custom_sources = [_RopeConfigSource(ropefolder)] + config = PyToolConfig( + "rope", + root.pathlib, + Prefs, + custom_sources=custom_sources, + bases=[".ropefolder"], + recursive=False, + global_config=True, + ) + return config + +@path C:/Repos/ekr-rope/rope/base/ +import os +import shutil +import sys +import warnings + +import rope.base.fscommands +import rope.base.resourceobserver as resourceobserver +from rope.base import exceptions, history, pycore, taskhandle, utils +from rope.base.exceptions import ModuleNotFoundError +from rope.base.prefs import Prefs, get_config +from rope.base.resources import File, Folder, _ResourceMatcher + +try: + import cPickle as pickle +except ImportError: + import pickle + + +@others +@language python +@tabwidth -4 + +class _Project: + prefs: Prefs + + @others + ropefolder = None + + + +def __init__(self, fscommands): + self.observers = [] + self.fscommands = fscommands + self.prefs = Prefs() + self.data_files = _DataFiles(self) + self._custom_source_folders = [] + + +def get_resource(self, resource_name): + """Get a resource in a project. + + `resource_name` is the path of a resource in a project. It is + the path of a resource relative to project root. Project root + folder address is an empty string. If the resource does not + exist a `exceptions.ResourceNotFound` exception would be + raised. Use `get_file()` and `get_folder()` when you need to + get nonexistent `Resource`. + + """ + path = self._get_resource_path(resource_name) + if not os.path.exists(path): + raise exceptions.ResourceNotFoundError( + "Resource <%s> does not exist" % resource_name + ) + elif os.path.isfile(path): + return File(self, resource_name) + elif os.path.isdir(path): + return Folder(self, resource_name) + else: + raise exceptions.ResourceNotFoundError("Unknown resource " + resource_name) + + +def get_module(self, name, folder=None): + """Returns a `PyObject` if the module was found.""" + # check if this is a builtin module + pymod = self.pycore.builtin_module(name) + if pymod is not None: + return pymod + module = self.find_module(name, folder) + if module is None: + raise ModuleNotFoundError("Module %s not found" % name) + return self.pycore.resource_to_pyobject(module) + + +def get_python_path_folders(self): + result = [] + for src in self.prefs.get("python_path", []) + sys.path: + try: + src_folder = get_no_project().get_resource(src) + result.append(src_folder) + except exceptions.ResourceNotFoundError: + pass + return result + + +# INFO: It was decided not to cache source folders, since: +# - Does not take much time when the root folder contains +# packages, that is most of the time +# - We need a separate resource observer; `self.observer` +# does not get notified about module and folder creations +def get_source_folders(self): + """Returns project source folders""" + if self.root is None: + return [] + result = list(self._custom_source_folders) + result.extend(self.pycore._find_source_folders(self.root)) + return result + + +def validate(self, folder): + """Validate files and folders contained in this folder + + It validates all of the files and folders contained in this + folder if some observers are interested in them. + + """ + for observer in list(self.observers): + observer.validate(folder) + + +def add_observer(self, observer): + """Register a `ResourceObserver` + + See `FilteredResourceObserver`. + """ + self.observers.append(observer) + + +def remove_observer(self, observer): + """Remove a registered `ResourceObserver`""" + if observer in self.observers: + self.observers.remove(observer) + + +def do(self, changes, task_handle=taskhandle.NullTaskHandle()): + """Apply the changes in a `ChangeSet` + + Most of the time you call this function for committing the + changes for a refactoring. + """ + self.history.do(changes, task_handle=task_handle) + + +def get_pymodule(self, resource, force_errors=False): + return self.pycore.resource_to_pyobject(resource, force_errors) + + +def get_pycore(self): + return self.pycore + + +def get_file(self, path): + """Get the file with `path` (it may not exist)""" + return File(self, path) + + +def get_folder(self, path): + """Get the folder with `path` (it may not exist)""" + return Folder(self, path) + + +def get_prefs(self): + return self.prefs + + +def get_relative_module(self, name, folder, level): + module = self.find_relative_module(name, folder, level) + if module is None: + raise ModuleNotFoundError("Module %s not found" % name) + return self.pycore.resource_to_pyobject(module) + + +def find_module(self, modname, folder=None): + """Returns a resource corresponding to the given module + + returns None if it can not be found + """ + for src in self.get_source_folders(): + module = _find_module_in_folder(src, modname) + if module is not None: + return module + for src in self.get_python_path_folders(): + module = _find_module_in_folder(src, modname) + if module is not None: + return module + if folder is not None: + module = _find_module_in_folder(folder, modname) + if module is not None: + return module + return None + + +def find_relative_module(self, modname, folder, level): + for i in range(level - 1): + folder = folder.parent + if modname == "": + return folder + else: + return _find_module_in_folder(folder, modname) + + +def is_ignored(self, resource): + return False + + +def _get_resource_path(self, name): + pass + + +@property +@utils.saveit +def history(self): + return history.History(self) + + +@property +@utils.saveit +def pycore(self): + return pycore.PyCore(self) + + +def close(self): + warnings.warn("Cannot close a NoProject", DeprecationWarning, stacklevel=2) + + +@path C:/Repos/ekr-rope/bin/ +#!/usr/bin/env python + +import re +import subprocess +from datetime import datetime + +import toml + + +pyproject = toml.load("pyproject.toml") +version = pyproject["project"]["version"] + + +@others +message = get_changelog(version) +proc = subprocess.Popen(["git", "tag", "-s", version, "-m", message]) +proc.wait() + +subprocess.check_call(["git", "show", version]) + +print() +if input("Push [yn]? ") in "yY": + subprocess.check_output(["git", "push", "origin", version]) +@language python +@tabwidth -4 + +class Project(_Project): + """A Project containing files and folders""" + + @others + root = property(lambda self: self.get_resource("")) + address = property(lambda self: self._address) + + + +def __init__( + self, projectroot, fscommands=None, ropefolder=".ropeproject", **prefs +): + """A rope project + + :parameters: + - `projectroot`: The address of the root folder of the project + - `fscommands`: Implements the file system operations used + by rope; have a look at `rope.base.fscommands` + - `ropefolder`: The name of the folder in which rope stores + project configurations and data. Pass `None` for not using + such a folder at all. + - `prefs`: Specify project preferences. These values + overwrite config file preferences. + + """ + if projectroot != "/": + projectroot = _realpath(projectroot).rstrip("/\\") + self._address = projectroot + self._ropefolder_name = ropefolder + if not os.path.exists(self._address): + os.mkdir(self._address) + elif not os.path.isdir(self._address): + raise exceptions.RopeError("Project root exists and" " is not a directory") + if fscommands is None: + fscommands = rope.base.fscommands.create_fscommands(self._address) + super().__init__(fscommands) + self.ignored = _ResourceMatcher() + self.file_list = _FileListCacher(self) + self._init_prefs(prefs) + if ropefolder is not None: + self.prefs.add("ignored_resources", ropefolder) + self._init_source_folders() + + +def __repr__(self): + return '<{}.{} "{}">'.format( + self.__class__.__module__, + self.__class__.__name__, + self.address, + ) + + +@utils.deprecated("Delete once deprecated functions are gone") +def _init_source_folders(self): + for path in self.prefs.get("source_folders", []): + folder = self.get_resource(path) + self._custom_source_folders.append(folder) + + +def get_files(self): + return self.file_list.get_files() + + +def get_python_files(self): + """Returns all python files available in the project""" + return [ + resource + for resource in self.get_files() + if self.pycore.is_python_file(resource) + ] + + +def _get_resource_path(self, name): + return os.path.join(self._address, *name.split("/")) + + +def _init_ropefolder(self): + if self.ropefolder is not None: + if not self.ropefolder.exists(): + self._create_recursively(self.ropefolder) + + +def _create_recursively(self, folder): + if folder.parent != self.root and not folder.parent.exists(): + self._create_recursively(folder.parent) + folder.create() + + +def _init_prefs(self, prefs): + config = get_config(self.root, self.ropefolder).parse() + self.prefs = config + self.prefs.add_callback("ignored_resources", self.ignored.set_patterns) + self.ignored.set_patterns(self.prefs.ignored_resources) + for key, value in prefs.items(): + self.prefs.set(key, value) + self._init_other_parts() + self._init_ropefolder() + if config.project_opened: + config.project_opened(self) + + +def _init_other_parts(self): + # Forcing the creation of `self.pycore` to register observers + self.pycore + + +def is_ignored(self, resource): + return self.ignored.does_match(resource) + + +def sync(self): + """Closes project open resources""" + self.close() + + +def close(self): + """Closes project open resources""" + self.data_files.write() + + +def set(self, key, value): + """Set the `key` preference to `value`""" + self.prefs.set(key, value) + + +@property +def ropefolder(self): + if self._ropefolder_name is not None: + return self.get_folder(self._ropefolder_name) + + +def validate(self, folder=None): + if folder is None: + folder = self.root + super().validate(folder) + + +class NoProject(_Project): + """A null object for holding out of project files. + + This class is singleton use `get_no_project` global function + """ + + @others + _no_project = None + + + +def __init__(self): + fscommands = rope.base.fscommands.FileSystemCommands() + super().__init__(fscommands) + + +def _get_resource_path(self, name): + real_name = name.replace("/", os.path.sep) + return _realpath(real_name) + + +def get_resource(self, name): + universal_name = _realpath(name).replace(os.path.sep, "/") + return super().get_resource(universal_name) + + +def get_files(self): + return [] + + +def get_python_files(self): + return [] + + +def get_no_project(): + if NoProject._no_project is None: + NoProject._no_project = NoProject() + return NoProject._no_project + + + +class _FileListCacher: + @others + +def __init__(self, project): + self.project = project + self.files = None + rawobserver = resourceobserver.ResourceObserver( + self._changed, self._invalid, self._invalid, self._invalid, self._invalid + ) + self.project.add_observer(rawobserver) + + +def get_files(self): + if self.files is None: + self.files = set() + self._add_files(self.project.root) + return self.files + + +def _add_files(self, folder): + for child in folder.get_children(): + if child.is_folder(): + self._add_files(child) + elif not self.project.is_ignored(child): + self.files.add(child) + + +def _changed(self, resource): + if resource.is_folder(): + self.files = None + + +def _invalid(self, resource, new_resource=None): + self.files = None + + + +class _DataFiles: + @others + +def __init__(self, project): + self.project = project + self.hooks = [] + + +def read_data(self, name, compress=False, import_=False): + if self.project.ropefolder is None: + return None + compress = compress and self._can_compress() + opener = self._get_opener(compress) + file = self._get_file(name, compress) + if not compress and import_: + self._import_old_files(name) + if file.exists(): + input = opener(file.real_path, "rb") + try: + result = [] + try: + while True: + result.append(pickle.load(input)) + except EOFError: + pass + if len(result) == 1: + return result[0] + if len(result) > 1: + return result + finally: + input.close() + + +def write_data(self, name, data, compress=False): + if self.project.ropefolder is not None: + compress = compress and self._can_compress() + file = self._get_file(name, compress) + opener = self._get_opener(compress) + output = opener(file.real_path, "wb") + try: + pickle.dump(data, output, 2) + finally: + output.close() + + +def add_write_hook(self, hook): + self.hooks.append(hook) + + +def write(self): + for hook in self.hooks: + hook() + + +def _can_compress(self): + try: + import gzip # noqa + + return True + except ImportError: + return False + + +def _import_old_files(self, name): + old = self._get_file(name + ".pickle", False) + new = self._get_file(name, False) + if old.exists() and not new.exists(): + shutil.move(old.real_path, new.real_path) + + +def _get_opener(self, compress): + if compress: + try: + import gzip + + return gzip.open + except ImportError: + pass + return open + + +def _get_file(self, name, compress): + path = self.project.ropefolder.path + "/" + name + if compress: + path += ".gz" + return self.project.get_file(path) + + + +def _realpath(path): + """Return the real path of `path` + + Is equivalent to ``realpath(abspath(expanduser(path)))``. + + Of the particular notice is the hack dealing with the unfortunate + situation of running native-Windows python (os.name == 'nt') inside + of Cygwin (abspath starts with '/'), which apparently normal + os.path.realpath completely messes up. + + """ + # there is a bug in cygwin for os.path.abspath() for abs paths + if sys.platform == "cygwin": + if path[1:3] == ":\\": + return path + elif path[1:3] == ":/": + path = "/cygdrive/" + path[0] + path[2:] + return os.path.abspath(os.path.expanduser(path)) + return os.path.realpath(os.path.abspath(os.path.expanduser(path))) + + + +def _find_module_in_folder(folder, modname): + module = folder + packages = modname.split(".") + for pkg in packages[:-1]: + if module.is_folder() and module.has_child(pkg): + module = module.get_child(pkg) + else: + return None + if module.is_folder(): + if ( + module.has_child(packages[-1]) + and module.get_child(packages[-1]).is_folder() + ): + return module.get_child(packages[-1]) + elif ( + module.has_child(packages[-1] + ".py") + and not module.get_child(packages[-1] + ".py").is_folder() + ): + return module.get_child(packages[-1] + ".py") + +@path C:/Repos/ekr-rope/rope/base/ +import bisect +import difflib +import sys +import warnings + +import rope.base.libutils +import rope.base.resourceobserver +import rope.base.resources +import rope.base.oi.doa +import rope.base.oi.objectinfo +import rope.base.oi.soa +from rope.base import builtins +from rope.base import exceptions +from rope.base import pyobjectsdef +from rope.base import stdmods +from rope.base import taskhandle +from rope.base import utils +from rope.base.exceptions import ModuleNotFoundError + + +@others +@language python +@tabwidth -4 + +class PyCore: + @others + +def __init__(self, project): + self.project = project + self._init_resource_observer() + self.cache_observers = [] + self.module_cache = _ModuleCache(self) + self.extension_cache = _ExtensionCache(self) + self.object_info = rope.base.oi.objectinfo.ObjectInfoManager(project) + self._init_python_files() + self._init_automatic_soa() + + +def _init_python_files(self): + self.python_matcher = None + patterns = self.project.prefs.get("python_files", None) + if patterns is not None: + self.python_matcher = rope.base.resources._ResourceMatcher() + self.python_matcher.set_patterns(patterns) + + +def _init_resource_observer(self): + callback = self._invalidate_resource_cache + observer = rope.base.resourceobserver.ResourceObserver( + changed=callback, moved=callback, removed=callback + ) + self.observer = rope.base.resourceobserver.FilteredResourceObserver(observer) + self.project.add_observer(self.observer) + + +def _init_automatic_soa(self): + if not self.automatic_soa: + return + callback = self._file_changed_for_soa + observer = rope.base.resourceobserver.ResourceObserver( + changed=callback, moved=callback, removed=callback + ) + self.project.add_observer(observer) + + +@property +def automatic_soa(self): + auto_soa = self.project.prefs.get("automatic_soi", None) + return self.project.prefs.get("automatic_soa", auto_soa) + + +def _file_changed_for_soa(self, resource, new_resource=None): + old_contents = self.project.history.contents_before_current_change(resource) + if old_contents is not None: + perform_soa_on_changed_scopes(self.project, resource, old_contents) + + +@path C:/Repos/ekr-rope/rope/base/ +"""This module tries to support builtin types and functions.""" +import ast +import inspect +import io + +try: + raw_input +except NameError: + raw_input = input + +import rope.base.evaluate +from rope.base import pynames, pyobjects, arguments, utils + + +@others +_initial_builtins = { + "list": BuiltinName(get_list_type()), + "dict": BuiltinName(get_dict_type()), + "tuple": BuiltinName(get_tuple_type()), + "set": BuiltinName(get_set_type()), + "str": BuiltinName(get_str_type()), + "file": BuiltinName(get_file_type()), + "open": BuiltinName(BuiltinFunction(function=_open_function, builtin=open)), + "unicode": BuiltinName(get_str_type()), + "range": BuiltinName(BuiltinFunction(function=_range_function, builtin=range)), + "reversed": BuiltinName( + BuiltinFunction(function=_reversed_function, builtin=reversed) + ), + "sorted": BuiltinName(BuiltinFunction(function=_sorted_function, builtin=sorted)), + "super": BuiltinName(BuiltinFunction(function=_super_function, builtin=super)), + "property": BuiltinName( + BuiltinFunction(function=_property_function, builtin=property) + ), + "zip": BuiltinName(BuiltinFunction(function=_zip_function, builtin=zip)), + "enumerate": BuiltinName( + BuiltinFunction(function=_enumerate_function, builtin=enumerate) + ), + "object": BuiltinName(BuiltinObject()), + "type": BuiltinName(BuiltinType()), + "iter": BuiltinName(BuiltinFunction(function=_iter_function, builtin=iter)), + "raw_input": BuiltinName( + BuiltinFunction(function=_input_function, builtin=raw_input) + ), +} + +builtins = BuiltinModule('builtins', initial=_initial_builtins) +@language python +@tabwidth -4 + +def is_python_file(self, resource): + if resource.is_folder(): + return False + if self.python_matcher is None: + return resource.name.endswith(".py") + return self.python_matcher.does_match(resource) + + +@utils.deprecated("Use `project.get_module` instead") +def get_module(self, name, folder=None): + """Returns a `PyObject` if the module was found.""" + return self.project.get_module(name, folder) + + +def _builtin_submodules(self, modname): + result = {} + for extension in self.extension_modules: + if extension.startswith(modname + "."): + name = extension[len(modname) + 1 :] + if "." not in name: + result[name] = self.builtin_module(extension) + return result + + +def builtin_module(self, name): + return self.extension_cache.get_pymodule(name) + + +@utils.deprecated("Use `project.get_relative_module` instead") +def get_relative_module(self, name, folder, level): + return self.project.get_relative_module(name, folder, level) + + +@utils.deprecated("Use `libutils.get_string_module` instead") +def get_string_module(self, code, resource=None, force_errors=False): + """Returns a `PyObject` object for the given code + + If `force_errors` is `True`, `exceptions.ModuleSyntaxError` is + raised if module has syntax errors. This overrides + ``ignore_syntax_errors`` project config. + + """ + return pyobjectsdef.PyModule(self, code, resource, force_errors=force_errors) + + +@utils.deprecated("Use `libutils.get_string_scope` instead") +def get_string_scope(self, code, resource=None): + """Returns a `Scope` object for the given code""" + return rope.base.libutils.get_string_scope(code, resource) + + +def _invalidate_resource_cache(self, resource, new_resource=None): + for observer in self.cache_observers: + observer(resource) + + +@utils.deprecated("Use `project.get_python_path_folders` instead") +def get_python_path_folders(self): + return self.project.get_python_path_folders() + + +@utils.deprecated("Use `project.find_module` instead") +def find_module(self, modname, folder=None): + """Returns a resource corresponding to the given module + + returns None if it can not be found + """ + return self.project.find_module(modname, folder) + + +class BuiltinModule(pyobjects.AbstractModule): + @others + +@utils.deprecated("Use `project.find_relative_module` instead") +def find_relative_module(self, modname, folder, level): + return self.project.find_relative_module(modname, folder, level) + + +# INFO: It was decided not to cache source folders, since: +# - Does not take much time when the root folder contains +# packages, that is most of the time +# - We need a separate resource observer; `self.observer` +# does not get notified about module and folder creations +@utils.deprecated("Use `project.get_source_folders` instead") +def get_source_folders(self): + """Returns project source folders""" + return self.project.get_source_folders() + + +def resource_to_pyobject(self, resource, force_errors=False): + return self.module_cache.get_pymodule(resource, force_errors) + + +@utils.deprecated("Use `project.get_python_files` instead") +def get_python_files(self): + """Returns all python files available in the project""" + return self.project.get_python_files() + + +def _is_package(self, folder): + return ( + folder.has_child("__init__.py") + and not folder.get_child("__init__.py").is_folder() + ) + + +def _find_source_folders(self, folder): + for resource in folder.get_folders(): + if self._is_package(resource): + return [folder] + result = [] + for resource in folder.get_files(): + if resource.name.endswith(".py"): + result.append(folder) + break + for resource in folder.get_folders(): + result.extend(self._find_source_folders(resource)) + return result + + +def run_module(self, resource, args=None, stdin=None, stdout=None): + """Run `resource` module + + Returns a `rope.base.oi.doa.PythonFileRunner` object for + controlling the process. + + """ + perform_doa = self.project.prefs.get("perform_doi", True) + perform_doa = self.project.prefs.get("perform_doa", perform_doa) + receiver = self.object_info.doa_data_received + if not perform_doa: + receiver = None + runner = rope.base.oi.doa.PythonFileRunner( + self, resource, args, stdin, stdout, receiver + ) + runner.add_finishing_observer(self.module_cache.forget_all_data) + runner.run() + return runner + + +def analyze_module( + self, + resource, + should_analyze=lambda py: True, + search_subscopes=lambda py: True, + followed_calls=None, +): + """Analyze `resource` module for static object inference + + This function forces rope to analyze this module to collect + information about function calls. `should_analyze` is a + function that is called with a `PyDefinedObject` argument. If + it returns `True` the element is analyzed. If it is `None` or + returns `False` the element is not analyzed. + + `search_subscopes` is like `should_analyze`; The difference is + that if it returns `False` the sub-scopes are all ignored. + That is it is assumed that `should_analyze` returns `False` + for all of its subscopes. + + `followed_calls` override the value of ``soa_followed_calls`` + project config. + """ + if followed_calls is None: + followed_calls = self.project.prefs.get("soa_followed_calls", 0) + pymodule = self.resource_to_pyobject(resource) + self.module_cache.forget_all_data() + rope.base.oi.soa.analyze_module( + self, pymodule, should_analyze, search_subscopes, followed_calls + ) + + +def get_classes(self, task_handle=taskhandle.NullTaskHandle()): + warnings.warn( + "`PyCore.get_classes()` is deprecated", DeprecationWarning, stacklevel=2 + ) + return [] + + +def __str__(self): + return str(self.module_cache) + str(self.object_info) + + +def __init__(self, name, pycore=None, initial={}): + super().__init__() + self.name = name + self.pycore = pycore + self.initial = initial + + +@utils.deprecated("Use `libutils.modname` instead") +def modname(self, resource): + return rope.base.libutils.modname(resource) + + +@property +@utils.cacheit +def extension_modules(self): + result = set(self.project.prefs.get("extension_modules", [])) + if self.project.prefs.get("import_dynload_stdmods", False): + result.update(stdmods.dynload_modules()) + return result + + + +class _ModuleCache: + @others + +def __init__(self, pycore): + self.pycore = pycore + self.module_map = {} + self.pycore.cache_observers.append(self._invalidate_resource) + self.observer = self.pycore.observer + + +def _invalidate_resource(self, resource): + if resource in self.module_map: + self.forget_all_data() + self.observer.remove_resource(resource) + del self.module_map[resource] + + +def get_pymodule(self, resource, force_errors=False): + if resource in self.module_map: + return self.module_map[resource] + if resource.is_folder(): + result = pyobjectsdef.PyPackage( + self.pycore, + resource, + force_errors=force_errors, + ) + else: + result = pyobjectsdef.PyModule( + self.pycore, + resource=resource, + force_errors=force_errors, + ) + if result.has_errors: + return result + self.module_map[resource] = result + self.observer.add_resource(resource) + return result + + +def forget_all_data(self): + for pymodule in self.module_map.values(): + pymodule._forget_concluded_data() + + +def __str__(self): + return "PyCore caches %d PyModules\n" % len(self.module_map) + + + +class _ExtensionCache: + @others + +def __init__(self, pycore): + self.pycore = pycore + self.extensions = {} + + +parent = None + + +def get_pymodule(self, name): + if name == "__builtin__": + return builtins.builtins + allowed = self.pycore.extension_modules + if name not in self.extensions and name in allowed: + self.extensions[name] = builtins.BuiltinModule(name, self.pycore) + return self.extensions.get(name) + + + +def perform_soa_on_changed_scopes(project, resource, old_contents): + pycore = project.pycore + if resource.exists() and pycore.is_python_file(resource): + try: + new_contents = resource.read() + # detecting changes in new_contents relative to old_contents + detector = _TextChangeDetector(new_contents, old_contents) + + def search_subscopes(pydefined): + scope = pydefined.get_scope() + return detector.is_changed(scope.get_start(), scope.get_end()) + + def should_analyze(pydefined): + scope = pydefined.get_scope() + start = scope.get_start() + end = scope.get_end() + return detector.consume_changes(start, end) + + pycore.analyze_module(resource, should_analyze, search_subscopes) + except exceptions.ModuleSyntaxError: + pass + + + +class _TextChangeDetector: + @others + +def __init__(self, old, new): + self.old = old + self.new = new + self._set_diffs() + + +def _set_diffs(self): + differ = difflib.Differ() + self.lines = [] + lineno = 0 + for line in differ.compare( + self.old.splitlines(True), self.new.splitlines(True) + ): + if line.startswith(" "): + lineno += 1 + elif line.startswith("-"): + lineno += 1 + self.lines.append(lineno) + + +def is_changed(self, start, end): + """Tell whether any of start till end lines have changed + + The end points are inclusive and indices start from 1. + """ + left, right = self._get_changed(start, end) + return left < right + + +def consume_changes(self, start, end): + """Clear the changed status of lines from start till end""" + left, right = self._get_changed(start, end) + if left < right: + del self.lines[left:right] + return left < right + + +def _get_changed(self, start, end): + left = bisect.bisect_left(self.lines, start) + right = bisect.bisect_right(self.lines, end) + return left, right + +@path C:/Repos/ekr-rope/rope/base/ +import rope.base.pyobjects +from rope.base import exceptions, utils + + +@others +@language python +@tabwidth -4 + +class PyName: + """References to `PyObject` inside python programs""" + + @others + +def get_attributes(self): + return self.attributes + + +def get_object(self): + """Return the `PyObject` object referenced by this `PyName`""" + + +def get_definition_location(self): + """Return a (module, lineno) tuple""" + + + +class DefinedName(PyName): + @others + +def __init__(self, pyobject): + self.pyobject = pyobject + + +def get_object(self): + return self.pyobject + + +def get_definition_location(self): + lineno = utils.guess_def_lineno( + self.pyobject.get_module(), self.pyobject.get_ast() + ) + return (self.pyobject.get_module(), lineno) + + + +class UnboundName(PyName): + @others + +def __init__(self, pyobject=None): + self.pyobject = pyobject + if self.pyobject is None: + self.pyobject = rope.base.pyobjects.get_unknown() + + +def get_object(self): + return self.pyobject + + +def get_changelog(version): + s = open("CHANGELOG.md").read() + search_heading = f"# Release {version}" + curdate = datetime.today().date().isoformat() + + headings = re.findall(r"# Release \d+\.\d+\.\d+", s) + version_heading_index = headings.index(search_heading) + version_changelog = s[ + s.index(headings[version_heading_index]) : s.index( + headings[version_heading_index + 1] + ) + ].strip() + + version_changelog = insert_date(version_changelog, curdate, after=search_heading) + version_changelog = remove_headings(version_changelog) + + return version_changelog + + + +def get_doc(self): + if self.module: + return self.module.__doc__ + + +def get_definition_location(self): + return (None, None) + + + +class AssignmentValue: + """An assigned expression""" + + @others + +def __init__( + self, ast_node, levels=None, evaluation="", assign_type=False, type_hint=None +): + """The `level` is `None` for simple assignments and is + a list of numbers for tuple assignments for example in:: + + a, (b, c) = x + + The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for + `c` is ``[1, 1]``. + + """ + self.ast_node = ast_node + if levels is None: + self.levels = [] + else: + self.levels = levels + self.evaluation = evaluation + self.assign_type = assign_type + self.type_hint = type_hint + + +def get_lineno(self): + return self.ast_node.lineno + + + +class EvaluatedName(PyName): + """A name whose object will be evaluated later""" + + @others + +def __init__(self, callback, module=None, lineno=None): + self.module = module + self.lineno = lineno + self.callback = callback + self.pyobject = _Inferred(callback, _get_concluded_data(module)) + + +def get_object(self): + return self.pyobject.get() + + +def get_definition_location(self): + return (self.module, self.lineno) + + +def invalidate(self): + """Forget the `PyObject` this `PyName` holds""" + self.pyobject.set(None) + + + +def get_name(self): + return self.name.split(".")[-1] + + +class ImportedModule(PyName): + @others + +def __init__(self, importing_module, module_name=None, level=0, resource=None): + self.importing_module = importing_module + self.module_name = module_name + self.level = level + self.resource = resource + self.pymodule = _get_concluded_data(self.importing_module) + + +def _current_folder(self): + resource = self.importing_module.get_module().get_resource() + if resource is None: + return None + return resource.parent + + +def _get_pymodule(self): + if self.pymodule.get() is None: + pycore = self.importing_module.pycore + if self.resource is not None: + self.pymodule.set(pycore.project.get_pymodule(self.resource)) + elif self.module_name is not None: + try: + if self.level == 0: + pymodule = pycore.project.get_module( + self.module_name, self._current_folder() + ) + else: + pymodule = pycore.project.get_relative_module( + self.module_name, self._current_folder(), self.level + ) + self.pymodule.set(pymodule) + except exceptions.ModuleNotFoundError: + pass + return self.pymodule.get() + + +def get_object(self): + if self._get_pymodule() is None: + return rope.base.pyobjects.get_unknown() + return self._get_pymodule() + + +def get_definition_location(self): + pymodule = self._get_pymodule() + if not isinstance(pymodule, rope.base.pyobjects.PyDefinedObject): + return (None, None) + return (pymodule.get_module(), 1) + + + +class ImportedName(PyName): + @others + +def __init__(self, imported_module, imported_name): + self.imported_module = imported_module + self.imported_name = imported_name + + +def _get_imported_pyname(self): + try: + result = self.imported_module.get_object()[self.imported_name] + if result != self: + return result + except exceptions.AttributeNotFoundError: + pass + return UnboundName() + + +@utils.prevent_recursion(rope.base.pyobjects.get_unknown) +def get_object(self): + return self._get_imported_pyname().get_object() + + +@property +@utils.saveit +def attributes(self): + result = _object_attributes(self.module, self) + result.update(self.initial) + if self.pycore is not None: + submodules = self.pycore._builtin_submodules(self.name) + for name, module in submodules.items(): + result[name] = rope.base.builtins.BuiltinName(module) + return result + + +@utils.prevent_recursion(lambda: (None, None)) +def get_definition_location(self): + return self._get_imported_pyname().get_definition_location() + + + +def _get_concluded_data(module): + if module is None: + return rope.base.pyobjects._ConcludedData() + return module._get_concluded_data() + + + +def _circular_inference(): + raise rope.base.pyobjects.IsBeingInferredError("Circular Object Inference") + + + +class _Inferred: + @others + +def __init__(self, get_inferred, concluded=None): + self.get_inferred = get_inferred + self.concluded = concluded + if self.concluded is None: + self.temp = None + + +@utils.prevent_recursion(_circular_inference) +def get(self, *args, **kwds): + if self.concluded is None or self.concluded.get() is None: + self.set(self.get_inferred(*args, **kwds)) + if self._get() is None: + self.set(rope.base.pyobjects.get_unknown()) + return self._get() + + +def set(self, pyobject): + if self.concluded is not None: + self.concluded.set(pyobject) + self.temp = pyobject + + +def _get(self): + if self.concluded is not None: + return self.concluded.get() + return self.temp + +class AssignedName(PyName): + @others + +@property +@utils.saveit +def module(self): + try: + result = __import__(self.name) + for token in self.name.split(".")[1:]: + result = getattr(result, token, None) + return result + except ImportError: + return + + + +"""Only a placeholder""" + + + + + + + +class ParameterName(PyName): + @others + +"""Only a placeholder""" + + + + + + +class _BuiltinElement: + @others + +@path C:/Repos/ekr-rope/rope/base/ +from typing import Optional + +from rope.base import ast, exceptions, utils + + +@others +@language python +@tabwidth -4 + +class PyObject: + @others + +def __init__(self, type_): + if type_ is None: + type_ = self + self.type = type_ + + +def get_attributes(self): + if self.type is self: + return {} + return self.type.get_attributes() + + +def get_attribute(self, name): + if name not in self.get_attributes(): + raise exceptions.AttributeNotFoundError("Attribute %s not found" % name) + return self.get_attributes()[name] + + +def get_type(self): + return self.type + + +def __getitem__(self, key): + """The same as ``get_attribute(key)``""" + return self.get_attribute(key) + + +def __contains__(self, key): + """The same as ``key in self.get_attributes()``""" + return key in self.get_attributes() + + +def __eq__(self, obj): + """Check the equality of two `PyObject` + + Currently it is assumed that instances (the direct instances + of `PyObject`, not the instances of its subclasses) are equal + if their types are equal. For every other object like + defineds or builtins rope assumes objects are reference + objects and their identities should match. + + """ + if self.__class__ != obj.__class__: + return False + if type(self) == PyObject: + if self is not self.type: + return self.type == obj.type + else: + return self.type is obj.type + return self is obj + + +def __ne__(self, obj): + return not self.__eq__(obj) + + +def __init__(self, builtin, parent=None): + self.builtin = builtin + self._parent = parent + + +def __hash__(self): + """See docs for `__eq__()` method""" + if type(self) == PyObject and self != self.type: + return hash(self.type) + 1 + else: + return super().__hash__() + + +def __iter__(self): + """The same as ``iter(self.get_attributes())``""" + return iter(self.get_attributes()) + + +_types = None +_unknown = None + + +@staticmethod +def _get_base_type(name): + if PyObject._types is None: + PyObject._types = {} + base_type = PyObject(None) + PyObject._types["Type"] = base_type + PyObject._types["Module"] = PyObject(base_type) + PyObject._types["Function"] = PyObject(base_type) + PyObject._types["Unknown"] = PyObject(base_type) + return PyObject._types[name] + + + +def get_base_type(name): + """Return the base type with name `name`. + + The base types are 'Type', 'Function', 'Module' and 'Unknown'. It + was used to check the type of a `PyObject` but currently its use + is discouraged. Use classes defined in this module instead. + For example instead of + ``pyobject.get_type() == get_base_type('Function')`` use + ``isinstance(pyobject, AbstractFunction)``. + + You can use `AbstractClass` for classes, `AbstractFunction` for + functions, and `AbstractModule` for modules. You can also use + `PyFunction` and `PyClass` for testing if an object is + defined somewhere and rope can access its source. These classes + provide more methods. + + """ + return PyObject._get_base_type(name) + + + +def get_unknown(): + """Return a pyobject whose type is unknown + + Note that two unknown objects are equal. So for example you can + write:: + + if pyname.get_object() == get_unknown(): + print('cannot determine what this pyname holds') + + Rope could have used `None` for indicating unknown objects but + we had to check that in many places. So actually this method + returns a null object. + + """ + if PyObject._unknown is None: + PyObject._unknown = PyObject(get_base_type("Unknown")) + return PyObject._unknown + + + +class AbstractClass(PyObject): + @others + +def __init__(self): + super().__init__(get_base_type("Type")) + + +def get_name(self): + pass + + +def get_doc(self): + pass + + +def get_doc(self): + if self.builtin: + return getattr(self.builtin, "__doc__", None) + + +def get_superclasses(self): + return [] + + + +class AbstractFunction(PyObject): + @others + +def __init__(self): + super().__init__(get_base_type("Function")) + + +def get_name(self): + pass + + +def get_doc(self): + pass + + +def get_param_names(self, special_args=True): + return [] + + +def get_returned_object(self, args): + return get_unknown() + + + +class AbstractModule(PyObject): + @others + +def __init__(self, doc=None): + super().__init__(get_base_type("Module")) + + +def get_doc(self): + pass + + +def get_name(self): + if self.builtin: + return getattr(self.builtin, "__name__", None) + + +def get_resource(self): + pass + + + +class PyDefinedObject: + """Python defined names that rope can access their sources""" + + @others + +def __init__(self, pycore, ast_node, parent): + self.pycore = pycore + self.ast_node = ast_node + self.scope = None + self.parent = parent + self.structural_attributes = None + self.concluded_attributes = self.get_module()._get_concluded_data() + self.attributes = self.get_module()._get_concluded_data() + self.defineds = None + + +def __repr__(self): + return '<{}.{} "{}" at {}>'.format( + self.__class__.__module__, + self.__class__.__name__, + self.absolute_name, + hex(id(self)), + ) + + +@property +def absolute_name(self): + obj_name = self.get_name() + return self.get_module().get_name() + ("::" + obj_name if obj_name else "") + + +visitor_class = None + + +@utils.prevent_recursion(lambda: {}) +def _get_structural_attributes(self): + if self.structural_attributes is None: + self.structural_attributes = self._create_structural_attributes() + return self.structural_attributes + + +@utils.prevent_recursion(lambda: {}) +def _get_concluded_attributes(self): + if self.concluded_attributes.get() is None: + self._get_structural_attributes() + self.concluded_attributes.set(self._create_concluded_attributes()) + return self.concluded_attributes.get() + + +def get_attributes(self): + if self.attributes.get() is None: + result = dict(self._get_concluded_attributes()) + result.update(self._get_structural_attributes()) + self.attributes.set(result) + return self.attributes.get() + + +def get_attribute(self, name): + if name in self._get_structural_attributes(): + return self._get_structural_attributes()[name] + if name in self._get_concluded_attributes(): + return self._get_concluded_attributes()[name] + raise exceptions.AttributeNotFoundError("Attribute %s not found" % name) + + +@property +def parent(self): + if self._parent is None: + return builtins + return self._parent + + + +def get_scope(self): + if self.scope is None: + self.scope = self._create_scope() + return self.scope + + +def get_module(self): + current_object = self + while current_object.parent is not None: + current_object = current_object.parent + return current_object + + +def get_doc(self) -> Optional[str]: + if len(self.get_ast().body) > 0: + expr = self.get_ast().body[0] + if isinstance(expr, ast.Expr) and isinstance(expr.value, ast.Str): + docstring = expr.value.s + assert isinstance(docstring, str) + return docstring + return None + + +def _get_defined_objects(self): + if self.defineds is None: + self._get_structural_attributes() + return self.defineds + + +def _create_structural_attributes(self): + if self.visitor_class is None: + return {} + new_visitor = self.visitor_class(self.pycore, self) + for child in ast.get_child_nodes(self.ast_node): + ast.walk(child, new_visitor) + self.defineds = new_visitor.defineds + return new_visitor.names + + +def _create_concluded_attributes(self): + return {} + + +def get_ast(self): + return self.ast_node + + +def _create_scope(self): + pass + + + +class PyFunction(PyDefinedObject, AbstractFunction): + """Only a placeholder""" + + + +class PyComprehension(PyDefinedObject, PyObject): + """Only a placeholder""" + + def get_name(self): + return "<comprehension>" + + + +class BuiltinClass(_BuiltinElement, pyobjects.AbstractClass): + @others + +class PyClass(PyDefinedObject, AbstractClass): + """Only a placeholder""" + + + +class _ConcludedData: + @others + +def __init__(self): + self.data_ = None + + +def set(self, data): + self.data_ = data + + +def get(self): + return self.data_ + + +data = property(get, set) + + +def _invalidate(self): + self.data = None + + +def __str__(self): + return "<" + str(self.data) + ">" + + + +class _PyModule(PyDefinedObject, AbstractModule): + @others + +def __init__(self, pycore, ast_node, resource): + self.resource = resource + self.concluded_data = [] + AbstractModule.__init__(self) + PyDefinedObject.__init__(self, pycore, ast_node, None) + + +def remove_headings(version_changelog): + # Remove Markdown-style headings as it matches Git comment syntax + version_changelog = re.sub(r"^#+\s+", "", version_changelog, flags=re.MULTILINE) + return version_changelog + + + +def __init__(self, builtin, attributes, parent=None): + _BuiltinElement.__init__(self, builtin, parent) + pyobjects.AbstractClass.__init__(self) + self.initial = attributes + + +@property +def absolute_name(self) -> str: + return self.get_name() + + +def _get_concluded_data(self): + new_data = _ConcludedData() + self.concluded_data.append(new_data) + return new_data + + +def _forget_concluded_data(self): + for data in self.concluded_data: + data._invalidate() + + +def get_resource(self): + return self.resource + + + +class PyModule(_PyModule): + """Only a placeholder""" + + + +class PyPackage(_PyModule): + """Only a placeholder""" + + + +class IsBeingInferredError(exceptions.RopeError): + pass + +@path C:/Repos/ekr-rope/rope/base/ +<< imports: pyobjectsdef >> +@others +@language python +@tabwidth -4 + +class PyFunction(pyobjects.PyFunction): + @others + +def __init__(self, pycore, ast_node, parent): + rope.base.pyobjects.AbstractFunction.__init__(self) + rope.base.pyobjects.PyDefinedObject.__init__(self, pycore, ast_node, parent) + self.arguments = self.ast_node.args + self.parameter_pyobjects = pynames._Inferred( + self._infer_parameters, self.get_module()._get_concluded_data() + ) + self.returned = pynames._Inferred(self._infer_returned) + self.parameter_pynames = None + + +@utils.saveit +def get_attributes(self): + result = _object_attributes(self.builtin, self) + result.update(self.initial) + return result + + +def _create_structural_attributes(self): + return {} + + +def _create_concluded_attributes(self): + return {} + + +def _create_scope(self): + return rope.base.pyscopes.FunctionScope(self.pycore, self, _FunctionVisitor) + + +def _infer_parameters(self): + pyobjects = rope.base.oi.soi.infer_parameter_objects(self) + self._handle_special_args(pyobjects) + return pyobjects + + +def _infer_returned(self, args=None): + return rope.base.oi.soi.infer_returned_object(self, args) + + +def _handle_special_args(self, pyobjects): + if len(pyobjects) == len(self.arguments.args): + if self.arguments.vararg: + pyobjects.append(rope.base.builtins.get_list()) + if self.arguments.kwarg: + pyobjects.append(rope.base.builtins.get_dict()) + + +def _set_parameter_pyobjects(self, pyobjects): + if pyobjects is not None: + self._handle_special_args(pyobjects) + self.parameter_pyobjects.set(pyobjects) + + +def get_parameters(self): + if self.parameter_pynames is None: + result = {} + for index, name in enumerate(self.get_param_names()): + # TODO: handle tuple parameters + result[name] = pynames.ParameterName(self, index) + self.parameter_pynames = result + return self.parameter_pynames + + +def get_parameter(self, index): + if index < len(self.parameter_pyobjects.get()): + return self.parameter_pyobjects.get()[index] + + +def get_returned_object(self, args): + return self.returned.get(args) + + +def get_module(self): + return builtins + + + +def get_name(self): + return self.get_ast().name + + +def get_param_names(self, special_args=True): + # TODO: handle tuple parameters + result = [ + node.arg for node in self.arguments.args if isinstance(node, ast.arg) + ] + if special_args: + if self.arguments.vararg: + result.append(self.arguments.vararg.arg) + if self.arguments.kwarg: + result.append(self.arguments.kwarg.arg) + return result + + +def get_kind(self): + """Get function type + + It returns one of 'function', 'method', 'staticmethod' or + 'classmethod' strs. + + """ + scope = self.parent.get_scope() + if isinstance(self.parent, PyClass): + for decorator in self.decorators: + pyname = rope.base.evaluate.eval_node(scope, decorator) + if pyname == rope.base.builtins.builtins["staticmethod"]: + return "staticmethod" + if pyname == rope.base.builtins.builtins["classmethod"]: + return "classmethod" + return "method" + return "function" + + +@property +def decorators(self): + try: + return getattr(self.ast_node, "decorator_list") + except AttributeError: + return getattr(self.ast_node, "decorators", None) + + + +class PyComprehension(pyobjects.PyComprehension): + @others + +def __init__(self, pycore, ast_node, parent): + self.visitor_class = _ComprehensionVisitor + rope.base.pyobjects.PyObject.__init__(self, type_="Comp") + rope.base.pyobjects.PyDefinedObject.__init__(self, pycore, ast_node, parent) + + +def _create_scope(self): + return rope.base.pyscopes.ComprehensionScope( + self.pycore, self, _ComprehensionVisitor + ) + + +def get_kind(self): + return "Comprehension" + + + +class PyClass(pyobjects.PyClass): + @others + +def __init__(self, pycore, ast_node, parent): + self.visitor_class = _ClassVisitor + rope.base.pyobjects.AbstractClass.__init__(self) + rope.base.pyobjects.PyDefinedObject.__init__(self, pycore, ast_node, parent) + self.parent = parent + self._superclasses = self.get_module()._get_concluded_data() + + +class BuiltinFunction(_BuiltinElement, pyobjects.AbstractFunction): + @others + +def get_superclasses(self): + if self._superclasses.get() is None: + self._superclasses.set(self._get_bases()) + return self._superclasses.get() + + +def get_name(self): + return self.get_ast().name + + +def _create_concluded_attributes(self): + result = {} + for base in reversed(self.get_superclasses()): + result.update(base.get_attributes()) + return result + + +def _get_bases(self): + result = [] + for base_name in self.ast_node.bases: + base = rope.base.evaluate.eval_node(self.parent.get_scope(), base_name) + if ( + base is not None + and base.get_object().get_type() + == rope.base.pyobjects.get_base_type("Type") + ): + result.append(base.get_object()) + return result + + +def _create_scope(self): + return rope.base.pyscopes.ClassScope(self.pycore, self) + + + +class PyModule(pyobjects.PyModule): + @others + +def __init__(self, pycore, source=None, resource=None, force_errors=False): + ignore = pycore.project.prefs.get("ignore_syntax_errors", False) + syntax_errors = force_errors or not ignore + self.has_errors = False + try: + source, node = self._init_source(pycore, source, resource) + except exceptions.ModuleSyntaxError: + self.has_errors = True + if syntax_errors: + raise + else: + source = "\n" + node = ast.parse("\n") + self.source_code = source + self.star_imports = [] + self.visitor_class = _GlobalVisitor + self.coding = fscommands.read_str_coding(self.source_code) + super().__init__(pycore, node, resource) + + +def _init_source(self, pycore, source_code, resource): + filename = "string" + if resource: + filename = resource.path + try: + if source_code is None: + source_bytes = resource.read_bytes() + source_code, _ = fscommands.file_data_to_unicode(source_bytes) + else: + if isinstance(source_code, str): + source_bytes = fscommands.unicode_to_file_data(source_code) + else: + source_bytes = source_code + ast_node = ast.parse(source_bytes, filename=filename) + except SyntaxError as e: + raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg) + except UnicodeDecodeError as e: + raise exceptions.ModuleSyntaxError(filename, 1, "%s" % (e.reason)) + return source_code, ast_node + + +@utils.prevent_recursion(lambda: {}) +def _create_concluded_attributes(self): + result = {} + for star_import in self.star_imports: + result.update(star_import.get_names()) + return result + + +def _create_scope(self): + return rope.base.pyscopes.GlobalScope(self.pycore, self) + + +def __init__( + self, returned=None, function=None, builtin=None, argnames=[], parent=None +): + _BuiltinElement.__init__(self, builtin, parent) + pyobjects.AbstractFunction.__init__(self) + self.argnames = argnames + self.returned = returned + self.function = function + + +@property +@utils.saveit +def lines(self): + """A `SourceLinesAdapter`""" + return rope.base.codeanalyze.SourceLinesAdapter(self.source_code) + + +@property +@utils.saveit +def logical_lines(self): + """A `LogicalLinesFinder`""" + return rope.base.codeanalyze.CachingLogicalLineFinder(self.lines) + + +def get_name(self): + return rope.base.libutils.modname(self.resource) if self.resource else "" + + + +class PyPackage(pyobjects.PyPackage): + @others + +def __init__(self, pycore, resource=None, force_errors=False): + self.resource = resource + init_dot_py = self._get_init_dot_py() + if init_dot_py is not None: + ast_node = pycore.project.get_pymodule( + init_dot_py, force_errors=force_errors + ).get_ast() + else: + ast_node = ast.parse("\n") + super().__init__(pycore, ast_node, resource) + + +def _create_structural_attributes(self): + result = {} + modname = rope.base.libutils.modname(self.resource) + extension_submodules = self.pycore._builtin_submodules(modname) + for name, module in extension_submodules.items(): + result[name] = rope.base.builtins.BuiltinName(module) + if self.resource is None: + return result + for name, resource in self._get_child_resources().items(): + result[name] = pynames.ImportedModule(self, resource=resource) + return result + + +def _create_concluded_attributes(self): + result = {} + init_dot_py = self._get_init_dot_py() + if init_dot_py: + init_object = self.pycore.project.get_pymodule(init_dot_py) + result.update(init_object.get_attributes()) + return result + + +def _get_child_resources(self): + result = {} + for child in self.resource.get_children(): + if child.is_folder(): + result[child.name] = child + elif child.name.endswith(".py") and child.name != "__init__.py": + name = child.name[:-3] + result[name] = child + return result + + +def _get_init_dot_py(self): + if self.resource is not None and self.resource.has_child("__init__.py"): + return self.resource.get_child("__init__.py") + else: + return None + + +def _create_scope(self): + return self.get_module().get_scope() + + +def get_returned_object(self, args): + if self.function is not None: + return self.function(_CallContext(self.argnames, args)) + else: + return self.returned + + +def get_module(self): + init_dot_py = self._get_init_dot_py() + if init_dot_py: + return self.pycore.project.get_pymodule(init_dot_py) + return self + + +def get_name(self): + return rope.base.libutils.modname(self.resource) if self.resource else "" + + + +class _AnnAssignVisitor: + @others + +def __init__(self, scope_visitor): + self.scope_visitor = scope_visitor + self.assigned_ast = None + self.type_hint = None + + +def _AnnAssign(self, node): + self.assigned_ast = node.value + self.type_hint = node.annotation + + ast.walk(node.target, self) + + +def _assigned(self, name, assignment=None): + self.scope_visitor._assigned(name, assignment) + + +def _Name(self, node): + assignment = pynames.AssignmentValue( + self.assigned_ast, assign_type=True, type_hint=self.type_hint + ) + self._assigned(node.id, assignment) + + +def _Tuple(self, node): + names = astutils.get_name_levels(node) + for name, levels in names: + assignment = None + if self.assigned_ast is not None: + assignment = pynames.AssignmentValue(self.assigned_ast, levels) + self._assigned(name, assignment) + + +def _Annotation(self, node): + pass + + +def _Attribute(self, node): + pass + + +def get_param_names(self, special_args=True): + return self.argnames + + + +def _Subscript(self, node): + pass + + +def _Slice(self, node): + pass + + + +class _ExpressionVisitor: + @others + +def __init__(self, scope_visitor): + self.scope_visitor = scope_visitor + + +def _assigned(self, name, assignment=None): + self.scope_visitor._assigned(name, assignment) + + +def _GeneratorExp(self, node): + list_comp = PyComprehension( + self.scope_visitor.pycore, node, self.scope_visitor.owner_object + ) + self.scope_visitor.defineds.append(list_comp) + + +def _SetComp(self, node): + self._GeneratorExp(node) + + +def _ListComp(self, node): + self._GeneratorExp(node) + + +def _DictComp(self, node): + self._GeneratorExp(node) + + +def _NamedExpr(self, node): + ast.walk(node.target, _AssignVisitor(self)) + ast.walk(node.value, self) + + + +class BuiltinUnknown(_BuiltinElement, pyobjects.PyObject): + @others + +class _AssignVisitor: + @others + +def __init__(self, scope_visitor): + self.scope_visitor = scope_visitor + self.assigned_ast = None + + +def _Assign(self, node): + self.assigned_ast = node.value + for child_node in node.targets: + ast.walk(child_node, self) + ast.walk(node.value, _ExpressionVisitor(self.scope_visitor)) + + +def _assigned(self, name, assignment=None): + self.scope_visitor._assigned(name, assignment) + + +def _Name(self, node): + assignment = None + if self.assigned_ast is not None: + assignment = pynames.AssignmentValue(self.assigned_ast) + self._assigned(node.id, assignment) + + +def _Tuple(self, node): + names = astutils.get_name_levels(node) + for name, levels in names: + assignment = None + if self.assigned_ast is not None: + assignment = pynames.AssignmentValue(self.assigned_ast, levels) + self._assigned(name, assignment) + + +def _Attribute(self, node): + pass + + +def _Subscript(self, node): + pass + + +def _Slice(self, node): + pass + + + +class _ScopeVisitor(_ExpressionVisitor): + @others + +def __init__(self, builtin): + super().__init__(pyobjects.get_unknown()) + self.builtin = builtin + self.type = pyobjects.get_unknown() + + +def __init__(self, pycore, owner_object): + _ExpressionVisitor.__init__(self, scope_visitor=self) + self.pycore = pycore + self.owner_object = owner_object + self.names = {} + self.defineds = [] + + +def get_module(self): + if self.owner_object is not None: + return self.owner_object.get_module() + else: + return None + + +def _ClassDef(self, node): + pyclass = PyClass(self.pycore, node, self.owner_object) + self.names[node.name] = pynames.DefinedName(pyclass) + self.defineds.append(pyclass) + + +def _FunctionDef(self, node): + pyfunction = PyFunction(self.pycore, node, self.owner_object) + for decorator in pyfunction.decorators: + if isinstance(decorator, ast.Name) and decorator.id == "property": + if isinstance(self, _ClassVisitor): + type_ = rope.base.builtins.Property(pyfunction) + arg = pynames.UnboundName( + rope.base.pyobjects.PyObject(self.owner_object) + ) + + def _eval(type_=type_, arg=arg): + return type_.get_property_object( + arguments.ObjectArguments([arg]) + ) + + lineno = utils.guess_def_lineno(self.get_module(), node) + + self.names[node.name] = pynames.EvaluatedName( + _eval, module=self.get_module(), lineno=lineno + ) + break + else: + self.names[node.name] = pynames.DefinedName(pyfunction) + self.defineds.append(pyfunction) + + +def _AsyncFunctionDef(self, node): + return self._FunctionDef(node) + + +def _Assign(self, node): + ast.walk(node, _AssignVisitor(self)) + + +def _AnnAssign(self, node): + ast.walk(node, _AnnAssignVisitor(self)) + + +def _AugAssign(self, node): + pass + + +def _For(self, node): + self._update_evaluated( + node.target, node.iter, ".__iter__().next()" # noqa + ) + for child in node.body + node.orelse: + ast.walk(child, self) + + +def _AsyncFor(self, node): + return self._For(node) + + +def get_name(self): + return getattr(type(self.builtin), "__name__", None) + + +def _assigned(self, name, assignment): + pyname = self.names.get(name, None) + if pyname is None: + pyname = pynames.AssignedName(module=self.get_module()) + if isinstance(pyname, pynames.AssignedName): + if assignment is not None: + pyname.assignments.append(assignment) + self.names[name] = pyname + + +def _update_evaluated( + self, targets, assigned, evaluation="", eval_type=False, type_hint=None +): + result = {} + if isinstance(targets, str): + assignment = pynames.AssignmentValue(assigned, [], evaluation, eval_type) + self._assigned(targets, assignment) + else: + names = astutils.get_name_levels(targets) + for name, levels in names: + assignment = pynames.AssignmentValue( + assigned, levels, evaluation, eval_type + ) + self._assigned(name, assignment) + return result + + +def _With(self, node): + for item in node.items: + if item.optional_vars: + self._update_evaluated( + item.optional_vars, item.context_expr, ".__enter__()" + ) + for child in node.body: + ast.walk(child, self) + + +def _AsyncWith(self, node): + return self._With(node) + + +def _excepthandler(self, node): + node_name_type = str + if node.name is not None and isinstance(node.name, node_name_type): + type_node = node.type + if isinstance(node.type, ast.Tuple) and type_node.elts: + type_node = type_node.elts[0] + self._update_evaluated(node.name, type_node, eval_type=True) + + for child in node.body: + ast.walk(child, self) + + +def _ExceptHandler(self, node): + self._excepthandler(node) + + +def _Import(self, node): + for import_pair in node.names: + module_name = import_pair.name + alias = import_pair.asname + first_package = module_name.split(".")[0] + if alias is not None: + imported = pynames.ImportedModule(self.get_module(), module_name) + if not self._is_ignored_import(imported): + self.names[alias] = imported + else: + imported = pynames.ImportedModule(self.get_module(), first_package) + if not self._is_ignored_import(imported): + self.names[first_package] = imported + + +def _ImportFrom(self, node): + level = 0 + if node.level: + level = node.level + imported_module = pynames.ImportedModule(self.get_module(), node.module, level) + if self._is_ignored_import(imported_module): + return + if len(node.names) == 1 and node.names[0].name == "*": + if isinstance(self.owner_object, PyModule): + self.owner_object.star_imports.append(StarImport(imported_module)) + else: + for imported_name in node.names: + imported = imported_name.name + alias = imported_name.asname + if alias is not None: + imported = alias + self.names[imported] = pynames.ImportedName( + imported_module, imported_name.name + ) + + +def _is_ignored_import(self, imported_module): + if not self.pycore.project.prefs.get("ignore_bad_imports", False): + return False + return not isinstance( + imported_module.get_object(), rope.base.pyobjects.AbstractModule + ) + + +def _Global(self, node): + module = self.get_module() + for name in node.names: + if module is not None: + try: + pyname = module[name] + except exceptions.AttributeNotFoundError: + pyname = pynames.AssignedName(node.lineno) + self.names[name] = pyname + + + +def insert_date(version_changelog, curdate, after): + # Add a date section, if it doesn't already exist in the changelog section + if "Date:" not in version_changelog: + version_changelog = version_changelog.replace( + after, f"{after}\n\nDate: {curdate}", 1 + ) + return version_changelog + + + +@utils.saveit +def get_attributes(self): + return _object_attributes(self.builtin, self) + + + +class _ComprehensionVisitor(_ScopeVisitor): + @others + +def _comprehension(self, node): + ast.walk(node.target, self) + ast.walk(node.iter, self) + + +def _Name(self, node): + if isinstance(node.ctx, ast.Store): + self.names[node.id] = self._get_pyobject(node) + + +def _get_pyobject(self, node): + return pynames.AssignedName(lineno=node.lineno, module=self.get_module()) + + + +class _GlobalVisitor(_ScopeVisitor): + def __init__(self, pycore, owner_object): + super().__init__(pycore, owner_object) + + + +class _ClassVisitor(_ScopeVisitor): + @others + +def __init__(self, pycore, owner_object): + super().__init__(pycore, owner_object) + + +def _FunctionDef(self, node): + _ScopeVisitor._FunctionDef(self, node) + if len(node.args.args) > 0: + first = node.args.args[0] + new_visitor = None + if isinstance(first, ast.arg): + new_visitor = _ClassInitVisitor(self, first.arg) + if new_visitor is not None: + for child in ast.get_child_nodes(node): + ast.walk(child, new_visitor) + + + +class _FunctionVisitor(_ScopeVisitor): + @others + +def __init__(self, pycore, owner_object): + super().__init__(pycore, owner_object) + self.returned_asts = [] + self.generator = False + + +def _object_attributes(obj, parent): + attributes = {} + for name in dir(obj): + if name == "None": + continue + try: + child = getattr(obj, name) + except AttributeError: + # descriptors are allowed to raise AttributeError + # even if they are in dir() + continue + pyobject = None + if inspect.isclass(child): + pyobject = BuiltinClass(child, {}, parent=parent) + elif inspect.isroutine(child): + pyobject = BuiltinFunction(builtin=child, parent=parent) + else: + pyobject = BuiltinUnknown(builtin=child) + attributes[name] = BuiltinName(pyobject) + return attributes + + + +def _Return(self, node): + if node.value is not None: + self.returned_asts.append(node.value) + + +def _Yield(self, node): + if node.value is not None: + self.returned_asts.append(node.value) + self.generator = True + + + +class _ClassInitVisitor(_AssignVisitor): + @others + +def __init__(self, scope_visitor, self_name): + super().__init__(scope_visitor) + self.self_name = self_name + + +def _Attribute(self, node): + if not isinstance(node.ctx, ast.Store): + return + if isinstance(node.value, ast.Name) and node.value.id == self.self_name: + if node.attr not in self.scope_visitor.names: + self.scope_visitor.names[node.attr] = pynames.AssignedName( + lineno=node.lineno, module=self.scope_visitor.get_module() + ) + if self.assigned_ast is not None: + pyname = self.scope_visitor.names[node.attr] + if isinstance(pyname, pynames.AssignedName): + pyname.assignments.append( + pynames.AssignmentValue(self.assigned_ast) + ) + + +def _Tuple(self, node): + if not isinstance(node.ctx, ast.Store): + return + for child in ast.get_child_nodes(node): + ast.walk(child, self) + + +def _Name(self, node): + pass + + +def _FunctionDef(self, node): + pass + + +def _ClassDef(self, node): + pass + + +def _For(self, node): + pass + + +def _create_builtin_type_getter(cls): + @others + return _get_builtin + + + +def _With(self, node): + pass + + + +class StarImport: + @others + +def __init__(self, imported_module): + self.imported_module = imported_module + + +def get_names(self): + result = {} + imported = self.imported_module.get_object() + for name in imported: + if not name.startswith("_"): + result[name] = pynames.ImportedName(self.imported_module, name) + return result + +@path C:/Repos/ekr-rope/rope/base/ +import rope.base.builtins +import rope.base.codeanalyze +import rope.base.pynames +from rope.base import ast, exceptions, utils +from rope.refactor import patchedast + + +@others +@language python +@tabwidth -4 + +class Scope: + @others + +def __init__(self, pycore, pyobject, parent_scope): + self.pycore = pycore + self.pyobject = pyobject + self.parent = parent_scope + + +def get_names(self): + """Return the names defined or imported in this scope""" + return self.pyobject.get_attributes() + + +def get_defined_names(self): + """Return the names defined in this scope""" + return self.pyobject._get_structural_attributes() + + +def get_name(self, name): + """Return name `PyName` defined in this scope""" + if name not in self.get_names(): + raise exceptions.NameNotFoundError("name %s not found" % name) + return self.get_names()[name] + + +def _get_builtin(*args): + if not hasattr(cls, "_generated"): + cls._generated = {} + if args not in cls._generated: + cls._generated[args] = cls(*args) + return cls._generated[args] + + +def __getitem__(self, key): + """The same as ``get_name(key)``""" + return self.get_name(key) + + +def __contains__(self, key): + """The same as ``key in self.get_names()``""" + return key in self.get_names() + + +@utils.saveit +def get_scopes(self): + """Return the subscopes of this scope + + The returned scopes should be sorted by the order they appear. + """ + return self._create_scopes() + + +def lookup(self, name): + if name in self.get_names(): + return self.get_names()[name] + if self.parent is not None: + return self.parent._propagated_lookup(name) + return None + + +def get_propagated_names(self): + """Return the visible names of this scope + + Return the names defined in this scope that are visible from + scopes containing this scope. This method returns the same + dictionary returned by `get_names()` except for `ClassScope` + which returns an empty dict. + """ + return self.get_names() + + +def _propagated_lookup(self, name): + if name in self.get_propagated_names(): + return self.get_propagated_names()[name] + if self.parent is not None: + return self.parent._propagated_lookup(name) + return None + + +def _create_scopes(self): + return [ + pydefined.get_scope() for pydefined in self.pyobject._get_defined_objects() + ] + + +def _get_global_scope(self): + current = self + while current.parent is not None: + current = current.parent + return current + + +def get_start(self): + return self.pyobject.get_ast().lineno + + +def get_body_start(self): + body = self.pyobject.get_ast().body + if body: + return body[0].lineno + return self.get_start() + + +def _create_builtin_getter(cls): + type_getter = _create_builtin_type_getter(cls) + + def _get_builtin(*args): + return pyobjects.PyObject(type_getter(*args)) + + return _get_builtin + + + +def get_end(self): + pymodule = self._get_global_scope().pyobject + return pymodule.logical_lines.logical_line_in(self.logical_end)[1] + + +@utils.saveit +def get_logical_end(self): + global_scope = self._get_global_scope() + return global_scope._scope_finder.find_scope_end(self) + + +start = property(get_start) +end = property(get_end) +logical_end = property(get_logical_end) + + +def get_kind(self): + pass + + +def get_region(self): + self._calculate_scope_regions_for_module() + node = self.pyobject.get_ast() + region = patchedast.node_region(node) + return region + + +def _calculate_scope_regions_for_module(self): + self._get_global_scope()._calculate_scope_regions() + + +def in_region(self, offset): + """Checks if offset is in scope region""" + + region = self.get_region() + return region[0] < offset < region[1] + + + +class GlobalScope(Scope): + @others + +def __init__(self, pycore, module): + super().__init__(pycore, module, None) + self.names = module._get_concluded_data() + + +def get_start(self): + return 1 + + +class _CallContext: + @others + +def get_kind(self): + return "Module" + + +def get_name(self, name): + try: + return self.pyobject[name] + except exceptions.AttributeNotFoundError: + if name in self.builtin_names: + return self.builtin_names[name] + raise exceptions.NameNotFoundError("name %s not found" % name) + + +@utils.saveit +def _calculate_scope_regions(self): + source = self._get_source() + patchedast.patch_ast(self.pyobject.get_ast(), source) + + +def _get_source(self): + return self.pyobject.source_code + + +def get_names(self): + if self.names.get() is None: + result = dict(self.builtin_names) + result.update(super().get_names()) + self.names.set(result) + return self.names.get() + + +def get_inner_scope_for_line(self, lineno, indents=None): + return self._scope_finder.get_holding_scope(self, lineno, indents) + + +def get_inner_scope_for_offset(self, offset): + return self._scope_finder.get_holding_scope_for_offset(self, offset) + + +@property +@utils.saveit +def _scope_finder(self): + return _HoldingScopeFinder(self.pyobject) + + +@property +def builtin_names(self): + return rope.base.builtins.builtins.get_attributes() + + + +class ComprehensionScope(Scope): + @others + +def __init__(self, argnames, args): + self.argnames = argnames + self.args = args + + +def __init__(self, pycore, pyobject, visitor): + super().__init__(pycore, pyobject, pyobject.parent.get_scope()) + self.names = None + self.returned_asts = None + self.defineds = None + self.visitor = visitor + + +def _get_names(self): + if self.names is None: + self._visit_comprehension() + return self.names + + +def get_names(self): + return self._get_names() + + +def _visit_comprehension(self): + if self.names is None: + new_visitor = self.visitor(self.pycore, self.pyobject) + for node in ast.get_child_nodes(self.pyobject.get_ast()): + ast.walk(node, new_visitor) + self.names = dict(self.parent.get_names()) + self.names.update(new_visitor.names) + self.defineds = new_visitor.defineds + + +def get_logical_end(self): + return self.get_start() + + +logical_end = property(get_logical_end) + + +def get_body_start(self): + return self.get_start() + + + +class FunctionScope(Scope): + @others + +def __init__(self, pycore, pyobject, visitor): + super().__init__(pycore, pyobject, pyobject.parent.get_scope()) + self.names = None + self.returned_asts = None + self.is_generator = None + self.defineds = None + self.visitor = visitor + + +def _get_names(self): + if self.names is None: + self._visit_function() + return self.names + + +def _get_scope_and_pyname(self, pyname): + if pyname is not None and isinstance(pyname, pynames.AssignedName): + pymodule, lineno = pyname.get_definition_location() + if pymodule is None: + return None, None + if lineno is None: + lineno = 1 + scope = pymodule.get_scope().get_inner_scope_for_line(lineno) + name = None + while name is None and scope is not None: + for current in scope.get_names(): + if scope[current] is pyname: + name = current + break + else: + scope = scope.parent + return scope, name + return None, None + + +def _visit_function(self): + if self.names is None: + new_visitor = self.visitor(self.pycore, self.pyobject) + for n in ast.get_child_nodes(self.pyobject.get_ast()): + ast.walk(n, new_visitor) + self.names = new_visitor.names + self.names.update(self.pyobject.get_parameters()) + self.returned_asts = new_visitor.returned_asts + self.is_generator = new_visitor.generator + self.defineds = new_visitor.defineds + + +def _get_returned_asts(self): + if self.names is None: + self._visit_function() + return self.returned_asts + + +def _is_generator(self): + if self.is_generator is None: + self._get_returned_asts() + return self.is_generator + + +def get_names(self): + return self._get_names() + + +def _create_scopes(self): + if self.defineds is None: + self._visit_function() + return [pydefined.get_scope() for pydefined in self.defineds] + + +def get_kind(self): + return "Function" + + +def invalidate_data(self): + for pyname in self.get_names().values(): + if isinstance( + pyname, + (rope.base.pynames.AssignedName, rope.base.pynames.EvaluatedName), + ): + pyname.invalidate() + + + +class ClassScope(Scope): + @others + +def __init__(self, pycore, pyobject): + super().__init__(pycore, pyobject, pyobject.parent.get_scope()) + + +def get_kind(self): + return "Class" + + +def get_argument(self, name): + if self.args: + args = self.args.get_arguments(self.argnames) + return args[self.argnames.index(name)] + + +def get_propagated_names(self): + return {} + + + +class _HoldingScopeFinder: + @others + +def __init__(self, pymodule): + self.pymodule = pymodule + + +def get_indents(self, lineno): + return rope.base.codeanalyze.count_line_indents(self.lines.get_line(lineno)) + + +def _get_scope_indents(self, scope): + return self.get_indents(scope.get_start()) + + +def get_holding_scope(self, module_scope, lineno, line_indents=None): + if line_indents is None: + line_indents = self.get_indents(lineno) + current_scope = module_scope + new_scope = current_scope + while new_scope is not None and ( + new_scope.get_kind() == "Module" + or self._get_scope_indents(new_scope) <= line_indents + ): + current_scope = new_scope + if ( + current_scope.get_start() == lineno + and current_scope.get_kind() != "Module" + ): + return current_scope + new_scope = None + for scope in current_scope.get_scopes(): + if scope.get_start() <= lineno: + if lineno <= scope.get_end(): + new_scope = scope + break + else: + break + return current_scope + + +def _is_empty_line(self, lineno): + line = self.lines.get_line(lineno) + return line.strip() == "" or line.lstrip().startswith("#") + + +def _get_body_indents(self, scope): + return self.get_indents(scope.get_body_start()) + + +@staticmethod +def get_holding_scope_for_offset(scope, offset): + for inner_scope in scope.get_scopes(): + if inner_scope.in_region(offset): + return _HoldingScopeFinder.get_holding_scope_for_offset( + inner_scope, offset + ) + return scope + + +def find_scope_end(self, scope): + if not scope.parent: + return self.lines.length() + end = scope.pyobject.get_ast().body[-1].lineno + scope_start = self.pymodule.logical_lines.logical_line_in(scope.start) + if scope_start[1] >= end: + # handling one-liners + body_indents = self._get_scope_indents(scope) + 4 + else: + body_indents = self._get_body_indents(scope) + for l in self.logical_lines.generate_starts( + min(end + 1, self.lines.length()), self.lines.length() + 1 + ): + if not self._is_empty_line(l): + if self.get_indents(l) < body_indents: + return end + else: + end = l + return end + + +def get_pyname(self, name): + if self.args: + args = self.args.get_pynames(self.argnames) + if name in self.argnames: + return args[self.argnames.index(name)] + + +@property +def lines(self): + return self.pymodule.lines + + +@property +def code(self): + return self.pymodule.source_code + + +@property +def logical_lines(self): + return self.pymodule.logical_lines + + + +class TemporaryScope(Scope): + """Currently used for list comprehensions and generator expressions + + These scopes do not appear in the `get_scopes()` method of their + parent scopes. + """ + + @others + +def __init__(self, pycore, parent_scope, names): + super().__init__(pycore, parent_scope.pyobject, parent_scope) + self.names = names + + +def get_names(self): + return self.names + + +def get_defined_names(self): + return self.names + + +def _create_scopes(self): + return [] + + +def get_kind(self): + return "Temporary" + +@path C:/Repos/ekr-rope/rope/base/ +import os + + +@others +@language python +@tabwidth -4 + + +def get_arguments(self, argnames): + if self.args: + return self.args.get_arguments(argnames) + + +class ResourceObserver: + """Provides the interface for observing resources + + `ResourceObserver` can be registered using `Project. + add_observer()`. But most of the time `FilteredResourceObserver` + should be used. `ResourceObserver` report all changes passed + to them and they don't report changes to all resources. For + example if a folder is removed, it only calls `removed()` for that + folder and not its contents. You can use + `FilteredResourceObserver` if you are interested in changes only + to a list of resources. And you want changes to be reported on + individual resources. + + """ + + @others + +def __init__( + self, changed=None, moved=None, created=None, removed=None, validate=None +): + self.changed = changed + self.moved = moved + self.created = created + self.removed = removed + self._validate = validate + + +def resource_changed(self, resource): + """It is called when the resource changes""" + if self.changed is not None: + self.changed(resource) + + +def resource_moved(self, resource, new_resource): + """It is called when a resource is moved""" + if self.moved is not None: + self.moved(resource, new_resource) + + +def resource_created(self, resource): + """Is called when a new resource is created""" + if self.created is not None: + self.created(resource) + + +def resource_removed(self, resource): + """Is called when a new resource is removed""" + if self.removed is not None: + self.removed(resource) + + +def validate(self, resource): + """Validate the existence of this resource and its children. + + This function is called when rope need to update its resource + cache about the files that might have been changed or removed + by other processes. + + """ + if self._validate is not None: + self._validate(resource) + + + +class FilteredResourceObserver: + """A useful decorator for `ResourceObserver` + + Most resource observers have a list of resources and are + interested only in changes to those files. This class satisfies + this need. It dispatches resource changed and removed messages. + It performs these tasks: + + * Changes to files and folders are analyzed to check whether any + of the interesting resources are changed or not. If they are, + it reports these changes to `resource_observer` passed to the + constructor. + * When a resource is removed it checks whether any of the + interesting resources are contained in that folder and reports + them to `resource_observer`. + * When validating a folder it validates all of the interesting + files in that folder. + + Since most resource observers are interested in a list of + resources that change over time, `add_resource` and + `remove_resource` might be useful. + + """ + + @others + +def __init__(self, resource_observer, initial_resources=None, timekeeper=None): + self.observer = resource_observer + self.resources = {} + if timekeeper is not None: + self.timekeeper = timekeeper + else: + self.timekeeper = ChangeIndicator() + if initial_resources is not None: + for resource in initial_resources: + self.add_resource(resource) + + +def add_resource(self, resource): + """Add a resource to the list of interesting resources""" + if resource.exists(): + self.resources[resource] = self.timekeeper.get_indicator(resource) + else: + self.resources[resource] = None + + +def get_pynames(self, argnames): + if self.args: + return self.args.get_pynames(argnames) + + +def remove_resource(self, resource): + """Add a resource to the list of interesting resources""" + if resource in self.resources: + del self.resources[resource] + + +def clear_resources(self): + """Removes all registered resources""" + self.resources.clear() + + +def resource_changed(self, resource): + changes = _Changes() + self._update_changes_caused_by_changed(changes, resource) + self._perform_changes(changes) + + +def _update_changes_caused_by_changed(self, changes, changed): + if changed in self.resources: + changes.add_changed(changed) + if self._is_parent_changed(changed): + changes.add_changed(changed.parent) + + +def _update_changes_caused_by_moved(self, changes, resource, new_resource=None): + if resource in self.resources: + changes.add_removed(resource, new_resource) + if new_resource in self.resources: + changes.add_created(new_resource) + if resource.is_folder(): + for file in list(self.resources): + if resource.contains(file): + new_file = self._calculate_new_resource( + resource, new_resource, file + ) + changes.add_removed(file, new_file) + if self._is_parent_changed(resource): + changes.add_changed(resource.parent) + if new_resource is not None: + if self._is_parent_changed(new_resource): + changes.add_changed(new_resource.parent) + + +def _is_parent_changed(self, child): + return child.parent in self.resources + + +def resource_moved(self, resource, new_resource): + changes = _Changes() + self._update_changes_caused_by_moved(changes, resource, new_resource) + self._perform_changes(changes) + + +def resource_created(self, resource): + changes = _Changes() + self._update_changes_caused_by_created(changes, resource) + self._perform_changes(changes) + + +def _update_changes_caused_by_created(self, changes, resource): + if resource in self.resources: + changes.add_created(resource) + if self._is_parent_changed(resource): + changes.add_changed(resource.parent) + + +def resource_removed(self, resource): + changes = _Changes() + self._update_changes_caused_by_moved(changes, resource) + self._perform_changes(changes) + + +def get_per_name(self): + if self.args is None: + return None + pyname = self.args.get_instance_pyname() + scope, name = self._get_scope_and_pyname(pyname) + if name is not None: + pymodule = pyname.get_definition_location()[0] + return pymodule.pycore.object_info.get_per_name(scope, name) + return None + + +def _perform_changes(self, changes): + for resource in changes.changes: + self.observer.resource_changed(resource) + self.resources[resource] = self.timekeeper.get_indicator(resource) + for resource, new_resource in changes.moves.items(): + self.resources[resource] = None + if new_resource is not None: + self.observer.resource_moved(resource, new_resource) + else: + self.observer.resource_removed(resource) + for resource in changes.creations: + self.observer.resource_created(resource) + self.resources[resource] = self.timekeeper.get_indicator(resource) + + +def validate(self, resource): + changes = _Changes() + for file in self._search_resource_moves(resource): + if file in self.resources: + self._update_changes_caused_by_moved(changes, file) + for file in self._search_resource_changes(resource): + if file in self.resources: + self._update_changes_caused_by_changed(changes, file) + for file in self._search_resource_creations(resource): + if file in self.resources: + changes.add_created(file) + self._perform_changes(changes) + + +def _search_resource_creations(self, resource): + creations = set() + if ( + resource in self.resources + and resource.exists() + and self.resources[resource] is None + ): + creations.add(resource) + if resource.is_folder(): + for file in self.resources: + if ( + file.exists() + and resource.contains(file) + and self.resources[file] is None + ): + creations.add(file) + return creations + + +def _search_resource_moves(self, resource): + all_moved = set() + if resource in self.resources and not resource.exists(): + all_moved.add(resource) + if resource.is_folder(): + for file in self.resources: + if resource.contains(file): + if not file.exists(): + all_moved.add(file) + moved = set(all_moved) + for folder in [file for file in all_moved if file.is_folder()]: + if folder in moved: + for file in list(moved): + if folder.contains(file): + moved.remove(file) + return moved + + +def _search_resource_changes(self, resource): + changed = set() + if resource in self.resources and self._is_changed(resource): + changed.add(resource) + if resource.is_folder(): + for file in self.resources: + if file.exists() and resource.contains(file): + if self._is_changed(file): + changed.add(file) + return changed + + +def _is_changed(self, resource): + if self.resources[resource] is None: + return False + return self.resources[resource] != self.timekeeper.get_indicator(resource) + + +def _calculate_new_resource(self, main, new_main, resource): + if new_main is None: + return None + diff = resource.path[len(main.path) :] + return resource.project.get_resource(new_main.path + diff) + + + +class ChangeIndicator: + @others + +def get_indicator(self, resource): + """Return the modification time and size of a `Resource`.""" + path = resource.real_path + # on dos, mtime does not change for a folder when files are added + if os.name != "posix" and os.path.isdir(path): + return ( + os.path.getmtime(path), + len(os.listdir(path)), + os.path.getsize(path), + ) + return (os.path.getmtime(path), os.path.getsize(path)) + + + +class _Changes: + @others + +def save_per_name(self, value): + if self.args is None: + return None + pyname = self.args.get_instance_pyname() + scope, name = self._get_scope_and_pyname(pyname) + if name is not None: + pymodule = pyname.get_definition_location()[0] + pymodule.pycore.object_info.save_per_name(scope, name, value) + + + +def __init__(self): + self.changes = set() + self.creations = set() + self.moves = {} + + +def add_changed(self, resource): + self.changes.add(resource) + + +def add_removed(self, resource, new_resource=None): + self.moves[resource] = new_resource + + +def add_created(self, resource): + self.creations.add(resource) + +@path C:/Repos/ekr-rope/rope/base/ +"""Files and folders in a project are represented as resource objects. + +Files and folders are access through `Resource` objects. `Resource` has +two subclasses: `File` and `Folder`. What we care about is that +refactorings and `rope.base.change.Change`s use resources. + +There are two options to create a `Resource` for a path in a project. +Note that in these examples `path` is the path to a file or folder +relative to the project's root. A project's root folder is represented +by an empty string. + + 1) Use the `rope.base.Project.get_resource()` method. E.g.: + + myresource = myproject.get_resource(path) + + + 2) Use the `rope.base.libutils` module. `libutils` has a function + named `path_to_resource()`. It takes a project and a path: + + from rope.base import libutils + + myresource = libutils.path_to_resource(myproject, path) + +Once we have a `Resource`, we can retrieve information from it, like +getting the path relative to the project's root (via `path`), reading +from and writing to the resource, moving the resource, etc. +""" + +import os +import re +import warnings + +from rope.base import change +from rope.base import exceptions +from rope.base import fscommands +from pathlib import Path + + +@others +@language python +@tabwidth -4 + +class Resource: + """Represents files and folders in a project""" + + @others + +def __init__(self, project, path): + self.project = project + self._path = path + + +def __repr__(self): + return '<{}.{} "{}" at {}>'.format( + self.__class__.__module__, + self.__class__.__name__, + self.path, + hex(id(self)), + ) + + +def move(self, new_location): + """Move resource to `new_location`""" + self._perform_change( + change.MoveResource(self, new_location), + "Moving <{}> to <{}>".format(self.path, new_location), + ) + + +def remove(self): + """Remove resource from the project""" + self._perform_change(change.RemoveResource(self), "Removing <%s>" % self.path) + + +class _AttributeCollector: + @others + +def is_folder(self): + """Return true if the resource is a folder""" + + +def create(self): + """Create this resource""" + + +def exists(self): + return os.path.exists(self.real_path) + + +@property +def parent(self): + parent = "/".join(self.path.split("/")[0:-1]) + return self.project.get_folder(parent) + + +@property +def path(self): + """Return the path of this resource relative to the project root + + The path is the list of parent directories separated by '/' followed + by the resource name. + """ + return self._path + + +@property +def name(self): + """Return the name of this resource""" + return self.path.split("/")[-1] + + +@property +def real_path(self): + """Return the file system path of this resource""" + return self.project._get_resource_path(self.path) + + +@property +def pathlib(self): + """Return the file as a pathlib path.""" + return Path(self.real_path) + + +def __eq__(self, obj): + return self.__class__ == obj.__class__ and self.path == obj.path + + +def __ne__(self, obj): + return not self.__eq__(obj) + + +def __init__(self, type): + self.attributes = {} + self.type = type + + +def __hash__(self): + return hash(self.path) + + +def _perform_change(self, change_, description): + changes = change.ChangeSet(description) + changes.add_change(change_) + self.project.do(changes) + + + +class File(Resource): + """Represents a file""" + + @others + +def __init__(self, project, name): + self.newlines = None + super().__init__(project, name) + + +def read(self): + data = self.read_bytes() + try: + content, self.newlines = fscommands.file_data_to_unicode(data) + return content + except UnicodeDecodeError as e: + raise exceptions.ModuleDecodeError(self.path, e.reason) + + +def read_bytes(self): + if not hasattr(self.project.fscommands, "read"): + warnings.warn( + "FileSystemCommands should implement read() method", + DeprecationWarning, + stacklevel=2, + ) + with open(self.real_path, "rb") as handle: + return handle.read() + return self.project.fscommands.read(self.real_path) + + +def write(self, contents): + try: + if contents == self.read(): + return + except OSError: + pass + self._perform_change( + change.ChangeContents(self, contents), "Writing file <%s>" % self.path + ) + + +def is_folder(self): + return False + + +def create(self): + self.parent.create_file(self.name) + + + +class Folder(Resource): + """Represents a folder""" + + @others + +def __call__( + self, + name, + returned=None, + function=None, + argnames=["self"], + check_existence=True, + parent=None, +): + try: + builtin = getattr(self.type, name) + except AttributeError: + if check_existence: + raise + builtin = None + self.attributes[name] = BuiltinName( + BuiltinFunction( + returned=returned, + function=function, + argnames=argnames, + builtin=builtin, + parent=parent, + ) + ) + + +def __init__(self, project, name): + super().__init__(project, name) + + +def is_folder(self): + return True + + +def get_children(self): + """Return the children of this folder""" + try: + children = os.listdir(self.real_path) + except OSError: + return [] + result = [] + for name in children: + try: + child = self.get_child(name) + except exceptions.ResourceNotFoundError: + continue + if not self.project.is_ignored(child): + result.append(self.get_child(name)) + return result + + +def create_file(self, file_name): + self._perform_change( + change.CreateFile(self, file_name), + "Creating file <%s>" % self._get_child_path(file_name), + ) + return self.get_child(file_name) + + +def create_folder(self, folder_name): + self._perform_change( + change.CreateFolder(self, folder_name), + "Creating folder <%s>" % self._get_child_path(folder_name), + ) + return self.get_child(folder_name) + + +def _get_child_path(self, name): + if self.path: + return self.path + "/" + name + else: + return name + + +def get_child(self, name): + return self.project.get_resource(self._get_child_path(name)) + + +def has_child(self, name): + try: + self.get_child(name) + return True + except exceptions.ResourceNotFoundError: + return False + + +def get_files(self): + return [ + resource for resource in self.get_children() if not resource.is_folder() + ] + + +def get_folders(self): + return [resource for resource in self.get_children() if resource.is_folder()] + + +def __setitem__(self, name, value): + self.attributes[name] = value + + + +def contains(self, resource): + if self == resource: + return False + return self.path == "" or resource.path.startswith(self.path + "/") + + +def create(self): + self.parent.create_folder(self.name) + + + +class _ResourceMatcher: + @others + +def __init__(self): + self.patterns = [] + self._compiled_patterns = [] + + +def set_patterns(self, patterns): + """Specify which resources to match + + `patterns` is a `list` of `str` that can contain ``*`` and + ``?`` signs for matching resource names. + + """ + self._compiled_patterns = None + self.patterns = patterns + + +def _add_pattern(self, pattern): + re_pattern = ( + pattern.replace(".", "\\.") + .replace("*", "[^/]*") + .replace("?", "[^/]") + .replace("//", "/(.*/)?") + ) + re_pattern = "^(.*/)?" + re_pattern + "(/.*)?$" + self.compiled_patterns.append(re.compile(re_pattern)) + + +def does_match(self, resource): + for pattern in self.compiled_patterns: + if pattern.match(resource.path): + return True + path = os.path.join(resource.project.address, *resource.path.split("/")) + return os.path.islink(path) + + +@property +def compiled_patterns(self): + if self._compiled_patterns is None: + self._compiled_patterns = [] + for pattern in self.patterns: + self._add_pattern(pattern) + return self._compiled_patterns + +@path C:/Repos/ekr-rope/rope/base/ +"""A module to ease code analysis + +This module is here to help source code analysis. +""" +import re + +from rope.base import codeanalyze, utils + + +@others +_str = re.compile( + "|".join( + [ + codeanalyze.get_comment_pattern(), + codeanalyze.get_any_string_pattern(), + ] + ) +) +_parens = re.compile(r"[\({\[\]}\)\n]") +@language python +@tabwidth -4 + +@utils.cached(7) +def real_code(source): + """Simplify `source` for analysis + + It replaces: + + * comments with spaces + * strs with a new str filled with spaces + * implicit and explicit continuations with spaces + * tabs and semicolons with spaces + + The resulting code is a lot easier to analyze if we are interested + only in offsets. + """ + collector = codeanalyze.ChangeCollector(source) + for start, end, matchgroups in ignored_regions(source): + if source[start] == "#": + replacement = " " * (end - start) + elif "f" in matchgroups.get("prefix", "").lower(): + replacement = None + else: + replacement = '"%s"' % (" " * (end - start - 2)) + if replacement is not None: + collector.add_change(start, end, replacement) + source = collector.get_changed() or source + collector = codeanalyze.ChangeCollector(source) + parens = 0 + for match in _parens.finditer(source): + i = match.start() + c = match.group() + if c in "({[": + parens += 1 + if c in ")}]": + parens -= 1 + if c == "\n" and parens > 0: + collector.add_change(i, i + 1, " ") + source = collector.get_changed() or source + return source.replace("\\\n", " ").replace("\t", " ").replace(";", "\n") + + + +class List(BuiltinClass): + @others + +@utils.cached(7) +def ignored_regions(source): + """Return ignored regions like strings and comments in `source`""" + return [ + (match.start(), match.end(), match.groupdict()) + for match in _str.finditer(source) + ] + + + +@path C:/Repos/ekr-rope/rope/base/ +import inspect +import os +import sys + +from rope.base import utils + + +@others +@language python +@tabwidth -4 + +def _stdlib_path(): + + return os.path.dirname(inspect.getsourcefile(inspect)) + + + +@utils.cached(1) +def standard_modules(): + return python_modules() | dynload_modules() + + + +@utils.cached(1) +def python_modules(): + result = set() + lib_path = _stdlib_path() + if os.path.exists(lib_path): + for name in os.listdir(lib_path): + path = os.path.join(lib_path, name) + if os.path.isdir(path): + if "-" not in name: + result.add(name) + else: + if name.endswith(".py"): + result.add(name[:-3]) + return result + + + +def normalize_so_name(name): + """ + Handle different types of python installations + """ + if "cpython" in name: + return os.path.splitext(os.path.splitext(name)[0])[0] + # XXX: Special handling for Fedora python2 distribution + # See: https://github.com/python-rope/rope/issues/211 + if name == "timemodule.so": + return "time" + return os.path.splitext(name)[0] + + + +@utils.cached(1) +def dynload_modules(): + result = set(sys.builtin_module_names) + dynload_path = os.path.join(_stdlib_path(), "lib-dynload") + if os.path.exists(dynload_path): + for name in os.listdir(dynload_path): + path = os.path.join(dynload_path, name) + if os.path.isfile(path): + if name.endswith(".dll"): + result.add(normalize_so_name(name)) + if name.endswith(".so"): + result.add(normalize_so_name(name)) + return result + +@path C:/Repos/ekr-rope/rope/base/ +from abc import ABC, abstractmethod +from typing import Optional, Sequence + +from rope.base import utils, exceptions + + +@others +@language python +@tabwidth -4 + +class BaseJobSet(ABC): + name: str = "" + job_name: str = "" + + @others + +@abstractmethod +def started_job(self, name: str) -> None: + pass + + +def __init__(self, holding=None): + self.holding = holding + collector = _AttributeCollector(list) + + collector("__iter__", function=self._iterator_get, parent=self) + collector("__new__", function=self._new_list, parent=self) + + # Adding methods + collector( + "append", function=self._list_add, argnames=["self", "value"], parent=self + ) + collector( + "__setitem__", + function=self._list_add, + argnames=["self", "index", "value"], + parent=self, + ) + collector( + "insert", + function=self._list_add, + argnames=["self", "index", "value"], + parent=self, + ) + collector( + "extend", + function=self._self_set, + argnames=["self", "iterable"], + parent=self, + ) + + # Getting methods + collector("__getitem__", function=self._list_get, parent=self) + collector("pop", function=self._list_get, parent=self) + try: + collector("__getslice__", function=self._list_get) + except AttributeError: + pass + + super().__init__(list, collector.attributes) + + +@abstractmethod +def finished_job(self) -> None: + pass + + +@abstractmethod +def check_status(self) -> None: + pass + + +@utils.deprecated("Just use JobSet.job_name attribute/property instead") +def get_active_job_name(self) -> str: + pass + + +@abstractmethod +def get_percent_done(self) -> Optional[float]: + pass + + +@utils.deprecated("Just use JobSet.name attribute/property instead") +def get_name(self) -> str: + pass + + +@abstractmethod +def increment(self) -> None: + """ + Increment the number of tasks to complete. + + This is used if the number is not known ahead of time. + """ + pass + + + +class BaseTaskHandle(ABC): + @others + +@abstractmethod +def stop(self) -> None: + pass + + +@abstractmethod +def current_jobset(self) -> Optional[BaseJobSet]: + pass + + +@abstractmethod +def add_observer(self) -> None: + pass + + +class FixSyntax: + @others + +def _last_non_blank(self, start): + while start > 0 and self.lines[start].strip() == "": + start -= 1 + return start + + +def get_type_object(imported_object) -> NameType: + """Determine the type of an object.""" + if inspect.isclass(imported_object): + return NameType.Class + if inspect.isfunction(imported_object) or inspect.isbuiltin(imported_object): + return NameType.Function + return NameType.Variable + + + +import_info = property(_get_import_info, _set_import_info) + + +def get_import_statement(self): + if self._is_changed or self.main_statement is None: + return self.import_info.get_import_statement() + else: + return self.main_statement + + +def empty_import(self): + self.import_info = ImportInfo.get_empty_import() + + +def move(self, lineno, blank_lines=0): + self.new_start = lineno + self.blank_lines = blank_lines + + +def get_old_location(self): + return self.start_line, self.end_line + + +def get_new_start(self): + return self.new_start + + +def is_changed(self): + return self._is_changed or ( + self.new_start is not None or self.new_start != self.start_line + ) + + +def accept(self, visitor): + return visitor.dispatch(self) + + + +class ImportInfo: + @others + +def get_imported_primaries(self, context): + pass + + +def get_names(module: ModuleInfo, package: Package) -> List[Name]: + """Get all names from a module and package.""" + if isinstance(module, ModuleCompiled): + return list( + get_names_from_compiled(package.name, package.source, module.underlined) + ) + if isinstance(module, ModuleFile): + return [ + combine(package, module, partial_name) + for partial_name in get_names_from_file( + module.filepath, + package.name, + underlined=module.underlined, + process_imports=module.process_imports, + ) + ] + return [] + + + +def get_imported_names(self, context): + return [ + primary.split(".")[0] for primary in self.get_imported_primaries(context) + ] + + +def get_import_statement(self): + pass + + +def is_empty(self): + pass + + +def __hash__(self): + return hash(self.get_import_statement()) + + +def _are_name_and_alias_lists_equal(self, list1, list2): + if len(list1) != len(list2): + return False + for pair1, pair2 in zip(list1, list2): + if pair1 != pair2: + return False + return True + + +def __eq__(self, obj): + return ( + isinstance(obj, self.__class__) + and self.get_import_statement() == obj.get_import_statement() + ) + + +def __ne__(self, obj): + return not self.__eq__(obj) + + +@staticmethod +def get_empty_import(): + return EmptyImport() + + + +class NormalImport(ImportInfo): + @others + +def __init__(self, names_and_aliases): + self.names_and_aliases = names_and_aliases + + +def get_names_from_compiled( + package: str, + source: Source, + underlined: bool = False, +) -> Generator[Name, None, None]: + """ + Get the names from a compiled module. + + Instead of using ast, it imports the module. + Parameters + ---------- + package : str + package to import. Must be in sys.path + underlined : bool + include underlined names + """ + # builtins is banned because you never have to import it + # python_crun is banned because it crashes python + banned = ["builtins", "python_crun"] + if package in banned or (package.startswith("_") and not underlined): + return # Builtins is redundant since you don't have to import it. + if source not in (Source.BUILTIN, Source.STANDARD): + return + try: + module = import_module(str(package)) + except ImportError: + logger.error(f"{package} could not be imported for autoimport analysis") + return + else: + for name, value in inspect.getmembers(module): + if underlined or not name.startswith("_"): + if ( + inspect.isclass(value) + or inspect.isfunction(value) + or inspect.isbuiltin(value) + ): + yield Name( + str(name), package, package, source, get_type_object(value) + ) + + + +def get_imported_primaries(self, context): + result = [] + for name, alias in self.names_and_aliases: + if alias: + result.append(alias) + else: + result.append(name) + return result + + +def get_import_statement(self): + result = "import " + for name, alias in self.names_and_aliases: + result += name + if alias: + result += " as " + alias + result += ", " + return result[:-2] + + +def is_empty(self): + return len(self.names_and_aliases) == 0 + + + +class FromImport(ImportInfo): + @others + +def __init__(self, module_name, level, names_and_aliases): + self.module_name = module_name + self.level = level + self.names_and_aliases = names_and_aliases + + +def get_imported_primaries(self, context): + if self.names_and_aliases[0][0] == "*": + module = self.get_imported_module(context) + return [name for name in module if not name.startswith("_")] + result = [] + for name, alias in self.names_and_aliases: + if alias: + result.append(alias) + else: + result.append(name) + return result + + +def get_imported_resource(self, context): + """Get the imported resource + + Returns `None` if module was not found. + """ + if self.level == 0: + return context.project.find_module(self.module_name, folder=context.folder) + else: + return context.project.find_relative_module( + self.module_name, context.folder, self.level + ) + + +def get_imported_module(self, context): + """Get the imported `PyModule` + + Raises `rope.base.exceptions.ModuleNotFoundError` if module + could not be found. + """ + if self.level == 0: + return context.project.get_module(self.module_name, context.folder) + else: + return context.project.get_relative_module( + self.module_name, context.folder, self.level + ) + + +def get_import_statement(self): + result = "from " + "." * self.level + self.module_name + " import " + for name, alias in self.names_and_aliases: + result += name + if alias: + result += " as " + alias + result += ", " + return result[:-2] + + +def is_empty(self): + return len(self.names_and_aliases) == 0 + + +def combine(package: Package, module: ModuleFile, name: PartialName) -> Name: + """Combine information to form a full name.""" + return Name(name.name, module.modname, package.name, package.source, name.name_type) + +def is_star_import(self): + return len(self.names_and_aliases) > 0 and self.names_and_aliases[0][0] == "*" + + + +class EmptyImport(ImportInfo): + + names_and_aliases = [] + + @others + +def is_empty(self): + return True + + +def get_imported_primaries(self, context): + return [] + + + +class ImportContext: + def __init__(self, project, folder): + self.project = project + self.folder = folder + +@path C:/Repos/ekr-rope/rope/refactor/importutils/ +from typing import Union, List + +from rope.base import ast, exceptions, pynames, pynamesdef, utils +from rope.refactor.importutils import actions, importinfo + + +@others +@language python +@tabwidth -4 + +class ModuleImports: + @others + +def __init__(self, project, pymodule, import_filter=None): + self.project = project + self.pymodule = pymodule + self.separating_lines = 0 + self.filter = import_filter + self.sorted = False + + +@property +@utils.saveit +def imports(self): + finder = _GlobalImportFinder(self.pymodule) + result = finder.find_import_statements() + self.separating_lines = finder.get_separating_line_count() + if self.filter is not None: + for import_stmt in result: + if not self.filter(import_stmt): + import_stmt.readonly = True + return result + + +def _get_unbound_names(self, defined_pyobject): + visitor = _GlobalUnboundNameFinder(self.pymodule, defined_pyobject) + ast.walk(self.pymodule.get_ast(), visitor) + return visitor.unbound + + +@path C:/Repos/ekr-rope/rope/contrib/autoimport/ +""" +IMPORTANT: This is a deprecated implementation of autoimport using pickle-based +storage. + +This pickle-based autoimport is provided only for backwards compatibility +purpose and will be removed and the sqlite backend will be the new default +implementation in the future. + +If you are still using this module, you should migrate to the new and improved +sqlite-based storage backend (rope.contrib.autoimport.sqlite.AutoImport). +""" + +import re + +from rope.base import builtins +from rope.base import exceptions +from rope.base import libutils +from rope.base import pynames +from rope.base import pyobjects +from rope.base import resources +from rope.base import resourceobserver +from rope.base import taskhandle +from rope.refactor import importutils + + +@others +@language python +@tabwidth -4 + +def _get_all_star_list(self, pymodule): + def _resolve_name( + name: Union[pynamesdef.AssignedName, pynames.ImportedName] + ) -> List: + while isinstance(name, pynames.ImportedName): + try: + name = name.imported_module.get_object().get_attribute( + name.imported_name, + ) + except exceptions.AttributeNotFoundError: + return [] + assert isinstance(name, pynamesdef.AssignedName) + return name.assignments + + result = set() + try: + all_star_list = pymodule.get_attribute("__all__") + except exceptions.AttributeNotFoundError: + return result + + assignments = [ + assignment.ast_node for assignment in _resolve_name(all_star_list) + ] + + # FIXME: Need a better way to recursively infer possible values. + # Currently pyobjects can recursively infer type, but not values. + # Do a very basic 1-level value inference + + while assignments: + assignment = assignments.pop() + if isinstance(assignment, ast.List): + stack = list(assignment.elts) + while stack: + el = stack.pop() + if isinstance(el, ast.IfExp): + stack.append(el.body) + stack.append(el.orelse) + elif isinstance(el, ast.Starred): + assignments.append(el.value) + else: + if isinstance(el, ast.Str): + result.add(el.s) + elif isinstance(el, ast.Name): + try: + name = pymodule.get_attribute(el.id) + except exceptions.AttributeNotFoundError: + continue + else: + for av in _resolve_name(name): + if isinstance(av.ast_node, ast.Str): + result.add(av.ast_node.s) + elif isinstance(assignment, ast.Name): + try: + name = pymodule.get_attribute(assignment.id) + except exceptions.AttributeNotFoundError: + continue + else: + assignments.extend( + assignment.ast_node for assignment in _resolve_name(name) + ) + elif isinstance(assignment, ast.BinOp): + assignments.append(assignment.left) + assignments.append(assignment.right) + return result + + +def remove_unused_imports(self): + can_select = _OneTimeSelector( + self._get_unbound_names(self.pymodule) + | self._get_all_star_list(self.pymodule) + | {"__all__"} + ) + visitor = actions.RemovingVisitor( + self.project, self._current_folder(), can_select + ) + for import_statement in self.imports: + import_statement.accept(visitor) + + +def get_used_imports(self, defined_pyobject): + result = [] + can_select = _OneTimeSelector(self._get_unbound_names(defined_pyobject)) + visitor = actions.FilteringVisitor( + self.project, self._current_folder(), can_select + ) + for import_statement in self.imports: + new_import = import_statement.accept(visitor) + if new_import is not None and not new_import.is_empty(): + result.append(new_import) + return result + + +def get_changed_source(self): + if not self.project.prefs.get("pull_imports_to_top") and not self.sorted: + return "".join(self._rewrite_imports(self.imports)) + + # Make sure we forward a removed import's preceding blank + # lines count to the following import statement. + prev_stmt = None + for stmt in self.imports: + if prev_stmt is not None and prev_stmt.import_info.is_empty(): + stmt.blank_lines = max(prev_stmt.blank_lines, stmt.blank_lines) + prev_stmt = stmt + # The new list of imports. + imports = [stmt for stmt in self.imports if not stmt.import_info.is_empty()] + + after_removing = self._remove_imports(self.imports) + first_non_blank = self._first_non_blank_line(after_removing, 0) + first_import = self._first_import_line() - 1 + result = [] + # Writing module docs + result.extend(after_removing[first_non_blank:first_import]) + # Writing imports + sorted_imports = sorted(imports, key=self._get_location) + for stmt in sorted_imports: + if stmt != sorted_imports[0]: + result.append("\n" * stmt.blank_lines) + result.append(stmt.get_import_statement() + "\n") + if sorted_imports and first_non_blank < len(after_removing): + result.append("\n" * self.separating_lines) + + # Writing the body + first_after_imports = self._first_non_blank_line(after_removing, first_import) + result.extend(after_removing[first_after_imports:]) + return "".join(result) + + +def _get_import_location(self, stmt): + start = stmt.get_new_start() + if start is None: + start = stmt.get_old_location()[0] + return start + + +def _get_location(self, stmt): + if stmt.get_new_start() is not None: + return stmt.get_new_start() + else: + return stmt.get_old_location()[0] + + +def _remove_imports(self, imports): + lines = self.pymodule.source_code.splitlines(True) + after_removing = [] + first_import_line = self._first_import_line() + last_index = 0 + for stmt in imports: + start, end = stmt.get_old_location() + blank_lines = 0 + if start != first_import_line: + blank_lines = _count_blank_lines( + lines.__getitem__, start - 2, last_index - 1, -1 + ) + after_removing.extend(lines[last_index : start - 1 - blank_lines]) + last_index = end - 1 + after_removing.extend(lines[last_index:]) + return after_removing + + +def _rewrite_imports(self, imports): + lines = self.pymodule.source_code.splitlines(True) + after_rewriting = [] + last_index = 0 + for stmt in imports: + start, end = stmt.get_old_location() + after_rewriting.extend(lines[last_index : start - 1]) + if not stmt.import_info.is_empty(): + after_rewriting.append(stmt.get_import_statement() + "\n") + last_index = end - 1 + after_rewriting.extend(lines[last_index:]) + return after_rewriting + + +def _first_non_blank_line(self, lines, lineno): + return lineno + _count_blank_lines(lines.__getitem__, lineno, len(lines)) + + +def add_import(self, import_info): + visitor = actions.AddingVisitor(self.project, [import_info]) + for import_statement in self.imports: + if import_statement.accept(visitor): + break + else: + lineno = self._get_new_import_lineno() + blanks = self._get_new_import_blanks() + self.imports.append( + importinfo.ImportStatement( + import_info, lineno, lineno, blank_lines=blanks + ) + ) + + +class AutoImport: + """A class for finding the module that provides a name + + This class maintains a cache of global names in python modules. + Note that this cache is not accurate and might be out of date. + + """ + + @others + +def _get_new_import_blanks(self): + return 0 + + +def _get_new_import_lineno(self): + if self.imports: + return self.imports[-1].end_line + return 1 + + +def filter_names(self, can_select): + visitor = actions.RemovingVisitor( + self.project, self._current_folder(), can_select + ) + for import_statement in self.imports: + import_statement.accept(visitor) + + +def expand_stars(self): + can_select = _OneTimeSelector(self._get_unbound_names(self.pymodule)) + visitor = actions.ExpandStarsVisitor( + self.project, self._current_folder(), can_select + ) + for import_statement in self.imports: + import_statement.accept(visitor) + + +def remove_duplicates(self): + added_imports = [] + for import_stmt in self.imports: + visitor = actions.AddingVisitor(self.project, [import_stmt.import_info]) + for added_import in added_imports: + if added_import.accept(visitor): + import_stmt.empty_import() + else: + added_imports.append(import_stmt) + + +def force_single_imports(self): + """force a single import per statement""" + for import_stmt in self.imports[:]: + import_info = import_stmt.import_info + if import_info.is_empty() or import_stmt.readonly: + continue + if len(import_info.names_and_aliases) > 1: + for name_and_alias in import_info.names_and_aliases: + if hasattr(import_info, "module_name"): + new_import = importinfo.FromImport( + import_info.module_name, import_info.level, [name_and_alias] + ) + else: + new_import = importinfo.NormalImport([name_and_alias]) + self.add_import(new_import) + import_stmt.empty_import() + + +def get_relative_to_absolute_list(self): + visitor = actions.RelativeToAbsoluteVisitor( + self.project, self._current_folder() + ) + for import_stmt in self.imports: + if not import_stmt.readonly: + import_stmt.accept(visitor) + return visitor.to_be_absolute + + +def get_self_import_fix_and_rename_list(self): + visitor = actions.SelfImportVisitor( + self.project, self._current_folder(), self.pymodule.get_resource() + ) + for import_stmt in self.imports: + if not import_stmt.readonly: + import_stmt.accept(visitor) + return visitor.to_be_fixed, visitor.to_be_renamed + + +def _current_folder(self): + return self.pymodule.get_resource().parent + + +def sort_imports(self): + if self.project.prefs.get("sort_imports_alphabetically"): + sort_kwargs = dict(key=self._get_import_name) + else: + sort_kwargs = dict(key=self._key_imports) + + # IDEA: Sort from import list + visitor = actions.SortingVisitor(self.project, self._current_folder()) + for import_statement in self.imports: + import_statement.accept(visitor) + in_projects = sorted(visitor.in_project, **sort_kwargs) + third_party = sorted(visitor.third_party, **sort_kwargs) + standards = sorted(visitor.standard, **sort_kwargs) + future = sorted(visitor.future, **sort_kwargs) + last_index = self._first_import_line() + last_index = self._move_imports(future, last_index, 0) + last_index = self._move_imports(standards, last_index, 1) + last_index = self._move_imports(third_party, last_index, 1) + last_index = self._move_imports(in_projects, last_index, 1) + self.separating_lines = 2 + self.sorted = True + + +def __init__(self, project, observe=True, underlined=False): + """Construct an AutoImport object + + If `observe` is `True`, listen for project changes and update + the cache. + + If `underlined` is `True`, underlined names are cached, too. + """ + self.project = project + self.underlined = underlined + self.names = project.data_files.read_data("globalnames") + if self.names is None: + self.names = {} + project.data_files.add_write_hook(self._write) + # XXX: using a filtered observer + observer = resourceobserver.ResourceObserver( + changed=self._changed, moved=self._moved, removed=self._removed + ) + if observe: + project.add_observer(observer) + + +def _first_import_line(self): + nodes = self.pymodule.get_ast().body + lineno = 0 + if self.pymodule.get_doc() is not None: + lineno = 1 + if len(nodes) > lineno: + if isinstance(nodes[lineno], ast.Import) or isinstance( + nodes[lineno], ast.ImportFrom + ): + return nodes[lineno].lineno + first_line = get_first_decorator_or_function_start_line(nodes[lineno]) + lineno = self.pymodule.logical_lines.logical_line_in(first_line)[0] + else: + lineno = self.pymodule.lines.length() + + return lineno - _count_blank_lines( + self.pymodule.lines.get_line, lineno - 1, 1, -1 + ) + + +def _get_import_name(self, import_stmt): + import_info = import_stmt.import_info + if hasattr(import_info, "module_name"): + return "{}.{}".format( + import_info.module_name, + import_info.names_and_aliases[0][0], + ) + else: + return import_info.names_and_aliases[0][0] + + +def _key_imports(self, stm1): + str1 = stm1.get_import_statement() + return str1.startswith("from "), str1 + + # str1 = stmt1.get_import_statement() + # str2 = stmt2.get_import_statement() + # if str1.startswith('from ') and not str2.startswith('from '): + # return 1 + # if not str1.startswith('from ') and str2.startswith('from '): + # return -1 + # return cmp(str1, str2) + + +def _move_imports(self, imports, index, blank_lines): + if imports: + imports[0].move(index, blank_lines) + index += 1 + if len(imports) > 1: + for stmt in imports[1:]: + stmt.move(index) + index += 1 + return index + + +def handle_long_imports(self, maxdots, maxlength): + visitor = actions.LongImportVisitor( + self._current_folder(), self.project, maxdots, maxlength + ) + for import_statement in self.imports: + if not import_statement.readonly: + import_statement.accept(visitor) + for import_info in visitor.new_imports: + self.add_import(import_info) + return visitor.to_be_renamed + + +def remove_pyname(self, pyname): + """Removes pyname when imported in ``from mod import x``""" + visitor = actions.RemovePyNameVisitor( + self.project, self.pymodule, pyname, self._current_folder() + ) + for import_stmt in self.imports: + import_stmt.accept(visitor) + + + +def get_first_decorator_or_function_start_line(node): + decorators = getattr(node, "decorator_list", []) + first_line = min([decorator.lineno for decorator in decorators] + [node.lineno]) + return first_line + + + +def _count_blank_lines(get_line, start, end, step=1): + count = 0 + for idx in range(start, end, step): + if get_line(idx).strip() == "": + count += 1 + else: + break + return count + + + +class _OneTimeSelector: + @others + +def __init__(self, names): + self.names = names + self.selected_names = set() + + +def import_assist(self, starting): + """Return a list of ``(name, module)`` tuples + + This function tries to find modules that have a global name + that starts with `starting`. + """ + # XXX: breaking if gave up! use generators + result = [] + for module in self.names: + for global_name in self.names[module]: + if global_name.startswith(starting): + result.append((global_name, module)) + return result + + +def __call__(self, imported_primary): + if self._can_name_be_added(imported_primary): + for name in self._get_dotted_tokens(imported_primary): + self.selected_names.add(name) + return True + return False + + +def _get_dotted_tokens(self, imported_primary): + tokens = imported_primary.split(".") + for i in range(len(tokens)): + yield ".".join(tokens[: i + 1]) + + +def _can_name_be_added(self, imported_primary): + for name in self._get_dotted_tokens(imported_primary): + if name in self.names and name not in self.selected_names: + return True + return False + + + +class _UnboundNameFinder: + @others + +def __init__(self, pyobject): + self.pyobject = pyobject + + +def _visit_child_scope(self, node): + pyobject = ( + self.pyobject.get_module() + .get_scope() + .get_inner_scope_for_line(node.lineno) + .pyobject + ) + visitor = _LocalUnboundNameFinder(pyobject, self) + for child in ast.get_child_nodes(node): + ast.walk(child, visitor) + + +def _FunctionDef(self, node): + self._visit_child_scope(node) + + +def _ClassDef(self, node): + self._visit_child_scope(node) + + +def _Name(self, node): + if self._get_root()._is_node_interesting(node) and not self.is_bound(node.id): + self.add_unbound(node.id) + + +def _Attribute(self, node): + result = [] + while isinstance(node, ast.Attribute): + result.append(node.attr) + node = node.value + if isinstance(node, ast.Name): + result.append(node.id) + primary = ".".join(reversed(result)) + if self._get_root()._is_node_interesting(node) and not self.is_bound( + primary + ): + self.add_unbound(primary) + else: + ast.walk(node, self) + + +def get_modules(self, name): + """Return the list of modules that have global `name`""" + return [module for module in self.names if name in self.names[module]] + + +def _get_root(self): + pass + + +def is_bound(self, name, propagated=False): + pass + + +def add_unbound(self, name): + pass + + + +class _GlobalUnboundNameFinder(_UnboundNameFinder): + @others + +def __init__(self, pymodule, wanted_pyobject): + super().__init__(pymodule) + self.unbound = set() + self.names = set() + for name, pyname in pymodule._get_structural_attributes().items(): + if not isinstance(pyname, (pynames.ImportedName, pynames.ImportedModule)): + self.names.add(name) + wanted_scope = wanted_pyobject.get_scope() + self.start = wanted_scope.get_start() + self.end = wanted_scope.get_end() + 1 + + +def _get_root(self): + return self + + +def is_bound(self, primary, propagated=False): + name = primary.split(".")[0] + return name in self.names + + +def add_unbound(self, name): + names = name.split(".") + for i in range(len(names)): + self.unbound.add(".".join(names[: i + 1])) + + +def _is_node_interesting(self, node): + return self.start <= node.lineno < self.end + + + +class _LocalUnboundNameFinder(_UnboundNameFinder): + @others + +def get_all_names(self): + """Return the list of all cached global names""" + result = set() + for module in self.names: + result.update(set(self.names[module])) + return result + + +def __init__(self, pyobject, parent): + super().__init__(pyobject) + self.parent = parent + + +def _get_root(self): + return self.parent._get_root() + + +def is_bound(self, primary, propagated=False): + name = primary.split(".")[0] + if propagated: + names = self.pyobject.get_scope().get_propagated_names() + else: + names = self.pyobject.get_scope().get_names() + return name in names or self.parent.is_bound(name, propagated=True) + + +def add_unbound(self, name): + self.parent.add_unbound(name) + + + +class _GlobalImportFinder: + @others + +def __init__(self, pymodule): + self.current_folder = None + if pymodule.get_resource(): + self.current_folder = pymodule.get_resource().parent + self.pymodule = pymodule + self.imports = [] + self.pymodule = pymodule + self.lines = self.pymodule.lines + + +def visit_import(self, node, end_line): + start_line = node.lineno + import_statement = importinfo.ImportStatement( + importinfo.NormalImport(self._get_names(node.names)), + start_line, + end_line, + self._get_text(start_line, end_line), + blank_lines=self._count_empty_lines_before(start_line), + ) + self.imports.append(import_statement) + + +def _count_empty_lines_before(self, lineno): + return _count_blank_lines(self.lines.get_line, lineno - 1, 0, -1) + + +def _count_empty_lines_after(self, lineno): + return _count_blank_lines(self.lines.get_line, lineno + 1, self.lines.length()) + + +def get_separating_line_count(self): + if not self.imports: + return 0 + return self._count_empty_lines_after(self.imports[-1].end_line - 1) + + +def _get_block_end(self, lineno): + end_line = lineno + base_indents = _get_line_indents(self.lines[lineno]) + for i in range(lineno + 1, len(self.lines)): + if _get_line_indents(self.lines[i]) >= base_indents: + end_line = i + else: + break + return end_line + + +def get_name_locations(self, name): + """Return a list of ``(resource, lineno)`` tuples""" + result = [] + for module in self.names: + if name in self.names[module]: + try: + pymodule = self.project.get_module(module) + if name in pymodule: + pyname = pymodule[name] + module, lineno = pyname.get_definition_location() + if module is not None: + resource = module.get_module().get_resource() + if resource is not None and lineno is not None: + result.append((resource, lineno)) + except exceptions.ModuleNotFoundError: + pass + return result + + +def _get_text(self, start_line, end_line): + result = [self.lines.get_line(index) for index in range(start_line, end_line)] + return "\n".join(result) + + +def visit_from(self, node, end_line): + level = 0 + if node.level: + level = node.level + import_info = importinfo.FromImport( + node.module or "", # see comment at rope.base.ast.walk + level, + self._get_names(node.names), + ) + start_line = node.lineno + self.imports.append( + importinfo.ImportStatement( + import_info, + node.lineno, + end_line, + self._get_text(start_line, end_line), + blank_lines=self._count_empty_lines_before(start_line), + ) + ) + + +def _get_names(self, alias_names): + return [(alias.name, alias.asname) for alias in alias_names] + + +def find_import_statements(self): + nodes = self.pymodule.get_ast().body + for index, node in enumerate(nodes): + if isinstance(node, (ast.Import, ast.ImportFrom)): + lines = self.pymodule.logical_lines + end_line = lines.logical_line_in(node.lineno)[1] + 1 + if isinstance(node, ast.Import): + self.visit_import(node, end_line) + if isinstance(node, ast.ImportFrom): + self.visit_from(node, end_line) + return self.imports + +@path C:/Repos/ekr-rope/rope/refactor/importutils/ +"""A package for handling imports + +This package provides tools for modifying module imports after +refactorings or as a separate task. + +""" +import rope.base.evaluate +from rope.base import libutils +from rope.base.change import ChangeSet, ChangeContents +from rope.refactor import occurrences, rename +from rope.refactor.importutils import module_imports, actions +from rope.refactor.importutils.importinfo import NormalImport, FromImport +import rope.base.codeanalyze + + +@others +@language python +@tabwidth -4 + +class ImportOrganizer: + """Perform some import-related commands + + Each method returns a `rope.base.change.Change` object. + + """ + + @others + +def __init__(self, project): + self.project = project + self.import_tools = ImportTools(self.project) + + +def organize_imports(self, resource, offset=None): + return self._perform_command_on_import_tools( + self.import_tools.organize_imports, resource, offset + ) + + +def expand_star_imports(self, resource, offset=None): + return self._perform_command_on_import_tools( + self.import_tools.expand_stars, resource, offset + ) + + +def froms_to_imports(self, resource, offset=None): + return self._perform_command_on_import_tools( + self.import_tools.froms_to_imports, resource, offset + ) + + +def generate_cache( + self, resources=None, underlined=None, task_handle=taskhandle.NullTaskHandle() +): + """Generate global name cache for project files + + If `resources` is a list of `rope.base.resource.File`, only + those files are searched; otherwise all python modules in the + project are cached. + + """ + if resources is None: + resources = self.project.get_python_files() + job_set = task_handle.create_jobset( + "Generating autoimport cache", len(resources) + ) + for file in resources: + job_set.started_job("Working on <%s>" % file.path) + self.update_resource(file, underlined) + job_set.finished_job() + + +def relatives_to_absolutes(self, resource, offset=None): + return self._perform_command_on_import_tools( + self.import_tools.relatives_to_absolutes, resource, offset + ) + + +def handle_long_imports(self, resource, offset=None): + return self._perform_command_on_import_tools( + self.import_tools.handle_long_imports, resource, offset + ) + + +def _perform_command_on_import_tools(self, method, resource, offset): + pymodule = self.project.get_pymodule(resource) + before_performing = pymodule.source_code + import_filter = None + if offset is not None: + import_filter = self._line_filter(pymodule.lines.get_line_number(offset)) + result = method(pymodule, import_filter=import_filter) + if result is not None and result != before_performing: + changes = ChangeSet( + method.__name__.replace("_", " ") + " in <%s>" % resource.path + ) + changes.add_change(ChangeContents(resource, result)) + return changes + + +def _line_filter(self, lineno): + def import_filter(import_stmt): + return import_stmt.start_line <= lineno < import_stmt.end_line + + return import_filter + + + +class ImportTools: + @others + +def __init__(self, project): + self.project = project + + +def get_import(self, resource): + """The import statement for `resource`""" + module_name = libutils.modname(resource) + return NormalImport(((module_name, None),)) + + +def get_from_import(self, resource, name): + """The from import statement for `name` in `resource`""" + module_name = libutils.modname(resource) + names = [] + if isinstance(name, list): + names = [(imported, None) for imported in name] + else: + names = [ + (name, None), + ] + return FromImport(module_name, 0, tuple(names)) + + +def module_imports(self, module, imports_filter=None): + return module_imports.ModuleImports(self.project, module, imports_filter) + + +def froms_to_imports(self, pymodule, import_filter=None): + pymodule = self._clean_up_imports(pymodule, import_filter) + module_imports = self.module_imports(pymodule, import_filter) + for import_stmt in module_imports.imports: + if import_stmt.readonly or not self._is_transformable_to_normal( + import_stmt.import_info + ): + continue + pymodule = self._from_to_normal(pymodule, import_stmt) + + # Adding normal imports in place of froms + module_imports = self.module_imports(pymodule, import_filter) + for import_stmt in module_imports.imports: + if not import_stmt.readonly and self._is_transformable_to_normal( + import_stmt.import_info + ): + import_stmt.import_info = NormalImport( + ((import_stmt.import_info.module_name, None),) + ) + module_imports.remove_duplicates() + return module_imports.get_changed_source() + + +def generate_modules_cache( + self, modules, underlined=None, task_handle=taskhandle.NullTaskHandle() +): + """Generate global name cache for modules listed in `modules`""" + job_set = task_handle.create_jobset( + "Generating autoimport cache for modules", len(modules) + ) + for modname in modules: + job_set.started_job("Working on <%s>" % modname) + if modname.endswith(".*"): + mod = self.project.find_module(modname[:-2]) + if mod: + for sub in submodules(mod): + self.update_resource(sub, underlined) + else: + self.update_module(modname, underlined) + job_set.finished_job() + + +def expand_stars(self, pymodule, import_filter=None): + module_imports = self.module_imports(pymodule, import_filter) + module_imports.expand_stars() + return module_imports.get_changed_source() + + +def _from_to_normal(self, pymodule, import_stmt): + resource = pymodule.get_resource() + from_import = import_stmt.import_info + module_name = from_import.module_name + for name, alias in from_import.names_and_aliases: + imported = name + if alias is not None: + imported = alias + occurrence_finder = occurrences.create_finder( + self.project, imported, pymodule[imported], imports=False + ) + source = rename.rename_in_module( + occurrence_finder, + module_name + "." + name, + pymodule=pymodule, + replace_primary=True, + ) + if source is not None: + pymodule = libutils.get_string_module(self.project, source, resource) + return pymodule + + +def _clean_up_imports(self, pymodule, import_filter): + resource = pymodule.get_resource() + module_with_imports = self.module_imports(pymodule, import_filter) + module_with_imports.expand_stars() + source = module_with_imports.get_changed_source() + if source is not None: + pymodule = libutils.get_string_module(self.project, source, resource) + source = self.relatives_to_absolutes(pymodule) + if source is not None: + pymodule = libutils.get_string_module(self.project, source, resource) + + module_with_imports = self.module_imports(pymodule, import_filter) + module_with_imports.remove_duplicates() + module_with_imports.remove_unused_imports() + source = module_with_imports.get_changed_source() + if source is not None: + pymodule = libutils.get_string_module(self.project, source, resource) + return pymodule + + +def relatives_to_absolutes(self, pymodule, import_filter=None): + module_imports = self.module_imports(pymodule, import_filter) + to_be_absolute_list = module_imports.get_relative_to_absolute_list() + for name, absolute_name in to_be_absolute_list: + pymodule = self._rename_in_module(pymodule, name, absolute_name) + module_imports = self.module_imports(pymodule, import_filter) + module_imports.get_relative_to_absolute_list() + source = module_imports.get_changed_source() + if source is None: + source = pymodule.source_code + return source + + +def _is_transformable_to_normal(self, import_info): + return isinstance(import_info, FromImport) + + +def organize_imports( + self, + pymodule, + unused=True, + duplicates=True, + selfs=True, + sort=True, + import_filter=None, +): + if unused or duplicates: + module_imports = self.module_imports(pymodule, import_filter) + if unused: + module_imports.remove_unused_imports() + if self.project.prefs.get("split_imports"): + module_imports.force_single_imports() + if duplicates: + module_imports.remove_duplicates() + source = module_imports.get_changed_source() + if source is not None: + pymodule = libutils.get_string_module( + self.project, source, pymodule.get_resource() + ) + if selfs: + pymodule = self._remove_self_imports(pymodule, import_filter) + if sort: + return self.sort_imports(pymodule, import_filter) + else: + return pymodule.source_code + + +def _remove_self_imports(self, pymodule, import_filter=None): + module_imports = self.module_imports(pymodule, import_filter) + ( + to_be_fixed, + to_be_renamed, + ) = module_imports.get_self_import_fix_and_rename_list() + for name in to_be_fixed: + try: + pymodule = self._rename_in_module(pymodule, name, "", till_dot=True) + except ValueError: + # There is a self import with direct access to it + return pymodule + for name, new_name in to_be_renamed: + pymodule = self._rename_in_module(pymodule, name, new_name) + module_imports = self.module_imports(pymodule, import_filter) + module_imports.get_self_import_fix_and_rename_list() + source = module_imports.get_changed_source() + if source is not None: + pymodule = libutils.get_string_module( + self.project, source, pymodule.get_resource() + ) + return pymodule + + +def _rename_in_module(self, pymodule, name, new_name, till_dot=False): + old_name = name.split(".")[-1] + old_pyname = rope.base.evaluate.eval_str(pymodule.get_scope(), name) + occurrence_finder = occurrences.create_finder( + self.project, old_name, old_pyname, imports=False + ) + changes = rope.base.codeanalyze.ChangeCollector(pymodule.source_code) + for occurrence in occurrence_finder.find_occurrences(pymodule=pymodule): + start, end = occurrence.get_primary_range() + if till_dot: + new_end = pymodule.source_code.index(".", end) + 1 + space = pymodule.source_code[end : new_end - 1].strip() + if not space == "": + for c in space: + if not c.isspace() and c not in "\\": + raise ValueError() + end = new_end + changes.add_change(start, end, new_name) + source = changes.get_changed() + if source is not None: + pymodule = libutils.get_string_module( + self.project, source, pymodule.get_resource() + ) + return pymodule + + +def sort_imports(self, pymodule, import_filter=None): + module_imports = self.module_imports(pymodule, import_filter) + module_imports.sort_imports() + return module_imports.get_changed_source() + + +def handle_long_imports( + self, pymodule, maxdots=2, maxlength=27, import_filter=None +): + # IDEA: `maxdots` and `maxlength` can be specified in project config + # adding new from imports + module_imports = self.module_imports(pymodule, import_filter) + to_be_fixed = module_imports.handle_long_imports(maxdots, maxlength) + # performing the renaming + pymodule = libutils.get_string_module( + self.project, + module_imports.get_changed_source(), + resource=pymodule.get_resource(), + ) + for name in to_be_fixed: + pymodule = self._rename_in_module(pymodule, name, name.split(".")[-1]) + # organizing imports + return self.organize_imports( + pymodule, selfs=False, sort=False, import_filter=import_filter + ) + + + +def clear_cache(self): + """Clear all entries in global-name cache + + It might be a good idea to use this function before + regenerating global names. + + """ + self.names.clear() + + +def get_imports(project, pydefined): + """A shortcut for getting the `ImportInfo` used in a scope""" + pymodule = pydefined.get_module() + module = module_imports.ModuleImports(project, pymodule) + if pymodule == pydefined: + return [stmt.import_info for stmt in module.imports] + return module.get_used_imports(pydefined) + + + +def get_module_imports(project, pymodule): + """A shortcut for creating a `module_imports.ModuleImports` object""" + return module_imports.ModuleImports(project, pymodule) + + + +def add_import(project, pymodule, module_name, name=None): + imports = get_module_imports(project, pymodule) + candidates = [] + names = [] + selected_import = None + # from mod import name + if name is not None: + from_import = FromImport(module_name, 0, [(name, None)]) + names.append(name) + candidates.append(from_import) + # from pkg import mod + if "." in module_name: + pkg, mod = module_name.rsplit(".", 1) + from_import = FromImport(pkg, 0, [(mod, None)]) + if project.prefs.get("prefer_module_from_imports"): + selected_import = from_import + candidates.append(from_import) + if name: + names.append(mod + "." + name) + else: + names.append(mod) + # import mod + normal_import = NormalImport([(module_name, None)]) + if name: + names.append(module_name + "." + name) + else: + names.append(module_name) + + candidates.append(normal_import) + + visitor = actions.AddingVisitor(project, candidates) + if selected_import is None: + selected_import = normal_import + for import_statement in imports.imports: + if import_statement.accept(visitor): + selected_import = visitor.import_info + break + imports.add_import(selected_import) + imported_name = names[candidates.index(selected_import)] + return imports.get_changed_source(), imported_name + + +@path C:/Repos/ekr-rope/ropetest/ +from textwrap import dedent + +from rope.base.builtins import Str + +import unittest + +import rope.base.libutils +import rope.base.oi +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class DynamicOITest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project(validate_objectdb=True) + self.pycore = self.project.pycore + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_dti(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + return eval("arg") + a_var = a_func(a_func) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + self.assertEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) + + +def test_module_dti(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + code = dedent("""\ + import mod1 + def a_func(arg): + return eval("arg") + a_var = a_func(mod1) + """) + mod2.write(code) + self.pycore.run_module(mod2).wait_process() + pymod2 = self.project.get_pymodule(mod2) + self.assertEqual(self.project.get_pymodule(mod1), pymod2["a_var"].get_object()) + + +def find_insertion_line(self, code): + """Guess at what line the new import should be inserted""" + match = re.search(r"^(def|class)\s+", code) + if match is not None: + code = code[: match.start()] + try: + pymodule = libutils.get_string_module(self.project, code) + except exceptions.ModuleSyntaxError: + return 1 + testmodname = "__rope_testmodule_rope" + importinfo = importutils.NormalImport(((testmodname, None),)) + module_imports = importutils.get_module_imports(self.project, pymodule) + module_imports.add_import(importinfo) + code = module_imports.get_changed_source() + offset = code.index(testmodname) + lineno = code.count("\n", 0, offset) + 1 + return lineno + + +def test_class_from_another_module_dti(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + code1 = dedent("""\ + class AClass(object): + pass + """) + code2 = dedent("""\ + from mod1 import AClass + + def a_func(arg): + return eval("arg") + a_var = a_func(AClass) + """) + mod1.write(code1) + mod2.write(code2) + self.pycore.run_module(mod2).wait_process() + # pymod1 = self.project.get_pymodule(mod1) + pymod2 = self.project.get_pymodule(mod2) + self.assertEqual(pymod2["AClass"].get_object(), pymod2["a_var"].get_object()) + + +def test_class_dti(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class AClass(object): + pass + + def a_func(arg): + return eval("arg") + a_var = a_func(AClass) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + self.assertEqual(pymod["AClass"].get_object(), pymod["a_var"].get_object()) + + +def test_instance_dti(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class AClass(object): + pass + + def a_func(arg): + return eval("arg()") + a_var = a_func(AClass) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + self.assertEqual( + pymod["AClass"].get_object(), pymod["a_var"].get_object().get_type() + ) + + +def test_method_dti(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class AClass(object): + def a_method(self, arg): + return eval("arg()") + an_instance = AClass() + a_var = an_instance.a_method(AClass) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + self.assertEqual( + pymod["AClass"].get_object(), pymod["a_var"].get_object().get_type() + ) + + +def test_function_argument_dti(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + pass + a_func(a_func) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pyscope = self.project.get_pymodule(mod).get_scope() + self.assertEqual( + pyscope["a_func"].get_object(), pyscope.get_scopes()[0]["arg"].get_object() + ) + + +def test_classes_with_the_same_name(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + class AClass(object): + pass + return eval("arg") + class AClass(object): + pass + a_var = a_func(AClass) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + self.assertEqual(pymod["AClass"].get_object(), pymod["a_var"].get_object()) + + +def test_nested_classes(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(): + class AClass(object): + pass + return AClass + def another_func(arg): + return eval("arg") + a_var = another_func(a_func()) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pyscope = self.project.get_pymodule(mod).get_scope() + self.assertEqual( + pyscope.get_scopes()[0]["AClass"].get_object(), + pyscope["a_var"].get_object(), + ) + + +def test_function_argument_dti2(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg, a_builtin_type): + pass + a_func(a_func, []) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pyscope = self.project.get_pymodule(mod).get_scope() + self.assertEqual( + pyscope["a_func"].get_object(), pyscope.get_scopes()[0]["arg"].get_object() + ) + + +def test_dti_and_concluded_data_invalidation(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + return eval("arg") + a_var = a_func(a_func) + """) + mod.write(code) + pymod = self.project.get_pymodule(mod) + pymod["a_var"].get_object() + self.pycore.run_module(mod).wait_process() + self.assertEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) + + +def test_list_objects_and_dynamicoi(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + pass + def a_func(arg): + return eval("arg") + a_var = a_func([C()])[0] + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def update_resource(self, resource, underlined=None): + """Update the cache for global names in `resource`""" + try: + pymodule = self.project.get_pymodule(resource) + modname = self._module_name(resource) + self._add_names(pymodule, modname, underlined) + except exceptions.ModuleSyntaxError: + pass + + +def test_for_loops_and_dynamicoi(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + pass + def a_func(arg): + return eval("arg") + for c in a_func([C()]): + a_var = c + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_dict_objects_and_dynamicoi(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + pass + def a_func(arg): + return eval("arg") + a_var = a_func({1: C()})[1] + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_dict_keys_and_dynamicoi(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + pass + def a_func(arg): + return eval("arg") + a_var = list(a_func({C(): 1}))[0] + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_dict_keys_and_dynamicoi2(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(arg): + return eval("arg") + a, b = a_func((C1(), C2())) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_strs_and_dynamicoi(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + return eval("arg") + a_var = a_func("hey") + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + a_var = pymod["a_var"].get_object() + self.assertTrue(isinstance(a_var.get_type(), rope.base.builtins.Str)) + + +def test_textual_transformations(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + pass + def f(): + pass + a_var = C() + a_list = [C()] + a_str = "hey" + a_file = open("file.txt") + """) + mod.write(code) + to_pyobject = rope.base.oi.transform.TextualToPyObject(self.project) + to_textual = rope.base.oi.transform.PyObjectToTextual(self.project) + pymod = self.project.get_pymodule(mod) + + def complex_to_textual(pyobject): + return to_textual.transform( + to_pyobject.transform(to_textual.transform(pyobject)) + ) + + test_variables = [ + ("C", ("defined", "mod.py", "C")), + ("f", ("defined", "mod.py", "f")), + ("a_var", ("instance", ("defined", "mod.py", "C"))), + ("a_list", ("builtin", "list", ("instance", ("defined", "mod.py", "C")))), + ("a_str", ("builtin", "str")), + ("a_file", ("builtin", "file")), + ] + test_cases = [(pymod[v].get_object(), r) for v, r in test_variables] + test_cases += [ + (pymod, ("defined", "mod.py")), + ( + rope.base.builtins.builtins["enumerate"].get_object(), + ("builtin", "function", "enumerate"), + ), + ] + for var, result in test_cases: + self.assertEqual(to_textual.transform(var), result) + self.assertEqual(complex_to_textual(var), result) + + +def test_arguments_with_keywords(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(arg): + return eval("arg") + a = a_func(arg=C1()) + b = a_func(arg=C2()) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_a_function_with_different_returns(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(arg): + return eval("arg") + a = a_func(C1()) + b = a_func(C2()) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_a_function_with_different_returns2(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(p): + if p == C1: + return C1() + else: + return C2() + a = a_func(C1) + b = a_func(C2) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_ignoring_star_args(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(p, *args): + if p == C1: + return C1() + else: + return C2() + a = a_func(C1, 1) + b = a_func(C2, 2) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def update_module(self, modname, underlined=None): + """Update the cache for global names in `modname` module + + `modname` is the name of a module. + """ + try: + pymodule = self.project.get_module(modname) + self._add_names(pymodule, modname, underlined) + except exceptions.ModuleNotFoundError: + pass + + +def test_ignoring_double_star_args(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(p, *kwds, **args): + if p == C1: + return C1() + else: + return C2() + a = a_func(C1, kwd=1) + b = a_func(C2, kwd=2) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_invalidating_data_after_changing(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + return eval("arg") + a_var = a_func(a_func) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + mod.write(code.replace("a_func", "newfunc")) + mod.write(code) + pymod = self.project.get_pymodule(mod) + self.assertNotEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) + + +def test_invalidating_data_after_moving(self): + mod2 = testutils.create_module(self.project, "mod2") + mod2.write("class C(object):\n pass\n") + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + import mod2 + def a_func(arg): + return eval(arg) + a_var = a_func("mod2.C") + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + mod.move("newmod.py") + pymod = self.project.get_module("newmod") + pymod2 = self.project.get_pymodule(mod2) + self.assertEqual(pymod2["C"].get_object(), pymod["a_var"].get_object()) + + + +class NewStaticOITest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project(validate_objectdb=True) + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_static_oi_for_simple_function_calls(self): + code = dedent("""\ + class C(object): + pass + def f(p): + pass + f(C()) + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + f_scope = pymod["f"].get_object().get_scope() + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(c_class, p_type) + + +def test_static_oi_not_failing_when_callin_callables(self): + code = dedent("""\ + class C(object): + pass + C() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + + +def test_static_oi_for_nested_calls(self): + code = dedent("""\ + class C(object): + pass + def f(p): + pass + def g(p): + return p + f(g(C())) + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + f_scope = pymod["f"].get_object().get_scope() + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(c_class, p_type) + + +def test_static_oi_class_methods(self): + code = dedent("""\ + class C(object): + def f(self, p): + pass + C().f(C())""") + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + f_scope = c_class["f"].get_object().get_scope() + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(c_class, p_type) + + +def _module_name(self, resource): + return libutils.modname(resource) + + +def test_static_oi_preventing_soi_maximum_recursion_exceptions(self): + code = dedent("""\ + item = {} + for item in item.keys(): + pass + """) + self.mod.write(code) + try: + self.pycore.analyze_module(self.mod) + except RuntimeError as e: + self.fail(str(e)) + + +def test_static_oi_for_infer_return_typs_from_funcs_based_on_params(self): + code = dedent("""\ + class C(object): + pass + def func(p): + return p + a_var = func(C()) + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_a_function_with_different_returns(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(arg): + return arg + a = a_func(C1()) + b = a_func(C2()) + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_not_reporting_out_of_date_information(self): + code = dedent("""\ + class C1(object): + pass + def f(arg): + return C1() + a_var = f() + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + + self.mod.write(code.replace("C1", "C2")) + pymod = self.project.get_pymodule(self.mod) + c2_class = pymod["C2"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c2_class, a_var.get_type()) + + +def test_invalidating_concluded_data_in_a_function(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write(dedent("""\ + def func(arg): + temp = arg + return temp + """)) + mod2.write(dedent("""\ + import mod1 + class C1(object): + pass + class C2(object): + pass + a_var = mod1.func(C1()) + """)) + pymod2 = self.project.get_pymodule(mod2) + c1_class = pymod2["C1"].get_object() + a_var = pymod2["a_var"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + + mod2.write(mod2.read()[: mod2.read().rfind("C1()")] + "C2())\n") + pymod2 = self.project.get_pymodule(mod2) + c2_class = pymod2["C2"].get_object() + a_var = pymod2["a_var"].get_object() + self.assertEqual(c2_class, a_var.get_type()) + + +def test_handling_generator_functions_for_strs(self): + self.mod.write(dedent("""\ + class C(object): + pass + def f(p): + yield p() + for c in f(C): + a_var = c + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +# TODO: Returning a generator for functions that yield unknowns +@unittest.skip("Returning a generator that yields unknowns") +def xxx_test_handl_generator_functions_when_unknown_type_is_yielded(self): + self.mod.write(dedent("""\ + class C(object): + pass + def f(): + yield eval("C()") + a_var = f() + """)) + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["a_var"].get_object() + self.assertTrue(isinstance(a_var.get_type(), rope.base.builtins.Generator)) + + +def test_static_oi_for_lists_depending_on_append_function(self): + code = dedent("""\ + class C(object): + pass + l = list() + l.append(C()) + a_var = l.pop() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_static_oi_for_lists_per_object_for_get_item(self): + code = dedent("""\ + class C(object): + pass + l = list() + l.append(C()) + a_var = l[0] + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_static_oi_for_lists_per_object_for_fields(self): + code = dedent("""\ + class C(object): + pass + class A(object): + def __init__(self): + self.l = [] + def set(self): + self.l.append(C()) + a = A() + a.set() + a_var = a.l[0] + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def _add_names(self, pymodule, modname, underlined): + if underlined is None: + underlined = self.underlined + globals = [] + if isinstance(pymodule, pyobjects.PyDefinedObject): + attributes = pymodule._get_structural_attributes() + else: + attributes = pymodule.get_attributes() + for name, pyname in attributes.items(): + if not underlined and name.startswith("_"): + continue + if isinstance(pyname, (pynames.AssignedName, pynames.DefinedName)): + globals.append(name) + if isinstance(pymodule, builtins.BuiltinModule): + globals.append(name) + self.names[modname] = globals + + +def test_static_oi_for_lists_per_object_for_set_item(self): + code = dedent("""\ + class C(object): + pass + l = [None] + l[0] = C() + a_var = l[0] + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_static_oi_for_lists_per_object_for_extending_lists(self): + code = dedent("""\ + class C(object): + pass + l = [] + l.append(C()) + l2 = [] + l2.extend(l) + a_var = l2[0] + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_static_oi_for_lists_per_object_for_iters(self): + code = dedent("""\ + class C(object): + pass + l = [] + l.append(C()) + for c in l: + a_var = c + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_static_oi_for_dicts_depending_on_append_function(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {} + d[C1()] = C2() + a, b = d.popitem() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_static_oi_for_dicts_depending_on_for_loops(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {} + d[C1()] = C2() + for k, v in d.items(): + a = k + b = v + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_static_oi_for_dicts_depending_on_update(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {} + d[C1()] = C2() + d2 = {} + d2.update(d) + a, b = d2.popitem() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_static_oi_for_dicts_depending_on_update_on_seqs(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {} + d.update([(C1(), C2())]) + a, b = d.popitem() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_static_oi_for_sets_per_object_for_set_item(self): + code = dedent("""\ + class C(object): + pass + s = set() + s.add(C()) + a_var = s.pop() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_properties_and_calling_get_property(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + c1 = C1() + def get_c1(self): + return self.c1 + p = property(get_c1) + c2 = C2() + a_var = c2.p + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + + +def test_soi_on_constructors(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + def __init__(self, arg): + self.attr = arg + c2 = C2(C1()) + a_var = c2.attr""") + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + + +def _write(self): + self.project.data_files.write_data("globalnames", self.names) + + +def test_soi_on_literal_assignment(self): + code = 'a_var = ""' + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["a_var"].get_object() + self.assertEqual(Str, type(a_var.get_type())) + + +@testutils.only_for_versions_higher("3.6") +def test_soi_on_typed_assignment(self): + code = "a_var: str" + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["a_var"].get_object() + self.assertEqual(Str, type(a_var.get_type())) + + +def test_not_saving_unknown_function_returns(self): + mod2 = testutils.create_module(self.project, "mod2") + self.mod.write(dedent("""\ + class C(object): + pass + l = [] + l.append(C()) + """)) + mod2.write(dedent("""\ + import mod + def f(): + return mod.l.pop() + a_var = f() + """)) + pymod = self.project.get_pymodule(self.mod) + pymod2 = self.project.get_pymodule(mod2) + c_class = pymod["C"].get_object() + a_var = pymod2["a_var"] + + self.pycore.analyze_module(mod2) + self.assertNotEqual(c_class, a_var.get_object().get_type()) + + self.pycore.analyze_module(self.mod) + self.assertEqual(c_class, a_var.get_object().get_type()) + + +def test_using_the_best_callinfo(self): + code = dedent("""\ + class C1(object): + pass + def f(arg1, arg2, arg3): + pass + f("", None, C1()) + f("", C1(), None) + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + f_scope = pymod["f"].get_object().get_scope() + arg2 = f_scope["arg2"].get_object() + self.assertEqual(c1_class, arg2.get_type()) + + +def test_call_function_and_parameters(self): + code = dedent("""\ + class A(object): + def __call__(self, p): + pass + A()("") + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + scope = self.project.get_pymodule(self.mod).get_scope() + p_object = scope.get_scopes()[0].get_scopes()[0]["p"].get_object() + self.assertTrue(isinstance(p_object.get_type(), rope.base.builtins.Str)) + + +def test_report_change_in_libutils(self): + self.project.prefs["automatic_soa"] = True + code = dedent("""\ + class C(object): + pass + def f(p): + pass + f(C()) + """) + with open(self.mod.real_path, "w") as mod_file: + mod_file.write(code) + + rope.base.libutils.report_change(self.project, self.mod.real_path, "") + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + f_scope = pymod["f"].get_object().get_scope() + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(c_class, p_type) + + +def test_report_libutils_and_analyze_all_modules(self): + code = dedent("""\ + class C(object): + pass + def f(p): + pass + f(C()) + """) + self.mod.write(code) + rope.base.libutils.analyze_modules(self.project) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + f_scope = pymod["f"].get_object().get_scope() + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(c_class, p_type) + + +def test_validation_problems_for_objectdb_retrievals(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write(dedent("""\ + l = [] + var = l.pop() + """)) + mod2.write(dedent("""\ + import mod1 + + class C(object): + pass + mod1.l.append(C()) + """)) + self.pycore.analyze_module(mod2) + + pymod2 = self.project.get_pymodule(mod2) + c_class = pymod2["C"].get_object() + pymod1 = self.project.get_pymodule(mod1) + var_pyname = pymod1["var"] + self.assertEqual(c_class, var_pyname.get_object().get_type()) + mod2.write(dedent("""\ + import mod1 + + mod1.l.append("") + """)) + self.assertNotEqual( + c_class, var_pyname.get_object().get_type(), "Class `C` no more exists" + ) + + +def test_validation_problems_for_changing_builtin_types(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + l = [] + l.append("") + """)) + self.pycore.analyze_module(mod1) + + mod1.write(dedent("""\ + l = {} + v = l["key"] + """)) + pymod1 = self.project.get_pymodule(mod1) # noqa + var = pymod1["v"].get_object() # noqa + + +def test_always_returning_containing_class_for_selfs(self): + code = dedent("""\ + class A(object): + def f(p): + return p + class B(object): + pass + b = B() + b.f() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + a_class = pymod["A"].get_object() + f_scope = a_class.get_scope().get_scopes()[0] + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(a_class, p_type) + + +def _get_stmt_end(self, lineno): + base_indents = _get_line_indents(self.lines[lineno]) + for i in range(lineno + 1, len(self.lines)): + if _get_line_indents(self.lines[i]) <= base_indents: + return i - 1 + return lineno + + +def _changed(self, resource): + if not resource.is_folder(): + self.update_resource(resource) + + +def test_following_function_calls_when_asked_to(self): + code = dedent("""\ + class A(object): + pass + class C(object): + def __init__(self, arg): + self.attr = arg + def f(p): + return C(p) + c = f(A()) + x = c.attr + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod, followed_calls=1) + pymod = self.project.get_pymodule(self.mod) + a_class = pymod["A"].get_object() + x_var = pymod["x"].get_object().get_type() + self.assertEqual(a_class, x_var) + + +def test_set_comprehension(self): + code = dedent("""\ + x = {s.strip() for s in X()} + x.add('x') + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + x_var = pymod["x"].pyobject.get() + +@path C:/Repos/ekr-rope/ropetest/ +from textwrap import dedent + +import unittest + +from rope.base import builtins, libutils, pyobjects +from ropetest import testutils +from rope.base.builtins import Dict + + +@others +@language python +@tabwidth -4 + +class BuiltinTypesTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_case(self): + self.mod.write("l = []\n") + pymod = self.project.get_pymodule(self.mod) + self.assertTrue("append" in pymod["l"].get_object()) + + +def test_holding_type_information(self): + self.mod.write(dedent("""\ + class C(object): + pass + l = [C()] + a_var = l.pop() + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_get_items(self): + self.mod.write(dedent("""\ + class C(object): + def __getitem__(self, i): + return C() + c = C() + a_var = c[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_get_items_for_lists(self): + self.mod.write(dedent("""\ + class C(object): + pass + l = [C()] + a_var = l[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def _moved(self, resource, newresource): + if not resource.is_folder(): + modname = self._module_name(resource) + if modname in self.names: + del self.names[modname] + self.update_resource(newresource) + + +def test_get_items_from_slices(self): + self.mod.write(dedent("""\ + class C(object): + pass + l = [C()] + a_var = l[:].pop() + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_simple_for_loops(self): + self.mod.write(dedent("""\ + class C(object): + pass + l = [C()] + for c in l: + a_var = c + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_definition_location_for_loop_variables(self): + self.mod.write(dedent("""\ + class C(object): + pass + l = [C()] + for c in l: + pass + """)) + pymod = self.project.get_pymodule(self.mod) + c_var = pymod["c"] + self.assertEqual((pymod, 4), c_var.get_definition_location()) + + +def test_simple_case_for_dicts(self): + self.mod.write("d = {}\n") + pymod = self.project.get_pymodule(self.mod) + self.assertTrue("get" in pymod["d"].get_object()) + + +def test_get_item_for_dicts(self): + self.mod.write(dedent("""\ + class C(object): + pass + d = {1: C()} + a_var = d[1] + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_dict_function_parent(self): + self.mod.write(dedent("""\ + d = {1: 2} + a_var = d.keys() + """)) + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["d"].get_object()["keys"].get_object() + self.assertEqual(type(a_var.parent), Dict) + + +def test_popping_dicts(self): + self.mod.write(dedent("""\ + class C(object): + pass + d = {1: C()} + a_var = d.pop(1) + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_getting_keys_from_dicts(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {C1(): C2()} + for c in d.keys(): + a_var = c + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C1"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_getting_values_from_dicts(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {C1(): C2()} + for c in d.values(): + a_var = c + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C2"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_getting_iterkeys_from_dicts(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {C1(): C2()} + for c in d.keys(): + a_var = c + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C1"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def _removed(self, resource): + if not resource.is_folder(): + modname = self._module_name(resource) + if modname in self.names: + del self.names[modname] + + + +def test_getting_itervalues_from_dicts(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {C1(): C2()} + for c in d.values(): + a_var = c + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C2"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_using_copy_for_dicts(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {C1(): C2()} + for c in d.copy(): + a_var = c + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C1"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_tuple_assignments_for_items(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {C1(): C2()} + key, value = d.items()[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + key = pymod["key"].get_object() + value = pymod["value"].get_object() + self.assertEqual(c1_class, key.get_type()) + self.assertEqual(c2_class, value.get_type()) + + +def test_tuple_assignment_for_lists(self): + self.mod.write(dedent("""\ + class C(object): + pass + l = [C(), C()] + a, b = l + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c_class, a_var.get_type()) + self.assertEqual(c_class, b_var.get_type()) + + +def test_tuple_assignments_for_iteritems_in_fors(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {C1(): C2()} + for x, y in d.items(): + a = x; + b = y + """)) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_simple_tuple_assignments(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + a, b = C1(), C2() + """)) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_overriding_builtin_names(self): + self.mod.write(dedent("""\ + class C(object): + pass + list = C + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + list_var = pymod["list"].get_object() + self.assertEqual(c_class, list_var) + + +def test_simple_builtin_scope_test(self): + self.mod.write("l = list()\n") + pymod = self.project.get_pymodule(self.mod) + self.assertTrue("append" in pymod["l"].get_object()) + + +def test_simple_sets(self): + self.mod.write("s = set()\n") + pymod = self.project.get_pymodule(self.mod) + self.assertTrue("add" in pymod["s"].get_object()) + + +def test_making_lists_using_the_passed_argument_to_init(self): + self.mod.write(dedent("""\ + class C(object): + pass + l1 = [C()] + l2 = list(l1) + a_var = l2.pop() + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def submodules(mod): + if isinstance(mod, resources.File): + if mod.name.endswith(".py") and mod.name != "__init__.py": + return {mod} + return set() + if not mod.has_child("__init__.py"): + return set() + result = {mod} + for child in mod.get_children(): + result |= submodules(child) + return result + +def test_making_tuples_using_the_passed_argument_to_init(self): + self.mod.write(dedent("""\ + class C(object): + pass + l1 = [C()] + l2 = tuple(l1) + a_var = l2[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_making_sets_using_the_passed_argument_to_init(self): + self.mod.write(dedent("""\ + class C(object): + pass + l1 = [C()] + l2 = set(l1) + a_var = l2.pop() + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_making_dicts_using_the_passed_argument_to_init(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + l1 = [(C1(), C2())] + l2 = dict(l1) + a, b = l2.items()[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_range_builtin_function(self): + self.mod.write("l = range(1)\n") + pymod = self.project.get_pymodule(self.mod) + l = pymod["l"].get_object() + self.assertTrue("append" in l) + + +def test_reversed_builtin_function(self): + self.mod.write(dedent("""\ + class C(object): + pass + l = [C()] + for x in reversed(l): + a_var = x + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_sorted_builtin_function(self): + self.mod.write(dedent("""\ + class C(object): + pass + l = [C()] + a_var = sorted(l).pop() + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_super_builtin_function(self): + self.mod.write(dedent("""\ + class C(object): + pass + class A(object): + def a_f(self): + return C() + class B(A): + def b_f(self): + return super(B, self).a_f() + a_var = B.b_f() + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_file_builtin_type(self): + self.mod.write(dedent("""\ + for line in open("file.txt"): + a_var = line + """)) + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["a_var"].get_object() + self.assertTrue(isinstance(a_var.get_type(), builtins.Str)) + + +def test_property_builtin_type(self): + self.mod.write("p = property()\n") + pymod = self.project.get_pymodule(self.mod) + p_var = pymod["p"].get_object() + self.assertTrue("fget" in p_var) + + +def test_lambda_functions(self): + self.mod.write("l = lambda: 1\n") + pymod = self.project.get_pymodule(self.mod) + l_var = pymod["l"].get_object() + self.assertEqual(pyobjects.get_base_type("Function"), l_var.get_type()) + + +@path C:/Repos/ekr-rope/rope/contrib/autoimport/ +"""AutoImport module for rope.""" +import re +import sqlite3 +import sys +from collections import OrderedDict +from concurrent.futures import Future, ProcessPoolExecutor, as_completed +from itertools import chain +from pathlib import Path +from typing import Generator, Iterable, List, Optional, Set, Tuple, Iterator + +from rope.base import exceptions, libutils, resourceobserver, taskhandle +from rope.base.project import Project +from rope.base.resources import Resource +from rope.contrib.autoimport.defs import ( + ModuleFile, + Name, + NameType, + Package, + PackageType, + SearchResult, + Source, +) +from rope.contrib.autoimport.parse import get_names +from rope.contrib.autoimport.utils import ( + get_files, + get_modname_from_path, + get_package_tuple, + sort_and_deduplicate, + sort_and_deduplicate_tuple, +) +from rope.refactor import importutils +from rope.contrib.autoimport import models + + +@others +@language python +@tabwidth -4 + +def test_lambda_function_definition(self): + self.mod.write("l = lambda x, y = 2, *a, **b: x + y\n") + pymod = self.project.get_pymodule(self.mod) + l_var = pymod["l"].get_object() + self.assertTrue(l_var.get_name() is not None) + self.assertEqual(len(l_var.get_param_names()), 4) + self.assertEqual((pymod, 1), pymod["l"].get_definition_location()) + + +def test_lambdas_that_return_unknown(self): + self.mod.write("a_var = (lambda: None)()\n") + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["a_var"].get_object() + self.assertTrue(a_var is not None) + + +def test_builtin_zip_function(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + c1_list = [C1()] + c2_list = [C2()] + a, b = zip(c1_list, c2_list)[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_builtin_zip_function_with_more_than_two_args(self): + self.mod.write(dedent("""\ + class C1(object): + pass + class C2(object): + pass + c1_list = [C1()] + c2_list = [C2()] + a, b, c = zip(c1_list, c2_list, c1_list)[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + c_var = pymod["c"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + self.assertEqual(c1_class, c_var.get_type()) + + +def test_wrong_arguments_to_zip_function(self): + self.mod.write(dedent("""\ + class C1(object): + pass + c1_list = [C1()] + a, b = zip(c1_list, 1)[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() # noqa + self.assertEqual(c1_class, a_var.get_type()) + + +def test_enumerate_builtin_function(self): + self.mod.write(dedent("""\ + class C(object): + pass + l = [C()] + for i, x in enumerate(l): + a_var = x + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_builtin_class_get_name(self): + self.assertEqual("object", builtins.builtins["object"].get_object().get_name()) + self.assertEqual( + "property", builtins.builtins["property"].get_object().get_name() + ) + + +def test_star_args_and_double_star_args(self): + self.mod.write(dedent("""\ + def func(p, *args, **kwds): + pass + """)) + pymod = self.project.get_pymodule(self.mod) + func_scope = pymod["func"].get_object().get_scope() + args = func_scope["args"].get_object() + kwds = func_scope["kwds"].get_object() + self.assertTrue(isinstance(args.get_type(), builtins.List)) + self.assertTrue(isinstance(kwds.get_type(), builtins.Dict)) + + +def test_simple_list_comprehension_test(self): + self.mod.write("a_var = [i for i in range(10)]\n") + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["a_var"].get_object() + self.assertTrue(isinstance(a_var.get_type(), builtins.List)) + + +def test_simple_list_generator_expression(self): + self.mod.write("a_var = (i for i in range(10))\n") + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["a_var"].get_object() + self.assertTrue(isinstance(a_var.get_type(), builtins.Iterator)) + + +def get_future_names( + packages: List[Package], underlined: bool, job_set: taskhandle.BaseJobSet +) -> Generator[Future, None, None]: + """Get all names as futures.""" + with ProcessPoolExecutor() as executor: + for package in packages: + for module in get_files(package, underlined): + job_set.started_job(module.modname) + job_set.increment() + yield executor.submit(get_names, module, package) + + + +def test_iter_builtin_function(self): + self.mod.write(dedent("""\ + class C(object): + pass + l = [C()] + for c in iter(l): + a_var = c + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_simple_int_type(self): + self.mod.write("l = 1\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + builtins.builtins["int"].get_object(), pymod["l"].get_object().get_type() + ) + + +def test_simple_float_type(self): + self.mod.write("l = 1.0\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + builtins.builtins["float"].get_object(), pymod["l"].get_object().get_type() + ) + + +def test_simple_float_type2(self): + self.mod.write("l = 1e1\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + builtins.builtins["float"].get_object(), pymod["l"].get_object().get_type() + ) + + +def test_simple_complex_type(self): + self.mod.write("l = 1.0j\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + builtins.builtins["complex"].get_object(), + pymod["l"].get_object().get_type(), + ) + + +def test_handling_unaryop_on_ints(self): + self.mod.write("l = -(1)\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + builtins.builtins["int"].get_object(), pymod["l"].get_object().get_type() + ) + + +def test_handling_binop_on_ints(self): + self.mod.write("l = 1 + 1\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + builtins.builtins["int"].get_object(), pymod["l"].get_object().get_type() + ) + + +def test_handling_compares(self): + self.mod.write("l = 1 == 1\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + builtins.builtins["bool"].get_object(), pymod["l"].get_object().get_type() + ) + + +def test_handling_boolops(self): + self.mod.write("l = 1 and 2\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + builtins.builtins["int"].get_object(), pymod["l"].get_object().get_type() + ) + + +def test_binary_or_left_value_unknown(self): + code = "var = (asdsd or 3)\n" + pymod = libutils.get_string_module(self.project, code) + self.assertEqual( + builtins.builtins["int"].get_object(), pymod["var"].get_object().get_type() + ) + + +def filter_packages( + packages: Iterable[Package], underlined: bool, existing: List[str] +) -> Iterable[Package]: + """Filter list of packages to parse.""" + if underlined: + + def filter_package(package: Package) -> bool: + return package.name not in existing + + else: + + def filter_package(package: Package) -> bool: + return package.name not in existing and not package.name.startswith("_") + + return filter(filter_package, packages) + + + +def test_unknown_return_object(self): + src = dedent("""\ + import sys + def foo(): + res = set(sys.builtin_module_names) + if foo: res.add(bar) + """) + self.project.prefs["import_dynload_stdmods"] = True + self.mod.write(src) + self.project.pycore.analyze_module(self.mod) + + +def test_abstractmethods_attribute(self): + # see http://bugs.python.org/issue10006 for details + src = "class SubType(type): pass\nsubtype = SubType()\n" + self.mod.write(src) + self.project.pycore.analyze_module(self.mod) + + + +class BuiltinModulesTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project( + extension_modules=["time", "invalid", "invalid.sub"] + ) + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_case(self): + self.mod.write("import time") + pymod = self.project.get_pymodule(self.mod) + self.assertTrue("time" in pymod["time"].get_object()) + + +def test_ignored_extensions(self): + self.mod.write("import os") + pymod = self.project.get_pymodule(self.mod) + self.assertTrue("rename" not in pymod["os"].get_object()) + + +def test_ignored_extensions_2(self): + self.mod.write("import os") + pymod = self.project.get_pymodule(self.mod) + self.assertTrue("rename" not in pymod["os"].get_object()) + + +def test_nonexistent_modules(self): + self.mod.write("import invalid") + pymod = self.project.get_pymodule(self.mod) + pymod["invalid"].get_object() + + +def test_nonexistent_modules_2(self): + self.mod.write(dedent("""\ + import invalid + import invalid.sub + """)) + pymod = self.project.get_pymodule(self.mod) + invalid = pymod["invalid"].get_object() + self.assertTrue("sub" in invalid) + + +class AutoImport: + """A class for finding the module that provides a name. + + This class maintains a cache of global names in python modules. + Note that this cache is not accurate and might be out of date. + + """ + + connection: sqlite3.Connection + underlined: bool + project: Project + project_package: Package + + @others + +def test_time_in_std_mods(self): + import rope.base.stdmods + + self.assertTrue("time" in rope.base.stdmods.standard_modules()) + + +def test_timemodule_normalizes_to_time(self): + import rope.base.stdmods + + self.assertEqual(rope.base.stdmods.normalize_so_name("timemodule.so"), "time") + +@path C:/Repos/ekr-rope/ropetest/ +from textwrap import dedent + +import unittest + +import rope.base.evaluate +from rope.base import libutils +from rope.base import exceptions, worder, codeanalyze +from rope.base.codeanalyze import SourceLinesAdapter, LogicalLineFinder, get_block_start +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class SourceLinesAdapterTest(unittest.TestCase): + @others + +def test_source_lines_simple(self): + to_lines = SourceLinesAdapter("line1\nline2\n") + self.assertEqual("line1", to_lines.get_line(1)) + self.assertEqual("line2", to_lines.get_line(2)) + self.assertEqual("", to_lines.get_line(3)) + self.assertEqual(3, to_lines.length()) + + +def test_source_lines_get_line_number(self): + to_lines = SourceLinesAdapter("line1\nline2\n") + self.assertEqual(1, to_lines.get_line_number(0)) + self.assertEqual(1, to_lines.get_line_number(5)) + self.assertEqual(2, to_lines.get_line_number(7)) + self.assertEqual(3, to_lines.get_line_number(12)) + + +def test_source_lines_get_line_start(self): + to_lines = SourceLinesAdapter("line1\nline2\n") + self.assertEqual(0, to_lines.get_line_start(1)) + self.assertEqual(6, to_lines.get_line_start(2)) + self.assertEqual(12, to_lines.get_line_start(3)) + + +def test_source_lines_get_line_end(self): + to_lines = SourceLinesAdapter("line1\nline2\n") + self.assertEqual(5, to_lines.get_line_end(1)) + self.assertEqual(11, to_lines.get_line_end(2)) + self.assertEqual(12, to_lines.get_line_end(3)) + + +def test_source_lines_last_line_with_no_new_line(self): + to_lines = SourceLinesAdapter("line1") + self.assertEqual(1, to_lines.get_line_number(5)) + + + +class WordRangeFinderTest(unittest.TestCase): + @others + +def __init__(self, project: Project, observe=True, underlined=False, memory=True): + """Construct an AutoImport object. + + Parameters + ___________ + project : rope.base.project.Project + the project to use for project imports + observe : bool + if true, listen for project changes and update the cache. + underlined : bool + If `underlined` is `True`, underlined names are cached, too. + memory : bool + if true, don't persist to disk + """ + self.project = project + project_package = get_package_tuple(Path(project.root.real_path), project) + assert project_package is not None + assert project_package.path is not None + self.project_package = project_package + self.underlined = underlined + db_path: str + if memory or project.ropefolder is None: + db_path = ":memory:" + else: + db_path = str(Path(project.ropefolder.real_path) / "autoimport.db") + self.connection = sqlite3.connect(db_path) + self._setup_db() + if observe: + observer = resourceobserver.ResourceObserver( + changed=self._changed, moved=self._moved, removed=self._removed + ) + project.add_observer(observer) + + +def _find_primary(self, code, offset): + word_finder = worder.Worder(code) + return word_finder.get_primary_at(offset) + + +def _annotated_code(self, annotated_code): + """ + Split annotated code into raw code and annotation. + + Odd lines in `annotated_code` is the actual Python code. + + Even lines in `annotated_code` are single-char annotation for the + previous line. + + The annotation may contain one extra character which annotates the + newline/end of line character. + """ + code_lines = annotated_code.splitlines()[::2] + annotations_lines = annotated_code.splitlines()[1::2] + if len(annotations_lines) < len(code_lines): + annotations_lines.append("") + for idx, (line, line_ann) in enumerate(zip(code_lines, annotations_lines)): + newline_ann_char = 1 # for annotation of the end of line character + self.assertLessEqual( + len(line_ann), + len(line) + newline_ann_char, + msg="Extra character in annotations", + ) + line_ann = line_ann.rstrip() + line_ann += " " * (len(line) - len(line_ann)) + if len(line_ann) != len(line) + newline_ann_char: + line_ann += " " + self.assertEqual(len(line_ann), len(line) + newline_ann_char) + annotations_lines[idx] = line_ann + code, annotations = "\n".join(code_lines), "\n".join(annotations_lines) + if code[-1] != "\n": + annotations = annotations[:-1] + self.assertEqual(len(code) + code.count("\n"), len(annotations)) + return code, annotations + + +def _make_offset_annotation(self, code, func): + """ + Create annotation by calling `func(offset)` for every offset in `code`. + + For example, when the annotated code looks like so: + + import a.b.c.d + ++++++++ + + This means that `func(offset)` returns True whenever offset points to + the 'a.b.c.d' part and returns False everywhere else. + """ + + def _annotation_char(offset): + ann_char = "+" if func(offset) else " " + if code[offset] == "\n": + ann_char = ann_char + "\n" + return ann_char + + return "".join([_annotation_char(offset) for offset in range(len(code))]) + + +def assert_equal_annotation(self, code, expected, actual): + if expected != actual: + msg = ["Annotation does not match:\n"] + for line, line_exp, line_actual in zip( + code.splitlines(), expected.splitlines(), actual.splitlines() + ): + msg.append(" " + line + "\n") + if line_exp != line_actual: + msg.append("e " + line_exp + "\n") + msg.append("a " + line_actual + "\n") + self.fail("".join(msg)) + + +def test_keyword_before_parens(self): + code = dedent("""\ + if (a_var).an_attr: + pass + """) + self.assertEqual("(a_var).an_attr", self._find_primary(code, code.index(":"))) + + +def test_inside_parans(self): + code = "a_func(a_var)" + self.assertEqual("a_var", self._find_primary(code, 10)) + + +def test_simple_names(self): + code = "a_var = 10" + self.assertEqual("a_var", self._find_primary(code, 3)) + + +def test_function_calls(self): + code = "sample_function()" + self.assertEqual("sample_function", self._find_primary(code, 10)) + + +def test_attribute_accesses(self): + code = "a_var.an_attr" + self.assertEqual("a_var.an_attr", self._find_primary(code, 10)) + + +def test_word_finder_on_word_beginning(self): + code = "print(a_var)\n" + word_finder = worder.Worder(code) + result = word_finder.get_word_at(code.index("a_var")) + self.assertEqual("a_var", result) + + +def _setup_db(self): + models.Name.create_table(self.connection) + models.Package.create_table(self.connection) + self.connection.commit() + + +def test_word_finder_on_primary_beginning(self): + code = "print(a_var)\n" + result = self._find_primary(code, code.index("a_var")) + self.assertEqual("a_var", result) + + +def test_word_finder_on_word_ending(self): + code = "print(a_var)\n" + word_finder = worder.Worder(code) + result = word_finder.get_word_at(code.index("a_var") + 5) + self.assertEqual("a_var", result) + + +def test_word_finder_on_primary_ending(self): + code = "print(a_var)\n" + result = self._find_primary(code, code.index("a_var") + 5) + self.assertEqual("a_var", result) + + +def test_word_finder_on_primaries_with_dots_inside_parens(self): + code = "(a_var.\nattr)" + result = self._find_primary(code, code.index("attr") + 1) + self.assertEqual("a_var.\nattr", result) + + +def test_word_finder_on_primary_like_keyword(self): + code = "is_keyword = False\n" + result = self._find_primary(code, 1) + self.assertEqual("is_keyword", result) + + +def test_keyword_before_parens_no_space(self): + code = dedent("""\ + if(a_var).an_attr: + pass + """) + self.assertEqual("(a_var).an_attr", self._find_primary(code, code.index(":"))) + + +def test_strings(self): + code = '"a string".split()' + self.assertEqual('"a string".split', self._find_primary(code, 14)) + + +def test_function_calls2(self): + code = 'file("afile.txt").read()' + self.assertEqual('file("afile.txt").read', self._find_primary(code, 18)) + + +def test_parens(self): + code = '("afile.txt").split()' + self.assertEqual('("afile.txt").split', self._find_primary(code, 18)) + + +def test_function_with_no_param(self): + code = "AClass().a_func()" + self.assertEqual("AClass().a_func", self._find_primary(code, 12)) + + +def _fix_incomplete_try_blocks(self, lineno, indents): + block_start = lineno + last_indents = indents + while block_start > 0: + block_start = ( + rope.base.codeanalyze.get_block_start( + ArrayLinesAdapter(self.lines), block_start + ) + - 1 + ) + if self.lines[block_start].strip().startswith("try:"): + indents = _get_line_indents(self.lines[block_start]) + if indents > last_indents: + continue + last_indents = indents + block_end = self._find_matching_deindent(block_start) + line = self.lines[block_end].strip() + if not ( + line.startswith("finally:") + or line.startswith("except ") + or line.startswith("except:") + ): + self._insert(block_end, " " * indents + "finally:") + self._insert(block_end + 1, " " * indents + " pass") + + +def import_assist(self, starting: str): + """ + Find modules that have a global name that starts with `starting`. + + For a more complete list, use the search or search_full methods. + + Parameters + __________ + starting : str + what all the names should start with + Return + __________ + Return a list of ``(name, module)`` tuples + """ + results = self._execute( + models.Name.import_assist.select("name", "module", "source"), (starting,) + ).fetchall() + return sort_and_deduplicate_tuple( + results + ) # Remove duplicates from multiple occurrences of the same item + + +def test_function_with_multiple_param(self): + code = 'AClass(a_param, another_param, "a string").a_func()' + self.assertEqual( + 'AClass(a_param, another_param, "a string").a_func', + self._find_primary(code, 44), + ) + + +def test_param_expressions(self): + code = "AClass(an_object.an_attr).a_func()" + self.assertEqual("an_object.an_attr", self._find_primary(code, 20)) + + +def test_string_parens(self): + code = 'a_func("(").an_attr' + self.assertEqual('a_func("(").an_attr', self._find_primary(code, 16)) + + +def test_extra_spaces(self): + code = 'a_func ( "(" ) . an_attr' + self.assertEqual('a_func ( "(" ) . an_attr', self._find_primary(code, 26)) + + +def test_relative_import(self): + code = "from .module import smt" + self.assertEqual(".module", self._find_primary(code, 5)) + + +def test_functions_on_ending_parens(self): + code = "A()" + self.assertEqual("A()", self._find_primary(code, 2)) + + +def test_splitted_statement(self): + word_finder = worder.Worder("an_object.an_attr") + self.assertEqual( + ("an_object", "an_at", 10), word_finder.get_splitted_primary_before(15) + ) + + +def test_empty_splitted_statement(self): + word_finder = worder.Worder("an_attr") + self.assertEqual(("", "an_at", 0), word_finder.get_splitted_primary_before(5)) + + +def test_empty_splitted_statement2(self): + word_finder = worder.Worder("an_object.") + self.assertEqual( + ("an_object", "", 10), word_finder.get_splitted_primary_before(10) + ) + + +def test_empty_splitted_statement3(self): + word_finder = worder.Worder("") + self.assertEqual(("", "", 0), word_finder.get_splitted_primary_before(0)) + + +def search(self, name: str, exact_match: bool = False) -> List[Tuple[str, str]]: + """ + Search both modules and names for an import string. + + This is a simple wrapper around search_full with basic sorting based on Source. + + Returns a sorted list of import statement, modname pairs + """ + results: List[Tuple[str, str, int]] = [ + (statement, import_name, source) + for statement, import_name, source, type in self.search_full( + name, exact_match + ) + ] + return sort_and_deduplicate_tuple(results) + + +def test_empty_splitted_statement4(self): + word_finder = worder.Worder("a_var = ") + self.assertEqual(("", "", 8), word_finder.get_splitted_primary_before(8)) + + +def test_empty_splitted_statement5(self): + word_finder = worder.Worder("a.") + self.assertEqual(("a", "", 2), word_finder.get_splitted_primary_before(2)) + + +def test_operators_inside_parens(self): + code = "(a_var + another_var).reverse()" + self.assertEqual("(a_var + another_var).reverse", self._find_primary(code, 25)) + + +def test_dictionaries(self): + code = 'print({1: "one", 2: "two"}.keys())' + self.assertEqual('{1: "one", 2: "two"}.keys', self._find_primary(code, 29)) + + +def test_following_parens(self): + code = "a_var = a_func()()" + result = self._find_primary(code, code.index(")(") + 3) + self.assertEqual("a_func()()", result) + + +def test_comments_for_finding_statements(self): + code = "# var2 . \n var3" + self.assertEqual("var3", self._find_primary(code, code.index("3"))) + + +def test_str_in_comments_for_finding_statements(self): + code = '# "var2" . \n var3' + self.assertEqual("var3", self._find_primary(code, code.index("3"))) + + +def test_comments_for_finding_statements2(self): + code = 'var1 + "# var2".\n var3' + self.assertEqual("var3", self._find_primary(code, 21)) + + +def test_comments_for_finding_statements3(self): + code = '"" + # var2.\n var3' + self.assertEqual("var3", self._find_primary(code, 21)) + + +def test_is_import_statement(self): + code, annotations = self._annotated_code(annotated_code=dedent("""\ + import a.b.c.d + ++++++++ + from a.b import c + + import a.b.c.d as d + +++++++++++++ + from a.b import c as e + + from a.b import ( + + abc + + ) + + result = a.b.c.d.f() + + """)) + word_finder = worder.Worder(code) + self.assert_equal_annotation( + code, + annotations, + self._make_offset_annotation(code, word_finder.is_import_statement), + ) + + +def search_full( + self, + name: str, + exact_match: bool = False, + ignored_names: Set[str] = set(), +) -> Generator[SearchResult, None, None]: + """ + Search both modules and names for an import string. + + Parameters + __________ + name: str + Name to search for + exact_match: bool + If using exact_match, only search for that name. + Otherwise, search for any name starting with that name. + ignored_names : Set[str] + Will ignore any names in this set + + Return + __________ + Unsorted Generator of SearchResults. Each is guaranteed to be unique. + """ + results = set(self._search_name(name, exact_match)) + results = results.union(self._search_module(name, exact_match)) + for result in results: + if result.name not in ignored_names: + yield result + + +def test_is_import_statement_finding(self): + code = dedent("""\ + import mod + a_var = 10 + """) + word_finder = worder.Worder(code) + self.assertTrue(word_finder.is_import_statement(code.index("mod") + 1)) + self.assertFalse(word_finder.is_import_statement(code.index("a_var") + 1)) + + +def test_is_import_statement_finding2(self): + code = dedent("""\ + import a.b.c.d + result = a.b.c.d.f() + """) + word_finder = worder.Worder(code) + self.assertFalse(word_finder.is_import_statement(code.rindex("d") + 1)) + + +def test_word_parens_range(self): + code = dedent("""\ + s = str() + s.title() + """) + word_finder = worder.Worder(code) + result = word_finder.get_word_parens_range(code.rindex("()") - 1) + self.assertEqual((len(code) - 3, len(code) - 1), result) + + +def test_getting_primary_before_get_index(self): + code = "\na = (b + c).d[0]()\n" + result = self._find_primary(code, len(code) - 2) + self.assertEqual("(b + c).d[0]()", result) + + +def test_getting_primary_and_strings_at_the_end_of_line(self): + code = "f('\\'')\n" + result = self._find_primary(code, len(code) - 1) # noqa + + +def test_getting_primary_and_not_crossing_newlines(self): + code = "\na = (b + c)\n(4 + 1).x\n" + result = self._find_primary(code, len(code) - 1) + self.assertEqual("(4 + 1).x", result) + + +# XXX: concatenated string literals +def xxx_test_getting_primary_cancatenating_strs(self): + code = 's = "a"\n"b" "c"\n' + result = self._find_primary(code, len(code) - 2) + self.assertEqual('"b" "c"', result) + + +def test_is_a_function_being_called_with_parens_on_next_line(self): + code = "func\n(1, 2)\n" + word_finder = worder.Worder(code) + self.assertFalse(word_finder.is_a_function_being_called(1)) + + +# XXX: handling triple quotes +def xxx_test_triple_quotes(self): + code = 's = """string"""\n' + result = self._find_primary(code, len(code) - 1) + self.assertEqual('"""string"""', result) + + +def test_triple_quotes_spanning_multiple_lines(self): + code = 's = """\\\nl1\nl2\n """\n' + result = self._find_primary(code, len(code) - 2) + self.assertEqual('"""\\\nl1\nl2\n """', result) + + +def _search_name( + self, name: str, exact_match: bool = False +) -> Generator[SearchResult, None, None]: + """ + Search both names for available imports. + + Returns the import statement, import name, source, and type. + """ + if not exact_match: + name = name + "%" # Makes the query a starts_with query + for import_name, module, source, name_type in self._execute( + models.Name.search_by_name_like.select("name", "module", "source", "type"), + (name,), + ): + yield ( + SearchResult( + f"from {module} import {import_name}", + import_name, + source, + name_type, + ) + ) + + +def test_get_word_parens_range_and_string_literals(self): + code = 'f(1, ")", 2)\n' + word_finder = worder.Worder(code) + result = word_finder.get_word_parens_range(0) + self.assertEqual((1, len(code) - 1), result) + + +def test_is_assigned_here_for_equality_test(self): + code = "a == 1\n" + word_finder = worder.Worder(code) + self.assertFalse(word_finder.is_assigned_here(0)) + + +def test_is_assigned_here_for_not_equal_test(self): + code = "a != 1\n" + word_finder = worder.Worder(code) + self.assertFalse(word_finder.is_assigned_here(0)) + + +# XXX: is_assigned_here should work for tuple assignments +def xxx_test_is_assigned_here_for_tuple_assignment(self): + code = "a, b = (1, 2)\n" + word_finder = worder.Worder(code) + self.assertTrue(word_finder.is_assigned_here(0)) + + +def test_is_from_statement(self): + code, annotations = self._annotated_code(annotated_code=dedent("""\ + import a.b.c.d + + from a.b import c + +++++++++++++ + import a.b.c.d as d + + from a.b import c as e + ++++++++++++++++++ + from a.b import ( + +++++++++++++ + abc + ++++++++ + ) + ++ + result = a.b.c.d.f() + + """)) + word_finder = worder.Worder(code) + self.assert_equal_annotation( + code, + annotations, + self._make_offset_annotation(code, word_finder.is_from_statement), + ) + + +def test_is_from_statement_module(self): + code, annotations = self._annotated_code(annotated_code=dedent("""\ + import a.b.c.d + + from a.b import c + +++++ + import a.b.c.d as d + + from a.b import c as e + +++++ + from a.b import ( + +++++ + abc + + ) + + result = a.b.c.d.f() + + """)) + word_finder = worder.Worder(code) + self.assert_equal_annotation( + code, + annotations, + self._make_offset_annotation(code, word_finder.is_from_statement_module), + ) + + +def test_is_import_statement_aliased_module(self): + code, annotations = self._annotated_code(annotated_code=dedent("""\ + import a.b.c.d + + from a.b import c + + import a.b.c.d as d + +++++++ + from a.b import c as e + + from a.b import ( + + abc + + ) + + import mod1, \\ + + mod2 as c, mod3, mod4 as d + +++++ +++++ + result = a.b.c.d.f() + + """)) + word_finder = worder.Worder(code) + self.assert_equal_annotation( + code, + annotations, + self._make_offset_annotation( + code, word_finder.is_import_statement_aliased_module + ), + ) + + +def test_is_from_aliased(self): + code, annotations = self._annotated_code(annotated_code=dedent("""\ + import a.b.c.d + + from a.b import c + + import a.b.c.d as d + + from a.b import c as e + ++ + from a.b import ( + + abc + + ) + + from a.b import mod1, \\ + + mod2 as c, mod3, mod4 as d + +++++ +++++ + result = a.b.c.d.f() + + """)) + word_finder = worder.Worder(code) + self.assert_equal_annotation( + code, + annotations, + self._make_offset_annotation(code, word_finder.is_from_aliased), + ) + + +def test_is_from_with_from_import_and_multiline_parens(self): + code = "from mod import \\\n (f,\n g, h)\n" + word_finder = worder.Worder(code) + self.assertTrue(word_finder.is_from_statement(code.rindex("g"))) + + +def test_is_from_with_from_import_and_line_breaks_in_the_middle(self): + code = "from mod import f,\\\n g\n" + word_finder = worder.Worder(code) + self.assertTrue(word_finder.is_from_statement(code.rindex("g"))) + + +def _search_module( + self, name: str, exact_match: bool = False +) -> Generator[SearchResult, None, None]: + """ + Search both modules for available imports. + + Returns the import statement, import name, source, and type. + """ + if not exact_match: + name = name + "%" # Makes the query a starts_with query + for module, source in self._execute( + models.Name.search_submodule_like.select("module", "source"), (name,) + ): + parts = module.split(".") + import_name = parts[-1] + remaining = parts[0] + for part in parts[1:-1]: + remaining += "." + remaining += part + yield ( + SearchResult( + f"from {remaining} import {import_name}", + import_name, + source, + NameType.Module.value, + ) + ) + for module, source in self._execute( + models.Name.search_module_like.select("module", "source"), (name,) + ): + if "." in module: + continue + yield SearchResult( + f"import {module}", module, source, NameType.Module.value + ) + + +def test_is_function_keyword_parameter(self): + code, annotations = self._annotated_code(annotated_code=dedent("""\ + func(param=1) + ++++++ + func( + + param=1 + ++++++ + ) + + def func(param=1): + ++++++ + pass + + """)) + word_finder = worder.Worder(code) + self.assert_equal_annotation( + code, + annotations, + self._make_offset_annotation( + code, word_finder.is_function_keyword_parameter + ), + ) + + +def test_one_letter_is_function_keyword_parameter(self): + code = "f(p=1)\n" + word_finder = worder.Worder(code) + index = code.rindex("p") + self.assertTrue(word_finder.is_function_keyword_parameter(index)) + + +def test_find_parens_start(self): + code = "f(p)\n" + finder = worder.Worder(code) + self.assertEqual(1, finder.find_parens_start_from_inside(2)) + + +def test_underlined_find_parens_start(self): + code = 'f(p="")\n' + finder = worder.Worder(code) + self.assertEqual(1, finder._find_parens_start(len(code) - 2)) + + +def test_find_parens_start_with_multiple_entries(self): + code = "myfunc(p1, p2, p3\n" + finder = worder.Worder(code) + self.assertEqual( + code.index("("), finder.find_parens_start_from_inside(len(code) - 1) + ) + + +def test_find_parens_start_with_nested_parens(self): + code = "myfunc(p1, (p2, p3), p4\n" + finder = worder.Worder(code) + self.assertEqual( + code.index("("), finder.find_parens_start_from_inside(len(code) - 1) + ) + + +def test_find_parens_start_with_parens_in_strs(self): + code = 'myfunc(p1, "(", p4\n' + finder = worder.Worder(code) + self.assertEqual( + code.index("("), finder.find_parens_start_from_inside(len(code) - 1) + ) + + +def test_find_parens_start_with_parens_in_strs_in_multiple_lines(self): + code = 'myfunc (\np1\n , \n "(" \n, \np4\n' + finder = worder.Worder(code) + self.assertEqual( + code.index("("), finder.find_parens_start_from_inside(len(code) - 1) + ) + + +def test_is_on_function_call_keyword(self): + code, annotations = self._annotated_code(annotated_code=dedent("""\ + myfunc(va + +++ + """)) + + finder = worder.Worder(code) + self.assert_equal_annotation( + code, + annotations, + self._make_offset_annotation(code, finder.is_on_function_call_keyword), + ) + + +def test_is_on_function_keyword_partial(self): + code = "myfunc(va" + finder = worder.Worder(code) + self.assertTrue(finder.is_on_function_call_keyword(len(code) - 1)) + + +def get_modules(self, name) -> List[str]: + """Get the list of modules that have global `name`.""" + results = self._execute( + models.Name.search_by_name_like.select("module", "source"), (name,) + ).fetchall() + return sort_and_deduplicate(results) + + +def test_get_word_range_with_fstring(self): + code = dedent('''\ + auth = 8 + my_var = f"some value {auth}" + print(auth) + other_val = "some other"''') + finder = worder.Worder(code) + self.assertEqual(finder.get_word_range(45), (45, 49)) + + + +class ScopeNameFinderTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +# FIXME: in normal scopes the interpreter raises `UnboundLocalName` +# exception, but not in class bodies +def xxx_test_global_name_in_class_body(self): + code = dedent("""\ + a_var = 10 + class C(object): + a_var = a_var + """) + scope = libutils.get_string_scope(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) + result = name_finder.get_pyname_at(len(code) - 3) + self.assertEqual(scope["a_var"], result) + + +def test_class_variable_attribute_in_class_body(self): + code = dedent("""\ + a_var = 10 + class C(object): + a_var = a_var + """) + scope = libutils.get_string_scope(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) + a_var_pyname = scope["C"].get_object()["a_var"] + result = name_finder.get_pyname_at(len(code) - 12) + self.assertEqual(a_var_pyname, result) + + +def test_class_variable_attribute_in_class_body2(self): + code = dedent("""\ + a_var = 10 + class C(object): + a_var \\ + = a_var + """) + scope = libutils.get_string_scope(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) + a_var_pyname = scope["C"].get_object()["a_var"] + result = name_finder.get_pyname_at(len(code) - 12) + self.assertEqual(a_var_pyname, result) + + +def test_class_method_attribute_in_class_body(self): + code = dedent("""\ + class C(object): + def a_method(self): + pass + """) + scope = libutils.get_string_scope(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) + a_method_pyname = scope["C"].get_object()["a_method"] + result = name_finder.get_pyname_at(code.index("a_method") + 2) + self.assertEqual(a_method_pyname, result) + + +def test_inner_class_attribute_in_class_body(self): + code = dedent("""\ + class C(object): + class CC(object): + pass + """) + scope = libutils.get_string_scope(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) + a_class_pyname = scope["C"].get_object()["CC"] + result = name_finder.get_pyname_at(code.index("CC") + 2) + self.assertEqual(a_class_pyname, result) + + +def test_class_method_in_class_body_but_not_indexed(self): + code = dedent("""\ + class C(object): + def func(self, func): + pass + """) + scope = libutils.get_string_scope(self.project, code) + a_func_pyname = scope.get_scopes()[0].get_scopes()[0]["func"] + name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) + result = name_finder.get_pyname_at(code.index(", func") + 3) + self.assertEqual(a_func_pyname, result) + + +def get_all_names(self) -> List[str]: + """Get the list of all cached global names.""" + return self._execute(models.Name.objects.select("name")).fetchall() + + +def test_function_but_not_indexed(self): + code = dedent("""\ + def a_func(a_func): + pass + """) + scope = libutils.get_string_scope(self.project, code) + a_func_pyname = scope["a_func"] + name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) + result = name_finder.get_pyname_at(code.index("a_func") + 3) + self.assertEqual(a_func_pyname, result) + + +def test_modules_after_from_statements(self): + root_folder = self.project.root + mod = testutils.create_module(self.project, "mod", root_folder) + mod.write(dedent("""\ + def a_func(): + pass + """)) + code = "from mod import a_func\n" + scope = libutils.get_string_scope(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) + mod_pyobject = self.project.get_pymodule(mod) + found_pyname = name_finder.get_pyname_at(code.index("mod") + 1) + self.assertEqual(mod_pyobject, found_pyname.get_object()) + + +def test_renaming_functions_with_from_import_and_parens(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + def afunc(): + pass + """)) + code = dedent("""\ + from mod1 import ( + afunc as func) + """) + scope = libutils.get_string_scope(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) + mod_pyobject = self.project.get_pymodule(mod1) + afunc = mod_pyobject["afunc"] + found_pyname = name_finder.get_pyname_at(code.index("afunc") + 1) + self.assertEqual(afunc.get_object(), found_pyname.get_object()) + + +@testutils.only_for("2.5") +def test_relative_modules_after_from_statements(self): + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) + mod1 = testutils.create_module(self.project, "mod1", pkg1) + mod2 = testutils.create_module(self.project, "mod2", pkg2) + mod1.write(dedent("""\ + def a_func(): + pass + """)) + code = "from ..mod1 import a_func\n" + mod2.write(code) + mod2_scope = self.project.get_pymodule(mod2).get_scope() + name_finder = rope.base.evaluate.ScopeNameFinder(mod2_scope.pyobject) + mod1_pyobject = self.project.get_pymodule(mod1) + found_pyname = name_finder.get_pyname_at(code.index("mod1") + 1) + self.assertEqual(mod1_pyobject, found_pyname.get_object()) + + +def test_relative_modules_after_from_statements2(self): + mod1 = testutils.create_module(self.project, "mod1") + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) + mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa + mod1.write("import pkg1.pkg2.mod2") + + mod1_scope = self.project.get_pymodule(mod1).get_scope() + name_finder = rope.base.evaluate.ScopeNameFinder(mod1_scope.pyobject) + pkg2_pyobject = self.project.get_pymodule(pkg2) + found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) + self.assertEqual(pkg2_pyobject, found_pyname.get_object()) + + +def test_get_pyname_at_on_language_keywords(self): + code = dedent("""\ + def a_func(a_func): + pass + """) + pymod = libutils.get_string_module(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(pymod) + with self.assertRaises(exceptions.RopeError): + name_finder.get_pyname_at(code.index("pass")) + + +def test_one_liners(self): + code = dedent("""\ + var = 1 + def f(): var = 2 + print(var) + """) + pymod = libutils.get_string_module(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(pymod) + pyname = name_finder.get_pyname_at(code.rindex("var")) + self.assertEqual(pymod["var"], pyname) + + +def test_one_liners_with_line_breaks(self): + code = dedent("""\ + var = 1 + def f( + ): var = 2 + print(var) + """) + pymod = libutils.get_string_module(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(pymod) + pyname = name_finder.get_pyname_at(code.rindex("var")) + self.assertEqual(pymod["var"], pyname) + + +def test_one_liners_with_line_breaks2(self): + code = dedent("""\ + var = 1 + def f( + p): var = 2 + print(var) + """) + pymod = libutils.get_string_module(self.project, code) + name_finder = rope.base.evaluate.ScopeNameFinder(pymod) + pyname = name_finder.get_pyname_at(code.rindex("var")) + self.assertEqual(pymod["var"], pyname) + + +def test_var_in_list_comprehension_differs_from_var_outside(self): + code = "var = 1\n[var for var in range(1)]\n" + pymod = libutils.get_string_module(self.project, code) + + name_finder = rope.base.evaluate.ScopeNameFinder(pymod) + + outside_pyname = name_finder.get_pyname_at(code.index("var")) + inside_pyname = name_finder.get_pyname_at(code.rindex("var")) + + self.assertNotEqual(outside_pyname, inside_pyname) + + + +def _dump_all(self) -> Tuple[List[Name], List[Package]]: + """Dump the entire database.""" + name_results = self._execute(models.Name.objects.select_star()).fetchall() + package_results = self._execute(models.Package.objects.select_star()).fetchall() + return name_results, package_results + + +class LogicalLineFinderTest(unittest.TestCase): + @others + +def _logical_finder(self, code): + return LogicalLineFinder(SourceLinesAdapter(code)) + + +def test_normal_lines(self): + code = "a_var = 10" + line_finder = self._logical_finder(code) + self.assertEqual((1, 1), line_finder.logical_line_in(1)) + + +def test_normal_lines2(self): + code = dedent("""\ + another = 10 + a_var = 20 + """) + line_finder = self._logical_finder(code) + self.assertEqual((1, 1), line_finder.logical_line_in(1)) + self.assertEqual((2, 2), line_finder.logical_line_in(2)) + + +def test_implicit_continuation(self): + code = "a_var = 3 + \\\n 4 + \\\n 5" + line_finder = self._logical_finder(code) + self.assertEqual((1, 3), line_finder.logical_line_in(2)) + + +def test_explicit_continuation(self): + code = dedent("""\ + print(2) + a_var = (3 + + 4, + 5) + """) + line_finder = self._logical_finder(code) + self.assertEqual((2, 4), line_finder.logical_line_in(2)) + + +def test_explicit_continuation_comments(self): + code = "#\na_var = 3\n" + line_finder = self._logical_finder(code) + self.assertEqual((2, 2), line_finder.logical_line_in(2)) + + +def test_multiple_indented_ifs(self): + code = dedent("""\ + if True: + if True: + if True: + pass + a = 10 + """) + line_finder = self._logical_finder(code) + self.assertEqual((5, 5), line_finder.logical_line_in(5)) + + +def test_list_comprehensions_and_fors(self): + code = dedent("""\ + a_list = [i + for i in range(10)] + """) + line_finder = self._logical_finder(code) + self.assertEqual((1, 2), line_finder.logical_line_in(2)) + + +def test_generator_expressions_and_fors(self): + code = dedent("""\ + a_list = (i + for i in range(10)) + """) + line_finder = self._logical_finder(code) + self.assertEqual((1, 2), line_finder.logical_line_in(2)) + + +def generate_cache( + self, + resources: List[Resource] = None, + underlined: bool = False, + task_handle: taskhandle.BaseTaskHandle = taskhandle.NullTaskHandle(), +): + """Generate global name cache for project files. + + If `resources` is a list of `rope.base.resource.File`, only + those files are searched; otherwise all python modules in the + project are cached. + """ + if resources is None: + resources = self.project.get_python_files() + job_set = task_handle.create_jobset( + "Generating autoimport cache", len(resources) + ) + self._execute( + models.Package.delete_by_package_name, (self.project_package.name,) + ) + futures = [] + with ProcessPoolExecutor() as executor: + for file in resources: + job_set.started_job(f"Working on {file.path}") + module = self._resource_to_module(file, underlined) + futures.append(executor.submit(get_names, module, self.project_package)) + for future in as_completed(futures): + self._add_names(future.result()) + job_set.finished_job() + self.connection.commit() + + +def test_fors_and_block_start(self): + code = dedent("""\ + l = range(10) + for i in l: + print(i) + """) + self.assertEqual(2, get_block_start(SourceLinesAdapter(code), 2)) + + +def test_problems_with_inner_indentations(self): + code = dedent("""\ + if True: + if True: + if True: + pass + a = \\ + 1 + """) + line_finder = self._logical_finder(code) + self.assertEqual((5, 6), line_finder.logical_line_in(6)) + + +def test_problems_with_inner_indentations2(self): + code = dedent("""\ + if True: + if True: + pass + a = 1 + """) + line_finder = self._logical_finder(code) + self.assertEqual((4, 4), line_finder.logical_line_in(4)) + + +def test_logical_lines_for_else(self): + code = dedent("""\ + if True: + pass + else: + pass + """) + line_finder = self._logical_finder(code) + self.assertEqual((3, 3), line_finder.logical_line_in(3)) + + +def test_logical_lines_for_lines_with_wrong_continues(self): + code = "var = 1 + \\" + line_finder = self._logical_finder(code) + self.assertEqual((1, 1), line_finder.logical_line_in(1)) + + +def test_logical_lines_for_multiline_string_with_extra_quotes_front(self): + code = '""""Docs."""\na = 1\n' + line_finder = self._logical_finder(code) + self.assertEqual((2, 2), line_finder.logical_line_in(2)) + + +def test_logical_lines_for_multiline_string_with_escaped_quotes(self): + code = '"""Quotes \\""" "\\"" \' """\na = 1\n' + line_finder = self._logical_finder(code) + self.assertEqual((2, 2), line_finder.logical_line_in(2)) + + +def test_generating_line_starts(self): + code = dedent("""\ + a = 1 + a = 2 + + a = 3 + """) + line_finder = self._logical_finder(code) + self.assertEqual([1, 2, 4], list(line_finder.generate_starts())) + + +def test_generating_line_starts2(self): + code = "a = 1\na = 2\n\na = \\ 3\n" + line_finder = self._logical_finder(code) + self.assertEqual([2, 4], list(line_finder.generate_starts(2))) + + +def test_generating_line_starts3(self): + code = "a = 1\na = 2\n\na = \\ 3\n" + line_finder = self._logical_finder(code) + self.assertEqual([2], list(line_finder.generate_starts(2, 3))) + + +def generate_modules_cache( + self, + modules: List[str] = None, + task_handle: taskhandle.BaseTaskHandle = taskhandle.NullTaskHandle(), + single_thread: bool = False, + underlined: Optional[bool] = None, +): + """ + Generate global name cache for external modules listed in `modules`. + + If no modules are provided, it will generate a cache for every module available. + This method searches in your sys.path and configured python folders. + Do not use this for generating your own project's internal names, + use generate_resource_cache for that instead. + """ + underlined = self.underlined if underlined is None else underlined + + packages: List[Package] = ( + self._get_available_packages() + if modules is None + else list(self._get_packages_from_modules(modules)) + ) + + existing = self._get_packages_from_cache() + packages = list(filter_packages(packages, underlined, existing)) + if len(packages) == 0: + return + self._add_packages(packages) + job_set = task_handle.create_jobset("Generating autoimport cache", 0) + if single_thread: + for package in packages: + for module in get_files(package, underlined): + job_set.started_job(module.modname) + for name in get_names(module, package): + self._add_name(name) + job_set.finished_job() + else: + for future_name in as_completed( + get_future_names(packages, underlined, job_set) + ): + self._add_names(future_name.result()) + job_set.finished_job() + + self.connection.commit() + + +def test_generating_line_starts_for_multi_line_statements(self): + code = "\na = \\\n 1 + \\\n 1\n" + line_finder = self._logical_finder(code) + self.assertEqual([2], list(line_finder.generate_starts())) + + +def test_generating_line_starts_and_unmatched_deindents(self): + code = dedent("""\ + if True: + if True: + if True: + a = 1 + b = 1 + """) + line_finder = self._logical_finder(code) + self.assertEqual([4, 5], list(line_finder.generate_starts(4))) + + +def test_false_triple_quoted_string(self): + code = dedent("""\ + def foo(): + a = 0 + p = 'foo''' + + def bar(): + a = 1 + a += 1 + """) + line_finder = self._logical_finder(code) + self.assertEqual([1, 2, 3, 5, 6, 7], list(line_finder.generate_starts())) + self.assertEqual((3, 3), line_finder.logical_line_in(3)) + self.assertEqual([5, 6, 7], list(line_finder.generate_starts(4))) + + + +class TokenizerLogicalLineFinderTest(LogicalLineFinderTest): + def _logical_finder(self, code): + lines = SourceLinesAdapter(code) + return codeanalyze.CachingLogicalLineFinder( + lines, codeanalyze.tokenizer_generator + ) + + + +class CustomLogicalLineFinderTest(LogicalLineFinderTest): + def _logical_finder(self, code): + lines = SourceLinesAdapter(code) + return codeanalyze.CachingLogicalLineFinder(lines, codeanalyze.custom_generator) + +@path C:/Repos/ekr-rope/ropetest/ +import base64 +import hashlib +import hmac +import multiprocessing + +try: + import cPickle as pickle +except ImportError: + import pickle +import socket + +import unittest + + +from rope.base.oi import doa + + +@others +@language python +@tabwidth -4 + +def cve_2014_3539_attacker(data_port, payload): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(("127.0.0.1", data_port)) + s_file = s.makefile("wb") + s_file.write(payload) + s.close() + + + +class DOATest(unittest.TestCase): + @others + +def try_CVE_2014_3539_exploit(self, receiver, payload): + # Simulated attacker writing to the socket + # Assume the attacker guesses the port correctly; 3037 is used by + # default if it is available. + attacker_proc = multiprocessing.Process( + target=cve_2014_3539_attacker, args=(receiver.data_port, payload) + ) + + attacker_proc.start() + received_objs = list(receiver.receive_data()) + attacker_proc.join() + return received_objs + + +def test_CVE_2014_3539_no_encoding(self): + # Attacker sends pickled data to the receiver socket. + receiver = doa._SocketReceiver() + + payload = pickle.dumps("def foo():\n return 123\n") + received_objs = self.try_CVE_2014_3539_exploit(receiver, payload) + + # Make sure the exploit did not run + self.assertEqual(0, len(received_objs)) + + +def _find_matching_deindent(self, line_number): + indents = _get_line_indents(self.lines[line_number]) + current_line = line_number + 1 + while current_line < len(self.lines): + line = self.lines[current_line] + if not line.strip().startswith("#") and not line.strip() == "": + # HACK: We should have used logical lines here + if _get_line_indents(self.lines[current_line]) <= indents: + return current_line + current_line += 1 + return len(self.lines) - 1 + + +def _get_packages_from_modules(self, modules: List[str]) -> Iterator[Package]: + for modname in modules: + package = self._find_package_path(modname) + if package is None: + continue + yield package + + +def test_CVE_2014_3539_signature_mismatch(self): + # Attacker sends well-formed data with an incorrect signature. + receiver = doa._SocketReceiver() + + pickled_data = pickle.dumps( + "def foo():\n return 123\n", pickle.HIGHEST_PROTOCOL + ) + digest = hmac.new(b"invalid-key", pickled_data, hashlib.sha256).digest() + payload = ( + base64.b64encode(digest) + b":" + base64.b64encode(pickled_data) + b"\n" + ) + received_objs = self.try_CVE_2014_3539_exploit(receiver, payload) + + # Make sure the exploit did not run + self.assertEqual(0, len(received_objs)) + + +def test_CVE_2014_3539_sanity(self): + # Tests that sending valid, signed data on the socket does work. + receiver = doa._SocketReceiver() + + pickled_data = base64.b64encode( + pickle.dumps("def foo():\n return 123\n", pickle.HIGHEST_PROTOCOL) + ) + digest = hmac.new(receiver.key, pickled_data, hashlib.sha256).digest() + payload = base64.b64encode(digest) + b":" + pickled_data + b"\n" + received_objs = self.try_CVE_2014_3539_exploit(receiver, payload) + + # Make sure the exploit did not run + self.assertEqual(1, len(received_objs)) + + +def test_compare_digest_compat(self): + self.assertTrue(doa._compat_compare_digest("", "")) + self.assertTrue(doa._compat_compare_digest("abc", "abc")) + self.assertFalse(doa._compat_compare_digest("abc", "abd")) + self.assertFalse(doa._compat_compare_digest("abc", "abcd")) + +@path C:/Repos/ekr-rope/ropetest/ +import unittest + +import rope.base.history +from rope.base import exceptions +import rope.base.change +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class HistoryTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.history = self.project.history + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_undoing_writes(self): + my_file = self.project.root.create_file("my_file.txt") + my_file.write("text1") + self.history.undo() + self.assertEqual("", my_file.read()) + + +def test_moving_files(self): + my_file = self.project.root.create_file("my_file.txt") + my_file.move("new_file.txt") + self.history.undo() + self.assertEqual("", my_file.read()) + + +def test_moving_files_to_folders(self): + my_file = self.project.root.create_file("my_file.txt") + my_folder = self.project.root.create_folder("my_folder") + my_file.move(my_folder.path) + self.history.undo() + self.assertEqual("", my_file.read()) + + +def update_module(self, module: str): + """Update a module in the cache, or add it if it doesn't exist.""" + self._del_if_exist(module) + self.generate_modules_cache([module]) + + +def test_writing_files_that_does_not_change_contents(self): + my_file = self.project.root.create_file("my_file.txt") + my_file.write("") + self.project.history.undo() + self.assertFalse(my_file.exists()) + + + +class IsolatedHistoryTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.history = rope.base.history.History(self.project) + self.file1 = self.project.root.create_file("file1.txt") + self.file2 = self.project.root.create_file("file2.txt") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_undo(self): + change = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change) + self.assertEqual("1", self.file1.read()) + self.history.undo() + self.assertEqual("", self.file1.read()) + + +def test_tobe_undone(self): + change1 = rope.base.change.ChangeContents(self.file1, "1") + self.assertEqual(None, self.history.tobe_undone) + self.history.do(change1) + self.assertEqual(change1, self.history.tobe_undone) + change2 = rope.base.change.ChangeContents(self.file1, "2") + self.history.do(change2) + self.assertEqual(change2, self.history.tobe_undone) + self.history.undo() + self.assertEqual(change1, self.history.tobe_undone) + + +def test_tobe_redone(self): + change = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change) + self.assertEqual(None, self.history.tobe_redone) + self.history.undo() + self.assertEqual(change, self.history.tobe_redone) + + +def test_undo_limit(self): + history = rope.base.history.History(self.project, maxundos=1) + history.do(rope.base.change.ChangeContents(self.file1, "1")) + history.do(rope.base.change.ChangeContents(self.file1, "2")) + try: + history.undo() + with self.assertRaises(exceptions.HistoryError): + history.undo() + finally: + self.assertEqual("1", self.file1.read()) + + +def test_simple_redo(self): + change = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change) + self.history.undo() + self.history.redo() + self.assertEqual("1", self.file1.read()) + + +def test_simple_re_undo(self): + change = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change) + self.history.undo() + self.history.redo() + self.history.undo() + self.assertEqual("", self.file1.read()) + + +def close(self): + """Close the autoimport database.""" + self.connection.commit() + self.connection.close() + + +def test_multiple_undos(self): + change = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change) + change = rope.base.change.ChangeContents(self.file1, "2") + self.history.do(change) + self.history.undo() + self.assertEqual("1", self.file1.read()) + change = rope.base.change.ChangeContents(self.file1, "3") + self.history.do(change) + self.history.undo() + self.assertEqual("1", self.file1.read()) + self.history.redo() + self.assertEqual("3", self.file1.read()) + + +def test_undo_list_underflow(self): + with self.assertRaises(exceptions.HistoryError): + self.history.undo() + + +def test_redo_list_underflow(self): + with self.assertRaises(exceptions.HistoryError): + self.history.redo() + + +def test_dropping_undone_changes(self): + self.file1.write("1") + with self.assertRaises(exceptions.HistoryError): + self.history.undo(drop=True) + self.history.redo() + + +def test_undoing_choosen_changes(self): + change = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change) + self.history.undo(change) + self.assertEqual("", self.file1.read()) + self.assertFalse(self.history.undo_list) + + +def test_undoing_choosen_changes2(self): + change1 = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change1) + self.history.do(rope.base.change.ChangeContents(self.file1, "2")) + self.history.undo(change1) + self.assertEqual("", self.file1.read()) + self.assertFalse(self.history.undo_list) + + +def test_undoing_choosen_changes_not_undoing_others(self): + change1 = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change1) + self.history.do(rope.base.change.ChangeContents(self.file2, "2")) + self.history.undo(change1) + self.assertEqual("", self.file1.read()) + self.assertEqual("2", self.file2.read()) + + +def test_undoing_writing_after_moving(self): + change1 = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change1) + self.history.do(rope.base.change.MoveResource(self.file1, "file3.txt")) + file3 = self.project.get_resource("file3.txt") + self.history.undo(change1) + self.assertEqual("", self.file1.read()) + self.assertFalse(file3.exists()) + + +def test_undoing_folder_movements_for_undoing_writes_inside_it(self): + folder = self.project.root.create_folder("folder") + file3 = folder.create_file("file3.txt") + change1 = rope.base.change.ChangeContents(file3, "1") + self.history.do(change1) + self.history.do(rope.base.change.MoveResource(folder, "new_folder")) + new_folder = self.project.get_resource("new_folder") + self.history.undo(change1) + self.assertEqual("", file3.read()) + self.assertFalse(new_folder.exists()) + + +def test_undoing_changes_that_depend_on_a_dependant_change(self): + change1 = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change1) + changes = rope.base.change.ChangeSet("2nd change") + changes.add_change(rope.base.change.ChangeContents(self.file1, "2")) + changes.add_change(rope.base.change.ChangeContents(self.file2, "2")) + self.history.do(changes) + self.history.do(rope.base.change.MoveResource(self.file2, "file3.txt")) + file3 = self.project.get_resource("file3.txt") + + self.history.undo(change1) + self.assertEqual("", self.file1.read()) + self.assertEqual("", self.file2.read()) + self.assertFalse(file3.exists()) + + +def get_name_locations(self, name): + """Return a list of ``(resource, lineno)`` tuples.""" + result = [] + modules = self._execute( + models.Name.search_by_name_like.select("module"), (name,) + ).fetchall() + for module in modules: + try: + module_name = module[0] + if module_name.startswith(f"{self.project_package.name}."): + module_name = ".".join(module_name.split(".")) + pymodule = self.project.get_module(module_name) + if name in pymodule: + pyname = pymodule[name] + module, lineno = pyname.get_definition_location() + if module is not None: + resource = module.get_module().get_resource() + if resource is not None and lineno is not None: + result.append((resource, lineno)) + except exceptions.ModuleNotFoundError: + pass + return result + + +def test_undoing_writes_for_undoing_folder_movements_containing_it(self): + folder = self.project.root.create_folder("folder") + old_file = folder.create_file("file3.txt") + change1 = rope.base.change.MoveResource(folder, "new_folder") + self.history.do(change1) + new_file = self.project.get_resource("new_folder/file3.txt") + self.history.do(rope.base.change.ChangeContents(new_file, "1")) + self.history.undo(change1) + self.assertEqual("", old_file.read()) + self.assertFalse(new_file.exists()) + + +def test_undoing_not_available_change(self): + change = rope.base.change.ChangeContents(self.file1, "1") + with self.assertRaises(exceptions.HistoryError): + self.history.undo(change) + + +def test_ignoring_ignored_resources(self): + self.project.set("ignored_resources", ["ignored*"]) + ignored = self.project.get_file("ignored.txt") + change = rope.base.change.CreateResource(ignored) + self.history.do(change) + self.assertTrue(ignored.exists()) + self.assertEqual(0, len(self.history.undo_list)) + + +def test_get_file_undo_list_simple(self): + change = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change) + self.assertEqual({change}, set(self.history.get_file_undo_list(self.file1))) + + +def test_get_file_undo_list_for_moves(self): + change = rope.base.change.MoveResource(self.file1, "file2.txt") + self.history.do(change) + self.assertEqual({change}, set(self.history.get_file_undo_list(self.file1))) + + +# XXX: What happens for moves before the file is created? +def xxx_test_get_file_undo_list_and_moving_its_contining_folder(self): + folder = self.project.root.create_folder("folder") + old_file = folder.create_file("file3.txt") + change1 = rope.base.change.MoveResource(folder, "new_folder") + self.history.do(change1) + self.assertEqual({change1}, set(self.history.get_file_undo_list(old_file))) + + +def test_clearing_redo_list_after_do(self): + change = rope.base.change.ChangeContents(self.file1, "1") + self.history.do(change) + self.history.undo() + self.history.do(change) + self.assertEqual(0, len(self.history.redo_list)) + + +def test_undoing_a_not_yet_performed_change(self): + change = rope.base.change.ChangeContents(self.file1, "1") + str(change) + with self.assertRaises(exceptions.HistoryError): + change.undo() + + +def test_clearing_up_the_history(self): + change1 = rope.base.change.ChangeContents(self.file1, "1") + change2 = rope.base.change.ChangeContents(self.file1, "2") + self.history.do(change1) + self.history.do(change2) + self.history.undo() + self.history.clear() + self.assertEqual(0, len(self.history.undo_list)) + self.assertEqual(0, len(self.history.redo_list)) + + +def test_redoing_choosen_changes_not_undoing_others(self): + change1 = rope.base.change.ChangeContents(self.file1, "1") + change2 = rope.base.change.ChangeContents(self.file2, "2") + self.history.do(change1) + self.history.do(change2) + self.history.undo() + self.history.undo() + redone = self.history.redo(change2) + self.assertEqual([change2], redone) + self.assertEqual("", self.file1.read()) + self.assertEqual("2", self.file2.read()) + + + +def clear_cache(self): + """Clear all entries in global-name cache. + + It might be a good idea to use this function before + regenerating global names. + + """ + self._execute(models.Name.objects.drop_table()) + self._execute(models.Package.objects.drop_table()) + self._setup_db() + self.connection.commit() + + +class SavingHistoryTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.history = rope.base.history.History(self.project) + self.to_data = rope.base.change.ChangeToData() + self.to_change = rope.base.change.DataToChange(self.project) + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_set_saving(self): + data = self.to_data(rope.base.change.ChangeSet("testing")) + change = self.to_change(data) + self.assertEqual("testing", str(change)) + + +def test_simple_change_content_saving(self): + myfile = self.project.get_file("myfile.txt") + myfile.create() + myfile.write("1") + data = self.to_data(rope.base.change.ChangeContents(myfile, "2")) + change = self.to_change(data) + self.history.do(change) + self.assertEqual("2", myfile.read()) + self.history.undo() + self.assertEqual("1", change.old_contents) + + +def test_move_resource_saving(self): + myfile = self.project.root.create_file("myfile.txt") + myfolder = self.project.root.create_folder("myfolder") + data = self.to_data(rope.base.change.MoveResource(myfile, "myfolder")) + change = self.to_change(data) + self.history.do(change) + self.assertFalse(myfile.exists()) + self.assertTrue(myfolder.has_child("myfile.txt")) + self.history.undo() + self.assertTrue(myfile.exists()) + self.assertFalse(myfolder.has_child("myfile.txt")) + + +def test_move_resource_saving_for_folders(self): + myfolder = self.project.root.create_folder("myfolder") + newfolder = self.project.get_folder("newfolder") + change = rope.base.change.MoveResource(myfolder, "newfolder") + self.history.do(change) + + data = self.to_data(change) + change = self.to_change(data) + change.undo() + self.assertTrue(myfolder.exists()) + self.assertFalse(newfolder.exists()) + + +def test_create_file_saving(self): + myfile = self.project.get_file("myfile.txt") + data = self.to_data( + rope.base.change.CreateFile(self.project.root, "myfile.txt") + ) + change = self.to_change(data) + self.history.do(change) + self.assertTrue(myfile.exists()) + self.history.undo() + self.assertFalse(myfile.exists()) + + +def test_create_folder_saving(self): + myfolder = self.project.get_folder("myfolder") + data = self.to_data( + rope.base.change.CreateFolder(self.project.root, "myfolder") + ) + change = self.to_change(data) + self.history.do(change) + self.assertTrue(myfolder.exists()) + self.history.undo() + self.assertFalse(myfolder.exists()) + + +def test_create_resource_saving(self): + myfile = self.project.get_file("myfile.txt") + data = self.to_data(rope.base.change.CreateResource(myfile)) + change = self.to_change(data) + self.history.do(change) + self.assertTrue(myfile.exists()) + self.history.undo() + self.assertFalse(myfile.exists()) + + +def find_insertion_line(self, code): + """Guess at what line the new import should be inserted.""" + match = re.search(r"^(def|class)\s+", code) + if match is not None: + code = code[: match.start()] + try: + pymodule = libutils.get_string_module(self.project, code) + except exceptions.ModuleSyntaxError: + return 1 + testmodname = "__rope_testmodule_rope" + importinfo = importutils.NormalImport(((testmodname, None),)) + module_imports = importutils.get_module_imports(self.project, pymodule) + module_imports.add_import(importinfo) + code = module_imports.get_changed_source() + offset = code.index(testmodname) + lineno = code.count("\n", 0, offset) + 1 + return lineno + + +def test_remove_resource_saving(self): + myfile = self.project.root.create_file("myfile.txt") + data = self.to_data(rope.base.change.RemoveResource(myfile)) + change = self.to_change(data) + self.history.do(change) + self.assertFalse(myfile.exists()) + + +def test_change_set_saving(self): + change = rope.base.change.ChangeSet("testing") + myfile = self.project.get_file("myfile.txt") + change.add_change(rope.base.change.CreateResource(myfile)) + change.add_change(rope.base.change.ChangeContents(myfile, "1")) + + data = self.to_data(change) + change = self.to_change(data) + self.history.do(change) + self.assertEqual("1", myfile.read()) + self.history.undo() + self.assertFalse(myfile.exists()) + + +def test_writing_and_reading_history(self): + history_file = self.project.get_file("history.pickle") # noqa + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") + history.do(rope.base.change.CreateResource(myfile)) + history.write() + + history = rope.base.history.History(self.project) + history.undo() + self.assertFalse(myfile.exists()) + + +def test_writing_and_reading_history2(self): + history_file = self.project.get_file("history.pickle") # noqa + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") + history.do(rope.base.change.CreateResource(myfile)) + history.undo() + history.write() + + history = rope.base.history.History(self.project) + history.redo() + self.assertTrue(myfile.exists()) + +@path C:/Repos/ekr-rope/ropetest/ +import unittest + + +from rope.base.oi import objectdb, memorydb +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +def _do_for_all_dbs(function): + def called(self): + for db in self.dbs: + function(self, db) + + return called + + + +class _MockValidation: + @others + +def is_value_valid(self, value): + return value != -1 + + +def is_more_valid(self, new, old): + return new != -1 + + +def is_file_valid(self, path): + return path != "invalid" + + +def update_resource( + self, resource: Resource, underlined: bool = False, commit: bool = True +): + """Update the cache for global names in `resource`.""" + underlined = underlined if underlined else self.underlined + module = self._resource_to_module(resource, underlined) + self._del_if_exist(module_name=module.modname, commit=False) + for name in get_names(module, self.project_package): + self._add_name(name) + if commit: + self.connection.commit() + + +def is_scope_valid(self, path, key): + return path != "invalid" and key != "invalid" + + + +class _MockFileListObserver: + + log = "" + + @others + +def added(self, path): + self.log += "added %s " % path + + +def removed(self, path): + self.log += "removed %s " % path + + + +class ObjectDBTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + validation = _MockValidation() + self.dbs = [objectdb.ObjectDB(memorydb.MemoryDB(self.project), validation)] + + +def tearDown(self): + for db in self.dbs: + db.write() + testutils.remove_project(self.project) + super().tearDown() + + +@_do_for_all_dbs +def test_simple_per_name(self, db): + db.add_pername("file", "key", "name", 1) + self.assertEqual(1, db.get_pername("file", "key", "name")) + + +@_do_for_all_dbs +def test_simple_per_name_does_not_exist(self, db): + self.assertEqual(None, db.get_pername("file", "key", "name")) + + +@_do_for_all_dbs +def test_simple_per_name_after_syncing(self, db): + db.add_pername("file", "key", "name", 1) + db.write() + self.assertEqual(1, db.get_pername("file", "key", "name")) + + +def _changed(self, resource): + if not resource.is_folder(): + self.update_resource(resource) + + +@_do_for_all_dbs +def test_getting_returned(self, db): + db.add_callinfo("file", "key", (1, 2), 3) + self.assertEqual(3, db.get_returned("file", "key", (1, 2))) + + +@_do_for_all_dbs +def test_getting_returned_when_does_not_match(self, db): + db.add_callinfo("file", "key", (1, 2), 3) + self.assertEqual(None, db.get_returned("file", "key", (1, 1))) + + +@_do_for_all_dbs +def test_getting_call_info(self, db): + db.add_callinfo("file", "key", (1, 2), 3) + + call_infos = list(db.get_callinfos("file", "key")) + self.assertEqual(1, len(call_infos)) + self.assertEqual((1, 2), call_infos[0].get_parameters()) + self.assertEqual(3, call_infos[0].get_returned()) + + +@_do_for_all_dbs +def test_invalid_per_name(self, db): + db.add_pername("file", "key", "name", -1) + self.assertEqual(None, db.get_pername("file", "key", "name")) + + +@_do_for_all_dbs +def test_overwriting_per_name(self, db): + db.add_pername("file", "key", "name", 1) + db.add_pername("file", "key", "name", 2) + self.assertEqual(2, db.get_pername("file", "key", "name")) + + +@_do_for_all_dbs +def test_not_overwriting_with_invalid_per_name(self, db): + db.add_pername("file", "key", "name", 1) + db.add_pername("file", "key", "name", -1) + self.assertEqual(1, db.get_pername("file", "key", "name")) + + +@_do_for_all_dbs +def test_getting_invalid_returned(self, db): + db.add_callinfo("file", "key", (1, 2), -1) + self.assertEqual(None, db.get_returned("file", "key", (1, 2))) + + +@_do_for_all_dbs +def test_not_overwriting_with_invalid_returned(self, db): + db.add_callinfo("file", "key", (1, 2), 3) + db.add_callinfo("file", "key", (1, 2), -1) + self.assertEqual(3, db.get_returned("file", "key", (1, 2))) + + +@_do_for_all_dbs +def test_get_files(self, db): + db.add_callinfo("file1", "key", (1, 2), 3) + db.add_callinfo("file2", "key", (1, 2), 3) + self.assertEqual({"file1", "file2"}, set(db.get_files())) + + +@_do_for_all_dbs +def test_validating_files(self, db): + db.add_callinfo("invalid", "key", (1, 2), 3) + db.validate_files() + self.assertEqual(0, len(db.get_files())) + + +def _moved(self, resource: Resource, newresource: Resource): + if not resource.is_folder(): + modname = self._resource_to_module(resource).modname + self._del_if_exist(modname) + self.update_resource(newresource) + + +@_do_for_all_dbs +def test_validating_file_for_scopes(self, db): + db.add_callinfo("file", "invalid", (1, 2), 3) + db.validate_file("file") + self.assertEqual(1, len(db.get_files())) + self.assertEqual(0, len(list(db.get_callinfos("file", "invalid")))) + + +@_do_for_all_dbs +def test_validating_file_moved(self, db): + db.add_callinfo("file", "key", (1, 2), 3) + + db.file_moved("file", "newfile") + self.assertEqual(1, len(db.get_files())) + self.assertEqual(1, len(list(db.get_callinfos("newfile", "key")))) + + +@_do_for_all_dbs +def test_using_file_list_observer(self, db): + db.add_callinfo("invalid", "key", (1, 2), 3) + observer = _MockFileListObserver() + db.add_file_list_observer(observer) + db.validate_files() + self.assertEqual("removed invalid ", observer.log) + +@path C:/Repos/ekr-rope/ropetest/ +from textwrap import dedent + +import unittest + +import rope.base.project +import rope.base.builtins +from rope.base import libutils +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class ObjectInferTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_type_inferencing(self): + code = dedent("""\ + class Sample(object): + pass + a_var = Sample() + """) + scope = libutils.get_string_scope(self.project, code) + sample_class = scope["Sample"].get_object() + a_var = scope["a_var"].get_object() + self.assertEqual(sample_class, a_var.get_type()) + + +def test_simple_type_inferencing_classes_defined_in_holding_scope(self): + code = dedent("""\ + class Sample(object): + pass + def a_func(): + a_var = Sample() + """) + scope = libutils.get_string_scope(self.project, code) + sample_class = scope["Sample"].get_object() + a_var = scope["a_func"].get_object().get_scope()["a_var"].get_object() + self.assertEqual(sample_class, a_var.get_type()) + + +def test_simple_type_inferencing_classes_in_class_methods(self): + code = dedent("""\ + class Sample(object): + pass + class Another(object): + def a_method(): + a_var = Sample() + """) + scope = libutils.get_string_scope(self.project, code) + sample_class = scope["Sample"].get_object() + another_class = scope["Another"].get_object() + a_var = another_class["a_method"].get_object().get_scope()["a_var"].get_object() + self.assertEqual(sample_class, a_var.get_type()) + + +def _del_if_exist(self, module_name, commit: bool = True): + self._execute(models.Name.delete_by_module_name, (module_name,)) + if commit: + self.connection.commit() + + +def test_simple_type_inferencing_class_attributes(self): + code = dedent("""\ + class Sample(object): + pass + class Another(object): + def __init__(self): + self.a_var = Sample() + """) + scope = libutils.get_string_scope(self.project, code) + sample_class = scope["Sample"].get_object() + another_class = scope["Another"].get_object() + a_var = another_class["a_var"].get_object() + self.assertEqual(sample_class, a_var.get_type()) + + +def test_simple_type_inferencing_for_in_class_assignments(self): + code = dedent("""\ + class Sample(object): + pass + class Another(object): + an_attr = Sample() + """) + scope = libutils.get_string_scope(self.project, code) + sample_class = scope["Sample"].get_object() + another_class = scope["Another"].get_object() + an_attr = another_class["an_attr"].get_object() + self.assertEqual(sample_class, an_attr.get_type()) + + +def test_simple_type_inferencing_for_chained_assignments(self): + mod = dedent("""\ + class Sample(object): + pass + copied_sample = Sample""") + mod_scope = libutils.get_string_scope(self.project, mod) + sample_class = mod_scope["Sample"] + copied_sample = mod_scope["copied_sample"] + self.assertEqual(sample_class.get_object(), copied_sample.get_object()) + + +def test_following_chained_assignments_avoiding_circles(self): + mod = dedent("""\ + class Sample(object): + pass + sample_class = Sample + sample_class = sample_class + """) + mod_scope = libutils.get_string_scope(self.project, mod) + sample_class = mod_scope["Sample"] + sample_class_var = mod_scope["sample_class"] + self.assertEqual(sample_class.get_object(), sample_class_var.get_object()) + + +def test_function_returned_object_static_type_inference1(self): + src = dedent("""\ + class Sample(object): + pass + def a_func(): + return Sample + a_var = a_func() + """) + scope = libutils.get_string_scope(self.project, src) + sample_class = scope["Sample"] + a_var = scope["a_var"] + self.assertEqual(sample_class.get_object(), a_var.get_object()) + + +def test_function_returned_object_static_type_inference2(self): + src = dedent("""\ + class Sample(object): + pass + def a_func(): + return Sample() + a_var = a_func() + """) + scope = libutils.get_string_scope(self.project, src) + sample_class = scope["Sample"].get_object() + a_var = scope["a_var"].get_object() + self.assertEqual(sample_class, a_var.get_type()) + + +def test_recursive_function_returned_object_static_type_inference(self): + src = dedent("""\ + class Sample(object): + pass + def a_func(): + if True: + return Sample() + else: + return a_func() + a_var = a_func() + """) + scope = libutils.get_string_scope(self.project, src) + sample_class = scope["Sample"].get_object() + a_var = scope["a_var"].get_object() + self.assertEqual(sample_class, a_var.get_type()) + + +def test_func_returned_obj_using_call_spec_func_static_type_infer(self): + src = dedent("""\ + class Sample(object): + def __call__(self): + return Sample + sample = Sample() + a_var = sample()""") + scope = libutils.get_string_scope(self.project, src) + sample_class = scope["Sample"] + a_var = scope["a_var"] + self.assertEqual(sample_class.get_object(), a_var.get_object()) + + +def test_list_type_inferencing(self): + src = dedent("""\ + class Sample(object): + pass + a_var = [Sample()] + """) + scope = libutils.get_string_scope(self.project, src) + sample_class = scope["Sample"].get_object() + a_var = scope["a_var"].get_object() + self.assertNotEqual(sample_class, a_var.get_type()) + + +def test_attributed_object_inference(self): + src = dedent("""\ + class Sample(object): + def __init__(self): + self.a_var = None + def set(self): + self.a_var = Sample() + """) + scope = libutils.get_string_scope(self.project, src) + sample_class = scope["Sample"].get_object() + a_var = sample_class["a_var"].get_object() + self.assertEqual(sample_class, a_var.get_type()) + + +def _set(self, lineno, line): + self.diffs[self.origs[lineno]] += len(line) - len(self.lines[lineno]) + self.lines[lineno] = line + + +def _get_python_folders(self) -> List[Path]: + def filter_folders(folder: Path) -> bool: + return folder.is_dir() and folder.as_posix() != "/usr/bin" + + folders = self.project.get_python_path_folders() + folder_paths = map(lambda folder: Path(folder.real_path), folders) + folder_paths = filter(filter_folders, folder_paths) + return list(OrderedDict.fromkeys(folder_paths)) + + +def test_getting_property_attributes(self): + src = dedent("""\ + class A(object): + pass + def f(*args): + return A() + class B(object): + p = property(f) + a_var = B().p + """) + pymod = libutils.get_string_module(self.project, src) + a_class = pymod["A"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(a_class, a_var.get_type()) + + +def test_getting_property_attributes_with_method_getters(self): + src = dedent("""\ + class A(object): + pass + class B(object): + def p_get(self): + return A() + p = property(p_get) + a_var = B().p + """) + pymod = libutils.get_string_module(self.project, src) + a_class = pymod["A"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(a_class, a_var.get_type()) + + +def test_lambda_functions(self): + code = dedent("""\ + class C(object): + pass + l = lambda: C() + a_var = l()""") + mod = libutils.get_string_module(self.project, code) + c_class = mod["C"].get_object() + a_var = mod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_mixing_subscript_with_tuple_assigns(self): + code = dedent("""\ + class C(object): + attr = 0 + d = {} + d[0], b = (0, C()) + """) + mod = libutils.get_string_module(self.project, code) + c_class = mod["C"].get_object() + a_var = mod["b"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_mixing_ass_attr_with_tuple_assignment(self): + code = dedent("""\ + class C(object): + attr = 0 + c = C() + c.attr, b = (0, C()) + """) + mod = libutils.get_string_module(self.project, code) + c_class = mod["C"].get_object() + a_var = mod["b"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_mixing_slice_with_tuple_assigns(self): + code = dedent("""\ + class C(object): + attr = 0 + d = [None] * 3 + d[0:2], b = ((0,), C()) + """) + mod = libutils.get_string_module(self.project, code) + + c_class = mod["C"].get_object() + a_var = mod["b"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_nested_tuple_assignments(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + a, (b, c) = (C1(), (C2(), C1())) + """) + mod = libutils.get_string_module(self.project, code) + + c1_class = mod["C1"].get_object() + c2_class = mod["C2"].get_object() + a_var = mod["a"].get_object() + b_var = mod["b"].get_object() + c_var = mod["c"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + self.assertEqual(c1_class, c_var.get_type()) + + +def test_empty_tuples(self): + code = dedent("""\ + t = () + a, b = t + """) + mod = libutils.get_string_module(self.project, code) + + a = mod["a"].get_object() # noqa + + +def test_handling_generator_functions(self): + code = dedent("""\ + class C(object): + pass + def f(): + yield C() + for c in f(): + a_var = c + """) + mod = libutils.get_string_module(self.project, code) + c_class = mod["C"].get_object() + a_var = mod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_handling_generator_functions_for_strs(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + def f(): + yield "" + for s in f(): + a_var = s + """)) + pymod = self.project.get_pymodule(mod) + a_var = pymod["a_var"].get_object() + self.assertTrue(isinstance(a_var.get_type(), rope.base.builtins.Str)) + + +def _get_available_packages(self) -> List[Package]: + packages: List[Package] = [ + Package(module, Source.BUILTIN, None, PackageType.BUILTIN) + for module in sys.builtin_module_names + ] + for folder in self._get_python_folders(): + for package in folder.iterdir(): + package_tuple = get_package_tuple(package, self.project) + if package_tuple is None: + continue + packages.append(package_tuple) + return packages + + +def test_considering_nones_to_be_unknowns(self): + code = dedent("""\ + class C(object): + pass + a_var = None + a_var = C() + a_var = None + """) + mod = libutils.get_string_module(self.project, code) + c_class = mod["C"].get_object() + a_var = mod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_basic_list_comprehensions(self): + code = dedent("""\ + class C(object): + pass + l = [C() for i in range(1)] + a_var = l[0] + """) + mod = libutils.get_string_module(self.project, code) + c_class = mod["C"].get_object() + a_var = mod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_basic_generator_expressions(self): + code = dedent("""\ + class C(object): + pass + l = (C() for i in range(1)) + a_var = list(l)[0] + """) + mod = libutils.get_string_module(self.project, code) + c_class = mod["C"].get_object() + a_var = mod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_list_comprehensions_and_loop_var(self): + code = dedent("""\ + class C(object): + pass + c_objects = [C(), C()] + l = [c for c in c_objects] + a_var = l[0] + """) + mod = libutils.get_string_module(self.project, code) + c_class = mod["C"].get_object() + a_var = mod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_list_comprehensions_and_multiple_loop_var(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + l = [(c1, c2) for c1 in [C1()] for c2 in [C2()]] + a, b = l[0] + """) + mod = libutils.get_string_module(self.project, code) + c1_class = mod["C1"].get_object() + c2_class = mod["C2"].get_object() + a_var = mod["a"].get_object() + b_var = mod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_list_comprehensions_and_multiple_iters(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + l = [(c1, c2) for c1, c2 in [(C1(), C2())]] + a, b = l[0] + """) + mod = libutils.get_string_module(self.project, code) + + c1_class = mod["C1"].get_object() + c2_class = mod["C2"].get_object() + a_var = mod["a"].get_object() + b_var = mod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_we_know_the_type_of_catched_exceptions(self): + code = dedent("""\ + class MyError(Exception): + pass + try: + raise MyError() + except MyError as e: + pass + """) + mod = libutils.get_string_module(self.project, code) + my_error = mod["MyError"].get_object() + e_var = mod["e"].get_object() + self.assertEqual(my_error, e_var.get_type()) + + +def test_we_know_the_type_of_catched_multiple_excepts(self): + code = dedent("""\ + class MyError(Exception): + pass + try: + raise MyError() + except (MyError, Exception) as e: + pass + """) + mod = libutils.get_string_module(self.project, code) + my_error = mod["MyError"].get_object() + e_var = mod["e"].get_object() + self.assertEqual(my_error, e_var.get_type()) + + +def test_using_property_as_decorators(self): + code = dedent("""\ + class A(object): + pass + class B(object): + @property + def f(self): + return A() + b = B() + var = b.f + """) + mod = libutils.get_string_module(self.project, code) + var = mod["var"].get_object() + a = mod["A"].get_object() + self.assertEqual(a, var.get_type()) + + +def test_using_property_as_decorators_and_passing_parameter(self): + code = dedent("""\ + class B(object): + @property + def f(self): + return self + b = B() + var = b.f + """) + mod = libutils.get_string_module(self.project, code) + var = mod["var"].get_object() + a = mod["B"].get_object() + self.assertEqual(a, var.get_type()) + +def _add_packages(self, packages: List[Package]): + data = [(p.name, str(p.path)) for p in packages] + self._executemany(models.Package.objects.insert_into(), data) + + +@path C:/Repos/ekr-rope/ropetest/ +import os.path +import shutil +from textwrap import dedent + +import pytest + +from rope.base.exceptions import RopeError, ResourceNotFoundError +from rope.base.fscommands import FileSystemCommands +from rope.base.libutils import path_to_resource +from rope.base.project import Project, NoProject, _realpath +from rope.base.resourceobserver import FilteredResourceObserver +from ropetest import testutils + + +import unittest + + +@others +@language python +@tabwidth -4 + +class ProjectTest(unittest.TestCase): + @others + +def setUp(self): + unittest.TestCase.setUp(self) + self.project = testutils.sample_project( + foldername="sampleproject", ropefolder=None + ) + self.project_root = self.project.address + self._make_sample_project() + self.no_project = NoProject() + + +def _make_sample_project(self): + self.sample_file = "sample_file.txt" + self.sample_path = os.path.join(self.project_root, "sample_file.txt") + if not os.path.exists(self.project_root): + os.mkdir(self.project_root) + self.sample_folder = "sample_folder" + os.mkdir(os.path.join(self.project_root, self.sample_folder)) + sample = open(self.sample_path, "w") + sample.write("sample text\n") + sample.close() + + +def tearDown(self): + testutils.remove_project(self.project) + unittest.TestCase.tearDown(self) + + +def test_project_creation(self): + self.assertEqual(_realpath(self.project_root), self.project.address) + + +def test_getting_project_file(self): + project_file = self.project.get_resource(self.sample_file) + self.assertTrue(project_file is not None) + + +def test_project_file_reading(self): + projectFile = self.project.get_resource(self.sample_file) + self.assertEqual("sample text\n", projectFile.read()) + + +def test_getting_not_existing_project_file(self): + with self.assertRaises(ResourceNotFoundError): + self.project.get_resource("DoesNotExistFile.txt") + + +def test_writing_in_project_files(self): + project_file = self.project.get_resource(self.sample_file) + project_file.write("another text\n") + self.assertEqual("another text\n", project_file.read()) + + +def _get_packages_from_cache(self) -> List[str]: + existing: List[str] = list( + chain(*self._execute(models.Package.objects.select_star()).fetchall()) + ) + existing.append(self.project_package.name) + return existing + + +def test_creating_files(self): + project_file = "newfile.txt" + self.project.root.create_file(project_file) + newFile = self.project.get_resource(project_file) + self.assertTrue(newFile is not None) + + +def test_creating_files_that_already_exist(self): + with self.assertRaises(RopeError): + self.project.root.create_file(self.sample_file) + + +def test_making_root_folder_if_it_does_not_exist(self): + project = Project("sampleproject2") + try: + self.assertTrue( + os.path.exists("sampleproject2") and os.path.isdir("sampleproject2") + ) + finally: + testutils.remove_project(project) + + +def test_failure_when_project_root_exists_and_is_a_file(self): + project_root = "sampleproject2" + try: + open(project_root, "w").close() + with self.assertRaises(RopeError): + Project(project_root) + finally: + testutils.remove_recursively(project_root) + + +def test_creating_folders(self): + folderName = "SampleFolder" + self.project.root.create_folder(folderName) + folderPath = os.path.join(self.project.address, folderName) + self.assertTrue(os.path.exists(folderPath) and os.path.isdir(folderPath)) + + +def test_making_folder_that_already_exists(self): + folderName = "SampleFolder" + with self.assertRaises(RopeError): + self.project.root.create_folder(folderName) + self.project.root.create_folder(folderName) + + +def test_failing_if_creating_folder_while_file_already_exists(self): + folderName = "SampleFolder" + with self.assertRaises(RopeError): + self.project.root.create_file(folderName) + self.project.root.create_folder(folderName) + + +def test_creating_file_inside_folder(self): + folder_name = "sampleFolder" + file_name = "sample2.txt" + file_path = folder_name + "/" + file_name + parent_folder = self.project.root.create_folder(folder_name) + parent_folder.create_file(file_name) + file = self.project.get_resource(file_path) + file.write("sample notes") + self.assertEqual(file_path, file.path) + self.assertEqual( + "sample notes", open(os.path.join(self.project.address, file_path)).read() + ) + + +def test_failing_when_creating_file_inside_non_existent_folder(self): + with self.assertRaises(ResourceNotFoundError): + self.project.root.create_file("NonexistentFolder/SomeFile.txt") + + +def test_nested_directories(self): + folder_name = "SampleFolder" + parent = self.project.root.create_folder(folder_name) + parent.create_folder(folder_name) + folder_path = os.path.join(self.project.address, folder_name, folder_name) + self.assertTrue(os.path.exists(folder_path) and os.path.isdir(folder_path)) + + +def _removed(self, resource): + if not resource.is_folder(): + modname = self._resource_to_module(resource).modname + self._del_if_exist(modname) + + +def test_removing_files(self): + self.assertTrue(os.path.exists(self.sample_path)) + self.project.get_resource(self.sample_file).remove() + self.assertFalse(os.path.exists(self.sample_path)) + + +def test_removing_files_invalidating_in_project_resource_pool(self): + root_folder = self.project.root + my_file = root_folder.create_file("my_file.txt") + my_file.remove() + self.assertFalse(root_folder.has_child("my_file.txt")) + + +def test_removing_directories(self): + self.assertTrue( + os.path.exists(os.path.join(self.project.address, self.sample_folder)) + ) + self.project.get_resource(self.sample_folder).remove() + self.assertFalse( + os.path.exists(os.path.join(self.project.address, self.sample_folder)) + ) + + +def test_removing_non_existent_files(self): + with self.assertRaises(ResourceNotFoundError): + self.project.get_resource("NonExistentFile.txt").remove() + + +def test_removing_nested_files(self): + file_name = self.sample_folder + "/sample_file.txt" + self.project.root.create_file(file_name) + self.project.get_resource(file_name).remove() + self.assertTrue( + os.path.exists(os.path.join(self.project.address, self.sample_folder)) + ) + self.assertTrue( + not os.path.exists(os.path.join(self.project.address, file_name)) + ) + + +def test_file_get_name(self): + file = self.project.get_resource(self.sample_file) + self.assertEqual(self.sample_file, file.name) + file_name = "nestedFile.txt" + parent = self.project.get_resource(self.sample_folder) + filePath = self.sample_folder + "/" + file_name + parent.create_file(file_name) + nestedFile = self.project.get_resource(filePath) + self.assertEqual(file_name, nestedFile.name) + + +def test_folder_get_name(self): + folder = self.project.get_resource(self.sample_folder) + self.assertEqual(self.sample_folder, folder.name) + + +def test_file_get_path(self): + file = self.project.get_resource(self.sample_file) + self.assertEqual(self.sample_file, file.path) + fileName = "nestedFile.txt" + parent = self.project.get_resource(self.sample_folder) + filePath = self.sample_folder + "/" + fileName + parent.create_file(fileName) + nestedFile = self.project.get_resource(filePath) + self.assertEqual(filePath, nestedFile.path) + + +def test_folder_get_path(self): + folder = self.project.get_resource(self.sample_folder) + self.assertEqual(self.sample_folder, folder.path) + + +def test_is_folder(self): + self.assertTrue(self.project.get_resource(self.sample_folder).is_folder()) + self.assertTrue(not self.project.get_resource(self.sample_file).is_folder()) + + +def _add_future_names(self, names: Future): + self._add_names(names.result()) + + +def testget_children(self): + children = self.project.get_resource(self.sample_folder).get_children() + self.assertEqual([], children) + + +def test_nonempty_get_children(self): + file_name = "nestedfile.txt" + filePath = self.sample_folder + "/" + file_name + parent = self.project.get_resource(self.sample_folder) + parent.create_file(file_name) + children = parent.get_children() + self.assertEqual(1, len(children)) + self.assertEqual(filePath, children[0].path) + + +def test_nonempty_get_children2(self): + file_name = "nestedfile.txt" + folder_name = "nestedfolder.txt" + filePath = self.sample_folder + "/" + file_name + folderPath = self.sample_folder + "/" + folder_name + parent = self.project.get_resource(self.sample_folder) + parent.create_file(file_name) + parent.create_folder(folder_name) + children = parent.get_children() + self.assertEqual(2, len(children)) + self.assertTrue(filePath == children[0].path or filePath == children[1].path) + self.assertTrue( + folderPath == children[0].path or folderPath == children[1].path + ) + + +def test_does_not_fail_for_permission_denied(self): + bad_dir = os.path.join(self.sample_folder, "bad_dir") + os.makedirs(bad_dir) + self.addCleanup(shutil.rmtree, bad_dir) + os.chmod(bad_dir, 0o000) + try: + parent = self.project.get_resource(self.sample_folder) + + parent.get_children() + + finally: + os.chmod(bad_dir, 0o755) + + +def test_getting_files(self): + files = self.project.root.get_files() + self.assertEqual(1, len(files)) + self.assertTrue(self.project.get_resource(self.sample_file) in files) + + +def test_getting_folders(self): + folders = self.project.root.get_folders() + self.assertEqual(1, len(folders)) + self.assertTrue(self.project.get_resource(self.sample_folder) in folders) + + +def test_nested_folder_get_files(self): + parent = self.project.root.create_folder("top") + parent.create_file("file1.txt") + parent.create_file("file2.txt") + files = parent.get_files() + self.assertEqual(2, len(files)) + self.assertTrue(self.project.get_resource("top/file2.txt") in files) + self.assertEqual(0, len(parent.get_folders())) + + +def test_nested_folder_get_folders(self): + parent = self.project.root.create_folder("top") + parent.create_folder("dir1") + parent.create_folder("dir2") + folders = parent.get_folders() + self.assertEqual(2, len(folders)) + self.assertTrue(self.project.get_resource("top/dir1") in folders) + self.assertEqual(0, len(parent.get_files())) + + +def test_root_folder(self): + root_folder = self.project.root + self.assertEqual(2, len(root_folder.get_children())) + self.assertEqual("", root_folder.path) + self.assertEqual("", root_folder.name) + + +def test_get_all_files(self): + files = tuple(self.project.get_files()) + self.assertEqual(1, len(files)) + self.assertEqual(self.sample_file, files[0].name) + + +@staticmethod +def _convert_name(name: Name) -> tuple: + return ( + name.name, + name.modname, + name.package, + name.source.value, + name.name_type.value, + ) + + +def test_get_all_files_after_changing(self): + self.assertEqual(1, len(self.project.get_files())) + myfile = self.project.root.create_file("myfile.txt") + self.assertEqual(2, len(self.project.get_files())) + myfile.move("newfile.txt") + self.assertEqual(2, len(self.project.get_files())) + self.project.get_file("newfile.txt").remove() + self.assertEqual(1, len(self.project.get_files())) + + +def test_multifile_get_all_files(self): + fileName = "nestedFile.txt" + parent = self.project.get_resource(self.sample_folder) + parent.create_file(fileName) + files = list(self.project.get_files()) + self.assertEqual(2, len(files)) + self.assertTrue(fileName == files[0].name or fileName == files[1].name) + + +def test_ignoring_dot_pyc_files_in_get_files(self): + root = self.project.address + src_folder = os.path.join(root, "src") + os.mkdir(src_folder) + test_pyc = os.path.join(src_folder, "test.pyc") + open(test_pyc, "w").close() + for x in self.project.get_files(): + self.assertNotEqual("src/test.pyc", x.path) + + +def test_folder_creating_files(self): + projectFile = "NewFile.txt" + self.project.root.create_file(projectFile) + new_file = self.project.get_resource(projectFile) + self.assertTrue(new_file is not None and not new_file.is_folder()) + + +def test_folder_creating_nested_files(self): + project_file = "NewFile.txt" + parent_folder = self.project.get_resource(self.sample_folder) + parent_folder.create_file(project_file) + new_file = self.project.get_resource(self.sample_folder + "/" + project_file) + self.assertTrue(new_file is not None and not new_file.is_folder()) + + +def test_folder_creating_files2(self): + projectFile = "newfolder" + self.project.root.create_folder(projectFile) + new_folder = self.project.get_resource(projectFile) + self.assertTrue(new_folder is not None and new_folder.is_folder()) + + +def test_folder_creating_nested_files2(self): + project_file = "newfolder" + parent_folder = self.project.get_resource(self.sample_folder) + parent_folder.create_folder(project_file) + new_folder = self.project.get_resource(self.sample_folder + "/" + project_file) + self.assertTrue(new_folder is not None and new_folder.is_folder()) + + +def test_folder_get_child(self): + folder = self.project.root + folder.create_file("myfile.txt") + folder.create_folder("myfolder") + self.assertEqual( + self.project.get_resource("myfile.txt"), folder.get_child("myfile.txt") + ) + self.assertEqual( + self.project.get_resource("myfolder"), folder.get_child("myfolder") + ) + + +def test_folder_get_child_nested(self): + root = self.project.root + folder = root.create_folder("myfolder") + folder.create_file("myfile.txt") + folder.create_folder("myfolder") + self.assertEqual( + self.project.get_resource("myfolder/myfile.txt"), + folder.get_child("myfile.txt"), + ) + self.assertEqual( + self.project.get_resource("myfolder/myfolder"), folder.get_child("myfolder") + ) + + +def test_project_root_is_root_folder(self): + self.assertEqual("", self.project.root.path) + + +def _add_names(self, names: Iterable[Name]): + if names is not None: + self._executemany( + models.Name.objects.insert_into(), + [self._convert_name(name) for name in names], + ) + + +def test_moving_files(self): + root_folder = self.project.root + my_file = root_folder.create_file("my_file.txt") + my_file.move("my_other_file.txt") + self.assertFalse(my_file.exists()) + root_folder.get_child("my_other_file.txt") + + +def test_moving_folders(self): + root_folder = self.project.root + my_folder = root_folder.create_folder("my_folder") + my_file = my_folder.create_file("my_file.txt") + my_folder.move("new_folder") + self.assertFalse(root_folder.has_child("my_folder")) + self.assertFalse(my_file.exists()) + self.assertTrue(root_folder.get_child("new_folder") is not None) + + +def test_moving_destination_folders(self): + root_folder = self.project.root + my_folder = root_folder.create_folder("my_folder") + my_file = root_folder.create_file("my_file.txt") + my_file.move("my_folder") + self.assertFalse(root_folder.has_child("my_file.txt")) + self.assertFalse(my_file.exists()) + my_folder.get_child("my_file.txt") + + +def test_moving_files_and_resource_objects(self): + root_folder = self.project.root + my_file = root_folder.create_file("my_file.txt") + old_hash = hash(my_file) + my_file.move("my_other_file.txt") + self.assertEqual(old_hash, hash(my_file)) + + +def test_file_encoding_reading(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = ( + b"# -*- coding: utf-8 -*-\n" + + br"#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" + ).decode("utf8") + file = open(sample_file.real_path, "wb") + file.write(contents.encode("utf-8")) + file.close() + self.assertEqual(contents, sample_file.read()) + + +def test_file_encoding_writing(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = ( + b"# -*- coding: utf-8 -*-\n" + br"\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" + ).decode("utf8") + sample_file.write(contents) + self.assertEqual(contents, sample_file.read()) + + +def test_using_utf8_when_writing_in_case_of_errors(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = br"\n\N{LATIN SMALL LETTER I WITH DIAERESIS}\n".decode("utf8") + sample_file.write(contents) + self.assertEqual(contents, sample_file.read()) + + +def test_encoding_declaration_in_the_second_line(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"\n# -*- coding: latin-1 -*-\n\xa9\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertEqual(contents, sample_file.read().encode("latin-1")) + + +def test_not_an_encoding_declaration(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"def my_method(self, encoding='latin-1'):\n var = {}\n\xc2\xa9\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertEqual(contents, sample_file.read().encode("utf-8")) + self.assertNotEqual(contents, sample_file.read().encode("latin-1")) + + +def test_read_bytes(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"\n# -*- coding: latin-1 -*-\n\xa9\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertEqual(contents, sample_file.read_bytes()) + + +def _add_name(self, name: Name): + self._execute(models.Name.objects.insert_into(), self._convert_name(name)) + + +def test_file_with_unix_line_ending(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"1\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertIsNone(sample_file.newlines) + self.assertEqual("1\n", sample_file.read()) + self.assertEqual("\n", sample_file.newlines) + + sample_file.write("1\n") + self.assertEqual(b"1\n", sample_file.read_bytes()) + + +def test_file_with_dos_line_ending(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"1\r\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertIsNone(sample_file.newlines) + self.assertEqual("1\n", sample_file.read()) + self.assertEqual("\r\n", sample_file.newlines) + + sample_file.write("1\n") + self.assertEqual(b"1\r\n", sample_file.read_bytes()) + + +def test_file_with_mac_line_ending(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"1\r" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertIsNone(sample_file.newlines) + self.assertEqual("1\n", sample_file.read()) + self.assertEqual("\r", sample_file.newlines) + + sample_file.write("1\n") + self.assertEqual(b"1\r", sample_file.read_bytes()) + + +def test_file_binary(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"1\r\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertIsNone(sample_file.newlines) + self.assertEqual(b"1\r\n", sample_file.read_bytes()) + self.assertIsNone(sample_file.newlines) + + sample_file.write(b"1\nx\r") + self.assertEqual((b"1\nx\r"), sample_file.read_bytes()) + + +# TODO: Detecting utf-16 encoding +def xxx_test_using_utf16(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"# -*- coding: utf-16 -*-\n# This is a sample file ...\n" + file = open(sample_file.real_path, "w") + file.write(contents.encode("utf-16")) + file.close() + sample_file.write(contents) + self.assertEqual(contents, sample_file.read()) + + +# XXX: supporting utf_8_sig +def xxx_test_file_encoding_reading_for_notepad_styles(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = "#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" + file = open(sample_file.real_path, "w") + # file.write('\xef\xbb\xbf') + file.write(contents.encode("utf-8-sig")) + file.close() + self.assertEqual(contents, sample_file.read()) + + +def test_using_project_get_file(self): + myfile = self.project.get_file(self.sample_file) + self.assertTrue(myfile.exists()) + + +def test_using_file_create(self): + myfile = self.project.get_file("myfile.txt") + self.assertFalse(myfile.exists()) + myfile.create() + self.assertTrue(myfile.exists()) + self.assertFalse(myfile.is_folder()) + + +def test_using_folder_create(self): + myfolder = self.project.get_folder("myfolder") + self.assertFalse(myfolder.exists()) + myfolder.create() + self.assertTrue(myfolder.exists()) + self.assertTrue(myfolder.is_folder()) + + +def test_exception_when_creating_twice(self): + with self.assertRaises(RopeError): + myfile = self.project.get_file("myfile.txt") + myfile.create() + myfile.create() + + +def _find_package_path(self, target_name: str) -> Optional[Package]: + if target_name in sys.builtin_module_names: + return Package(target_name, Source.BUILTIN, None, PackageType.BUILTIN) + for folder in self._get_python_folders(): + for package in folder.iterdir(): + package_tuple = get_package_tuple(package, self.project) + if package_tuple is None: + continue + name, source, package_path, package_type = package_tuple + if name == target_name: + return package_tuple + + return None + + +def test_exception_when_parent_does_not_exist(self): + with self.assertRaises(ResourceNotFoundError): + myfile = self.project.get_file("myfolder/myfile.txt") + myfile.create() + + +def test_simple_path_to_resource(self): + myfile = self.project.root.create_file("myfile.txt") + self.assertEqual(myfile, path_to_resource(self.project, myfile.real_path)) + self.assertEqual( + myfile, path_to_resource(self.project, myfile.real_path, type="file") + ) + myfolder = self.project.root.create_folder("myfolder") + self.assertEqual(myfolder, path_to_resource(self.project, myfolder.real_path)) + self.assertEqual( + myfolder, path_to_resource(self.project, myfolder.real_path, type="folder") + ) + + +@testutils.skipNotPOSIX() +def test_ignoring_symlinks_inside_project(self): + project2 = testutils.sample_project(folder_name="sampleproject2") + mod = project2.root.create_file("mod.py") + try: + path = os.path.join(self.project.address, "linkedfile.txt") + os.symlink(mod.real_path, path) + files = self.project.root.get_files() + self.assertEqual(1, len(files)) + finally: + testutils.remove_project(project2) + + +def test_getting_empty_source_folders(self): + self.assertEqual([], self.project.get_source_folders()) + + +def test_root_source_folder(self): + self.project.root.create_file("sample.py") + source_folders = self.project.get_source_folders() + self.assertEqual(1, len(source_folders)) + self.assertTrue(self.project.root in source_folders) + + +def test_root_source_folder2(self): + self.project.root.create_file("mod1.py") + self.project.root.create_file("mod2.py") + source_folders = self.project.get_source_folders() + self.assertEqual(1, len(source_folders)) + self.assertTrue(self.project.root in source_folders) + + +def test_src_source_folder(self): + src = self.project.root.create_folder("src") + src.create_file("sample.py") + source_folders = self.project.get_source_folders() + self.assertEqual(1, len(source_folders)) + self.assertTrue(self.project.get_resource("src") in source_folders) + + +def test_packages(self): + src = self.project.root.create_folder("src") + pkg = src.create_folder("package") + pkg.create_file("__init__.py") + source_folders = self.project.get_source_folders() + self.assertEqual(1, len(source_folders)) + self.assertTrue(src in source_folders) + + +def test_multi_source_folders(self): + src = self.project.root.create_folder("src") + package = src.create_folder("package") + package.create_file("__init__.py") + test = self.project.root.create_folder("test") + test.create_file("alltests.py") + source_folders = self.project.get_source_folders() + self.assertEqual(2, len(source_folders)) + self.assertTrue(src in source_folders) + self.assertTrue(test in source_folders) + + +def test_multi_source_folders2(self): + testutils.create_module(self.project, "mod1") + src = self.project.root.create_folder("src") + package = testutils.create_package(self.project, "package", src) + testutils.create_module(self.project, "mod2", package) + source_folders = self.project.get_source_folders() + self.assertEqual(2, len(source_folders)) + self.assertTrue(self.project.root in source_folders and src in source_folders) + + + +def _insert(self, lineno, line): + self.diffs[self.origs[lineno]] += len(line) + 1 + self.origs.insert(lineno, self.origs[lineno]) + self.lines.insert(lineno, line) + + + +def _resource_to_module( + self, resource: Resource, underlined: bool = False +) -> ModuleFile: + assert self.project_package.path + underlined = underlined if underlined else self.underlined + resource_path: Path = Path(resource.real_path) + # The project doesn't need its name added to the path, + # since the standard python file layout accounts for that + # so we set add_package_name to False + resource_modname: str = get_modname_from_path( + resource_path, self.project_package.path, add_package_name=False + ) + return ModuleFile( + resource_path, + resource_modname, + underlined, + resource_path.name == "__init__.py", + ) + + +class ResourceObserverTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_resource_change_observer(self): + sample_file = self.project.root.create_file("my_file.txt") + sample_file.write("a sample file version 1") + sample_observer = _SampleObserver() + self.project.add_observer(sample_observer) + sample_file.write("a sample file version 2") + self.assertEqual(1, sample_observer.change_count) + self.assertEqual(sample_file, sample_observer.last_changed) + + +def test_resource_change_observer_after_removal(self): + sample_file = self.project.root.create_file("my_file.txt") + sample_file.write("text") + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [sample_file]) + ) + sample_file.remove() + self.assertEqual(1, sample_observer.change_count) + self.assertEqual(sample_file, sample_observer.last_removed) + + +def test_resource_change_observer2(self): + sample_file = self.project.root.create_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(sample_observer) + self.project.remove_observer(sample_observer) + sample_file.write("a sample file version 2") + self.assertEqual(0, sample_observer.change_count) + + +def test_resource_change_observer_for_folders(self): + root_folder = self.project.root + my_folder = root_folder.create_folder("my_folder") + my_folder_observer = _SampleObserver() + root_folder_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(my_folder_observer, [my_folder]) + ) + self.project.add_observer( + FilteredResourceObserver(root_folder_observer, [root_folder]) + ) + my_file = my_folder.create_file("my_file.txt") + self.assertEqual(1, my_folder_observer.change_count) + my_file.move("another_file.txt") + self.assertEqual(2, my_folder_observer.change_count) + self.assertEqual(1, root_folder_observer.change_count) + self.project.get_resource("another_file.txt").remove() + self.assertEqual(2, my_folder_observer.change_count) + self.assertEqual(2, root_folder_observer.change_count) + + +def test_resource_change_observer_after_moving(self): + sample_file = self.project.root.create_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(sample_observer) + sample_file.move("new_file.txt") + self.assertEqual(1, sample_observer.change_count) + self.assertEqual( + (sample_file, self.project.get_resource("new_file.txt")), + sample_observer.last_moved, + ) + + +def test_revalidating_files(self): + root = self.project.root + my_file = root.create_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) + os.remove(my_file.real_path) + self.project.validate(root) + self.assertEqual(my_file, sample_observer.last_removed) + self.assertEqual(1, sample_observer.change_count) + + +def test_revalidating_files_and_no_changes2(self): + root = self.project.root + my_file = root.create_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) + self.project.validate(root) + self.assertEqual(None, sample_observer.last_moved) + self.assertEqual(0, sample_observer.change_count) + + +def _execute(self, query: models.FinalQuery, *args, **kwargs): + assert isinstance(query, models.FinalQuery) + return self.connection.execute(query._query, *args, **kwargs) + + +def test_revalidating_folders(self): + root = self.project.root + my_folder = root.create_folder("myfolder") + my_file = my_folder.create_file("myfile.txt") # noqa + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [my_folder]) + ) + testutils.remove_recursively(my_folder.real_path) + self.project.validate(root) + self.assertEqual(my_folder, sample_observer.last_removed) + self.assertEqual(1, sample_observer.change_count) + + +def test_removing_and_adding_resources_to_filtered_observer(self): + my_file = self.project.root.create_file("my_file.txt") + sample_observer = _SampleObserver() + filtered_observer = FilteredResourceObserver(sample_observer) + self.project.add_observer(filtered_observer) + my_file.write("1") + self.assertEqual(0, sample_observer.change_count) + filtered_observer.add_resource(my_file) + my_file.write("2") + self.assertEqual(1, sample_observer.change_count) + filtered_observer.remove_resource(my_file) + my_file.write("3") + self.assertEqual(1, sample_observer.change_count) + + +def test_validation_and_changing_files(self): + my_file = self.project.root.create_file("my_file.txt") + sample_observer = _SampleObserver() + timekeeper = _MockChangeIndicator() + filtered_observer = FilteredResourceObserver( + sample_observer, [my_file], timekeeper=timekeeper + ) + self.project.add_observer(filtered_observer) + self._write_file(my_file.real_path) + timekeeper.set_indicator(my_file, 1) + self.project.validate(self.project.root) + self.assertEqual(1, sample_observer.change_count) + + +def test_validation_and_changing_files2(self): + my_file = self.project.root.create_file("my_file.txt") + sample_observer = _SampleObserver() + timekeeper = _MockChangeIndicator() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [my_file], timekeeper=timekeeper) + ) + timekeeper.set_indicator(my_file, 1) + my_file.write("hey") + self.assertEqual(1, sample_observer.change_count) + self.project.validate(self.project.root) + self.assertEqual(1, sample_observer.change_count) + + +def test_not_reporting_multiple_changes_to_folders(self): + root = self.project.root + file1 = root.create_file("file1.txt") + file2 = root.create_file("file2.txt") + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [root, file1, file2]) + ) + os.remove(file1.real_path) + os.remove(file2.real_path) + self.assertEqual(0, sample_observer.change_count) + self.project.validate(self.project.root) + self.assertEqual(3, sample_observer.change_count) + + +def _write_file(self, path): + my_file = open(path, "w") + my_file.write("\n") + my_file.close() + + +def test_moving_and_being_interested_about_a_folder_and_a_child(self): + my_folder = self.project.root.create_folder("my_folder") + my_file = my_folder.create_file("my_file.txt") + sample_observer = _SampleObserver() + filtered_observer = FilteredResourceObserver( + sample_observer, [my_folder, my_file] + ) + self.project.add_observer(filtered_observer) + my_folder.move("new_folder") + self.assertEqual(2, sample_observer.change_count) + + +def test_contains_for_folders(self): + folder1 = self.project.root.create_folder("folder") + folder2 = self.project.root.create_folder("folder2") + self.assertFalse(folder1.contains(folder2)) + + +def test_validating_when_created(self): + root = self.project.root + my_file = self.project.get_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) + open(my_file.real_path, "w").close() + self.project.validate(root) + self.assertEqual(my_file, sample_observer.last_created) + self.assertEqual(1, sample_observer.change_count) + + +def test_validating_twice_when_created(self): + root = self.project.root + my_file = self.project.get_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) + open(my_file.real_path, "w").close() + self.project.validate(root) + self.project.validate(root) + self.assertEqual(my_file, sample_observer.last_created) + self.assertEqual(1, sample_observer.change_count) + + +def _executemany(self, query: models.FinalQuery, *args, **kwargs): + assert isinstance(query, models.FinalQuery) + return self.connection.executemany(query._query, *args, **kwargs) + +def test_changes_and_adding_resources(self): + root = self.project.root # noqa + file1 = self.project.get_file("file1.txt") + file2 = self.project.get_file("file2.txt") + file1.create() + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [file1, file2]) + ) + file1.move(file2.path) + self.assertEqual(2, sample_observer.change_count) + self.assertEqual(file2, sample_observer.last_created) + self.assertEqual((file1, file2), sample_observer.last_moved) + + +def test_validating_get_files_list(self): + root = self.project.root # noqa + self.assertEqual(0, len(self.project.get_files())) + file = open(os.path.join(self.project.address, "myfile.txt"), "w") + file.close() + self.project.validate() + self.assertEqual(1, len(self.project.get_files())) + + +def test_clear_observered_resources_for_filtered_observers(self): + sample_file = self.project.root.create_file("myfile.txt") + sample_observer = _SampleObserver() + filtered = FilteredResourceObserver(sample_observer) + self.project.add_observer(filtered) + filtered.add_resource(sample_file) + filtered.clear_resources() + sample_file.write("1") + self.assertEqual(0, sample_observer.change_count) + + + +class _MockChangeIndicator: + @others + +def __init__(self): + self.times = {} + + +def set_indicator(self, resource, time): + self.times[resource] = time + + +def get_indicator(self, resource): + return self.times.get(resource, 0) + + + +class _SampleObserver: + @others + +def __init__(self): + self.change_count = 0 + self.last_changed = None + self.last_moved = None + self.last_created = None + self.last_removed = None + + +def resource_changed(self, resource): + self.last_changed = resource + self.change_count += 1 + + +@path C:/Repos/ekr-rope/rope/contrib/autoimport/ +"""Utility functions for the autoimport code.""" +import pathlib +import sys +from collections import OrderedDict +from typing import Generator, List, Optional, Tuple + +from rope.base.project import Project + +from .defs import ModuleCompiled, ModuleFile, ModuleInfo, Package, PackageType, Source + + +@others +@language python +@tabwidth -4 + +def resource_moved(self, resource, new_resource): + self.last_moved = (resource, new_resource) + self.change_count += 1 + + +def resource_created(self, resource): + self.last_created = resource + self.change_count += 1 + + +def resource_removed(self, resource): + self.last_removed = resource + self.change_count += 1 + + + +class OutOfProjectTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.test_directory = "temp_test_directory" + testutils.remove_recursively(self.test_directory) + os.mkdir(self.test_directory) + self.project = testutils.sample_project() + self.no_project = NoProject() + + +def tearDown(self): + testutils.remove_project(self.project) + testutils.remove_recursively(self.test_directory) + super().tearDown() + + +def test_simple_out_of_project_file(self): + sample_file_path = os.path.join(self.test_directory, "sample.txt") + sample_file = open(sample_file_path, "w") + sample_file.write("sample content\n") + sample_file.close() + sample_resource = self.no_project.get_resource(sample_file_path) + self.assertEqual("sample content\n", sample_resource.read()) + + +def test_simple_out_of_project_folder(self): + sample_folder_path = os.path.join(self.test_directory, "sample_folder") + os.mkdir(sample_folder_path) + sample_folder = self.no_project.get_resource(sample_folder_path) + self.assertEqual([], sample_folder.get_children()) + + sample_file_path = os.path.join(sample_folder_path, "sample.txt") + open(sample_file_path, "w").close() + sample_resource = self.no_project.get_resource(sample_file_path) + self.assertEqual(sample_resource, sample_folder.get_children()[0]) + + +def test_using_absolute_path(self): + sample_file_path = os.path.join(self.test_directory, "sample.txt") + open(sample_file_path, "w").close() + normal_sample_resource = self.no_project.get_resource(sample_file_path) + absolute_sample_resource = self.no_project.get_resource( + os.path.abspath(sample_file_path) + ) + self.assertEqual(normal_sample_resource, absolute_sample_resource) + + +def test_folder_get_child(self): + sample_folder_path = os.path.join(self.test_directory, "sample_folder") + os.mkdir(sample_folder_path) + sample_folder = self.no_project.get_resource(sample_folder_path) + self.assertEqual([], sample_folder.get_children()) + + sample_file_path = os.path.join(sample_folder_path, "sample.txt") + open(sample_file_path, "w").close() + sample_resource = self.no_project.get_resource(sample_file_path) + self.assertTrue(sample_folder.has_child("sample.txt")) + self.assertFalse(sample_folder.has_child("doesnothave.txt")) + self.assertEqual(sample_resource, sample_folder.get_child("sample.txt")) + + +def get_package_tuple( + package_path: pathlib.Path, project: Optional[Project] = None +) -> Optional[Package]: + """ + Get package name and type from a path. + + Checks for common issues, such as not being a viable python module + Returns None if not a viable package. + """ + package_name = package_path.name + package_type: PackageType + if package_name.startswith(".") or package_name == "__pycache__": + return None + if package_name.endswith((".egg-info", ".dist-info")): + return None + if package_path.is_file(): + if package_name.endswith(".so"): + package_name = package_name.split(".")[0] + package_type = PackageType.COMPILED + elif package_name.endswith(".pyd"): + package_name = package_name.split(".")[0] + package_type = PackageType.COMPILED + elif package_name.endswith(".py"): + package_name = package_path.stem + package_type = PackageType.SINGLE_FILE + else: + return None + else: + package_type = PackageType.STANDARD + package_source: Source = get_package_source(package_path, project, package_name) + return Package(package_name, package_source, package_path, package_type) + + + +def test_out_of_project_files_and_path_to_resource(self): + sample_file_path = os.path.join(self.test_directory, "sample.txt") + sample_file = open(sample_file_path, "w") + sample_file.write("sample content\n") + sample_file.close() + sample_resource = self.no_project.get_resource(sample_file_path) + self.assertEqual( + sample_resource, path_to_resource(self.project, sample_file_path) + ) + + + +class _MockFSCommands: + @others + +def __init__(self): + self.log = "" + self.fscommands = FileSystemCommands() + + +def create_file(self, path): + self.log += "create_file " + self.fscommands.create_file(path) + + +def create_folder(self, path): + self.log += "create_folder " + self.fscommands.create_folder(path) + + +def move(self, path, new_location): + self.log += "move " + self.fscommands.move(path, new_location) + + +def remove(self, path): + self.log += "remove " + self.fscommands.remove(path) + + +def read(self, path): + self.log += "read " + return self.fscommands.read(path) + + + +class _DeprecatedFSCommands: + @others + +def __init__(self): + self.log = "" + self.fscommands = FileSystemCommands() + + +def get_package_source( + package: pathlib.Path, project: Optional[Project], name: str +) -> Source: + """Detect the source of a given package. Rudimentary implementation.""" + if name in sys.builtin_module_names: + return Source.BUILTIN + if project is not None and project.address in str(package): + return Source.PROJECT + if "site-packages" in package.parts: + return Source.SITE_PACKAGE + if sys.version_info < (3, 10, 0): + if str(package).startswith(sys.prefix): + return Source.STANDARD + else: + if name in sys.stdlib_module_names: + return Source.STANDARD + return Source.UNKNOWN + + + +def create_file(self, path): + self.log += "create_file " + self.fscommands.create_file(path) + + +def create_folder(self, path): + self.log += "create_folder " + self.fscommands.create_folder(path) + + +def move(self, path, new_location): + self.log += "move " + self.fscommands.move(path, new_location) + + +def remove(self, path): + self.log += "remove " + self.fscommands.remove(path) + + + +class RopeFolderTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = None + + +def tearDown(self): + if self.project: + testutils.remove_project(self.project) + super().tearDown() + + +def test_none_project_rope_folder(self): + self.project = testutils.sample_project(ropefolder=None) + self.assertTrue(self.project.ropefolder is None) + + +def test_getting_project_rope_folder(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + self.assertTrue(self.project.ropefolder.exists()) + self.assertTrue(".ropeproject", self.project.ropefolder.path) + + +def test_setting_ignored_resources(self): + self.project = testutils.sample_project(ignored_resources=["myfile.txt"]) + myfile = self.project.get_file("myfile.txt") + file2 = self.project.get_file("file2.txt") + self.assertTrue(self.project.is_ignored(myfile)) + self.assertFalse(self.project.is_ignored(file2)) + + +def get_modname_from_path( + modpath: pathlib.Path, package_path: pathlib.Path, add_package_name: bool = True +) -> str: + """Get module name from a path in respect to package.""" + package_name: str = package_path.stem + rel_path_parts = modpath.relative_to(package_path).parts + modname = "" + if len(rel_path_parts) > 0: + for part in rel_path_parts[:-1]: + modname += part + modname += "." + if rel_path_parts[-1] == "__init__": + modname = modname[:-1] + else: + modname = modname + modpath.stem + if add_package_name: + modname = package_name if modname == "" else package_name + "." + modname + else: + assert modname != "." + return modname + + + +def test_ignored_folders(self): + self.project = testutils.sample_project(ignored_resources=["myfolder"]) + myfolder = self.project.root.create_folder("myfolder") + self.assertTrue(self.project.is_ignored(myfolder)) + myfile = myfolder.create_file("myfile.txt") + self.assertTrue(self.project.is_ignored(myfile)) + + +def test_ignored_resources_and_get_files(self): + self.project = testutils.sample_project( + ignored_resources=["myfile.txt"], ropefolder=None + ) + myfile = self.project.get_file("myfile.txt") + self.assertEqual(0, len(self.project.get_files())) + myfile.create() + self.assertEqual(0, len(self.project.get_files())) + + +def test_ignored_resources_and_get_files2(self): + self.project = testutils.sample_project( + ignored_resources=["myfile.txt"], ropefolder=None + ) + myfile = self.project.root.create_file("myfile.txt") # noqa + self.assertEqual(0, len(self.project.get_files())) + + +def test_setting_ignored_resources_patterns(self): + self.project = testutils.sample_project(ignored_resources=["m?file.*"]) + myfile = self.project.get_file("myfile.txt") + file2 = self.project.get_file("file2.txt") + self.assertTrue(self.project.is_ignored(myfile)) + self.assertFalse(self.project.is_ignored(file2)) + + +def test_star_should_not_include_slashes(self): + self.project = testutils.sample_project(ignored_resources=["f*.txt"]) + folder = self.project.root.create_folder("folder") + file1 = folder.create_file("myfile.txt") + file2 = folder.create_file("file2.txt") + self.assertFalse(self.project.is_ignored(file1)) + self.assertTrue(self.project.is_ignored(file2)) + + +def test_normal_fscommands(self): + fscommands = _MockFSCommands() + self.project = testutils.sample_project(fscommands=fscommands) + myfile = self.project.get_file("myfile.txt") + myfile.create() + self.assertTrue("create_file ", fscommands.log) + + +def test_fscommands_and_ignored_resources(self): + fscommands = _MockFSCommands() + self.project = testutils.sample_project( + fscommands=fscommands, ignored_resources=["myfile.txt"], ropefolder=None + ) + myfile = self.project.get_file("myfile.txt") + myfile.create() + self.assertEqual("", fscommands.log) + + +def test_deprecated_fscommands(self): + fscommands = _DeprecatedFSCommands() + self.project = testutils.sample_project(fscommands=fscommands) + myfile = self.project.get_file("myfile.txt") + myfile.create() + self.assertTrue("create_file ", fscommands.log) + + +def test_ignored_resources_and_prefixes(self): + self.project = testutils.sample_project(ignored_resources=[".hg"]) + myfile = self.project.root.create_file(".hgignore") + self.assertFalse(self.project.is_ignored(myfile)) + + +def test_loading_config_dot_py(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + config = self.project.get_file(".ropeproject/config.py") + if not config.exists(): + config.create() + config.write(dedent("""\ + def set_prefs(prefs): + prefs["ignored_resources"] = ["myfile.txt"] + def project_opened(project): + project.root.create_file("loaded") + """)) + self.project.close() + self.project = Project(self.project.address, ropefolder=".ropeproject") + self.assertTrue(self.project.get_file("loaded").exists()) + myfile = self.project.get_file("myfile.txt") + self.assertTrue(self.project.is_ignored(myfile)) + + +def sort_and_deduplicate(results: List[Tuple[str, int]]) -> List[str]: + """Sort and deduplicate a list of name, source entries.""" + results = sorted(results, key=lambda y: y[-1]) + results_sorted = [name for name, source in results] + return list(OrderedDict.fromkeys(results_sorted)) + + + +def test_loading_pyproject(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + config = self.project.get_file("pyproject.toml") + if not config.exists(): + config.create() + config.write(dedent("""\ + [tool.rope] + ignored_resources=["pyproject.py"] + """)) + self.project.close() + self.project = Project(self.project.address, ropefolder=".ropeproject") + myfile = self.project.get_file("pyproject.py") + self.assertTrue(self.project.is_ignored(myfile)) + + +def test_loading_pyproject_empty_file(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + config = self.project.get_file("pyproject.toml") + if not config.exists(): + config.create() + config.write("") + self.project.close() + self.project = Project(self.project.address, ropefolder=".ropeproject") + myfile = self.project.get_file("pyproject.py") + self.assertFalse(self.project.is_ignored(myfile)) + + +def test_loading_pyproject_no_tool_section(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + config = self.project.get_file("pyproject.toml") + if not config.exists(): + config.create() + config.write(dedent("""\ + [project] + name = 'testproject' + """)) + self.project.close() + self.project = Project(self.project.address, ropefolder=".ropeproject") + myfile = self.project.get_file("pyproject.py") + self.assertFalse(self.project.is_ignored(myfile)) + + +def test_loading_pyproject_no_tool_rope_section(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + config = self.project.get_file("pyproject.toml") + if not config.exists(): + config.create() + config.write(dedent("""\ + [tool.anothertool] + name = 'testproject' + """)) + self.project.close() + self.project = Project(self.project.address, ropefolder=".ropeproject") + myfile = self.project.get_file("pyproject.py") + self.assertFalse(self.project.is_ignored(myfile)) + + +def test_ignoring_syntax_errors(self): + self.project = testutils.sample_project( + ropefolder=None, ignore_syntax_errors=True + ) + mod = testutils.create_module(self.project, "mod") + mod.write("xyz print") + pymod = self.project.get_pymodule(mod) # noqa + + +def test_compressed_history(self): + self.project = testutils.sample_project(compress_history=True) + mod = testutils.create_module(self.project, "mod") + mod.write("") + + +def test_compressed_objectdb(self): + self.project = testutils.sample_project(compress_objectdb=True) + mod = testutils.create_module(self.project, "mod") + self.project.pycore.analyze_module(mod) + + +def test_nested_dot_ropeproject_folder(self): + self.project = testutils.sample_project(ropefolder=".f1/f2") + ropefolder = self.project.ropefolder + self.assertEqual(".f1/f2", ropefolder.path) + self.assertTrue(ropefolder.exists()) + +@path C:/Repos/ekr-rope/ropetest/ +import sys +from textwrap import dedent + +from rope.base.builtins import File, BuiltinClass + +import unittest + +from rope.base import exceptions +from rope.base import libutils +from rope.base.pycore import _TextChangeDetector +from rope.base.pyobjects import get_base_type, AbstractFunction +from rope.base.pynamesdef import AssignedName +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class PyCoreTest(unittest.TestCase): + @others + +def sort_and_deduplicate_tuple( + results: List[Tuple[str, str, int]] +) -> List[Tuple[str, str]]: + """Sort and deduplicate a list of name, module, source entries.""" + results = sorted(results, key=lambda y: y[-1]) + results_sorted = [result[:-1] for result in results] + return list(OrderedDict.fromkeys(results_sorted)) + + + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_module(self): + testutils.create_module(self.project, "mod") + result = self.project.get_module("mod") + self.assertEqual(get_base_type("Module"), result.type) + self.assertEqual(0, len(result.get_attributes())) + + +def test_nested_modules(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) # noqa + package = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), package.get_type()) + self.assertEqual(1, len(package.get_attributes())) + module = package["mod"].get_object() + self.assertEqual(get_base_type("Module"), module.get_type()) + + +def test_package(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) # noqa + result = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), result.type) + + +def test_simple_class(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + class SampleClass(object): + pass + """)) + mod_element = self.project.get_module("mod") + result = mod_element["SampleClass"].get_object() + self.assertEqual(get_base_type("Type"), result.get_type()) + + +def test_simple_function(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + def sample_function(): + pass + """)) + mod_element = self.project.get_module("mod") + result = mod_element["sample_function"].get_object() + self.assertEqual(get_base_type("Function"), result.get_type()) + + +def test_class_methods(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class SampleClass(object): + def sample_method(self): + pass + """) + mod.write(code) + mod_element = self.project.get_module("mod") + sample_class = mod_element["SampleClass"].get_object() + self.assertTrue("sample_method" in sample_class) + method = sample_class["sample_method"].get_object() + self.assertEqual(get_base_type("Function"), method.get_type()) + + +def test_global_variable_without_type_annotation(self): + mod = testutils.create_module(self.project, "mod") + mod.write("var = 10") + mod_element = self.project.get_module("mod") + var = mod_element["var"] + self.assertEqual(AssignedName, type(var)) + + +@testutils.only_for_versions_higher("3.6") +def test_global_variable_with_type_annotation(self): + mod = testutils.create_module(self.project, "mod") + mod.write("py3_var: str = foo_bar") + mod_element = self.project.get_module("mod") + py3_var = mod_element["py3_var"] + self.assertEqual(AssignedName, type(py3_var)) + + +def should_parse(path: pathlib.Path, underlined: bool) -> bool: + if underlined: + return True + for part in path.parts: + if part.startswith("_"): + return False + return True + + + +def test_class_variables(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + class SampleClass(object): + var = 10 + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["SampleClass"].get_object() + var = sample_class["var"] # noqa + + +def test_class_attributes_set_in_init(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + class C(object): + def __init__(self): + self.var = 20 + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["C"].get_object() + var = sample_class["var"] # noqa + + +def test_class_attributes_set_in_init_overwriting_a_defined(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + def __init__(self): + self.f = 20 + def f(): + pass + """) + mod.write(code) + mod_element = self.project.get_module("mod") + sample_class = mod_element["C"].get_object() + f = sample_class["f"].get_object() + self.assertTrue(isinstance(f, AbstractFunction)) + + +def test_classes_inside_other_classes(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class SampleClass(object): + class InnerClass(object): + pass + + """) + mod.write(code) + mod_element = self.project.get_module("mod") + sample_class = mod_element["SampleClass"].get_object() + var = sample_class["InnerClass"].get_object() + self.assertEqual(get_base_type("Type"), var.get_type()) + + +def test_non_existent_module(self): + with self.assertRaises(exceptions.ModuleNotFoundError): + self.project.get_module("doesnotexistmodule") + + +def test_imported_names(self): + testutils.create_module(self.project, "mod1") + mod = testutils.create_module(self.project, "mod2") + mod.write("import mod1\n") + module = self.project.get_module("mod2") + imported_sys = module["mod1"].get_object() + self.assertEqual(get_base_type("Module"), imported_sys.get_type()) + + +def test_imported_as_names(self): + testutils.create_module(self.project, "mod1") + mod = testutils.create_module(self.project, "mod2") + mod.write("import mod1 as my_import\n") + module = self.project.get_module("mod2") + imported_mod = module["my_import"].get_object() + self.assertEqual(get_base_type("Module"), imported_mod.get_type()) + + +def test_get_string_module(self): + code = dedent("""\ + class Sample(object): + pass + """) + mod = libutils.get_string_module(self.project, code) + sample_class = mod["Sample"].get_object() + self.assertEqual(get_base_type("Type"), sample_class.get_type()) + + +def test_get_string_module_with_extra_spaces(self): + code = "a = 10\n " + mod = libutils.get_string_module(self.project, code) # noqa + + +def test_parameter_info_for_functions(self): + code = dedent("""\ + def func(param1, param2=10, *param3, **param4): + pass""") + mod = libutils.get_string_module(self.project, code) + sample_function = mod["func"] + self.assertEqual( + ["param1", "param2", "param3", "param4"], + sample_function.get_object().get_param_names(), + ) + + +def _logical_start(lines, lineno, check_prev=False): + logical_finder = LogicalLineFinder(ArrayLinesAdapter(lines)) + if check_prev: + prev = lineno - 1 + while prev > 0: + start, end = logical_finder.logical_line_in(prev) + if end is None or start <= lineno < end: + return start + if start <= prev: + break + prev -= 1 + return logical_finder.logical_line_in(lineno)[0] + + + +def get_files( + package: Package, underlined: bool = False +) -> Generator[ModuleInfo, None, None]: + """Find all files to parse in a given path using __init__.py.""" + if package.type in (PackageType.COMPILED, PackageType.BUILTIN): + if package.source in (Source.STANDARD, Source.BUILTIN): + yield ModuleCompiled(None, package.name, underlined, True) + elif package.type == PackageType.SINGLE_FILE: + assert package.path + assert package.path.suffix == ".py" + yield ModuleFile(package.path, package.path.stem, underlined, False) + else: + assert package.path + for file in package.path.glob("*.py"): + if file.name == "__init__.py": + yield ModuleFile( + file, + get_modname_from_path(file.parent, package.path), + underlined, + True, + ) + elif should_parse(file, underlined): + yield ModuleFile( + file, get_modname_from_path(file, package.path), underlined, False + ) + +# FIXME: Not found modules +def xxx_test_not_found_module_is_module(self): + code = "import doesnotexist\n" + mod = libutils.get_string_module(self.project, code) + self.assertEqual( + get_base_type("Module"), mod["doesnotexist"].get_object().get_type() + ) + + +def test_mixing_scopes_and_objects_hierarchy(self): + code = "var = 200\n" + mod = libutils.get_string_module(self.project, code) + scope = mod.get_scope() + self.assertTrue("var" in scope.get_names()) + + +def test_inheriting_base_class_attributes(self): + code = dedent("""\ + class Base(object): + def method(self): + pass + class Derived(Base): + pass + """) + mod = libutils.get_string_module(self.project, code) + derived = mod["Derived"].get_object() + self.assertTrue("method" in derived) + self.assertEqual( + get_base_type("Function"), derived["method"].get_object().get_type() + ) + + +def test_inheriting_multiple_base_class_attributes(self): + code = dedent("""\ + class Base1(object): + def method1(self): + pass + class Base2(object): + def method2(self): + pass + class Derived(Base1, Base2): + pass + """) + mod = libutils.get_string_module(self.project, code) + derived = mod["Derived"].get_object() + self.assertTrue("method1" in derived) + self.assertTrue("method2" in derived) + + +def test_inherit_multiple_base_class_attrs_with_the_same_name(self): + code = dedent("""\ + class Base1(object): + def method(self): + pass + class Base2(object): + def method(self): + pass + class Derived(Base1, Base2): + pass + """) + mod = libutils.get_string_module(self.project, code) + base1 = mod["Base1"].get_object() + derived = mod["Derived"].get_object() + self.assertEqual(base1["method"].get_object(), derived["method"].get_object()) + + +def test_inheriting_unknown_base_class(self): + code = dedent("""\ + class Derived(NotFound): + def f(self): + pass + """) + mod = libutils.get_string_module(self.project, code) + derived = mod["Derived"].get_object() + self.assertTrue("f" in derived) + + +def test_module_creation(self): + new_module = testutils.create_module(self.project, "module") + self.assertFalse(new_module.is_folder()) + self.assertEqual(self.project.get_resource("module.py"), new_module) + + +def test_packaged_module_creation(self): + package = self.project.root.create_folder("package") # noqa + new_module = testutils.create_module(self.project, "package.module") + self.assertEqual(self.project.get_resource("package/module.py"), new_module) + + +def test_packaged_module_creation_with_nested_src(self): + src = self.project.root.create_folder("src") + src.create_folder("pkg") + new_module = testutils.create_module(self.project, "pkg.mod", src) + self.assertEqual(self.project.get_resource("src/pkg/mod.py"), new_module) + + +def test_package_creation(self): + new_package = testutils.create_package(self.project, "pkg") + self.assertTrue(new_package.is_folder()) + self.assertEqual(self.project.get_resource("pkg"), new_package) + self.assertEqual( + self.project.get_resource("pkg/__init__.py"), + new_package.get_child("__init__.py"), + ) + + +@path C:/Repos/ekr-rope/rope/contrib/autoimport/ +"""AutoImport module for rope.""" +from .pickle import AutoImport as _PickleAutoImport +from .sqlite import AutoImport as _SqliteAutoImport + + +AutoImport = _PickleAutoImport + +__all__ = ["AutoImport"] +@language python +@tabwidth -4 + +def test_nested_package_creation(self): + testutils.create_package(self.project, "pkg1") + nested_package = testutils.create_package(self.project, "pkg1.pkg2") + self.assertEqual(self.project.get_resource("pkg1/pkg2"), nested_package) + + +def test_packaged_package_creation_with_nested_src(self): + src = self.project.root.create_folder("src") + testutils.create_package(self.project, "pkg1", src) + nested_package = testutils.create_package(self.project, "pkg1.pkg2", src) + self.assertEqual(self.project.get_resource("src/pkg1/pkg2"), nested_package) + + +def test_find_module(self): + src = self.project.root.create_folder("src") + samplemod = testutils.create_module(self.project, "samplemod", src) + found_module = self.project.find_module("samplemod") + self.assertEqual(samplemod, found_module) + + +def test_find_nested_module(self): + src = self.project.root.create_folder("src") + samplepkg = testutils.create_package(self.project, "samplepkg", src) + samplemod = testutils.create_module(self.project, "samplemod", samplepkg) + found_module = self.project.find_module("samplepkg.samplemod") + self.assertEqual(samplemod, found_module) + + +def test_find_multiple_module(self): + src = self.project.root.create_folder("src") + samplemod1 = testutils.create_module(self.project, "samplemod", src) + samplemod2 = testutils.create_module(self.project, "samplemod") + test = self.project.root.create_folder("test") + samplemod3 = testutils.create_module(self.project, "samplemod", test) + found_module = self.project.find_module("samplemod") + self.assertTrue( + samplemod1 == found_module + or samplemod2 == found_module + or samplemod3 == found_module + ) + + +def test_find_module_packages(self): + src = self.project.root + samplepkg = testutils.create_package(self.project, "samplepkg", src) + found_module = self.project.find_module("samplepkg") + self.assertEqual(samplepkg, found_module) + + +def test_find_module_when_module_and_package_with_the_same_name(self): + src = self.project.root + testutils.create_module(self.project, "sample", src) + samplepkg = testutils.create_package(self.project, "sample", src) + found_module = self.project.find_module("sample") + self.assertEqual(samplepkg, found_module) + + +def test_source_folders_preference(self): + testutils.create_package(self.project, "pkg1") + testutils.create_package(self.project, "pkg1.src2") + lost = testutils.create_module(self.project, "pkg1.src2.lost") + self.assertEqual(self.project.find_module("lost"), None) + self.project.close() + from rope.base.project import Project + + self.project = Project(self.project.address, source_folders=["pkg1/src2"]) + self.assertEqual(self.project.find_module("lost"), lost) + + +def test_get_pyname_definition_location(self): + code = "a_var = 20\n" + mod = libutils.get_string_module(self.project, code) + a_var = mod["a_var"] + self.assertEqual((mod, 1), a_var.get_definition_location()) + + +def test_get_pyname_definition_location_functions(self): + code = dedent("""\ + def a_func(): + pass + """) + mod = libutils.get_string_module(self.project, code) + a_func = mod["a_func"] + self.assertEqual((mod, 1), a_func.get_definition_location()) + + + +def test_get_pyname_definition_location_class(self): + code = dedent("""\ + class AClass(object): + pass + + """) + mod = libutils.get_string_module(self.project, code) + a_class = mod["AClass"] + self.assertEqual((mod, 1), a_class.get_definition_location()) + + +def test_get_pyname_definition_location_local_variables(self): + code = dedent("""\ + def a_func(): + a_var = 10 + """) + mod = libutils.get_string_module(self.project, code) + a_func_scope = mod.get_scope().get_scopes()[0] + a_var = a_func_scope["a_var"] + self.assertEqual((mod, 2), a_var.get_definition_location()) + + +def test_get_pyname_definition_location_reassigning(self): + code = dedent("""\ + a_var = 20 + a_var=30 + """) + mod = libutils.get_string_module(self.project, code) + a_var = mod["a_var"] + self.assertEqual((mod, 1), a_var.get_definition_location()) + + +def test_get_pyname_definition_location_importes(self): + testutils.create_module(self.project, "mod") + code = "import mod\n" + mod = libutils.get_string_module(self.project, code) + imported_module = self.project.get_module("mod") + module_pyname = mod["mod"] + self.assertEqual((imported_module, 1), module_pyname.get_definition_location()) + + +def test_get_pyname_definition_location_imports(self): + module_resource = testutils.create_module(self.project, "mod") + module_resource.write(dedent("""\ + + def a_func(): + pass + """)) + imported_module = self.project.get_module("mod") + code = dedent("""\ + from mod import a_func + """) + mod = libutils.get_string_module(self.project, code) + a_func = mod["a_func"] + self.assertEqual((imported_module, 2), a_func.get_definition_location()) + + +def test_get_pyname_definition_location_parameters(self): + code = dedent("""\ + def a_func(param1, param2): + a_var = param + """) + mod = libutils.get_string_module(self.project, code) + a_func_scope = mod.get_scope().get_scopes()[0] + param1 = a_func_scope["param1"] + self.assertEqual((mod, 1), param1.get_definition_location()) + param2 = a_func_scope["param2"] + self.assertEqual((mod, 1), param2.get_definition_location()) + + +def test_module_get_resource(self): + module_resource = testutils.create_module(self.project, "mod") + module = self.project.get_module("mod") + self.assertEqual(module_resource, module.get_resource()) + code = dedent("""\ + from mod import a_func + """) + string_module = libutils.get_string_module(self.project, code) + self.assertEqual(None, string_module.get_resource()) + + +def test_get_pyname_definition_location_class2(self): + code = dedent("""\ + class AClass(object): + def __init__(self): + self.an_attr = 10 + """) + mod = libutils.get_string_module(self.project, code) + a_class = mod["AClass"].get_object() + an_attr = a_class["an_attr"] + self.assertEqual((mod, 3), an_attr.get_definition_location()) + + +def test_import_not_found_module_get_definition_location(self): + code = "import doesnotexist\n" + mod = libutils.get_string_module(self.project, code) + does_not_exist = mod["doesnotexist"] + self.assertEqual((None, None), does_not_exist.get_definition_location()) + + +def test_from_not_found_module_get_definition_location(self): + code = "from doesnotexist import Sample\n" + mod = libutils.get_string_module(self.project, code) + sample = mod["Sample"] + self.assertEqual((None, None), sample.get_definition_location()) + + +@path C:/Repos/ekr-rope/rope/refactor/ +import copy + +import rope.base.exceptions +from rope.base import codeanalyze +from rope.base import evaluate +from rope.base import pyobjects +from rope.base import taskhandle +from rope.base import utils +from rope.base import worder +from rope.base.change import ChangeContents, ChangeSet +from rope.refactor import occurrences, functionutils + + +@others +@language python +@tabwidth -4 + +def test_from_package_import_module_get_definition_location(self): + pkg = testutils.create_package(self.project, "pkg") + testutils.create_module(self.project, "mod", pkg) + pkg_mod = self.project.get_module("pkg.mod") + code = "from pkg import mod\n" + mod = libutils.get_string_module(self.project, code) + imported_mod = mod["mod"] + self.assertEqual((pkg_mod, 1), imported_mod.get_definition_location()) + + +def test_get_module_for_defined_pyobjects(self): + code = dedent("""\ + class AClass(object): + pass + """) + mod = libutils.get_string_module(self.project, code) + a_class = mod["AClass"].get_object() + self.assertEqual(mod, a_class.get_module()) + + +def test_get_definition_location_for_packages(self): + testutils.create_package(self.project, "pkg") + init_module = self.project.get_module("pkg.__init__") + code = "import pkg\n" + mod = libutils.get_string_module(self.project, code) + pkg_pyname = mod["pkg"] + self.assertEqual((init_module, 1), pkg_pyname.get_definition_location()) + + +def test_get_definition_location_for_filtered_packages(self): + pkg = testutils.create_package(self.project, "pkg") + testutils.create_module(self.project, "mod", pkg) + init_module = self.project.get_module("pkg.__init__") + code = "import pkg.mod" + mod = libutils.get_string_module(self.project, code) + pkg_pyname = mod["pkg"] + self.assertEqual((init_module, 1), pkg_pyname.get_definition_location()) + + +def test_out_of_project_modules(self): + code = "import rope.base.project as project\n" + scope = libutils.get_string_scope(self.project, code) + imported_module = scope["project"].get_object() + self.assertTrue("Project" in imported_module) + + +def test_file_encoding_reading(self): + contents = ( + "# -*- coding: utf-8 -*-\n" + "#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" + ) + mod = testutils.create_module(self.project, "mod") + mod.write(contents) + self.project.get_module("mod") + + +def test_global_keyword(self): + code = dedent("""\ + a_var = 1 + def a_func(): + global a_var + """) + mod = libutils.get_string_module(self.project, code) + global_var = mod["a_var"] + func_scope = mod["a_func"].get_object().get_scope() + local_var = func_scope["a_var"] + self.assertEqual(global_var, local_var) + + +def test_not_leaking_for_vars_inside_parent_scope(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + def f(self): + for my_var1, my_var2 in []: + pass + """) + mod.write(code) + pymod = self.pycore.resource_to_pyobject(mod) + c_class = pymod["C"].get_object() + self.assertFalse("my_var1" in c_class) + self.assertFalse("my_var2" in c_class) + + +def test_not_leaking_for_vars_inside_parent_scope2(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + def f(self): + for my_var in []: + pass + """) + mod.write(code) + pymod = self.pycore.resource_to_pyobject(mod) + c_class = pymod["C"].get_object() + self.assertFalse("my_var" in c_class) + + +def test_variables_defined_in_excepts(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + try: + myvar1 = 1 + except: + myvar2 = 1 + finally: + myvar3 = 1 + """) + mod.write(code) + pymod = self.pycore.resource_to_pyobject(mod) + self.assertTrue("myvar1" in pymod) + self.assertTrue("myvar2" in pymod) + self.assertTrue("myvar3" in pymod) + + +class ChangeSignature: + @others + +def test_not_leaking_tuple_assigned_names_inside_parent_scope(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + def f(self): + var1, var2 = range(2) + """) + mod.write(code) + pymod = self.pycore.resource_to_pyobject(mod) + c_class = pymod["C"].get_object() + self.assertFalse("var1" in c_class) + + +@testutils.only_for("2.5") +def test_with_statement_variables(self): + code = dedent("""\ + import threading + with threading.lock() as var: pass + """) + if sys.version_info < (2, 6, 0): + code = "from __future__ import with_statement\n" + code + pymod = libutils.get_string_module(self.project, code) + self.assertTrue("var" in pymod) + + +@testutils.only_for("2.5") +def test_with_statement_variables_and_tuple_assignment(self): + code = dedent("""\ + class A(object): + def __enter__(self): return (1, 2) + def __exit__(self, type, value, tb): + pass + with A() as (a, b): + pass + """) + if sys.version_info < (2, 6, 0): + code = "from __future__ import with_statement\n" + code + pymod = libutils.get_string_module(self.project, code) + self.assertTrue("a" in pymod) + self.assertTrue("b" in pymod) + + +@testutils.only_for("2.5") +def test_with_statement_variable_type(self): + code = dedent("""\ + class A(object): + def __enter__(self): + return self + def __exit__(self, type, value, tb): + pass + with A() as var: + pass + """) + if sys.version_info < (2, 6, 0): + code = "from __future__ import with_statement\n" + code + pymod = libutils.get_string_module(self.project, code) + a_class = pymod["A"].get_object() + var = pymod["var"].get_object() + self.assertEqual(a_class, var.get_type()) + + +@testutils.only_for("2.7") +def test_nested_with_statement_variable_type(self): + code = dedent("""\ + class A(object): + def __enter__(self): + return self + def __exit__(self, type, value, tb): + pass + class B(object): + def __enter__(self): + return self + def __exit__(self, type, value, tb): + pass + with A() as var_a, B() as var_b: + pass + """) + if sys.version_info < (2, 6, 0): + code = "from __future__ import with_statement\n" + code + pymod = libutils.get_string_module(self.project, code) + a_class = pymod["A"].get_object() + var_a = pymod["var_a"].get_object() + self.assertEqual(a_class, var_a.get_type()) + + b_class = pymod["B"].get_object() + var_b = pymod["var_b"].get_object() + self.assertEqual(b_class, var_b.get_type()) + + +@testutils.only_for("2.5") +def test_with_statement_with_no_vars(self): + code = dedent("""\ + with open("file"): pass + """) + if sys.version_info < (2, 6, 0): + code = "from __future__ import with_statement\n" + code + pymod = libutils.get_string_module(self.project, code) + pymod.get_attributes() + + +def test_with_statement(self): + code = dedent("""\ + a = 10 + with open("file") as f: pass + """) + pymod = libutils.get_string_module(self.project, code) + assigned = pymod.get_attribute("a") + self.assertEqual(BuiltinClass, type(assigned.get_object().get_type())) + + assigned = pymod.get_attribute("f") + self.assertEqual(File, type(assigned.get_object().get_type())) + + +def test_check_for_else_block(self): + code = dedent("""\ + for i in range(10): + pass + else: + myvar = 1 + """) + mod = libutils.get_string_module(self.project, code) + a_var = mod["myvar"] + self.assertEqual((mod, 4), a_var.get_definition_location()) + + +def test_check_names_defined_in_whiles(self): + code = dedent("""\ + while False: + myvar = 1 + """) + mod = libutils.get_string_module(self.project, code) + a_var = mod["myvar"] + self.assertEqual((mod, 2), a_var.get_definition_location()) + + +def test_get_definition_location_in_tuple_assnames(self): + code = dedent("""\ + def f(x): + x.z, a = range(2) + """) + mod = libutils.get_string_module(self.project, code) + x = mod["f"].get_object().get_scope()["x"] + a = mod["f"].get_object().get_scope()["a"] + self.assertEqual((mod, 1), x.get_definition_location()) + self.assertEqual((mod, 2), a.get_definition_location()) + + +def __init__(self, project, resource, offset): + self.project = project + self.resource = resource + self.offset = offset + self._set_name_and_pyname() + if ( + self.pyname is None + or self.pyname.get_object() is None + or not isinstance(self.pyname.get_object(), pyobjects.PyFunction) + ): + raise rope.base.exceptions.RefactoringError( + "Change method signature should be performed on functions" + ) + + +def test_syntax_errors_in_code(self): + with self.assertRaises(exceptions.ModuleSyntaxError): + libutils.get_string_module(self.project, "xyx print\n") + + +def test_holding_error_location_information(self): + try: + libutils.get_string_module(self.project, "xyx print\n") + except exceptions.ModuleSyntaxError as e: + self.assertEqual(1, e.lineno) + + +def test_no_exceptions_on_module_encoding_problems(self): + mod = testutils.create_module(self.project, "mod") + contents = b"\nsdsdsd\n\xa9\n" + file = open(mod.real_path, "wb") + file.write(contents) + file.close() + mod.read() + + +def test_syntax_errors_when_cannot_decode_file2(self): + mod = testutils.create_module(self.project, "mod") + contents = b"\n\xa9\n" + file = open(mod.real_path, "wb") + file.write(contents) + file.close() + with self.assertRaises(exceptions.ModuleSyntaxError): + self.pycore.resource_to_pyobject(mod) + + +def test_syntax_errors_when_null_bytes(self): + mod = testutils.create_module(self.project, "mod") + contents = b"\n\x00\n" + file = open(mod.real_path, "wb") + file.write(contents) + file.close() + with self.assertRaises(exceptions.ModuleSyntaxError): + self.pycore.resource_to_pyobject(mod) + + +def test_syntax_errors_when_bad_strs(self): + mod = testutils.create_module(self.project, "mod") + contents = b'\n"\\x0"\n' + file = open(mod.real_path, "wb") + file.write(contents) + file.close() + with self.assertRaises(exceptions.ModuleSyntaxError): + self.pycore.resource_to_pyobject(mod) + + +def test_not_reaching_maximum_recursions_with_from_star_imports(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("from mod2 import *\n") + mod2.write("from mod1 import *\n") + pymod1 = self.pycore.resource_to_pyobject(mod1) + pymod1.get_attributes() + + +def test_not_reaching_maximum_recursions_when_importing_variables(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("from mod2 import myvar\n") + mod2.write("from mod1 import myvar\n") + pymod1 = self.pycore.resource_to_pyobject(mod1) + pymod1["myvar"].get_object() + + +def test_not_reaching_maximum_recursions_when_importing_variables2(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write("from mod1 import myvar\n") + pymod1 = self.pycore.resource_to_pyobject(mod1) + pymod1["myvar"].get_object() + + +def test_pyobject_equality_should_compare_types(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + var1 = "" + var2 = "" + """)) + pymod1 = self.pycore.resource_to_pyobject(mod1) + self.assertEqual(pymod1["var1"].get_object(), pymod1["var2"].get_object()) + + + +def _set_name_and_pyname(self): + self.name = worder.get_name_at(self.resource, self.offset) + this_pymodule = self.project.get_pymodule(self.resource) + self.primary, self.pyname = evaluate.eval_location2(this_pymodule, self.offset) + if self.pyname is None: + return + pyobject = self.pyname.get_object() + if isinstance(pyobject, pyobjects.PyClass) and "__init__" in pyobject: + self.pyname = pyobject["__init__"] + self.name = "__init__" + pyobject = self.pyname.get_object() + self.others = None + if ( + self.name == "__init__" + and isinstance(pyobject, pyobjects.PyFunction) + and isinstance(pyobject.parent, pyobjects.PyClass) + ): + pyclass = pyobject.parent + self.others = (pyclass.get_name(), pyclass.parent[pyclass.get_name()]) + + +class PyCoreInProjectsTest(unittest.TestCase): + @others + +def setUp(self): + super(self.__class__, self).setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + samplemod = testutils.create_module(self.project, "samplemod") + code = dedent("""\ + class SampleClass(object): + def sample_method(): + pass + + def sample_func(): + pass + sample_var = 10 + + def _underlined_func(): + pass + + """) + samplemod.write(code) + package = testutils.create_package(self.project, "package") + testutils.create_module(self.project, "nestedmod", package) + + +def tearDown(self): + testutils.remove_project(self.project) + super(self.__class__, self).tearDown() + + +def test_simple_import(self): + code = "import samplemod\n" + mod = libutils.get_string_module(self.project, code) + samplemod = mod["samplemod"].get_object() + self.assertEqual(get_base_type("Module"), samplemod.get_type()) + + +def test_from_import_class(self): + code = "from samplemod import SampleClass\n" + mod = libutils.get_string_module(self.project, code) + result = mod["SampleClass"].get_object() + self.assertEqual(get_base_type("Type"), result.get_type()) + self.assertTrue("sample_func" not in mod.get_attributes()) + + +def test_from_import_star(self): + code = "from samplemod import *\n" + mod = libutils.get_string_module(self.project, code) + self.assertEqual( + get_base_type("Type"), mod["SampleClass"].get_object().get_type() + ) + self.assertEqual( + get_base_type("Function"), mod["sample_func"].get_object().get_type() + ) + self.assertTrue(mod["sample_var"] is not None) + + +def test_from_import_star_overwriting(self): + code = dedent("""\ + from samplemod import * + class SampleClass(object): + pass + """) + mod = libutils.get_string_module(self.project, code) + samplemod = self.project.get_module("samplemod") + sample_class = samplemod["SampleClass"].get_object() + self.assertNotEqual( + sample_class, mod.get_attributes()["SampleClass"].get_object() + ) + + +def test_from_import_star_not_imporing_underlined(self): + code = "from samplemod import *" + mod = libutils.get_string_module(self.project, code) + self.assertTrue("_underlined_func" not in mod.get_attributes()) + + +def test_from_import_star_imports_in_functions(self): + code = dedent("""\ + def f(): + from os import * + """) + mod = libutils.get_string_module(self.project, code) + mod["f"].get_object().get_scope().get_names() + + +def test_from_package_import_mod(self): + code = "from package import nestedmod\n" + mod = libutils.get_string_module(self.project, code) + self.assertEqual( + get_base_type("Module"), mod["nestedmod"].get_object().get_type() + ) + + +def _change_calls( + self, + call_changer, + in_hierarchy=None, + resources=None, + handle=taskhandle.NullTaskHandle(), +): + if resources is None: + resources = self.project.get_python_files() + changes = ChangeSet("Changing signature of <%s>" % self.name) + job_set = handle.create_jobset("Collecting Changes", len(resources)) + finder = occurrences.create_finder( + self.project, + self.name, + self.pyname, + instance=self.primary, + in_hierarchy=in_hierarchy and self.is_method(), + ) + if self.others: + name, pyname = self.others + constructor_finder = occurrences.create_finder( + self.project, name, pyname, only_calls=True + ) + finder = _MultipleFinders([finder, constructor_finder]) + for file in resources: + job_set.started_job(file.path) + change_calls = _ChangeCallsInModule( + self.project, finder, file, call_changer + ) + changed_file = change_calls.get_changed_module() + if changed_file is not None: + changes.add_change(ChangeContents(file, changed_file)) + job_set.finished_job() + return changes + + +# XXX: Deciding to import everything on import start from packages +def xxx_test_from_package_import_star(self): + code = "from package import *\n" + mod = libutils.get_string_module(self.project, code) + self.assertTrue("nestedmod" not in mod.get_attributes()) + + +def test_unknown_when_module_cannot_be_found(self): + code = "from doesnotexist import nestedmod\n" + mod = libutils.get_string_module(self.project, code) + self.assertTrue("nestedmod" in mod) + + +def test_from_import_function(self): + code = dedent("""\ + def f(): + from samplemod import SampleClass + """) + scope = libutils.get_string_scope(self.project, code) + self.assertEqual( + get_base_type("Type"), + scope.get_scopes()[0]["SampleClass"].get_object().get_type(), + ) + + +def test_circular_imports(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("import mod2\n") + mod2.write("import mod1\n") + self.project.get_module("mod1") + + +def test_circular_imports2(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write(dedent("""\ + from mod2 import Sample2 + class Sample1(object): + pass + """)) + mod2.write(dedent("""\ + from mod1 import Sample1 + class Sample2(object): + pass + """)) + self.project.get_module("mod1").get_attributes() + + +def test_multi_dot_imports(self): + pkg = testutils.create_package(self.project, "pkg") + pkg_mod = testutils.create_module(self.project, "mod", pkg) + pkg_mod.write(dedent("""\ + def sample_func(): + pass + """)) + code = "import pkg.mod\n" + mod = libutils.get_string_module(self.project, code) + self.assertTrue("pkg" in mod) + self.assertTrue("sample_func" in mod["pkg"].get_object()["mod"].get_object()) + + +def test_multi_dot_imports2(self): + pkg = testutils.create_package(self.project, "pkg") + testutils.create_module(self.project, "mod1", pkg) + testutils.create_module(self.project, "mod2", pkg) + code = dedent("""\ + import pkg.mod1 + import pkg.mod2 + """) + mod = libutils.get_string_module(self.project, code) + package = mod["pkg"].get_object() + self.assertEqual(2, len(package.get_attributes())) + self.assertTrue("mod1" in package and "mod2" in package) + + +def test_multi_dot_imports3(self): + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) + testutils.create_module(self.project, "mod1", pkg2) + testutils.create_module(self.project, "mod2", pkg2) + code = dedent("""\ + import pkg1.pkg2.mod1 + import pkg1.pkg2.mod2 + """) + mod = libutils.get_string_module(self.project, code) + package1 = mod["pkg1"].get_object() + package2 = package1["pkg2"].get_object() + self.assertEqual(2, len(package2.get_attributes())) + self.assertTrue("mod1" in package2 and "mod2" in package2) + + +def test_multi_dot_imports_as(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod1.write(dedent("""\ + def f(): + pass + """)) + code = "import pkg.mod1 as mod1\n" + mod = libutils.get_string_module(self.project, code) + module = mod["mod1"].get_object() + self.assertTrue("f" in module) + + +# TODO: not showing unimported names as attributes of packages +def xxx_test_from_package_import_package(self): + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) + testutils.create_module(self.project, "mod", pkg2) + code = "from pkg1 import pkg2\n" + mod = libutils.get_string_module(self.project, code) + package = mod["pkg2"] + self.assertEqual(0, len(package.get_attributes())) + + +def get_args(self): + """Get function arguments. + + Return a list of ``(name, default)`` tuples for all but star + and double star arguments. For arguments that don't have a + default, `None` will be used. + """ + return self._definfo().args_with_defaults + + +def test_invalidating_cache_after_resource_change(self): + module = testutils.create_module(self.project, "mod") + module.write("import sys\n") + mod1 = self.project.get_module("mod") + self.assertTrue("var" not in mod1.get_attributes()) + module.write("var = 10\n") + mod2 = self.project.get_module("mod") + self.assertTrue("var" in mod2) + + +def test_invalidating_cache_after_resource_change_for_init_dot_pys(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod") + init_dot_py = pkg.get_child("__init__.py") + init_dot_py.write("a_var = 10\n") + mod.write("import pkg\n") + pymod = self.project.get_module("mod") + self.assertTrue("a_var" in pymod["pkg"].get_object()) + init_dot_py.write("new_var = 10\n") + self.assertTrue("a_var" not in pymod["pkg"].get_object().get_attributes()) + + +def test_invalidating_cache_after_rsrc_chng_for_nested_init_dot_pys(self): + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) + mod = testutils.create_module(self.project, "mod") + init_dot_py = pkg2.get_child("__init__.py") + init_dot_py.write("a_var = 10\n") + mod.write("import pkg1\n") + pymod = self.project.get_module("mod") + self.assertTrue("a_var" in pymod["pkg1"].get_object()["pkg2"].get_object()) + init_dot_py.write("new_var = 10\n") + self.assertTrue("a_var" not in pymod["pkg1"].get_object()["pkg2"].get_object()) + + +def test_from_import_nonexistent_module(self): + code = "from doesnotexistmod import DoesNotExistClass\n" + mod = libutils.get_string_module(self.project, code) + self.assertTrue("DoesNotExistClass" in mod) + self.assertEqual( + get_base_type("Unknown"), mod["DoesNotExistClass"].get_object().get_type() + ) + + +def test_from_import_nonexistent_name(self): + code = "from samplemod import DoesNotExistClass\n" + mod = libutils.get_string_module(self.project, code) + self.assertTrue("DoesNotExistClass" in mod) + self.assertEqual( + get_base_type("Unknown"), mod["DoesNotExistClass"].get_object().get_type() + ) + + +def test_not_considering_imported_names_as_sub_scopes(self): + code = "from samplemod import SampleClass\n" + scope = libutils.get_string_scope(self.project, code) + self.assertEqual(0, len(scope.get_scopes())) + + +def test_not_considering_imported_modules_as_sub_scopes(self): + code = "import samplemod\n" + scope = libutils.get_string_scope(self.project, code) + self.assertEqual(0, len(scope.get_scopes())) + + +def test_inheriting_dotted_base_class(self): + code = dedent("""\ + import samplemod + class Derived(samplemod.SampleClass): + pass + """) + mod = libutils.get_string_module(self.project, code) + derived = mod["Derived"].get_object() + self.assertTrue("sample_method" in derived) + + +def test_self_in_methods(self): + code = dedent("""\ + class Sample(object): + def func(self): + pass + """) + scope = libutils.get_string_scope(self.project, code) + sample_class = scope["Sample"].get_object() + func_scope = scope.get_scopes()[0].get_scopes()[0] + self.assertEqual(sample_class, func_scope["self"].get_object().get_type()) + self.assertTrue("func" in func_scope["self"].get_object()) + + +def test_none_assignments_in_classes(self): + code = dedent("""\ + class C(object): + var = "" + def f(self): + self.var += "".join([]) + """) + scope = libutils.get_string_scope(self.project, code) + c_class = scope["C"].get_object() + self.assertTrue("var" in c_class) + + +def is_method(self): + pyfunction = self.pyname.get_object() + return isinstance(pyfunction.parent, pyobjects.PyClass) + + +def test_self_in_methods_with_decorators(self): + code = dedent("""\ + class Sample(object): + @staticmethod + def func(self): + pass + """) + scope = libutils.get_string_scope(self.project, code) + sample_class = scope["Sample"].get_object() + func_scope = scope.get_scopes()[0].get_scopes()[0] + self.assertNotEqual(sample_class, func_scope["self"].get_object().get_type()) + + +def test_location_of_imports_when_importing(self): + mod = testutils.create_module(self.project, "mod") + mod.write("from samplemod import SampleClass\n") + code = "from mod import SampleClass\n" + scope = libutils.get_string_scope(self.project, code) + sample_class = scope["SampleClass"] + samplemod = self.project.get_module("samplemod") + self.assertEqual((samplemod, 1), sample_class.get_definition_location()) + + +def test_nested_modules(self): + pkg = testutils.create_package(self.project, "pkg") + testutils.create_module(self.project, "mod", pkg) + imported_module = self.project.get_module("pkg.mod") + code = "import pkg.mod\n" + scope = libutils.get_string_scope(self.project, code) + mod_pyobject = scope["pkg"].get_object()["mod"] + self.assertEqual((imported_module, 1), mod_pyobject.get_definition_location()) + + +def test_reading_init_dot_py(self): + pkg = testutils.create_package(self.project, "pkg") + init_dot_py = pkg.get_child("__init__.py") + init_dot_py.write("a_var = 1\n") + pkg_object = self.project.get_module("pkg") + self.assertTrue("a_var" in pkg_object) + + +def test_relative_imports(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod2.write("import mod1\n") + mod1_object = self.pycore.resource_to_pyobject(mod1) + mod2_object = self.pycore.resource_to_pyobject(mod2) + self.assertEqual(mod1_object, mod2_object.get_attributes()["mod1"].get_object()) + + +def test_relative_froms(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod1.write(dedent("""\ + def a_func(): + pass + """)) + mod2.write("from mod1 import a_func\n") + mod1_object = self.pycore.resource_to_pyobject(mod1) + mod2_object = self.pycore.resource_to_pyobject(mod2) + self.assertEqual( + mod1_object["a_func"].get_object(), mod2_object["a_func"].get_object() + ) + + +def test_relative_imports_for_string_modules(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod2.write("import mod1\n") + mod1_object = self.pycore.resource_to_pyobject(mod1) + mod2_object = libutils.get_string_module(self.project, mod2.read(), mod2) + self.assertEqual(mod1_object, mod2_object["mod1"].get_object()) + + +def test_relative_imports_for_string_scopes(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod2.write("import mod1\n") + mod1_object = self.pycore.resource_to_pyobject(mod1) + mod2_scope = libutils.get_string_scope(self.project, mod2.read(), mod2) + self.assertEqual(mod1_object, mod2_scope["mod1"].get_object()) + + +@testutils.only_for("2.5") +def test_new_style_relative_imports(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod2.write("from . import mod1\n") + mod1_object = self.pycore.resource_to_pyobject(mod1) + mod2_object = self.pycore.resource_to_pyobject(mod2) + self.assertEqual(mod1_object, mod2_object["mod1"].get_object()) + + +@testutils.only_for("2.5") +def test_new_style_relative_imports2(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod1.write(dedent("""\ + def a_func(): + pass + """)) + mod2.write("from ..mod1 import a_func\n") + mod1_object = self.pycore.resource_to_pyobject(mod1) + mod2_object = self.pycore.resource_to_pyobject(mod2) + self.assertEqual( + mod1_object["a_func"].get_object(), mod2_object["a_func"].get_object() + ) + + +def _get_line_indents(line): + return rope.base.codeanalyze.count_line_indents(line) + +@utils.deprecated("Use `ChangeSignature.get_args()` instead") +def get_definition_info(self): + return self._definfo() + + +def test_invalidating_cache_for_from_imports_after_resource_change(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + def a_func(): + print(1) + """)) + mod1.write(dedent("""\ + from mod2 import a_func + a_func() + """)) + + pymod1 = self.project.get_module("mod1") + pymod2 = self.project.get_module("mod2") + self.assertEqual(pymod1["a_func"].get_object(), pymod2["a_func"].get_object()) + mod2.write(mod2.read() + "\n") + pymod2 = self.project.get_module("mod2") + self.assertEqual(pymod1["a_func"].get_object(), pymod2["a_func"].get_object()) + + +def test_invalidating_superclasses_after_change(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write(dedent("""\ + class A(object): + def func1(self): + pass + """)) + mod2.write(dedent("""\ + import mod1 + class B(mod1.A): + pass + """)) + + b_class = self.project.get_module("mod2")["B"].get_object() + self.assertTrue("func1" in b_class) + + mod1.write(dedent("""\ + class A(object): + def func2(self): + pass + """)) + self.assertTrue("func2" in b_class) + + +def test_caching_pymodule_with_syntax_errors(self): + self.project.prefs["ignore_syntax_errors"] = True + self.project.prefs["automatic_soa"] = True + self.project.pycore._init_automatic_soa() + source = dedent("""\ + import sys + ab cd + """) + mod = testutils.create_module(self.project, "mod") + mod.write(source) + from rope.contrib import fixsyntax + + fixer = fixsyntax.FixSyntax(self.project, source, mod, 10) + pymodule = fixer.get_pymodule() + self.assertTrue(pymodule.source_code.startswith("import sys\npass\n")) + + + +class TextChangeDetectorTest(unittest.TestCase): + @others + +def test_trivial_case(self): + detector = _TextChangeDetector("\n", "\n") + self.assertFalse(detector.is_changed(1, 1)) + + +def test_one_line_change(self): + detector = _TextChangeDetector("1\n2\n", "1\n3\n") + self.assertFalse(detector.is_changed(1, 1)) + self.assertTrue(detector.is_changed(2, 2)) + + +def test_line_expansion(self): + detector = _TextChangeDetector("1\n2\n", "1\n3\n4\n2\n") + self.assertFalse(detector.is_changed(1, 1)) + self.assertFalse(detector.is_changed(2, 2)) + + +def test_line_removals(self): + detector = _TextChangeDetector("1\n3\n4\n2\n", "1\n2\n") + self.assertFalse(detector.is_changed(1, 1)) + self.assertTrue(detector.is_changed(2, 3)) + self.assertFalse(detector.is_changed(4, 4)) + + +def test_multi_line_checks(self): + detector = _TextChangeDetector("1\n2\n", "1\n3\n") + self.assertTrue(detector.is_changed(1, 2)) + + +def test_consume_change(self): + detector = _TextChangeDetector("1\n2\n", "1\n3\n") + self.assertTrue(detector.is_changed(1, 2)) + self.assertTrue(detector.consume_changes(1, 2)) + self.assertFalse(detector.is_changed(1, 2)) + + + +def _definfo(self): + return functionutils.DefinitionInfo.read(self.pyname.get_object()) + + +class PyCoreProjectConfigsTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = None + + +def tearDown(self): + if self.project: + testutils.remove_project(self.project) + super().tearDown() + + +def test_python_files_config(self): + self.project = testutils.sample_project(python_files=["myscript"]) + myscript = self.project.root.create_file("myscript") + self.assertTrue(self.project.pycore.is_python_file(myscript)) + + +def test_ignore_bad_imports(self): + self.project = testutils.sample_project(ignore_bad_imports=True) + code = "import some_nonexistent_module\n" + pymod = libutils.get_string_module(self.project, code) + self.assertFalse("some_nonexistent_module" in pymod) + + +def test_ignore_bad_imports_for_froms(self): + self.project = testutils.sample_project(ignore_bad_imports=True) + code = "from some_nonexistent_module import var\n" + pymod = libutils.get_string_module(self.project, code) + self.assertFalse("var" in pymod) + + +def test_reporting_syntax_errors_with_force_errors(self): + self.project = testutils.sample_project(ignore_syntax_errors=True) + mod = testutils.create_module(self.project, "mod") + mod.write("syntax error ...\n") + with self.assertRaises(exceptions.ModuleSyntaxError): + self.project.pycore.resource_to_pyobject(mod, force_errors=True) + + +def test_reporting_syntax_errors_in_strings_with_force_errors(self): + self.project = testutils.sample_project(ignore_syntax_errors=True) + with self.assertRaises(exceptions.ModuleSyntaxError): + libutils.get_string_module( + self.project, "syntax error ...", force_errors=True + ) + + +def test_not_raising_errors_for_strings_with_ignore_errors(self): + self.project = testutils.sample_project(ignore_syntax_errors=True) + libutils.get_string_module(self.project, "syntax error ...") + + +def test_reporting_syntax_errors_with_force_errors_for_packages(self): + self.project = testutils.sample_project(ignore_syntax_errors=True) + pkg = testutils.create_package(self.project, "pkg") + pkg.get_child("__init__.py").write("syntax error ...\n") + with self.assertRaises(exceptions.ModuleSyntaxError): + self.project.pycore.resource_to_pyobject(pkg, force_errors=True) + +@utils.deprecated() +def normalize(self): + changer = _FunctionChangers( + self.pyname.get_object(), self.get_definition_info(), [ArgumentNormalizer()] + ) + return self._change_calls(changer) + + +@path C:/Repos/ekr-rope/ropetest/ +import unittest + +from textwrap import dedent + +from rope.base import libutils +from rope.base.pyobjects import get_base_type +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class PyCoreScopesTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_scope(self): + code = dedent("""\ + def sample_func(): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + sample_func = scope["sample_func"].get_object() + self.assertEqual(get_base_type("Function"), sample_func.get_type()) + + +def test_simple_function_scope(self): + code = dedent("""\ + def sample_func(): + a = 10 + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(1, len(scope.get_scopes())) + sample_func_scope = scope.get_scopes()[0] + self.assertEqual(1, len(sample_func_scope.get_names())) + self.assertEqual(0, len(sample_func_scope.get_scopes())) + + +def test_classes_inside_function_scopes(self): + code = dedent("""\ + def sample_func(): + class SampleClass(object): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(1, len(scope.get_scopes())) + sample_func_scope = scope.get_scopes()[0] + self.assertEqual( + get_base_type("Type"), + sample_func_scope["SampleClass"].get_object().get_type(), + ) + + +def test_list_comprehension_scope_inside_assignment(self): + code = "a_var = [b_var + d_var for b_var, c_var in e_var]\n" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual( + list(sorted(scope.get_defined_names())), + ["a_var"], + ) + self.assertEqual( + list(sorted(scope.get_scopes()[0].get_defined_names())), + ["b_var", "c_var"], + ) + + +def test_list_comprehension_scope(self): + code = "[b_var + d_var for b_var, c_var in e_var]\n" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual( + list(sorted(scope.get_scopes()[0].get_defined_names())), + ["b_var", "c_var"], + ) + + +def test_set_comprehension_scope(self): + code = "{b_var + d_var for b_var, c_var in e_var}\n" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual( + list(sorted(scope.get_scopes()[0].get_defined_names())), + ["b_var", "c_var"], + ) + + +@utils.deprecated() +def remove(self, index): + changer = _FunctionChangers( + self.pyname.get_object(), + self.get_definition_info(), + [ArgumentRemover(index)], + ) + return self._change_calls(changer) + + +def test_generator_comprehension_scope(self): + code = "(b_var + d_var for b_var, c_var in e_var)\n" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual( + list(sorted(scope.get_scopes()[0].get_defined_names())), + ["b_var", "c_var"], + ) + + +def test_dict_comprehension_scope(self): + code = "{b_var: d_var for b_var, c_var in e_var}\n" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual( + list(sorted(scope.get_scopes()[0].get_defined_names())), + ["b_var", "c_var"], + ) + + +@testutils.only_for_versions_higher("3.8") +def test_inline_assignment(self): + code = """values = (a_var := 2,)""" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual( + list(sorted(scope.get_defined_names())), + ["a_var", "values"], + ) + + +@testutils.only_for_versions_higher("3.8") +def test_inline_assignment_in_comprehensions(self): + code = dedent("""\ + [ + (a_var := b_var + (f_var := g_var)) + for b_var in [(j_var := i_var) + for i_var in c_var] if a_var + (h_var := d_var) + ] + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual( + list(sorted(scope.get_scopes()[0].get_defined_names())), + ["a_var", "b_var", "f_var"], + ) + self.assertEqual( + list(sorted(scope.get_scopes()[0].get_scopes()[0].get_defined_names())), + ["i_var", "j_var"], + ) + + +def test_nested_comprehension(self): + code = dedent("""\ + [ + b_var + d_var for b_var, c_var in [ + e_var for e_var in f_var + ] + ] + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual( + list(sorted(scope.get_scopes()[0].get_defined_names())), + ["b_var", "c_var"], + ) + self.assertEqual( + list(sorted(scope.get_scopes()[0].get_scopes()[0].get_defined_names())), + ["e_var"], + ) + + +def test_simple_class_scope(self): + code = dedent("""\ + class SampleClass(object): + def f(self): + var = 10 + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(1, len(scope.get_scopes())) + sample_class_scope = scope.get_scopes()[0] + self.assertTrue("f" in sample_class_scope) + self.assertEqual(1, len(sample_class_scope.get_scopes())) + f_in_class = sample_class_scope.get_scopes()[0] + self.assertTrue("var" in f_in_class) + + +def test_get_lineno(self): + code = dedent("""\ + + def sample_func(): + a = 10 + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(1, len(scope.get_scopes())) + sample_func_scope = scope.get_scopes()[0] + self.assertEqual(1, scope.get_start()) + self.assertEqual(2, sample_func_scope.get_start()) + + +def test_scope_kind(self): + code = dedent("""\ + class SampleClass(object): + pass + def sample_func(): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + sample_class_scope = scope.get_scopes()[0] + sample_func_scope = scope.get_scopes()[1] + self.assertEqual("Module", scope.get_kind()) + self.assertEqual("Class", sample_class_scope.get_kind()) + self.assertEqual("Function", sample_func_scope.get_kind()) + + +def test_function_parameters_in_scope_names(self): + code = dedent("""\ + def sample_func(param): + a = 10 + """) + scope = libutils.get_string_scope(self.project, code) + + sample_func_scope = scope.get_scopes()[0] + self.assertTrue("param" in sample_func_scope) + + +def test_get_names_contains_only_names_defined_in_a_scope(self): + code = dedent("""\ + var1 = 10 + def sample_func(param): + var2 = 20 + """) + scope = libutils.get_string_scope(self.project, code) + + sample_func_scope = scope.get_scopes()[0] + self.assertTrue("var1" not in sample_func_scope) + + +@utils.deprecated() +def add(self, index, name, default=None, value=None): + changer = _FunctionChangers( + self.pyname.get_object(), + self.get_definition_info(), + [ArgumentAdder(index, name, default, value)], + ) + return self._change_calls(changer) + + +def test_scope_lookup(self): + code = dedent("""\ + var1 = 10 + def sample_func(param): + var2 = 20 + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertTrue(scope.lookup("var2") is None) + self.assertEqual( + get_base_type("Function"), + scope.lookup("sample_func").get_object().get_type(), + ) + sample_func_scope = scope.get_scopes()[0] + self.assertTrue(sample_func_scope.lookup("var1") is not None) + + +def test_function_scopes(self): + code = dedent("""\ + def func(): + var = 10 + """) + scope = libutils.get_string_scope(self.project, code) + + func_scope = scope.get_scopes()[0] + self.assertTrue("var" in func_scope) + + +def test_function_scopes_classes(self): + code = dedent("""\ + def func(): + class Sample(object): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + func_scope = scope.get_scopes()[0] + self.assertTrue("Sample" in func_scope) + + +def test_function_getting_scope(self): + code = dedent("""\ + def func(): var = 10 + """) + mod = libutils.get_string_module(self.project, code) + + func_scope = mod["func"].get_object().get_scope() + self.assertTrue("var" in func_scope) + + +def test_scopes_in_function_scopes(self): + code = dedent("""\ + def func(): + def inner(): + var = 10 + """) + scope = libutils.get_string_scope(self.project, code) + + func_scope = scope.get_scopes()[0] + inner_scope = func_scope.get_scopes()[0] + self.assertTrue("var" in inner_scope) + + +def test_for_variables_in_scopes(self): + code = dedent("""\ + for a_var in range(10): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertTrue("a_var" in scope) + + +def test_assists_inside_fors(self): + code = dedent("""\ + for i in range(10): + a_var = i + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertTrue("a_var" in scope) + + +def test_first_parameter_of_a_method(self): + code = dedent("""\ + class AClass(object): + def a_func(self, param): + pass + """) + a_class = libutils.get_string_module(self.project, code)["AClass"].get_object() + function_scope = a_class["a_func"].get_object().get_scope() + self.assertEqual(a_class, function_scope["self"].get_object().get_type()) + self.assertNotEqual(a_class, function_scope["param"].get_object().get_type()) + + +def test_first_parameter_of_static_methods(self): + code = dedent("""\ + class AClass(object): + @staticmethod + def a_func(param): + pass + """) + a_class = libutils.get_string_module(self.project, code)["AClass"].get_object() + function_scope = a_class["a_func"].get_object().get_scope() + self.assertNotEqual(a_class, function_scope["param"].get_object().get_type()) + + +def test_first_parameter_of_class_methods(self): + code = dedent("""\ + class AClass(object): + @classmethod + def a_func(cls): + pass + """) + a_class = libutils.get_string_module(self.project, code)["AClass"].get_object() + function_scope = a_class["a_func"].get_object().get_scope() + self.assertEqual(a_class, function_scope["cls"].get_object()) + + +@utils.deprecated() +def inline_default(self, index): + changer = _FunctionChangers( + self.pyname.get_object(), + self.get_definition_info(), + [ArgumentDefaultInliner(index)], + ) + return self._change_calls(changer) + + +def test_first_parameter_with_self_as_name_and_unknown_decorator(self): + code = dedent("""\ + def my_decorator(func): + return func + class AClass(object): + @my_decorator + def a_func(self): + pass + """) + a_class = libutils.get_string_module(self.project, code)["AClass"].get_object() + function_scope = a_class["a_func"].get_object().get_scope() + self.assertEqual(a_class, function_scope["self"].get_object().get_type()) + + +def test_inside_class_scope_attribute_lookup(self): + code = dedent("""\ + class C(object): + an_attr = 1 + def a_func(self): + pass""") + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(1, len(scope.get_scopes())) + c_scope = scope.get_scopes()[0] + self.assertTrue("an_attr" in c_scope.get_names()) + self.assertTrue(c_scope.lookup("an_attr") is not None) + f_in_c = c_scope.get_scopes()[0] + self.assertTrue(f_in_c.lookup("an_attr") is None) + + +def test_inside_class_scope_attribute_lookup2(self): + code = dedent("""\ + class C(object): + def __init__(self): + self.an_attr = 1 + def a_func(self): + pass""") + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(1, len(scope.get_scopes())) + c_scope = scope.get_scopes()[0] + f_in_c = c_scope.get_scopes()[0] + self.assertTrue(f_in_c.lookup("an_attr") is None) + + +def test_get_inner_scope_for_staticmethods(self): + code = dedent("""\ + class C(object): + @staticmethod + def a_func(self): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + c_scope = scope.get_scopes()[0] + f_in_c = c_scope.get_scopes()[0] + self.assertEqual(f_in_c, scope.get_inner_scope_for_line(4)) + + +def test_get_scope_for_offset_for_comprehension(self): + code = "a = [i for i in range(10)]\n" + scope = libutils.get_string_scope(self.project, code) + + c_scope = scope.get_scopes()[0] + self.assertEqual(c_scope, scope.get_inner_scope_for_offset(10)) + self.assertEqual(scope, scope.get_inner_scope_for_offset(1)) + + +def test_get_scope_for_offset_for_in_nested_comprehension(self): + code = "[i for i in [j for j in k]]\n" + scope = libutils.get_string_scope(self.project, code) + + c_scope = scope.get_scopes()[0] + self.assertEqual(c_scope, scope.get_inner_scope_for_offset(5)) + inner_scope = c_scope.get_scopes()[0] + self.assertEqual(inner_scope, scope.get_inner_scope_for_offset(15)) + + +def test_get_scope_for_offset_for_scope_with_indent(self): + code = dedent("""\ + def f(a): + print(a) + """) + scope = libutils.get_string_scope(self.project, code) + + inner_scope = scope.get_scopes()[0] + self.assertEqual(inner_scope, scope.get_inner_scope_for_offset(10)) + + +@testutils.only_for("3.5") +def test_get_scope_for_offset_for_function_scope_and_async_with_statement(self): + scope = libutils.get_string_scope( + self.project, + dedent("""\ + async def func(): + async with a_func() as var: + print(var) + """), + ) + inner_scope = scope.get_scopes()[0] + self.assertEqual(inner_scope, scope.get_inner_scope_for_offset(27)) + + +def test_getting_overwritten_scopes(self): + code = dedent("""\ + def f(): + pass + def f(): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(2, len(scope.get_scopes())) + f1_scope = scope.get_scopes()[0] + f2_scope = scope.get_scopes()[1] + self.assertNotEqual(f1_scope, f2_scope) + + +def test_assigning_builtin_names(self): + code = "range = 1\n" + mod = libutils.get_string_module(self.project, code) + + range = mod.get_scope().lookup("range") + self.assertEqual((mod, 1), range.get_definition_location()) + + +@utils.deprecated() +def reorder(self, new_ordering): + changer = _FunctionChangers( + self.pyname.get_object(), + self.get_definition_info(), + [ArgumentReorderer(new_ordering)], + ) + return self._change_calls(changer) + + +def test_get_inner_scope_and_logical_lines(self): + code = dedent('''\ + class C(object): + def f(): + s = """ + 1 + 2 + """ + a = 1 + ''') + scope = libutils.get_string_scope(self.project, code) + + c_scope = scope.get_scopes()[0] + f_in_c = c_scope.get_scopes()[0] + self.assertEqual(f_in_c, scope.get_inner_scope_for_line(7)) + + +def test_getting_defined_names_for_classes(self): + code = dedent("""\ + class A(object): + def a(self): + pass + class B(A): + def b(self): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + a_scope = scope["A"].get_object().get_scope() # noqa + b_scope = scope["B"].get_object().get_scope() + self.assertTrue("a" in b_scope.get_names()) + self.assertTrue("b" in b_scope.get_names()) + self.assertTrue("a" not in b_scope.get_defined_names()) + self.assertTrue("b" in b_scope.get_defined_names()) + + +def test_getting_defined_names_for_modules(self): + code = dedent("""\ + class A(object): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertTrue("open" in scope.get_names()) + self.assertTrue("A" in scope.get_names()) + self.assertTrue("open" not in scope.get_defined_names()) + self.assertTrue("A" in scope.get_defined_names()) + + +def test_get_inner_scope_for_list_comprhension_with_many_targets(self): + code = "a = [(i, j) for i,j in enumerate(range(10))]\n" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(len(scope.get_scopes()), 1) + self.assertNotIn("i", scope) + self.assertNotIn("j", scope) + self.assertIn("i", scope.get_scopes()[0]) + self.assertIn("j", scope.get_scopes()[0]) + + +def test_get_inner_scope_for_generator(self): + code = "a = (i for i in range(10))\n" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(len(scope.get_scopes()), 1) + self.assertNotIn("i", scope) + self.assertIn("i", scope.get_scopes()[0]) + + +def test_get_inner_scope_for_set_comprehension(self): + code = "a = {i for i in range(10)}\n" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(len(scope.get_scopes()), 1) + self.assertNotIn("i", scope) + self.assertIn("i", scope.get_scopes()[0]) + + +def test_get_inner_scope_for_dict_comprehension(self): + code = "a = {i:i for i in range(10)}\n" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(len(scope.get_scopes()), 1) + self.assertNotIn("i", scope) + self.assertIn("i", scope.get_scopes()[0]) + + +def test_get_inner_scope_for_nested_list_comprhension(self): + code = "a = [[i + j for j in range(10)] for i in range(10)]\n" + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(len(scope.get_scopes()), 1) + self.assertNotIn("i", scope) + self.assertNotIn("j", scope) + self.assertIn("i", scope.get_scopes()[0]) + self.assertEqual(len(scope.get_scopes()[0].get_scopes()), 1) + self.assertIn("j", scope.get_scopes()[0].get_scopes()[0]) + self.assertIn("i", scope.get_scopes()[0].get_scopes()[0]) + + +def test_get_scope_region(self): + scope = libutils.get_string_scope( + self.project, + dedent(""" + def func1(ala): + pass + + def func2(o): + pass + """), + ) + + self.assertEqual(scope.get_region(), (0, 48)) + self.assertEqual(scope.get_scopes()[0].get_region(), (1, 24)) + self.assertEqual(scope.get_scopes()[1].get_region(), (26, 47)) + + +def test_only_get_inner_scope_region(self): + scope = libutils.get_string_scope( + self.project, + dedent(""" + def func1(ala): + pass + + def func2(o): + pass + """), + ) + + self.assertEqual(scope.get_scopes()[1].get_region(), (26, 47)) + +def get_changes( + self, + changers, + in_hierarchy=False, + resources=None, + task_handle=taskhandle.NullTaskHandle(), +): + """Get changes caused by this refactoring + + `changers` is a list of `_ArgumentChanger`. If `in_hierarchy` + is `True` the changers are applied to all matching methods in + the class hierarchy. + `resources` can be a list of `rope.base.resource.File` that + should be searched for occurrences; if `None` all python files + in the project are searched. + + """ + function_changer = _FunctionChangers( + self.pyname.get_object(), self._definfo(), changers + ) + return self._change_calls( + function_changer, in_hierarchy, resources, task_handle + ) + + + +@path C:/Repos/ekr-rope/ropetest/ +import pathlib +import tempfile + +import pytest + +from rope.base import libutils, resources, pyobjectsdef +from rope.base.project import Project +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +@pytest.fixture +def project(): + proj = testutils.sample_project() + yield proj + testutils.remove_project(proj) + + + +@pytest.fixture +def mod(project): + return testutils.create_module(project, "mod") + + + +@pytest.fixture +def mod1(project): + testutils.create_package(project, "pkg1") + return testutils.create_module(project, "pkg1.mod1") + + + +def test_repr_project(): + with tempfile.TemporaryDirectory() as folder: + folder = pathlib.Path(folder).resolve() + obj = testutils.sample_project(folder) + assert isinstance(obj, Project) + assert repr(obj) == f'<rope.base.project.Project "{folder}">' + + + +def test_repr_file(project): + obj = project.get_file("test/file.py") + assert isinstance(obj, resources.File) + assert repr(obj).startswith('<rope.base.resources.File "test/file.py" at 0x') + + + +def test_repr_folder(project): + obj = project.get_folder("test/folder") + assert isinstance(obj, resources.Folder) + assert repr(obj).startswith('<rope.base.resources.Folder "test/folder" at 0x') + + + +def test_repr_pyobjectsdef_pymodule(project, mod1): + obj = project.get_module("pkg1.mod1") + assert isinstance(obj, pyobjectsdef.PyModule) + assert repr(obj).startswith('<rope.base.pyobjectsdef.PyModule "pkg1.mod1" at 0x') + + + +def test_repr_pyobjectsdef_pymodule_without_associated_resource(project): + obj = pyobjectsdef.PyModule(project.pycore, "a = 1") + assert isinstance(obj, pyobjectsdef.PyModule) + assert repr(obj).startswith('<rope.base.pyobjectsdef.PyModule "" at 0x') + + + +def test_repr_pyobjectsdef_pypackage(project, mod1): + obj = project.get_module("pkg1") + assert isinstance(obj, pyobjectsdef.PyPackage) + assert repr(obj).startswith('<rope.base.pyobjectsdef.PyPackage "pkg1" at 0x') + + + +class _FunctionChangers: + @others + +def test_repr_pyobjectsdef_pypackage_without_associated_resource(project, mod1): + obj = pyobjectsdef.PyPackage(project.pycore) + assert isinstance(obj, pyobjectsdef.PyPackage) + assert repr(obj).startswith('<rope.base.pyobjectsdef.PyPackage "" at 0x') + + + +def test_repr_pyobjectsdef_pyfunction(project, mod1): + code = """def func(arg): pass""" + mod = libutils.get_string_module(project, code, mod1) + obj = mod.get_attribute("func").pyobject + assert isinstance(obj, pyobjectsdef.PyFunction) + assert repr(obj).startswith( + '<rope.base.pyobjectsdef.PyFunction "pkg1.mod1::func" at 0x' + ) + + + +def test_repr_pyobjectsdef_pyfunction_without_associated_resource(project): + code = """def func(arg): pass""" + mod = libutils.get_string_module(project, code) + obj = mod.get_attribute("func").pyobject + assert isinstance(obj, pyobjectsdef.PyFunction) + assert repr(obj).startswith('<rope.base.pyobjectsdef.PyFunction "::func" at 0x') + + + +def test_repr_pyobjectsdef_pyclass(project, mod1): + code = """class MyClass: pass""" + mod = libutils.get_string_module(project, code, mod1) + obj = mod.get_attribute("MyClass").pyobject + assert isinstance(obj, pyobjectsdef.PyClass) + assert repr(obj).startswith( + '<rope.base.pyobjectsdef.PyClass "pkg1.mod1::MyClass" at 0x' + ) + + + +def test_repr_pyobjectsdef_pyclass_without_associated_resource(project): + code = """class MyClass: pass""" + mod = libutils.get_string_module(project, code) + obj = mod.get_attribute("MyClass").pyobject + assert isinstance(obj, pyobjectsdef.PyClass) + assert repr(obj).startswith('<rope.base.pyobjectsdef.PyClass "::MyClass" at 0x') + + + +def test_repr_pyobjectsdef_pycomprehension(project, mod1): + code = """[a for a in b]""" + mod = libutils.get_string_module(project, code, mod1) + mod._create_structural_attributes() + assert len(mod.defineds) == 1 + obj = mod.defineds[0] + assert isinstance(obj, pyobjectsdef.PyComprehension) + assert repr(obj).startswith( + '<rope.base.pyobjectsdef.PyComprehension "pkg1.mod1::<comprehension>" at 0x' + ) + + + +def test_repr_pyobjectsdef_pycomprehension_without_associated_resource(project): + code = """[a for a in b]""" + mod = libutils.get_string_module(project, code) + mod._create_structural_attributes() + assert len(mod.defineds) == 1 + obj = mod.defineds[0] + assert isinstance(obj, pyobjectsdef.PyComprehension) + assert repr(obj).startswith( + '<rope.base.pyobjectsdef.PyComprehension "::<comprehension>" at 0x' + ) + +@path C:/Repos/ekr-rope/ropetest/ +import os +from textwrap import dedent + +import unittest + + +from rope.base import exceptions +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class PythonFileRunnerTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + + +def __init__(self, pyfunction, definition_info, changers=None): + self.pyfunction = pyfunction + self.definition_info = definition_info + self.changers = changers + self.changed_definition_infos = self._get_changed_definition_infos() + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def make_sample_python_file(self, file_path, get_text_function_source=None): + self.project.root.create_file(file_path) + file = self.project.get_resource(file_path) + if not get_text_function_source: + get_text_function_source = "def get_text():\n return 'run'\n\n" + file_content = ( + get_text_function_source + "output = open('output.txt', 'w')\n" + "output.write(get_text())\noutput.close()\n" + ) + file.write(file_content) + + +def get_output_file_content(self, file_path): + try: + output_path = "" + last_slash = file_path.rfind("/") + if last_slash != -1: + output_path = file_path[0 : last_slash + 1] + file = self.project.get_resource(output_path + "output.txt") + return file.read() + except exceptions.ResourceNotFoundError: + return "" + + +def test_making_runner(self): + file_path = "sample.py" + self.make_sample_python_file(file_path) + file_resource = self.project.get_resource(file_path) + runner = self.pycore.run_module(file_resource) + runner.wait_process() + self.assertEqual("run", self.get_output_file_content(file_path)) + + +def test_passing_arguments(self): + file_path = "sample.py" + function_source = dedent("""\ + import sys + def get_text(): + return str(sys.argv[1:]) + """) + self.make_sample_python_file(file_path, function_source) + file_resource = self.project.get_resource(file_path) + runner = self.pycore.run_module(file_resource, args=["hello", "world"]) + runner.wait_process() + self.assertTrue( + self.get_output_file_content(file_path).endswith("['hello', 'world']") + ) + + +def test_passing_arguments_with_spaces(self): + file_path = "sample.py" + function_source = dedent("""\ + import sys + def get_text(): + return str(sys.argv[1:]) + """) + self.make_sample_python_file(file_path, function_source) + file_resource = self.project.get_resource(file_path) + runner = self.pycore.run_module(file_resource, args=["hello world"]) + runner.wait_process() + self.assertTrue( + self.get_output_file_content(file_path).endswith("['hello world']") + ) + + +def test_killing_runner(self): + file_path = "sample.py" + code = dedent("""\ + def get_text(): + import time + time.sleep(1) + return 'run' + """) + self.make_sample_python_file( + file_path, + code, + ) + file_resource = self.project.get_resource(file_path) + runner = self.pycore.run_module(file_resource) + runner.kill_process() + self.assertEqual("", self.get_output_file_content(file_path)) + + +def test_running_nested_files(self): + self.project.root.create_folder("src") + file_path = "src/sample.py" + self.make_sample_python_file(file_path) + file_resource = self.project.get_resource(file_path) + runner = self.pycore.run_module(file_resource) + runner.wait_process() + self.assertEqual("run", self.get_output_file_content(file_path)) + + +def test_setting_process_input(self): + file_path = "sample.py" + code = dedent("""\ + def get_text(): + import sys + return sys.stdin.readline() + """) + self.make_sample_python_file(file_path, code) + temp_file_name = "processtest.tmp" + try: + temp_file = open(temp_file_name, "w") + temp_file.write("input text\n") + temp_file.close() + file_resource = self.project.get_resource(file_path) + stdin = open(temp_file_name) + runner = self.pycore.run_module(file_resource, stdin=stdin) + runner.wait_process() + stdin.close() + self.assertEqual("input text\n", self.get_output_file_content(file_path)) + finally: + os.remove(temp_file_name) + + +def test_setting_process_output(self): + file_path = "sample.py" + code = dedent("""\ + def get_text(): + print('output text') + return 'run' + """) + self.make_sample_python_file(file_path, code) + temp_file_name = "processtest.tmp" + try: + file_resource = self.project.get_resource(file_path) + stdout = open(temp_file_name, "w") + runner = self.pycore.run_module(file_resource, stdout=stdout) + runner.wait_process() + stdout.close() + temp_file = open(temp_file_name) + self.assertEqual("output text\n", temp_file.read()) + temp_file.close() + finally: + os.remove(temp_file_name) + + +@path C:/Repos/ekr-rope/rope/contrib/ +import rope.base.evaluate +from rope.base import libutils +from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze +from rope.refactor import sourceutils, importutils, functionutils, suites + + +@others +@language python +@tabwidth -4 + +def _get_changed_definition_infos(self): + result = [] + definition_info = self.definition_info + result.append(definition_info) + for changer in self.changers: + definition_info = copy.deepcopy(definition_info) + changer.change_definition_info(definition_info) + result.append(definition_info) + return result + + +def test_setting_pythonpath(self): + src = self.project.root.create_folder("src") + src.create_file("sample.py") + src.get_child("sample.py").write("def f():\n pass\n") + self.project.root.create_folder("test") + file_path = "test/test.py" + code = dedent("""\ + def get_text(): + import sample + sample.f() + return'run' + """) + self.make_sample_python_file(file_path, code) + file_resource = self.project.get_resource(file_path) + runner = self.pycore.run_module(file_resource) + runner.wait_process() + self.assertEqual("run", self.get_output_file_content(file_path)) + + +def test_making_runner_when_doi_is_disabled(self): + self.project.set("enable_doi", False) + file_path = "sample.py" + self.make_sample_python_file(file_path) + file_resource = self.project.get_resource(file_path) + runner = self.pycore.run_module(file_resource) + runner.wait_process() + self.assertEqual("run", self.get_output_file_content(file_path)) + +@path C:/Repos/ekr-rope/ropetest/ +import unittest + +from rope.base import simplify + + +@others +@language python +@tabwidth -4 + +class SimplifyTest(unittest.TestCase): + @others + +def test_trivial_case(self): + self.assertEqual("", simplify.real_code("")) + + +def test_empty_strs(self): + code = 's = ""\n' + self.assertEqual(code, simplify.real_code(code)) + + +def test_blanking_strs(self): + code = 's = "..."\n' + self.assertEqual('s = " "\n', simplify.real_code(code)) + + +def test_changing_to_double_quotes(self): + code = "s = ''\n" + self.assertEqual('s = ""\n', simplify.real_code(code)) + + +def test_changing_to_double_quotes2(self): + code = 's = """\n"""\n' + self.assertEqual('s = " "\n', simplify.real_code(code)) + + +def test_removing_comments(self): + code = "# c\n" + self.assertEqual(" \n", simplify.real_code(code)) + + +def change_definition(self, call): + return self.changed_definition_infos[-1].to_string() + + +def test_removing_comments_that_contain_strings(self): + code = '# "c"\n' + self.assertEqual(" \n", simplify.real_code(code)) + + +def test_removing_strings_containing_comments(self): + code = '"#c"\n' + self.assertEqual('" "\n', simplify.real_code(code)) + + +def test_joining_implicit_continuations(self): + code = "(\n)\n" + self.assertEqual("( )\n", simplify.real_code(code)) + + +def test_joining_explicit_continuations(self): + code = "1 + \\\n 2\n" + self.assertEqual("1 + 2\n", simplify.real_code(code)) + + +def test_replacing_tabs(self): + code = "1\t+\t2\n" + self.assertEqual("1 + 2\n", simplify.real_code(code)) + + +def test_replacing_semicolons(self): + code = "a = 1;b = 2\n" + self.assertEqual("a = 1\nb = 2\n", simplify.real_code(code)) + + +def test_simplifying_f_string(self): + code = 's = f"..{hello}.."\n' + self.assertEqual('s = f"..{hello}.."\n', simplify.real_code(code)) + + +def test_simplifying_f_string_containing_quotes(self): + code = """s = f"..'{hello}'.."\n""" + self.assertEqual("""s = f"..'{hello}'.."\n""", simplify.real_code(code)) + + +def test_simplifying_uppercase_f_string_containing_quotes(self): + code = """s = Fr"..'{hello}'.."\n""" + self.assertEqual("""s = Fr"..'{hello}'.."\n""", simplify.real_code(code)) + +@path C:/Repos/ekr-rope/ropetest/ +import os.path +import shutil +import sys +import logging + +logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) +import unittest + +import rope.base.project +from rope.contrib import generate + + +@others +@language python +@tabwidth -4 + +def change_call(self, primary, pyname, call): + call_info = functionutils.CallInfo.read( + primary, pyname, self.definition_info, call + ) + mapping = functionutils.ArgumentMapping(self.definition_info, call_info) + + for definition_info, changer in zip( + self.changed_definition_infos, self.changers + ): + changer.change_argument_mapping(definition_info, mapping) + + return mapping.to_call_info(self.changed_definition_infos[-1]).to_string() + + + +def sample_project(root=None, foldername=None, **kwds): + if root is None: + root = "sample_project" + if foldername: + root = foldername + # HACK: Using ``/dev/shm/`` for faster tests + if os.name == "posix": + if os.path.isdir("/dev/shm") and os.access("/dev/shm", os.W_OK): + root = "/dev/shm/" + root + elif os.path.isdir("/tmp") and os.access("/tmp", os.W_OK): + root = "/tmp/" + root + logging.debug("Using %s as root of the project.", root) + # Using these prefs for faster tests + prefs = { + "save_objectdb": False, + "save_history": False, + "validate_objectdb": False, + "automatic_soa": False, + "ignored_resources": [".ropeproject", "*.pyc"], + "import_dynload_stdmods": False, + } + prefs.update(kwds) + remove_recursively(root) + project = rope.base.project.Project(root, **prefs) + return project + + + +create_module = generate.create_module +create_package = generate.create_package + + + +def remove_project(project): + project.close() + remove_recursively(project.address) + + + +def remove_recursively(path): + import time + + # windows sometimes raises exceptions instead of removing files + if os.name == "nt" or sys.platform == "cygwin": + for i in range(12): + try: + _remove_recursively(path) + except OSError as e: + if e.errno not in (13, 16, 32): + raise + time.sleep(0.3) + else: + break + else: + _remove_recursively(path) + + + +def _remove_recursively(path): + if not os.path.exists(path): + return + if os.path.isfile(path): + os.remove(path) + else: + shutil.rmtree(path) + + + +def parse_version(version): + return tuple(map(int, version.split("."))) + + + +def only_for(version): + """Should be used as a decorator for a unittest.TestCase test method""" + return unittest.skipIf( + sys.version_info < parse_version(version), + "This test requires at least {0} version of Python.".format(version), + ) + + + +def only_for_versions_lower(version): + """Should be used as a decorator for a unittest.TestCase test method""" + return unittest.skipIf( + sys.version_info > parse_version(version), + "This test requires version of Python lower than {0}".format(version), + ) + + + +def only_for_versions_higher(version): + """Should be used as a decorator for a unittest.TestCase test method""" + return unittest.skipIf( + sys.version_info < parse_version(version), + "This test requires version of Python higher than {0}".format(version), + ) + + + +def skipNotPOSIX(): + return unittest.skipIf(os.name != "posix", "This test works only on POSIX") + + + +class _ArgumentChanger: + def change_definition_info(self, definition_info): + pass + + def change_argument_mapping(self, definition_info, argument_mapping): + pass + + + +def time_limit(timeout): + if not any(procname in sys.argv[0] for procname in {"pytest", "py.test"}): + # no-op when running tests without pytest + return lambda *args, **kwargs: lambda func: func + + # do a local import so we don't import pytest when running without pytest + import pytest + + # this prevents infinite loop/recursion from taking forever in CI + return pytest.mark.time_limit(timeout) + +@path C:/Repos/ekr-rope/ropetest/ +import unittest +from textwrap import dedent +from textwrap import dedent, indent + +import pytest + +from rope.base.oi.type_hinting import evaluate +from rope.contrib.codeassist import code_assist +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class AbstractHintingTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _assist(self, code, offset=None, resource=None, **kwds): + if offset is None: + offset = len(code) + return code_assist(self.project, code, offset, resource, **kwds) + + +def assert_completion_in_result(self, name, scope, result): + for proposal in result: + if proposal.name == name and proposal.scope == scope: + return + self.fail( + "completion <%s> in scope %r not proposed, available names: %r" + % (name, scope, [(i.name, i.scope) for i in result]) + ) + + +def assert_completion_not_in_result(self, name, scope, result): + for proposal in result: + if proposal.name == name and proposal.scope == scope: + self.fail("completion <%s> was proposed" % name) + + +def run(self, result=None): + if self.__class__.__name__.startswith("Abstract"): + return + super().run(result) + + + +class DocstringParamHintingTest(AbstractHintingTest): + @others + +class ArgumentNormalizer(_ArgumentChanger): + pass + + + +def test_hint_param(self): + code = dedent('''\ + class Sample(object): + def a_method(self, a_arg): + """:type a_arg: threading.Thread""" + a_arg.is_a''') + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hierarchical_hint_param(self): + code = dedent('''\ + class ISample(object): + def a_method(self, a_arg): + """:type a_arg: threading.Thread""" + + + class Sample(ISample): + def a_method(self, a_arg): + a_arg.is_a''') + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + + +class DocstringReturnHintingTest(AbstractHintingTest): + @others + +def test_hierarchical_hint_rtype(self): + code = dedent('''\ + class ISample(object): + def b_method(self): + """:rtype: threading.Thread""" + + + class Sample(ISample): + def b_method(self): + pass + def a_method(self): + self.b_method().is_a''') + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def fix_indents(hint): +return indent(hint, " " * 12).strip() + + + +class AbstractAssignmentHintingTest(AbstractHintingTest): + @others + +def _make_class_hint(self, type_str): + raise NotImplementedError + + +def _make_constructor_hint(self, type_str): + raise NotImplementedError + + +def test_hint_attr(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("threading.Thread"))} + def a_method(self): + self.a_attr.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hierarchical_hint_attr(self): + code = dedent(f"""\ + class ISample(object): + {fix_indents(self._make_class_hint("threading.Thread"))} + + + class Sample(ISample): + a_attr = None + def a_method(self): + self.a_attr.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_defined_by_constructor(self): + code = dedent(f"""\ + class Sample(object): + def __init__(self, arg): + {fix_indents(self._make_constructor_hint("threading.Thread"))} + def a_method(self): + self.a_attr.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +class ArgumentRemover(_ArgumentChanger): + @others + +def test_hint_attr_redefined_by_constructor(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("threading.Thread"))} + def __init__(self): + self.a_attr = None + def a_method(self): + self.a_attr.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hierarchical_hint_attr_redefined_by_constructor(self): + code = dedent(f"""\ + class ISample(object): + {fix_indents(self._make_class_hint("threading.Thread"))} + + + class Sample(ISample): + def __init__(self): + self.a_attr = None + def a_method(self): + self.a_attr.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_attr_for_pre_defined_type(self): + code = dedent(f"""\ + class Other(object): + def is_alive(self): + pass + + + class Sample(object): + {fix_indents(self._make_class_hint("Other"))} + def a_method(self): + self.a_attr.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_attr_for_post_defined_type(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("Other"))} + def a_method(self): + self.a_attr.is_a""") + offset = len(code) + code += dedent(f"""\ + + + class Other(object): + def is_alive(self): + pass + """) + result = self._assist(code, offset) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_parametrized_list(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("list[threading.Thread]"))} + def a_method(self): + for i in self.a_attr: + i.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_parametrized_tuple(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("tuple[threading.Thread]"))} + def a_method(self): + for i in self.a_attr: + i.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_parametrized_set(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("set[threading.Thread]"))} + def a_method(self): + for i in self.a_attr: + i.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_parametrized_iterable(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("collections.Iterable[threading.Thread]"))} + def a_method(self): + for i in self.a_attr: + i.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_parametrized_iterator(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("collections.Iterator[threading.Thread]"))} + def a_method(self): + for i in self.a_attr: + i.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_parametrized_dict_key(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("dict[str, threading.Thread]"))} + def a_method(self): + for i in self.a_attr.keys(): + i.sta""") + result = self._assist(code) + self.assert_completion_in_result("startswith", "builtin", result) + + +def __init__(self, index): + self.index = index + + +def test_hint_parametrized_dict_value(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("dict[str, threading.Thread]"))} + def a_method(self): + for i in self.a_attr.values(): + i.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_parametrized_nested_tuple_list(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("tuple[list[threading.Thread]]"))} + def a_method(self): + for j in self.a_attr: + for i in j: + i.is_a""") + result = self._assist(code) + self.assert_completion_in_result("is_alive", "attribute", result) + + +def test_hint_or(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("str | threading.Thread"))} + def a_method(self): + for i in self.a_attr.values(): + i.is_a""") + result = self._assist(code) + try: + # Be sure, there isn't errors currently + self.assert_completion_in_result('is_alive', 'attribute', result) + except AssertionError as e: + pytest.xfail("failing configuration (but should work)") + + +def test_hint_nonexistent(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("sdfdsf.asdfasdf.sdfasdf.Dffg"))} + def a_method(self): + for i in self.a_attr.values(): + i.is_a""") + result = self._assist(code) + self.assertEqual(result, []) + + +def test_hint_invalid_syntax(self): + code = dedent(f"""\ + class Sample(object): + {fix_indents(self._make_class_hint("sdf | & # &*"))} + def a_method(self): + for i in self.a_attr.values(): + i.is_a""") + result = self._assist(code) + self.assertEqual(result, []) + + + +class DocstringNoneAssignmentHintingTest(AbstractAssignmentHintingTest): + @others + +def _make_class_hint(self, type_str): + hint = dedent(f'''\ + """:type a_attr: {type_str}""" + a_attr = None + ''') + return indent(hint, " " * 4) + + +def _make_constructor_hint(self, type_str): + hint = dedent(f'''\ + """:type arg: {type_str}""" + self.a_attr = arg + ''') + return indent(hint, " " * 8) + + + +class DocstringNotImplementedAssignmentHintingTest(AbstractAssignmentHintingTest): + @others + +def _make_class_hint(self, type_str): + hint = dedent(f'''\ + """:type a_attr: {type_str}""" + a_attr = NotImplemented + ''') + return indent(hint, " " * 4) + + +def change_definition_info(self, call_info): + if self.index < len(call_info.args_with_defaults): + del call_info.args_with_defaults[self.index] + elif ( + self.index == len(call_info.args_with_defaults) + and call_info.args_arg is not None + ): + call_info.args_arg = None + elif ( + self.index == len(call_info.args_with_defaults) + and call_info.args_arg is None + and call_info.keywords_arg is not None + ) or ( + self.index == len(call_info.args_with_defaults) + 1 + and call_info.args_arg is not None + and call_info.keywords_arg is not None + ): + call_info.keywords_arg = None + + +def _make_constructor_hint(self, type_str): + hint = dedent(f'''\ + """:type arg: {type_str}""" + self.a_attr = arg + ''') + return indent(hint, " " * 8) + + + +class PEP0484CommentNoneAssignmentHintingTest(AbstractAssignmentHintingTest): + def _make_class_hint(self, type_str): + hint = dedent(f"""\ + a_attr = None # type: {type_str} + """) + return indent(hint, " " * 4) + + def _make_constructor_hint(self, type_str): + hint = dedent(f"""\ + self.a_attr = None # type: {type_str} + """) + return indent(hint, " " * 8) + + + +class PEP0484CommentNotImplementedAssignmentHintingTest(AbstractAssignmentHintingTest): + def _make_class_hint(self, type_str): + hint = dedent(f"""\ + a_attr = NotImplemented # type: {type_str} + """) + return indent(hint, " " * 4) + + def _make_constructor_hint(self, type_str): + hint = dedent(f"""\ + self.a_attr = NotImplemented # type: {type_str} + """) + return indent(hint, " " * 8) + + + +class EvaluateTest(unittest.TestCase): + @others + +def test_parser(self): + tests = [ + ("Foo", "(name Foo)"), + ("mod1.Foo", "(name mod1.Foo)"), + ("mod1.mod2.Foo", "(name mod1.mod2.Foo)"), + ("Foo[Bar]", "('[' (name Foo) [(name Bar)])"), + ( + "Foo[Bar1, Bar2, Bar3]", + "('[' (name Foo) [(name Bar1), (name Bar2), (name Bar3)])", + ), + ("Foo[Bar[Baz]]", "('[' (name Foo) [('[' (name Bar) [(name Baz)])])"), + ( + "Foo[Bar1[Baz1], Bar2[Baz2]]", + "('[' (name Foo) [('[' (name Bar1) [(name Baz1)]), ('[' (name Bar2) [(name Baz2)])])", + ), + ("mod1.mod2.Foo[Bar]", "('[' (name mod1.mod2.Foo) [(name Bar)])"), + ( + "mod1.mod2.Foo[mod1.mod2.Bar]", + "('[' (name mod1.mod2.Foo) [(name mod1.mod2.Bar)])", + ), + ( + "mod1.mod2.Foo[Bar1, Bar2, Bar3]", + "('[' (name mod1.mod2.Foo) [(name Bar1), (name Bar2), (name Bar3)])", + ), + ( + "mod1.mod2.Foo[mod1.mod2.Bar[mod1.mod2.Baz]]", + "('[' (name mod1.mod2.Foo) [('[' (name mod1.mod2.Bar) [(name mod1.mod2.Baz)])])", + ), + ( + "mod1.mod2.Foo[mod1.mod2.Bar1[mod1.mod2.Baz1], mod1.mod2.Bar2[mod1.mod2.Baz2]]", + "('[' (name mod1.mod2.Foo) [('[' (name mod1.mod2.Bar1) [(name mod1.mod2.Baz1)]), ('[' (name mod1.mod2.Bar2) [(name mod1.mod2.Baz2)])])", + ), + ("(Foo, Bar) -> Baz", "('(' [(name Foo), (name Bar)] (name Baz))"), + ( + "(mod1.mod2.Foo[mod1.mod2.Bar1[mod1.mod2.Baz1], mod1.mod2.Bar2[mod1.mod2.Baz2]], mod1.mod2.Bar[mod1.mod2.Bar1[mod1.mod2.Baz1], mod1.mod2.Bar2[mod1.mod2.Baz2]]) -> mod1.mod2.Baz[mod1.mod2.Bar1[mod1.mod2.Baz1], mod1.mod2.Bar2[mod1.mod2.Baz2]]", + "('(' [('[' (name mod1.mod2.Foo) [('[' (name mod1.mod2.Bar1) [(name mod1.mod2.Baz1)]), ('[' (name mod1.mod2.Bar2) [(name mod1.mod2.Baz2)])]), ('[' (name mod1.mod2.Bar) [('[' (name mod1.mod2.Bar1) [(name mod1.mod2.Baz1)]), ('[' (name mod1.mod2.Bar2) [(name mod1.mod2.Baz2)])])] ('[' (name mod1.mod2.Baz) [('[' (name mod1.mod2.Bar1) [(name mod1.mod2.Baz1)]), ('[' (name mod1.mod2.Bar2) [(name mod1.mod2.Baz2)])]))", + ), + ( + "(Foo, Bar) -> Baz | Foo[Bar[Baz]]", + "('|' ('(' [(name Foo), (name Bar)] (name Baz)) ('[' (name Foo) [('[' (name Bar) [(name Baz)])]))", + ), + ( + "Foo[Bar[Baz | (Foo, Bar) -> Baz]]", + "('[' (name Foo) [('[' (name Bar) [('|' (name Baz) ('(' [(name Foo), (name Bar)] (name Baz)))])])", + ), + ] + + for t, expected in tests: + result = repr(evaluate.compile(t)) + self.assertEqual(expected, result) + + + +class RegressionHintingTest(AbstractHintingTest): + @others + +def test_hierarchical_hint_for_mutable_attr_type(self): + """Test for #157, AttributeError: 'PyObject' object has no attribute 'get_doc'""" + code = dedent("""\ + class SuperClass(object): + def __init__(self): + self.foo = None + + + class SubClass(SuperClass): + def __init__(self): + super(SubClass, self).__init__() + self.bar = 3 + + + def foo(self): + return self.bar""") + result = self._assist(code) + self.assert_completion_in_result("bar", "attribute", result) + +@path C:/Repos/ekr-rope/ropetest/ +import sys + +import unittest + +import ropetest.projecttest +import ropetest.codeanalyzetest +import ropetest.doatest +import ropetest.type_hinting_test +import ropetest.pycoretest +import ropetest.pyscopestest +import ropetest.objectinfertest +import ropetest.objectdbtest +import ropetest.advanced_oi_test +import ropetest.runmodtest +import ropetest.builtinstest +import ropetest.historytest +import ropetest.simplifytest + +import ropetest.contrib +import ropetest.refactor + + +@others +if __name__ == "__main__": + runner = unittest.TextTestRunner() + result = runner.run(suite()) + sys.exit(not result.wasSuccessful()) +@language python +@tabwidth -4 + +def suite(): + result = unittest.TestSuite() + result.addTests(ropetest.projecttest.suite()) + result.addTests(ropetest.codeanalyzetest.suite()) + result.addTests(ropetest.doatest.suite()) + result.addTests(ropetest.type_hinting_test.suite()) + result.addTests(ropetest.pycoretest.suite()) + result.addTests(ropetest.pyscopestest.suite()) + result.addTests(ropetest.objectinfertest.suite()) + result.addTests(ropetest.objectdbtest.suite()) + result.addTests(ropetest.advanced_oi_test.suite()) + result.addTests(ropetest.runmodtest.suite()) + result.addTests(ropetest.builtinstest.suite()) + result.addTests(ropetest.historytest.suite()) + result.addTests(ropetest.simplifytest.suite()) + + result.addTests(ropetest.refactor.suite()) + result.addTests(ropetest.contrib.suite()) + + return result + + + + +def change_argument_mapping(self, definition_info, mapping): + if self.index < len(definition_info.args_with_defaults): + name = definition_info.args_with_defaults[0] + if name in mapping.param_dict: + del mapping.param_dict[name] + + + +@path C:/Repos/ekr-rope/ropetest/contrib/ +import unittest + +from rope.contrib.autoimport import sqlite as autoimport +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class AutoImportTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project(extension_modules=["sys"]) + self.mod1 = testutils.create_module(self.project, "mod1") + self.pkg = testutils.create_package(self.project, "pkg") + self.mod2 = testutils.create_module(self.project, "mod2", self.pkg) + self.importer = autoimport.AutoImport(self.project, observe=False) + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_case(self): + self.assertEqual([], self.importer.import_assist("A")) + + +def test_update_resource(self): + self.mod1.write("myvar = None\n") + self.importer.update_resource(self.mod1) + self.assertEqual([("myvar", "mod1")], self.importer.import_assist("myva")) + + +def test_update_non_existent_module(self): + self.importer.update_module("does_not_exists_this") + self.assertEqual([], self.importer.import_assist("myva")) + + +def test_module_with_syntax_errors(self): + self.mod1.write("this is a syntax error\n") + self.importer.update_resource(self.mod1) + self.assertEqual([], self.importer.import_assist("myva")) + + +def test_excluding_imported_names(self): + self.mod1.write("import pkg\n") + self.importer.update_resource(self.mod1) + self.assertEqual([], self.importer.import_assist("pkg")) + + +def test_get_modules(self): + self.mod1.write("myvar = None\n") + self.importer.update_resource(self.mod1) + self.assertEqual(["mod1"], self.importer.get_modules("myvar")) + + +class ArgumentAdder(_ArgumentChanger): + @others + +def test_get_modules_inside_packages(self): + self.mod1.write("myvar = None\n") + self.mod2.write("myvar = None\n") + self.importer.update_resource(self.mod1) + self.importer.update_resource(self.mod2) + self.assertEqual({"mod1", "pkg.mod2"}, set(self.importer.get_modules("myvar"))) + + +def test_trivial_insertion_line(self): + result = self.importer.find_insertion_line("") + self.assertEqual(1, result) + + +def test_insertion_line(self): + result = self.importer.find_insertion_line("import mod\n") + self.assertEqual(2, result) + + +def test_insertion_line_with_pydocs(self): + result = self.importer.find_insertion_line('"""docs\n\ndocs"""\nimport mod\n') + self.assertEqual(5, result) + + +def test_insertion_line_with_multiple_imports(self): + result = self.importer.find_insertion_line("import mod1\n\nimport mod2\n") + self.assertEqual(4, result) + + +def test_insertion_line_with_blank_lines(self): + result = self.importer.find_insertion_line("import mod1\n\n# comment\n") + self.assertEqual(2, result) + + +def test_empty_cache(self): + self.mod1.write("myvar = None\n") + self.importer.update_resource(self.mod1) + self.assertEqual(["mod1"], self.importer.get_modules("myvar")) + self.importer.clear_cache() + self.assertEqual([], self.importer.get_modules("myvar")) + + +def test_not_caching_underlined_names(self): + self.mod1.write("_myvar = None\n") + self.importer.update_resource(self.mod1, underlined=False) + self.assertEqual([], self.importer.get_modules("_myvar")) + self.importer.update_resource(self.mod1, underlined=True) + self.assertEqual(["mod1"], self.importer.get_modules("_myvar")) + + +def test_caching_underlined_names_passing_to_the_constructor(self): + importer = autoimport.AutoImport(self.project, False, True) + self.mod1.write("_myvar = None\n") + importer.update_resource(self.mod1) + self.assertEqual(["mod1"], importer.get_modules("_myvar")) + + +def test_name_locations(self): + self.mod1.write("myvar = None\n") + self.importer.update_resource(self.mod1) + self.assertEqual([(self.mod1, 1)], self.importer.get_name_locations("myvar")) + + +def __init__(self, project, code, resource, maxfixes=1): + self.project = project + self.code = code + self.resource = resource + self.maxfixes = maxfixes + + +def create_generate(kind, project, resource, offset, goal_resource=None): + """A factory for creating `Generate` objects + + `kind` can be 'variable', 'function', 'class', 'module' or + 'package'. + + """ + generate = eval("Generate" + kind.title()) + return generate(project, resource, offset, goal_resource=goal_resource) + + + +def __init__(self, index, name, default=None, value=None): + self.index = index + self.name = name + self.default = default + self.value = value + + +def test_name_locations_with_multiple_occurrences(self): + self.mod1.write("myvar = None\n") + self.mod2.write("\nmyvar = None\n") + self.importer.update_resource(self.mod1) + self.importer.update_resource(self.mod2) + self.assertEqual( + {(self.mod1, 1), (self.mod2, 2)}, + set(self.importer.get_name_locations("myvar")), + ) + + +def test_handling_builtin_modules(self): + self.importer.update_module("sys") + self.assertIn("sys", self.importer.get_modules("exit")) + + +def test_search_submodule(self): + self.importer.update_module("build") + import_statement = ("from build import env", "env") + self.assertIn(import_statement, self.importer.search("env", exact_match=True)) + self.assertIn(import_statement, self.importer.search("en")) + self.assertIn(import_statement, self.importer.search("env")) + + +def test_search_module(self): + self.importer.update_module("os") + import_statement = ("import os", "os") + self.assertIn(import_statement, self.importer.search("os", exact_match=True)) + self.assertIn(import_statement, self.importer.search("os")) + self.assertIn(import_statement, self.importer.search("o")) + + +def test_search(self): + self.importer.update_module("typing") + import_statement = ("from typing import Dict", "Dict") + self.assertIn(import_statement, self.importer.search("Dict", exact_match=True)) + self.assertIn(import_statement, self.importer.search("Dict")) + self.assertIn(import_statement, self.importer.search("Dic")) + self.assertIn(import_statement, self.importer.search("Di")) + self.assertIn(import_statement, self.importer.search("D")) + + +def test_generate_full_cache(self): + """The single thread test takes much longer than the multithread test but is easier to debug""" + single_thread = False + self.importer.generate_modules_cache(single_thread=single_thread) + self.assertIn(("from typing import Dict", "Dict"), self.importer.search("Dict")) + self.assertTrue(len(self.importer._dump_all()) > 0) + for table in self.importer._dump_all(): + self.assertTrue(len(table) > 0) + + + +class AutoImportObservingTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.mod1 = testutils.create_module(self.project, "mod1") + self.pkg = testutils.create_package(self.project, "pkg") + self.mod2 = testutils.create_module(self.project, "mod2", self.pkg) + self.importer = autoimport.AutoImport(self.project, observe=True) + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_writing_files(self): + self.mod1.write("myvar = None\n") + self.assertEqual(["mod1"], self.importer.get_modules("myvar")) + + +def change_definition_info(self, definition_info): + for pair in definition_info.args_with_defaults: + if pair[0] == self.name: + raise rope.base.exceptions.RefactoringError( + "Adding duplicate parameter: <%s>." % self.name + ) + definition_info.args_with_defaults.insert(self.index, (self.name, self.default)) + + +def test_moving_files(self): + self.mod1.write("myvar = None\n") + self.mod1.move("mod3.py") + self.assertEqual(["mod3"], self.importer.get_modules("myvar")) + + +def test_removing_files(self): + self.mod1.write("myvar = None\n") + self.mod1.remove() + self.assertEqual([], self.importer.get_modules("myvar")) + +@path C:/Repos/ekr-rope/ropetest/contrib/ +import unittest + + +import rope.base.history +import rope.contrib.changestack +import rope.base.change +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class ChangeStackTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_change_stack(self): + myfile = self.project.root.create_file("myfile.txt") + myfile.write("1") + stack = rope.contrib.changestack.ChangeStack(self.project) + stack.push(rope.base.change.ChangeContents(myfile, "2")) + self.assertEqual("2", myfile.read()) + stack.push(rope.base.change.ChangeContents(myfile, "3")) + self.assertEqual("3", myfile.read()) + stack.pop_all() + self.assertEqual("1", myfile.read()) + changes = stack.merged() + self.project.do(changes) + self.assertEqual("3", myfile.read()) + +@path C:/Repos/ekr-rope/ropetest/contrib/ +import os.path +from textwrap import dedent + +import unittest + +from rope.base import exceptions +from rope.contrib.codeassist import ( + get_definition_location, + get_doc, + starting_expression, + code_assist, + sorted_proposals, + starting_offset, + get_calltip, + get_canonical_path, +) +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class CodeAssistTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + +def change_argument_mapping(self, definition_info, mapping): + if self.value is not None: + mapping.param_dict[self.name] = self.value + + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _assist(self, code, offset=None, **args): + if offset is None: + offset = len(code) + return code_assist(self.project, code, offset, **args) + + +def test_simple_assist(self): + self._assist("", 0) + + +def assert_completion_in_result(self, name, scope, result, type=None): + for proposal in result: + if proposal.name == name: + self.assertEqual( + scope, + proposal.scope, + "proposal <%s> has wrong scope, expected " + "%r, got %r" % (name, scope, proposal.scope), + ) + if type is not None: + self.assertEqual( + type, + proposal.type, + "proposal <%s> has wrong type, expected " + "%r, got %r" % (name, type, proposal.type), + ) + return + self.fail("completion <%s> not proposed" % name) + + +def assert_completion_not_in_result(self, name, scope, result): + for proposal in result: + if proposal.name == name and proposal.scope == scope: + self.fail("completion <%s> was proposed" % name) + + +def test_completing_global_variables(self): + code = dedent("""\ + my_global = 10 + t = my""") + result = self._assist(code) + self.assert_completion_in_result("my_global", "global", result) + + +def test_not_proposing_unmatched_vars(self): + code = dedent("""\ + my_global = 10 + t = you""") + result = self._assist(code) + self.assert_completion_not_in_result("my_global", "global", result) + + +def test_not_proposing_unmatched_vars_with_underlined_starting(self): + code = dedent("""\ + my_global = 10 + t = your_""") + result = self._assist(code) + self.assert_completion_not_in_result("my_global", "global", result) + + +def test_not_proposing_local_assigns_as_global_completions(self): + code = dedent("""\ + def f(): my_global = 10 + t = my_""") + result = self._assist(code) + self.assert_completion_not_in_result("my_global", "global", result) + + +def test_proposing_functions(self): + code = dedent("""\ + def my_func(): return 2 + t = my_""") + result = self._assist(code) + self.assert_completion_in_result("my_func", "global", result) + + +class ArgumentDefaultInliner(_ArgumentChanger): + @others + +def test_proposing_classes(self): + code = dedent("""\ + class Sample(object): pass + t = Sam""") + result = self._assist(code) + self.assert_completion_in_result("Sample", "global", result) + + +def test_proposing_each_name_at_most_once(self): + code = dedent("""\ + variable = 10 + variable = 20 + t = vari""") + result = self._assist(code) + count = len([x for x in result if x.name == "variable" and x.scope == "global"]) + self.assertEqual(1, count) + + +def test_throwing_exception_in_case_of_syntax_errors(self): + code = dedent("""\ + sample (sdf+) + """) + with self.assertRaises(exceptions.ModuleSyntaxError): + self._assist(code, maxfixes=0) + + +def test_fixing_errors_with_maxfixes(self): + code = dedent("""\ + def f(): + sldj sldj + def g(): + ran""") + result = self._assist(code, maxfixes=2) + self.assertTrue(len(result) > 0) + + +def test_ignoring_errors_in_current_line(self): + code = dedent("""\ + def my_func(): + return 2 + t = """) + result = self._assist(code) + self.assert_completion_in_result("my_func", "global", result) + + +def test_not_reporting_variables_in_current_line(self): + code = dedent("""\ + def my_func(): return 2 + t = my_""") + result = self._assist(code) + self.assert_completion_not_in_result("my_", "global", result) + + +def test_completion_result(self): + code = dedent("""\ + my_global = 10 + t = my""") + self.assertEqual(len(code) - 2, starting_offset(code, len(code))) + + +def test_completing_imported_names(self): + code = dedent("""\ + import sys + a = sy""") + result = self._assist(code) + self.assert_completion_in_result("sys", "imported", result) + + +def test_completing_imported_names_with_as(self): + code = dedent("""\ + import sys as mysys + a = mys""") + result = self._assist(code) + self.assert_completion_in_result("mysys", "imported", result) + + +def test_not_completing_imported_names_with_as(self): + code = dedent("""\ + import sys as mysys + a = sy""") + result = self._assist(code) + self.assert_completion_not_in_result("sys", "global", result) + + +def __init__(self, index): + self.index = index + self.remove = False + + +def test_including_matching_builtins_types(self): + code = "my_var = Excep" + result = self._assist(code) + self.assert_completion_in_result("Exception", "builtin", result) + self.assert_completion_not_in_result("zip", "builtin", result) + + +def test_including_matching_builtins_functions(self): + code = "my_var = zi" + result = self._assist(code) + self.assert_completion_in_result("zip", "builtin", result) + + +def test_builtin_instances(self): + # ``import_dynload_stdmods`` pref is disabled for test project. + # we need to have it enabled to make pycore._find_module() + # load ``sys`` module. + self.project.prefs["import_dynload_stdmods"] = True + code = dedent("""\ + from sys import stdout + stdout.wr""") + result = self._assist(code) + self.assert_completion_in_result("write", "builtin", result) + self.assert_completion_in_result("writelines", "builtin", result) + + +def test_including_keywords(self): + code = "fo" + result = self._assist(code) + self.assert_completion_in_result("for", "keyword", result) + + +def test_not_reporting_proposals_after_dot(self): + code = dedent("""\ + a_dict = {} + key = 3 + a_dict.ke""") + result = self._assist(code) + self.assert_completion_not_in_result("key", "global", result) + + +def test_proposing_local_variables_in_functions(self): + code = dedent("""\ + def f(self): + my_var = 10 + my_""") + result = self._assist(code) + self.assert_completion_in_result("my_var", "local", result) + + +def test_local_variables_override_global_ones(self): + code = dedent("""\ + my_var = 20 + def f(self): + my_var = 10 + my_""") + result = self._assist(code) + self.assert_completion_in_result("my_var", "local", result) + + +def test_not_including_class_body_variables(self): + code = dedent("""\ + class C(object): + my_var = 20 + def f(self): + a = 20 + my_""") + result = self._assist(code) + self.assert_completion_not_in_result("my_var", "local", result) + + +def test_nested_functions(self): + code = dedent("""\ + def my_func(): + func_var = 20 + def inner_func(): + a = 20 + func""") + result = self._assist(code) + self.assert_completion_in_result("func_var", "local", result) + + +def test_scope_endpoint_selection(self): + code = dedent("""\ + def my_func(): + func_var = 20 + """) + result = self._assist(code) + self.assert_completion_not_in_result("func_var", "local", result) + + +def change_definition_info(self, definition_info): + if self.remove: + definition_info.args_with_defaults[self.index] = ( + definition_info.args_with_defaults[self.index][0], + None, + ) + + +def test_scope_better_endpoint_selection(self): + code = dedent("""\ + if True: + def f(): + my_var = 10 + my_""") + result = self._assist(code) + self.assert_completion_not_in_result("my_var", "local", result) + + +def test_imports_inside_function(self): + code = dedent("""\ + def f(): + import sys + sy""") + result = self._assist(code) + self.assert_completion_in_result("sys", "imported", result) + + +def test_imports_inside_function_dont_mix_with_globals(self): + code = dedent("""\ + def f(): + import sys + sy""") + result = self._assist(code) + self.assert_completion_not_in_result("sys", "local", result) + + +def test_nested_classes_local_names(self): + code = dedent("""\ + global_var = 10 + def my_func(): + func_var = 20 + class C(object): + def another_func(self): + local_var = 10 + func""") + result = self._assist(code) + self.assert_completion_in_result("func_var", "local", result) + + +def test_nested_classes_global(self): + code = dedent("""\ + global_var = 10 + def my_func(): + func_var = 20 + class C(object): + def another_func(self): + local_var = 10 + globa""") + result = self._assist(code) + self.assert_completion_in_result("global_var", "global", result) + + +def test_nested_classes_global_function(self): + code = dedent("""\ + global_var = 10 + def my_func(): + func_var = 20 + class C(object): + def another_func(self): + local_var = 10 + my_f""") + result = self._assist(code) + self.assert_completion_in_result("my_func", "global", result) + + +def test_proposing_function_parameters_in_functions(self): + code = dedent("""\ + def my_func(my_param): + my_var = 20 + my_""") + result = self._assist(code) + self.assert_completion_in_result("my_param", "local", result) + + +def test_proposing_function_keyword_parameters_in_functions(self): + code = dedent("""\ + def my_func(my_param, *my_list, **my_kws): + my_var = 20 + my_""") + result = self._assist(code) + self.assert_completion_in_result("my_param", "local", result) + self.assert_completion_in_result("my_list", "local", result) + self.assert_completion_in_result("my_kws", "local", result) + + +def test_not_proposing_unmatching_function_parameters_in_functions(self): + code = dedent("""\ + def my_func(my_param): + my_var = 20 + you_""") + result = self._assist(code) + self.assert_completion_not_in_result("my_param", "local", result) + + +def test_ignoring_current_statement(self): + code = dedent("""\ + my_var = 10 + my_tuple = (10, + my_""") + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def change_argument_mapping(self, definition_info, mapping): + default = definition_info.args_with_defaults[self.index][1] + name = definition_info.args_with_defaults[self.index][0] + if default is not None and name not in mapping.param_dict: + mapping.param_dict[name] = default + + + +def test_ignoring_current_statement_brackets_continuation(self): + code = dedent("""\ + my_var = 10 + 'hello'[10: + my_""") + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def test_ignoring_current_statement_explicit_continuation(self): + code = dedent("""\ + my_var = 10 + my_var2 = 2 + \\ + my_""") + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def test_ignor_current_statement_while_the_first_stmnt_of_the_block(self): + code = dedent("""\ + my_var = 10 + def f(): + my_""") + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def test_ignor_current_stmnt_while_current_line_ends_with_a_colon(self): + code = dedent("""\ + my_var = 10 + if my_: + pass""") + result = self._assist(code, 18) + self.assert_completion_in_result("my_var", "global", result) + + +def test_ignoring_string_contents(self): + code = "my_var = '('\nmy_" + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def test_ignoring_comment_contents(self): + code = "my_var = 10 #(\nmy_" + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def test_ignoring_string_contents_backslash_plus_quotes(self): + code = "my_var = '\\''\nmy_" + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def test_ignoring_string_contents_backslash_plus_backslash(self): + code = "my_var = '\\\\'\nmy_" + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def test_not_proposing_later_defined_variables_in_current_block(self): + code = dedent("""\ + my_ + my_var = 10 + """) + result = self._assist(code, 3, later_locals=False) + self.assert_completion_not_in_result("my_var", "global", result) + + +def test_not_proposing_later_defined_variables_in_current_function(self): + code = dedent("""\ + def f(): + my_ + my_var = 10 + """) + result = self._assist(code, 16, later_locals=False) + self.assert_completion_not_in_result("my_var", "local", result) + + +class ArgumentReorderer(_ArgumentChanger): + @others + +def test_ignoring_string_contents_with_triple_quotes(self): + code = "my_var = '''(\n'('''\nmy_" + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def test_ignoring_string_contents_with_triple_quotes_and_backslash(self): + code = 'my_var = """\\"""("""\nmy_' + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def test_ignor_str_contents_with_triple_quotes_and_double_backslash(self): + code = 'my_var = """\\\\"""\nmy_' + result = self._assist(code) + self.assert_completion_in_result("my_var", "global", result) + + +def test_reporting_params_when_in_the_first_line_of_a_function(self): + code = dedent("""\ + def f(param): + para""") + result = self._assist(code) + self.assert_completion_in_result("param", "local", result) + + +def test_code_assist_when_having_a_two_line_function_header(self): + code = dedent("""\ + def f(param1, + param2): + para""") + result = self._assist(code) + self.assert_completion_in_result("param1", "local", result) + + +def test_code_assist_with_function_with_two_line_return(self): + code = dedent("""\ + def f(param1, param2): + return(param1, + para""") + result = self._assist(code) + self.assert_completion_in_result("param2", "local", result) + + +def test_get_definition_location(self): + code = dedent("""\ + def a_func(): + pass + a_func()""") + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, 1), result) + + +def test_get_definition_location_underlined_names(self): + code = dedent("""\ + def a_sample_func(): + pass + a_sample_func()""") + result = get_definition_location(self.project, code, len(code) - 11) + self.assertEqual((None, 1), result) + + +def test_get_definition_location_dotted_names_method(self): + code = dedent("""\ + class AClass(object): + @staticmethod + def a_method(): + pass + AClass.a_method()""") + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, 3), result) + + +def test_get_definition_location_dotted_names_property(self): + code = dedent("""\ + class AClass(object): + @property + @somedecorator + def a_method(): + pass + AClass.a_method()""") + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, 4), result) + + +def __init__(self, new_order, autodef=None): + """Construct an `ArgumentReorderer` + + Note that the `new_order` is a list containing the new + position of parameters; not the position each parameter + is going to be moved to. (changed in ``0.5m4``) + + For example changing ``f(a, b, c)`` to ``f(c, a, b)`` + requires passing ``[2, 0, 1]`` and *not* ``[1, 2, 0]``. + + The `autodef` (automatic default) argument, forces rope to use + it as a default if a default is needed after the change. That + happens when an argument without default is moved after + another that has a default value. Note that `autodef` should + be a string or `None`; the latter disables adding automatic + default. + + """ + self.new_order = new_order + self.autodef = autodef + + +def test_get_definition_location_dotted_names_free_function(self): + code = dedent("""\ + @custom_decorator + def a_method(): + pass + a_method()""") + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, 2), result) + + +@testutils.only_for_versions_higher("3.5") +def test_get_definition_location_dotted_names_async_def(self): + code = dedent("""\ + class AClass(object): + @property + @decorator2 + async def a_method(): + pass + AClass.a_method()""") + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, 4), result) + + +def test_get_definition_location_dotted_names_class(self): + code = dedent("""\ + @custom_decorator + class AClass(object): + def a_method(): + pass + AClass.a_method()""") + result = get_definition_location(self.project, code, len(code) - 12) + self.assertEqual((None, 2), result) + + +def test_get_definition_location_dotted_names_with_space(self): + code = dedent("""\ + class AClass(object): + @staticmethod + def a_method(): + + pass + AClass.a_method()""") + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, 3), result) + + +def test_get_definition_location_dotted_names_inline_body(self): + code = dedent("""\ + class AClass(object): + @staticmethod + def a_method(): pass + AClass.a_method()""") + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, 3), result) + + +def test_get_definition_location_dotted_names_inline_body_split_arg(self): + code = dedent("""\ + class AClass(object): + @staticmethod + def a_method( + self, + arg1 + ): pass + AClass.a_method()""") + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, 3), result) + + +def test_get_definition_location_dotted_module_names(self): + module_resource = testutils.create_module(self.project, "mod") + module_resource.write("def a_func():\n pass\n") + code = "import mod\nmod.a_func()" + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((module_resource, 1), result) + + +def test_get_definition_location_for_nested_packages(self): + mod1 = testutils.create_module(self.project, "mod1") + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) + mod1.write("import pkg1.pkg2.mod2") + + init_dot_py = pkg2.get_child("__init__.py") + found_pyname = get_definition_location( + self.project, mod1.read(), mod1.read().index("pkg2") + 1 + ) + self.assertEqual(init_dot_py, found_pyname[0]) + + +def test_get_definition_location_unknown(self): + code = "a_func()\n" + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, None), result) + + +def test_get_definition_location_dot_spaces(self): + code = dedent("""\ + class AClass(object): + @staticmethod + def a_method(): + pass + AClass.\\ + a_method()""") + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, 3), result) + + +def change_definition_info(self, definition_info): + new_args = list(definition_info.args_with_defaults) + for new_index, index in enumerate(self.new_order): + new_args[new_index] = definition_info.args_with_defaults[index] + seen_default = False + for index, (arg, default) in enumerate(list(new_args)): + if default is not None: + seen_default = True + if seen_default and default is None and self.autodef is not None: + new_args[index] = (arg, self.autodef) + definition_info.args_with_defaults = new_args + + + +def test_get_definition_location_dot_line_break_inside_parens(self): + code = dedent("""\ + class A(object): + def a_method(self): + pass + (A. + a_method)""") + result = get_definition_location( + self.project, code, code.rindex("a_method") + 1 + ) + self.assertEqual((None, 2), result) + + +def test_if_scopes_in_other_scopes_for_get_definition_location(self): + code = dedent("""\ + def f(a_var): + pass + a_var = 10 + if True: + print(a_var) + """) + result = get_definition_location(self.project, code, len(code) - 3) + self.assertEqual((None, 3), result) + + +def test_get_definition_location_false_triple_quoted_string(self): + code = dedent('''\ + def foo(): + a = 0 + p = "foo""" + + def bar(): + a = 1 + a += 1 + ''') + result = get_definition_location(self.project, code, code.index("a += 1")) + self.assertEqual((None, 6), result) + + +def test_code_assists_in_parens(self): + code = dedent("""\ + def a_func(a_var): + pass + a_var = 10 + a_func(a_""") + result = self._assist(code) + self.assert_completion_in_result("a_var", "global", result) + + +def test_simple_type_inferencing(self): + code = dedent("""\ + class Sample(object): + def __init__(self, a_param): + pass + def a_method(self): + pass + Sample("hey").a_""") + result = self._assist(code) + self.assert_completion_in_result("a_method", "attribute", result) + + +def test_proposals_sorter(self): + code = dedent("""\ + def my_sample_function(self): + my_sample_var = 20 + my_sample_""") + proposals = sorted_proposals(self._assist(code)) + self.assertEqual("my_sample_var", proposals[0].name) + self.assertEqual("my_sample_function", proposals[1].name) + + +def test_proposals_sorter_for_methods_and_attributes(self): + code = dedent("""\ + class A(object): + def __init__(self): + self.my_a_var = 10 + def my_b_func(self): + pass + def my_c_func(self): + pass + a_var = A() + a_var.my_""") + proposals = sorted_proposals(self._assist(code)) + self.assertEqual("my_b_func", proposals[0].name) + self.assertEqual("my_c_func", proposals[1].name) + self.assertEqual("my_a_var", proposals[2].name) + + +def test_proposals_sorter_for_global_methods_and_funcs(self): + code = dedent("""\ + def my_b_func(self): + pass + my_a_var = 10 + my_""") + proposals = sorted_proposals(self._assist(code)) + self.assertEqual("my_b_func", proposals[0].name) + self.assertEqual("my_a_var", proposals[1].name) + + +def test_proposals_sorter_underlined_methods(self): + code = dedent("""\ + class A(object): + def _my_func(self): + self.my_a_var = 10 + def my_func(self): + pass + a_var = A() + a_var.""") + proposals = sorted_proposals(self._assist(code)) + self.assertEqual("my_func", proposals[0].name) + self.assertEqual("_my_func", proposals[1].name) + + +def test_proposals_sorter_and_scope_prefs(self): + code = dedent("""\ + my_global_var = 1 + def func(self): + my_local_var = 2 + my_""") + result = self._assist(code) + proposals = sorted_proposals(result, scopepref=["global", "local"]) + self.assertEqual("my_global_var", proposals[0].name) + self.assertEqual("my_local_var", proposals[1].name) + + +def create_module(project, name, sourcefolder=None): + """Creates a module and returns a `rope.base.resources.File`""" + if sourcefolder is None: + sourcefolder = project.root + packages = name.split(".") + parent = sourcefolder + for package in packages[:-1]: + parent = parent.get_child(package) + return parent.create_file(packages[-1] + ".py") + + + +class _ChangeCallsInModule: + @others + +def test_proposals_sorter_and_type_prefs(self): + code = dedent("""\ + my_global_var = 1 + def my_global_func(self): + pass + my_""") + result = self._assist(code) + proposals = sorted_proposals(result, typepref=["instance", "function"]) + self.assertEqual("my_global_var", proposals[0].name) + self.assertEqual("my_global_func", proposals[1].name) + + +def test_proposals_sorter_and_missing_type_in_typepref(self): + code = dedent("""\ + my_global_var = 1 + def my_global_func(): + pass + my_""") + result = self._assist(code) + proposals = sorted_proposals(result, typepref=["function"]) # noqa + + +def test_get_pydoc_unicode(self): + src = dedent('''\ + # coding: utf-8 + def foo(): + u"юникод-объект"''') + doc = get_doc(self.project, src, src.index("foo") + 1) + self.assertTrue(isinstance(doc, str)) + self.assertTrue("юникод-объект" in doc) + + +def test_get_pydoc_utf8_bytestring(self): + src = dedent('''\ + # coding: utf-8 + def foo(): + "байтстринг"''') + doc = get_doc(self.project, src, src.index("foo") + 1) + self.assertTrue(isinstance(doc, str)) + self.assertTrue("байтстринг" in doc) + + +def test_get_pydoc_for_functions(self): + src = dedent('''\ + def a_func(): + """a function""" + a_var = 10 + a_func()''') + self.assertTrue(get_doc(self.project, src, len(src) - 4).endswith("a function")) + get_doc(self.project, src, len(src) - 4).index("a_func()") + + +def test_get_pydoc_for_classes(self): + src = dedent("""\ + class AClass(object): + pass + """) + get_doc(self.project, src, src.index("AClass") + 1).index("AClass") + + +def test_get_pydoc_for_classes_with_init(self): + src = dedent("""\ + class AClass(object): + def __init__(self): + pass + """) + get_doc(self.project, src, src.index("AClass") + 1).index("AClass") + + +def test_get_pydoc_for_modules(self): + mod = testutils.create_module(self.project, "mod") + mod.write('"""a module"""\n') + src = "import mod\nmod" + self.assertEqual("a module", get_doc(self.project, src, len(src) - 1)) + + +def test_get_pydoc_for_builtins(self): + src = "print(object)\n" + self.assertTrue(get_doc(self.project, src, src.index("obj")) is not None) + + +def test_get_pydoc_for_methods_should_include_class_name(self): + src = dedent('''\ + class AClass(object): + def a_method(self): + """hey""" + pass + ''') + doc = get_doc(self.project, src, src.index("a_method") + 1) + doc.index("AClass.a_method") + doc.index("hey") + + +def __init__(self, project, occurrence_finder, resource, call_changer): + self.project = project + self.occurrence_finder = occurrence_finder + self.resource = resource + self.call_changer = call_changer + + +def test_get_pydoc_for_meths_should_inc_methods_from_super_classes(self): + src = dedent('''\ + class A(object): + def a_method(self): + """hey1""" + pass + class B(A): + def a_method(self): + """hey2""" + pass + ''') + doc = get_doc(self.project, src, src.rindex("a_method") + 1) + doc.index("A.a_method") + doc.index("hey1") + doc.index("B.a_method") + doc.index("hey2") + + +def test_get_pydoc_for_classes_should_name_super_classes(self): + src = dedent("""\ + class A(object): + pass + class B(A): + pass + """) + doc = get_doc(self.project, src, src.rindex("B") + 1) + doc.index("B(A)") + + +def test_get_pydoc_for_builtin_functions(self): + src = dedent("""\ + s = "hey" + s.replace + """) + doc = get_doc(self.project, src, src.rindex("replace") + 1) + self.assertTrue(doc is not None) + + +def test_commenting_errors_before_offset(self): + src = dedent("""\ + lsjd lsjdf + s = "hey" + s.replace() + """) + doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa + + +def test_proposing_variables_defined_till_the_end_of_scope(self): + code = dedent("""\ + if True: + a_v + a_var = 10 + """) + result = self._assist(code, code.index("a_v") + 3) + self.assert_completion_in_result("a_var", "global", result) + + +def test_completing_in_uncomplete_try_blocks(self): + code = dedent("""\ + try: + a_var = 10 + a_""") + result = self._assist(code) + self.assert_completion_in_result("a_var", "global", result) + + +def test_completing_in_uncomplete_try_blocks_in_functions(self): + code = dedent("""\ + def a_func(): + try: + a_var = 10 + a_""") + result = self._assist(code) + self.assert_completion_in_result("a_var", "local", result) + + +def test_already_complete_try_blocks_with_finally(self): + code = dedent("""\ + def a_func(): + try: + a_var = 10 + a_""") + result = self._assist(code) + self.assert_completion_in_result("a_var", "local", result) + + +def test_already_complete_try_blocks_with_finally2(self): + code = dedent("""\ + try: + a_var = 10 + a_ + finally: + pass + """) + result = self._assist(code, code.rindex("a_") + 2) + self.assert_completion_in_result("a_var", "global", result) + + +def test_already_complete_try_blocks_with_except(self): + code = dedent("""\ + try: + a_var = 10 + a_ + except Exception: + pass + """) + result = self._assist(code, code.rindex("a_") + 2) + self.assert_completion_in_result("a_var", "global", result) + + +def get_changed_module(self): + word_finder = worder.Worder(self.source) + change_collector = codeanalyze.ChangeCollector(self.source) + for occurrence in self.occurrence_finder.find_occurrences(self.resource): + if not occurrence.is_called() and not occurrence.is_defined(): + continue + start, end = occurrence.get_primary_range() + begin_parens, end_parens = word_finder.get_word_parens_range(end - 1) + if occurrence.is_called(): + primary, pyname = occurrence.get_primary_and_pyname() + changed_call = self.call_changer.change_call( + primary, pyname, self.source[start:end_parens] + ) + else: + changed_call = self.call_changer.change_definition( + self.source[start:end_parens] + ) + if changed_call is not None: + change_collector.add_change(start, end_parens, changed_call) + return change_collector.get_changed() + + +def test_already_complete_try_blocks_with_except2(self): + code = dedent("""\ + a_var = 10 + try: + another_var = a_ + another_var = 10 + except Exception: + pass + """) + result = self._assist(code, code.rindex("a_") + 2) + self.assert_completion_in_result("a_var", "global", result) + + +def test_completing_ifs_in_uncomplete_try_blocks(self): + code = dedent("""\ + try: + if True: + a_var = 10 + a_""") + result = self._assist(code) + self.assert_completion_in_result("a_var", "global", result) + + +def test_completing_ifs_in_uncomplete_try_blocks2(self): + code = dedent("""\ + try: + if True: + a_var = 10 + a_""") + result = self._assist(code) + self.assert_completion_in_result("a_var", "global", result) + + +def test_completing_excepts_in_uncomplete_try_blocks(self): + code = dedent("""\ + try: + pass + except Exc""") + result = self._assist(code) + self.assert_completion_in_result("Exception", "builtin", result) + + +def test_and_normal_complete_blocks_and_single_fixing(self): + code = dedent("""\ + try: + range. + except: + pass + """) + result = self._assist(code, code.index("."), maxfixes=1) # noqa + + +def test_nested_blocks(self): + code = dedent("""\ + a_var = 10 + try: + try: + a_v""") + result = self._assist(code) + self.assert_completion_in_result("a_var", "global", result) + + +def test_proposing_function_keywords_when_calling(self): + code = dedent("""\ + def f(p): + pass + f(p""") + result = self._assist(code) + self.assert_completion_in_result("p=", "parameter_keyword", result) + + +def test_proposing_function_keywords_when_calling_for_non_functions(self): + code = dedent("""\ + f = 1 + f(p""") + result = self._assist(code) # noqa + + +def test_proposing_function_keywords_when_calling_extra_spaces(self): + code = dedent("""\ + def f(p): + pass + f( p""") + result = self._assist(code) + self.assert_completion_in_result("p=", "parameter_keyword", result) + + +def test_proposing_function_keywords_when_calling_on_second_argument(self): + code = dedent("""\ + def f(p1, p2): + pass + f(1, p""") + result = self._assist(code) + self.assert_completion_in_result("p2=", "parameter_keyword", result) + + +@property +@utils.saveit +def pymodule(self): + return self.project.get_pymodule(self.resource) + + +def test_proposing_function_keywords_when_calling_not_proposing_args(self): + code = dedent("""\ + def f(p1, *args): + pass + f(1, a""") + result = self._assist(code) + self.assert_completion_not_in_result("args=", "parameter_keyword", result) + + +def test_propos_function_kwrds_when_call_with_no_noth_after_parens(self): + code = dedent("""\ + def f(p): + pass + f(""") + result = self._assist(code) + self.assert_completion_in_result("p=", "parameter_keyword", result) + + +def test_propos_function_kwrds_when_call_with_no_noth_after_parens2(self): + code = dedent("""\ + def f(p): + pass + def g(): + h = f + f(""") + result = self._assist(code) + self.assert_completion_in_result("p=", "parameter_keyword", result) + + +def test_codeassists_before_opening_of_parens(self): + code = dedent("""\ + def f(p): + pass + a_var = 1 + f(1) + """) + result = self._assist(code, code.rindex("f") + 1) + self.assert_completion_not_in_result("a_var", "global", result) + + +def test_codeassist_before_single_line_indents(self): + code = dedent("""\ + myvar = 1 + if True: + (myv + if True: + pass + """) + result = self._assist(code, code.rindex("myv") + 3) + self.assert_completion_not_in_result("myvar", "local", result) + + +def test_codeassist_before_line_indents_in_a_blank_line(self): + code = dedent("""\ + myvar = 1 + if True: + + if True: + pass + """) + result = self._assist(code, code.rindex(" ") + 4) + self.assert_completion_not_in_result("myvar", "local", result) + + +def test_simple_get_calltips(self): + src = dedent("""\ + def f(): + pass + var = f() + """) + doc = get_calltip(self.project, src, src.rindex("f")) + self.assertEqual("f()", doc) + + +def test_get_calltips_for_classes(self): + src = dedent("""\ + class C(object): + def __init__(self): + pass + C(""") + doc = get_calltip(self.project, src, len(src) - 1) + self.assertEqual("C.__init__(self)", doc) + + +def test_get_calltips_for_objects_with_call(self): + src = dedent("""\ + class C(object): + def __call__(self, p): + pass + c = C() + c(1,""") + doc = get_calltip(self.project, src, src.rindex("c")) + self.assertEqual("C.__call__(self, p)", doc) + + +def test_get_calltips_and_including_module_name(self): + src = dedent("""\ + class C(object): + def __call__(self, p): + pass + c = C() + c(1,""") + mod = testutils.create_module(self.project, "mod") + mod.write(src) + doc = get_calltip(self.project, src, src.rindex("c"), mod) + self.assertEqual("mod.C.__call__(self, p)", doc) + + +@property +@utils.saveit +def source(self): + if self.resource is not None: + return self.resource.read() + else: + return self.pymodule.source_code + + +def test_get_calltips_and_including_module_name_2(self): + src = "range()\n" + doc = get_calltip(self.project, src, 1, ignore_unknown=True) + self.assertTrue(doc is None) + + +def test_removing_self_parameter(self): + src = dedent("""\ + class C(object): + def f(self): + pass + C().f()""") + doc = get_calltip(self.project, src, src.rindex("f"), remove_self=True) + self.assertEqual("C.f()", doc) + + +def test_removing_self_parameter_and_more_than_one_parameter(self): + src = dedent("""\ + class C(object): + def f(self, p1): + pass + C().f()""") + doc = get_calltip(self.project, src, src.rindex("f"), remove_self=True) + self.assertEqual("C.f(p1)", doc) + + +def test_lambda_calltip(self): + src = dedent("""\ + foo = lambda x, y=1: None + foo()""") + doc = get_calltip(self.project, src, src.rindex("f")) + self.assertEqual(doc, "lambda(x, y)") + + +def test_keyword_before_parens(self): + code = dedent("""\ + if (1).: + pass""") + result = self._assist(code, offset=len("if (1).")) + self.assertTrue(result) + + +# TESTING PROPOSAL'S KINDS AND TYPES. +# SEE RELATION MATRIX IN `CompletionProposal`'s DOCSTRING + + +def test_local_variable_completion_proposal(self): + code = dedent("""\ + def foo(): + xvar = 5 + x""") + result = self._assist(code) + self.assert_completion_in_result("xvar", "local", result, "instance") + + +def test_global_variable_completion_proposal(self): + code = dedent("""\ + yvar = 5 + y""") + result = self._assist(code) + self.assert_completion_in_result("yvar", "global", result, "instance") + + +def test_builtin_variable_completion_proposal(self): + for varname in ("False", "True"): + result = self._assist(varname[0]) + self.assert_completion_in_result( + varname, "builtin", result, type="instance" + ) + + +def test_attribute_variable_completion_proposal(self): + code = dedent("""\ + class AClass(object): + def foo(self): + self.bar = 1 + self.b""") + result = self._assist(code) + self.assert_completion_in_result("bar", "attribute", result, type="instance") + + +@property +@utils.saveit +def lines(self): + return self.pymodule.lines + + + +def test_local_class_completion_proposal(self): + code = dedent("""\ + def foo(): + class LocalClass(object): pass + Lo""") + result = self._assist(code) + self.assert_completion_in_result("LocalClass", "local", result, type="class") + + +def test_global_class_completion_proposal(self): + code = dedent("""\ + class GlobalClass(object): pass + Gl""") + result = self._assist(code) + self.assert_completion_in_result("GlobalClass", "global", result, type="class") + + +def test_builtin_class_completion_proposal(self): + for varname in ("object", "dict", "file"): + result = self._assist(varname[0]) + self.assert_completion_in_result(varname, "builtin", result, type="class") + + +def test_attribute_class_completion_proposal(self): + code = dedent("""\ + class Outer(object): + class Inner(object): pass + Outer.""") + result = self._assist(code) + self.assert_completion_in_result("Inner", "attribute", result, type="class") + + +def test_local_function_completion_proposal(self): + code = dedent("""\ + def outer(): + def inner(): pass + in""") + result = self._assist(code) + self.assert_completion_in_result("inner", "local", result, type="function") + + +def test_global_function_completion_proposal(self): + code = dedent("""\ + def foo(): pass + f""") + result = self._assist(code) + self.assert_completion_in_result("foo", "global", result, type="function") + + +def test_builtin_function_completion_proposal(self): + code = "a" + result = self._assist(code) + for expected in ("all", "any", "abs"): + self.assert_completion_in_result( + expected, "builtin", result, type="function" + ) + + +def test_attribute_function_completion_proposal(self): + code = dedent("""\ + class Some(object): + def method(self): + self.""") + result = self._assist(code) + self.assert_completion_in_result("method", "attribute", result, type="function") + + +def test_local_module_completion_proposal(self): + code = dedent("""\ + def foo(): + import types + t""") + result = self._assist(code) + self.assert_completion_in_result("types", "imported", result, type="module") + + +def test_global_module_completion_proposal(self): + code = dedent("""\ + import operator + o""") + result = self._assist(code) + self.assert_completion_in_result("operator", "imported", result, type="module") + + +class _MultipleFinders: + @others + +def test_attribute_module_completion_proposal(self): + code = dedent("""\ + class Some(object): + import os + Some.o""") + result = self._assist(code) + self.assert_completion_in_result("os", "imported", result, type="module") + + +def test_builtin_exception_completion_proposal(self): + code = dedent("""\ + def blah(): + Z""") + result = self._assist(code) + self.assert_completion_in_result( + "ZeroDivisionError", "builtin", result, type="class" + ) + + +def test_keyword_completion_proposal(self): + code = "f" + result = self._assist(code) + self.assert_completion_in_result("for", "keyword", result, type=None) + self.assert_completion_in_result("from", "keyword", result, type=None) + + +def test_parameter_keyword_completion_proposal(self): + code = dedent("""\ + def func(abc, aloha, alpha, amigo): pass + func(a""") + result = self._assist(code) + for expected in ("abc=", "aloha=", "alpha=", "amigo="): + self.assert_completion_in_result( + expected, "parameter_keyword", result, type=None + ) + + +def test_object_path_global(self): + code = "GLOBAL_VARIABLE = 42\n" + resource = testutils.create_module(self.project, "mod") + resource.write(code) + result = get_canonical_path(self.project, resource, 1) + mod_path = os.path.join(self.project.address, "mod.py") + self.assertEqual( + result, [(mod_path, "MODULE"), ("GLOBAL_VARIABLE", "VARIABLE")] + ) + + +def test_object_path_attribute(self): + code = dedent("""\ + class Foo(object): + attr = 42 + """) + resource = testutils.create_module(self.project, "mod") + resource.write(code) + result = get_canonical_path(self.project, resource, 24) + mod_path = os.path.join(self.project.address, "mod.py") + self.assertEqual( + result, [(mod_path, "MODULE"), ("Foo", "CLASS"), ("attr", "VARIABLE")] + ) + + +def test_object_path_subclass(self): + code = dedent("""\ + class Foo(object): + class Bar(object): + pass + """) + resource = testutils.create_module(self.project, "mod") + resource.write(code) + result = get_canonical_path(self.project, resource, 30) + mod_path = os.path.join(self.project.address, "mod.py") + self.assertEqual( + result, [(mod_path, "MODULE"), ("Foo", "CLASS"), ("Bar", "CLASS")] + ) + + +def test_object_path_method_parameter(self): + code = dedent("""\ + class Foo(object): + def bar(self, a, b, c): + pass + """) + resource = testutils.create_module(self.project, "mod") + resource.write(code) + result = get_canonical_path(self.project, resource, 41) + mod_path = os.path.join(self.project.address, "mod.py") + self.assertEqual( + result, + [ + (mod_path, "MODULE"), + ("Foo", "CLASS"), + ("bar", "FUNCTION"), + ("b", "PARAMETER"), + ], + ) + + +def test_object_path_variable(self): + code = dedent("""\ + def bar(a): + x = a + 42 + """) + resource = testutils.create_module(self.project, "mod") + resource.write(code) + result = get_canonical_path(self.project, resource, 17) + mod_path = os.path.join(self.project.address, "mod.py") + self.assertEqual( + result, [(mod_path, "MODULE"), ("bar", "FUNCTION"), ("x", "VARIABLE")] + ) + + + +class CodeAssistInProjectsTest(unittest.TestCase): + @others + +def __init__(self, finders): + self.finders = finders + + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + samplemod = testutils.create_module(self.project, "samplemod") + code = dedent("""\ + class SampleClass(object): + def sample_method(): + pass + + def sample_func(): + pass + sample_var = 10 + + def _underlined_func(): + pass + + """) + samplemod.write(code) + package = testutils.create_package(self.project, "package") + nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa + + +def tearDown(self): + testutils.remove_project(self.project) + super(self.__class__, self).tearDown() + + +def _assist(self, code, resource=None, **kwds): + return code_assist(self.project, code, len(code), resource, **kwds) + + +def assert_completion_in_result(self, name, scope, result): + for proposal in result: + if proposal.name == name and proposal.scope == scope: + return + self.fail("completion <%s> not proposed" % name) + + +def assert_completion_not_in_result(self, name, scope, result): + for proposal in result: + if proposal.name == name and proposal.scope == scope: + self.fail("completion <%s> was proposed" % name) + + +def test_simple_import(self): + code = dedent("""\ + import samplemod + sample""") + result = self._assist(code) + self.assert_completion_in_result("samplemod", "imported", result) + + +def test_from_import_class(self): + code = dedent("""\ + from samplemod import SampleClass + Sample""") + result = self._assist(code) + self.assert_completion_in_result("SampleClass", "imported", result) + + +def test_from_import_function(self): + code = dedent("""\ + from samplemod import sample_func + sample""") + result = self._assist(code) + self.assert_completion_in_result("sample_func", "imported", result) + + +def test_from_import_variable(self): + code = dedent("""\ + from samplemod import sample_var + sample""") + result = self._assist(code) + self.assert_completion_in_result("sample_var", "imported", result) + + +def test_from_imports_inside_functions(self): + code = dedent("""\ + def f(): + from samplemod import SampleClass + Sample""") + result = self._assist(code) + self.assert_completion_in_result("SampleClass", "imported", result) + + +def find_occurrences(self, resource=None, pymodule=None): + all_occurrences = [] + for finder in self.finders: + all_occurrences.extend(finder.find_occurrences(resource, pymodule)) + all_occurrences.sort(key=lambda x: x.get_primary_range()) + return all_occurrences + +def test_from_import_only_imports_imported(self): + code = dedent("""\ + from samplemod import sample_func + Sample""") + result = self._assist(code) + self.assert_completion_not_in_result("SampleClass", "global", result) + + +def test_from_import_star(self): + code = dedent("""\ + from samplemod import * + Sample""") + result = self._assist(code) + self.assert_completion_in_result("SampleClass", "imported", result) + + +def test_from_import_star2(self): + code = dedent("""\ + from samplemod import * + sample""") + result = self._assist(code) + self.assert_completion_in_result("sample_func", "imported", result) + self.assert_completion_in_result("sample_var", "imported", result) + + +def test_from_import_star_not_imporing_underlined(self): + code = dedent("""\ + from samplemod import * + _under""") + result = self._assist(code) + self.assert_completion_not_in_result("_underlined_func", "global", result) + + +def test_from_package_import_mod(self): + code = dedent("""\ + from package import nestedmod + nest""") + result = self._assist(code) + self.assert_completion_in_result("nestedmod", "imported", result) + + +def test_completing_after_dot(self): + code = dedent("""\ + class SampleClass(object): + def sample_method(self): + pass + SampleClass.sam""") + result = self._assist(code) + self.assert_completion_in_result("sample_method", "attribute", result) + + +def test_completing_after_multiple_dots(self): + code = dedent("""\ + class Class1(object): + class Class2(object): + def sample_method(self): + pass + Class1.Class2.sam""") + result = self._assist(code) + self.assert_completion_in_result("sample_method", "attribute", result) + + +def test_completing_after_self_dot(self): + code = dedent("""\ + class Sample(object): + def method1(self): + pass + def method2(self): + self.m""") + result = self._assist(code) + self.assert_completion_in_result("method1", "attribute", result) + + +def test_result_start_offset_for_dotted_completions(self): + code = dedent("""\ + class Sample(object): + def method1(self): + pass + Sample.me""") + self.assertEqual(len(code) - 2, starting_offset(code, len(code))) + + +def test_backslash_after_dots(self): + code = dedent("""\ + class Sample(object): + def a_method(self): + pass + Sample.\\ + a_m""") + result = self._assist(code) + self.assert_completion_in_result("a_method", "attribute", result) + + +@path C:/Repos/ekr-rope/rope/refactor/ +from rope.base import evaluate +from rope.base import exceptions +from rope.base import libutils +from rope.base import pynames +from rope.base import taskhandle +from rope.base import utils +from rope.base import worder +from rope.base.change import ChangeSet, ChangeContents +from rope.refactor import sourceutils, occurrences + + +@others +@language python +@tabwidth -4 + +def test_not_proposing_global_names_after_dot(self): + code = dedent("""\ + class Sample(object): + def a_method(self): + pass + Sample.""") + result = self._assist(code) + self.assert_completion_not_in_result("Sample", "global", result) + + +def test_assist_on_relative_imports(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod1.write(dedent("""\ + def a_func(): + pass + """)) + code = dedent("""\ + import mod1 + mod1.""") + result = self._assist(code, resource=mod2) + self.assert_completion_in_result("a_func", "imported", result) + + +def test_get_location_on_relative_imports(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod1.write(dedent("""\ + def a_func(): + pass + """)) + code = dedent("""\ + import mod1 + mod1.a_func + """) + result = get_definition_location(self.project, code, len(code) - 2, mod2) + self.assertEqual((mod1, 1), result) + + +def test_get_definition_location_for_builtins(self): + code = "import sys\n" + result = get_definition_location(self.project, code, len(code) - 2) + self.assertEqual((None, None), result) + + +def test_get_doc_on_relative_imports(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod1.write(dedent('''\ + def a_func(): + """hey""" + pass + ''')) + code = dedent("""\ + import mod1 + mod1.a_func + """) + result = get_doc(self.project, code, len(code) - 2, mod2) + self.assertTrue(result.endswith("hey")) + + +def test_get_doc_on_from_import_module(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent('''\ + """mod1 docs""" + var = 1 + ''')) + code = "from mod1 import var\n" + result = get_doc(self.project, code, code.index("mod1")) + result.index("mod1 docs") + + +def test_fixing_errors_with_maxfixes_in_resources(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def f(): + sldj sldj + def g(): + ran""") + mod.write(code) + result = self._assist(code, maxfixes=2, resource=mod) + self.assertTrue(len(result) > 0) + + +def test_completing_names_after_from_import(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("myvar = None\n") + result = self._assist("from mod1 import myva", resource=mod2) + self.assertTrue(len(result) > 0) + self.assert_completion_in_result("myvar", "global", result) + + +def test_completing_names_after_from_import_and_sorted_proposals(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("myvar = None\n") + result = self._assist("from mod1 import myva", resource=mod2) + result = sorted_proposals(result) + self.assertTrue(len(result) > 0) + self.assert_completion_in_result("myvar", "global", result) + + +def test_completing_names_after_from_import2(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("myvar = None\n") + result = self._assist("from mod1 import ", resource=mod2) + self.assertTrue(len(result) > 0) + self.assert_completion_in_result("myvar", "global", result) + + +def create_package(project, name, sourcefolder=None): + """Creates a package and returns a `rope.base.resources.Folder`""" + if sourcefolder is None: + sourcefolder = project.root + packages = name.split(".") + parent = sourcefolder + for package in packages[:-1]: + parent = parent.get_child(package) + made_packages = parent.create_folder(packages[-1]) + made_packages.create_file("__init__.py") + return made_packages + + + +class EncapsulateField: + @others + +def test_starting_expression(self): + code = dedent("""\ + l = list() + l.app""") + self.assertEqual("l.app", starting_expression(code, len(code))) + +@path C:/Repos/ekr-rope/ropetest/contrib/ +from textwrap import dedent + +import unittest + + +from rope.contrib import finderrors +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class FindErrorsTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.mod = self.project.root.create_file("mod.py") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_unresolved_variables(self): + self.mod.write("print(var)\n") + result = finderrors.find_errors(self.project, self.mod) + self.assertEqual(1, len(result)) + self.assertEqual(1, result[0].lineno) + + +def test_defined_later(self): + self.mod.write(dedent("""\ + print(var) + var = 1 + """)) + result = finderrors.find_errors(self.project, self.mod) + self.assertEqual(1, len(result)) + self.assertEqual(1, result[0].lineno) + + +def test_ignoring_builtins(self): + self.mod.write("range(2)\n") + result = finderrors.find_errors(self.project, self.mod) + self.assertEqual(0, len(result)) + + +def test_ignoring_none(self): + self.mod.write("var = None\n") + result = finderrors.find_errors(self.project, self.mod) + self.assertEqual(0, len(result)) + + +def test_bad_attributes(self): + code = dedent("""\ + class C(object): + pass + c = C() + print(c.var) + """) + self.mod.write(code) + result = finderrors.find_errors(self.project, self.mod) + self.assertEqual(1, len(result)) + self.assertEqual(4, result[0].lineno) + +def __init__(self, project, resource, offset): + self.project = project + self.name = worder.get_name_at(resource, offset) + this_pymodule = self.project.get_pymodule(resource) + self.pyname = evaluate.eval_location(this_pymodule, offset) + if not self._is_an_attribute(self.pyname): + raise exceptions.RefactoringError( + "Encapsulate field should be performed on class attributes." + ) + self.resource = self.pyname.get_definition_location()[0].get_resource() + + +@path C:/Repos/ekr-rope/ropetest/contrib/ +from textwrap import dedent + +import unittest + +from rope.base import exceptions +from rope.contrib.findit import find_occurrences, find_implementations, find_definition +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class FindItTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_finding_occurrences(self): + mod = testutils.create_module(self.project, "mod") + mod.write("a_var = 1\n") + result = find_occurrences(self.project, mod, 1) + self.assertEqual(mod, result[0].resource) + self.assertEqual(0, result[0].offset) + self.assertEqual(False, result[0].unsure) + + +def test_finding_occurrences_in_more_than_one_module(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("a_var = 1\n") + mod2.write(dedent("""\ + import mod1 + my_var = mod1.a_var""")) + result = find_occurrences(self.project, mod1, 1) + self.assertEqual(2, len(result)) + modules = (result[0].resource, result[1].resource) + self.assertTrue(mod1 in modules and mod2 in modules) + + +def test_finding_occurrences_matching_when_unsure(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + class C(object): + def a_func(self): + pass + def f(arg): + arg.a_func() + """)) + result = find_occurrences( + self.project, mod1, mod1.read().index("a_func"), unsure=True + ) + self.assertEqual(2, len(result)) + + +def test_find_occurrences_resources_parameter(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("a_var = 1\n") + mod2.write(dedent("""\ + import mod1 + my_var = mod1.a_var""")) + result = find_occurrences(self.project, mod1, 1, resources=[mod1]) + self.assertEqual(1, len(result)) + self.assertEqual((mod1, 0), (result[0].resource, result[0].offset)) + + +def test_find_occurrences_and_class_hierarchies(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + class A(object): + def f(): + pass + class B(A): + def f(): + pass + """)) + offset = mod1.read().rindex("f") + result1 = find_occurrences(self.project, mod1, offset) + result2 = find_occurrences(self.project, mod1, offset, in_hierarchy=True) + self.assertEqual(1, len(result1)) + self.assertEqual(2, len(result2)) + + +def test_trivial_find_implementations(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + class A(object): + def f(self): + pass + """)) + offset = mod1.read().rindex("f(") + result = find_implementations(self.project, mod1, offset) + self.assertEqual([], result) + + +def get_changes( + self, + getter=None, + setter=None, + resources=None, + task_handle=taskhandle.NullTaskHandle(), +): + """Get the changes this refactoring makes + + If `getter` is not `None`, that will be the name of the + getter, otherwise ``get_${field_name}`` will be used. The + same is true for `setter` and if it is None set_${field_name} is + used. + + `resources` can be a list of `rope.base.resource.File` that + the refactoring should be applied on; if `None` all python + files in the project are searched. + + """ + if resources is None: + resources = self.project.get_python_files() + changes = ChangeSet("Encapsulate field <%s>" % self.name) + job_set = task_handle.create_jobset("Collecting Changes", len(resources)) + if getter is None: + getter = "get_" + self.name + if setter is None: + setter = "set_" + self.name + renamer = GetterSetterRenameInModule( + self.project, self.name, self.pyname, getter, setter + ) + for file in resources: + job_set.started_job(file.path) + if file == self.resource: + result = self._change_holding_module(changes, renamer, getter, setter) + changes.add_change(ChangeContents(self.resource, result)) + else: + result = renamer.get_changed_module(file) + if result is not None: + changes.add_change(ChangeContents(file, result)) + job_set.finished_job() + return changes + + +def test_find_implementations_and_not_returning_parents(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + class A(object): + def f(self): + pass + class B(A): + def f(self): + pass + """)) + offset = mod1.read().rindex("f(") + result = find_implementations(self.project, mod1, offset) + self.assertEqual([], result) + + +def test_find_implementations_real_implementation(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + class A(object): + def f(self): + pass + class B(A): + def f(self): + pass + """)) + offset = mod1.read().index("f(") + result = find_implementations(self.project, mod1, offset) + self.assertEqual(1, len(result)) + self.assertEqual(mod1.read().rindex("f("), result[0].offset) + + +def test_find_implementations_real_implementation_simple(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write("class A(object):\n pass\n") + offset = mod1.read().index("A") + with self.assertRaises(exceptions.BadIdentifierError): + find_implementations(self.project, mod1, offset) + + +def test_trivial_find_definition(self): + code = dedent("""\ + def a_func(): + pass + a_func()""") + result = find_definition(self.project, code, code.rindex("a_func")) + start = code.index("a_func") + self.assertEqual(start, result.offset) + self.assertEqual(None, result.resource) + self.assertEqual(1, result.lineno) + self.assertEqual((start, start + len("a_func")), result.region) + + +def test_find_definition_in_other_modules(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write("var = 1\n") + code = dedent("""\ + import mod1 + print(mod1.var) + """) + result = find_definition(self.project, code, code.index("var")) + self.assertEqual(mod1, result.resource) + self.assertEqual(0, result.offset) + +@path C:/Repos/ekr-rope/ropetest/contrib/ +import unittest + + +from ropetest import testutils +from rope.contrib.fixmodnames import FixModuleNames +from rope.contrib.generate import create_module, create_package + + +@others +@language python +@tabwidth -4 + +# HACK: for making this test work on case-insensitive file-systems, it +# uses a name.replace('x', '_') fixer. +class FixModuleNamesTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_module_renaming(self): + mod = create_module(self.project, "xod") + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + self.assertFalse(mod.exists()) + self.assertTrue(self.project.get_resource("_od.py").exists()) + + +def get_field_name(self): + """Get the name of the field to be encapsulated""" + return self.name + + +def test_packages_module_renaming(self): + pkg = create_package(self.project, "xkg") + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + self.assertFalse(pkg.exists()) + self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) + + +def test_fixing_contents(self): + mod1 = create_module(self.project, "xod1") + mod2 = create_module(self.project, "xod2") + mod1.write("import xod2\n") + mod2.write("import xod1\n") + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + newmod1 = self.project.get_resource("_od1.py") + newmod2 = self.project.get_resource("_od2.py") + self.assertEqual("import _od2\n", newmod1.read()) + self.assertEqual("import _od1\n", newmod2.read()) + + +def test_handling_nested_modules(self): + pkg = create_package(self.project, "xkg") + mod = create_module(self.project, "xkg.xod") # noqa + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + self.assertFalse(pkg.exists()) + self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) + self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) + + + +def _fixer(name): + return name.replace("x", "_") + +@path C:/Repos/ekr-rope/ropetest/contrib/ +from textwrap import dedent + +import unittest + +from rope.base import exceptions +from rope.contrib import generate +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class GenerateTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod1") + self.mod2 = testutils.create_module(self.project, "mod2") + self.pkg = testutils.create_package(self.project, "pkg") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _get_generate(self, offset): + return generate.GenerateVariable(self.project, self.mod, offset) + + +def _get_generate_class(self, offset, goal_mod=None): + return generate.GenerateClass( + self.project, self.mod, offset, goal_resource=goal_mod + ) + + +def _is_an_attribute(self, pyname): + if pyname is not None and isinstance(pyname, pynames.AssignedName): + pymodule, lineno = self.pyname.get_definition_location() + scope = pymodule.get_scope().get_inner_scope_for_line(lineno) + if scope.get_kind() == "Class": + return pyname in scope.get_names().values() + parent = scope.parent + if parent is not None and parent.get_kind() == "Class": + return pyname in parent.get_names().values() + return False + + +def _get_generate_module(self, offset): + return generate.GenerateModule(self.project, self.mod, offset) + + +def _get_generate_package(self, offset): + return generate.GeneratePackage(self.project, self.mod, offset) + + +def _get_generate_function(self, offset): + return generate.GenerateFunction(self.project, self.mod, offset) + + +def test_getting_location(self): + code = "a_var = name\n" + self.mod.write(code) + generator = self._get_generate(code.index("name")) + self.assertEqual((self.mod, 1), generator.get_location()) + + +def test_generating_variable(self): + code = dedent("""\ + a_var = name + """) + self.mod.write(code) + changes = self._get_generate(code.index("name")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + name = None + + + a_var = name + """), + self.mod.read(), + ) + + +def test_generating_variable_inserting_before_statement(self): + code = dedent("""\ + c = 1 + c = b + """) + self.mod.write(code) + changes = self._get_generate(code.index("b")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + c = 1 + b = None + + + c = b + """), + self.mod.read(), + ) + + +def test_generating_variable_in_local_scopes(self): + code = dedent("""\ + def f(): + c = 1 + c = b + """) + self.mod.write(code) + changes = self._get_generate(code.index("b")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + def f(): + c = 1 + b = None + c = b + """), + self.mod.read(), + ) + + +def test_generating_variable_in_other_modules(self): + code = dedent("""\ + import mod2 + c = mod2.b + """) + self.mod.write(code) + generator = self._get_generate(code.index("b")) + self.project.do(generator.get_changes()) + self.assertEqual((self.mod2, 1), generator.get_location()) + self.assertEqual("b = None\n", self.mod2.read()) + + +def test_generating_variable_in_classes(self): + code = dedent("""\ + class C(object): + def f(self): + pass + c = C() + a_var = c.attr""") + self.mod.write(code) + changes = self._get_generate(code.index("attr")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + class C(object): + def f(self): + pass + + attr = None + c = C() + a_var = c.attr"""), + self.mod.read(), + ) + + +def test_generating_variable_in_classes_removing_pass(self): + code = dedent("""\ + class C(object): + pass + c = C() + a_var = c.attr""") + self.mod.write(code) + changes = self._get_generate(code.index("attr")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + class C(object): + + attr = None + c = C() + a_var = c.attr"""), + self.mod.read(), + ) + + +def _get_defining_class_scope(self): + defining_scope = self._get_defining_scope() + if defining_scope.get_kind() == "Function": + defining_scope = defining_scope.parent + return defining_scope + + +def test_generating_variable_in_packages(self): + code = "import pkg\na = pkg.a\n" + self.mod.write(code) + generator = self._get_generate(code.rindex("a")) + self.project.do(generator.get_changes()) + init = self.pkg.get_child("__init__.py") + self.assertEqual((init, 1), generator.get_location()) + self.assertEqual("a = None\n", init.read()) + + +def test_generating_classes(self): + code = "c = C()\n" + self.mod.write(code) + changes = self._get_generate_class(code.index("C")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + class C(object): + pass + + + c = C() + """), + self.mod.read(), + ) + + +def test_generating_classes_in_other_module(self): + code = "c = C()\n" + self.mod.write(code) + changes = self._get_generate_class(code.index("C"), self.mod2).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + class C(object): + pass + """), + self.mod2.read(), + ) + self.assertEqual( + dedent("""\ + from mod2 import C + c = C() + """), + self.mod.read(), + ) + + +def test_generating_modules(self): + code = dedent("""\ + import pkg + pkg.mod + """) + self.mod.write(code) + generator = self._get_generate_module(code.rindex("mod")) + self.project.do(generator.get_changes()) + mod = self.pkg.get_child("mod.py") + self.assertEqual((mod, 1), generator.get_location()) + self.assertEqual( + dedent("""\ + import pkg.mod + pkg.mod + """), + self.mod.read(), + ) + + +def test_generating_packages(self): + code = dedent("""\ + import pkg + pkg.pkg2 + """) + self.mod.write(code) + generator = self._get_generate_package(code.rindex("pkg2")) + self.project.do(generator.get_changes()) + pkg2 = self.pkg.get_child("pkg2") + init = pkg2.get_child("__init__.py") + self.assertEqual((init, 1), generator.get_location()) + self.assertEqual( + dedent("""\ + import pkg.pkg2 + pkg.pkg2 + """), + self.mod.read(), + ) + + +def test_generating_function(self): + code = "a_func()\n" + self.mod.write(code) + changes = self._get_generate_function(code.index("a_func")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + def a_func(): + pass + + + a_func() + """), + self.mod.read(), + ) + + +def test_generating_modules_with_empty_primary(self): + code = "mod\n" + self.mod.write(code) + generator = self._get_generate_module(code.rindex("mod")) + self.project.do(generator.get_changes()) + mod = self.project.root.get_child("mod.py") + self.assertEqual((mod, 1), generator.get_location()) + self.assertEqual("import mod\nmod\n", self.mod.read()) + + +def test_generating_variable_already_exists(self): + code = dedent("""\ + b = 1 + c = b + """) + self.mod.write(code) + with self.assertRaises(exceptions.RefactoringError): + self._get_generate(code.index("b")).get_changes() + + +def test_generating_variable_primary_cannot_be_determined(self): + code = "c = can_not_be_found.b\n" + self.mod.write(code) + with self.assertRaises(exceptions.RefactoringError): + self._get_generate(code.rindex("b")).get_changes() + + +def test_generating_modules_when_already_exists(self): + code = "mod2\n" + self.mod.write(code) + generator = self._get_generate_module(code.rindex("mod")) + with self.assertRaises(exceptions.RefactoringError): + self.project.do(generator.get_changes()) + + +def _get_defining_scope(self): + pymodule, line = self.pyname.get_definition_location() + return pymodule.get_scope().get_inner_scope_for_line(line) + + +def test_generating_static_methods(self): + code = dedent("""\ + class C(object): + pass + C.a_func() + """) + self.mod.write(code) + changes = self._get_generate_function(code.index("a_func")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + class C(object): + + @staticmethod + def a_func(): + pass + C.a_func() + """), + self.mod.read(), + ) + + +def test_generating_methods(self): + code = dedent("""\ + class C(object): + pass + c = C() + c.a_func() + """) + self.mod.write(code) + changes = self._get_generate_function(code.index("a_func")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + class C(object): + + def a_func(self): + pass + c = C() + c.a_func() + """), + self.mod.read(), + ) + + +def test_generating_constructors(self): + code = dedent("""\ + class C(object): + pass + c = C() + """) + self.mod.write(code) + changes = self._get_generate_function(code.rindex("C")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + class C(object): + + def __init__(self): + pass + c = C() + """), + self.mod.read(), + ) + + +def test_generating_calls(self): + code = dedent("""\ + class C(object): + pass + c = C() + c() + """) + self.mod.write(code) + changes = self._get_generate_function(code.rindex("c")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + class C(object): + + def __call__(self): + pass + c = C() + c() + """), + self.mod.read(), + ) + + +def test_generating_calls_in_other_modules(self): + self.mod2.write(dedent("""\ + class C(object): + pass + """)) + code = dedent("""\ + import mod2 + c = mod2.C() + c() + """) + self.mod.write(code) + changes = self._get_generate_function(code.rindex("c")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + class C(object): + + def __call__(self): + pass + """), + self.mod2.read(), + ) + + +def test_generating_function_handling_arguments(self): + code = "a_func(1)\n" + self.mod.write(code) + changes = self._get_generate_function(code.index("a_func")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + def a_func(arg0): + pass + + + a_func(1) + """), + self.mod.read(), + ) + + +def test_generating_function_handling_keyword_xarguments(self): + code = "a_func(p=1)\n" + self.mod.write(code) + changes = self._get_generate_function(code.index("a_func")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + def a_func(p): + pass + + + a_func(p=1) + """), + self.mod.read(), + ) + + +def test_generating_function_handling_arguments_better_naming(self): + code = dedent("""\ + a_var = 1 + a_func(a_var) + """) + self.mod.write(code) + changes = self._get_generate_function(code.index("a_func")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + a_var = 1 + def a_func(a_var): + pass + + + a_func(a_var) + """), + self.mod.read(), + ) + + +def test_generating_variable_in_other_modules2(self): + self.mod2.write("\n\n\nprint(1)\n") + code = dedent("""\ + import mod2 + c = mod2.b + """) + self.mod.write(code) + generator = self._get_generate(code.index("b")) + self.project.do(generator.get_changes()) + self.assertEqual((self.mod2, 5), generator.get_location()) + self.assertEqual( + dedent("""\ + + + + print(1) + + + b = None + """), + self.mod2.read(), + ) + + +def test_generating_function_in_a_suite(self): + code = dedent("""\ + if True: + a_func() + """) + self.mod.write(code) + changes = self._get_generate_function(code.index("a_func")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + def a_func(): + pass + + + if True: + a_func() + """), + self.mod.read(), + ) + + +def _change_holding_module(self, changes, renamer, getter, setter): + pymodule = self.project.get_pymodule(self.resource) + class_scope = self._get_defining_class_scope() + defining_object = self._get_defining_scope().pyobject + start, end = sourceutils.get_body_region(defining_object) + + new_source = renamer.get_changed_module( + pymodule=pymodule, skip_start=start, skip_end=end + ) + if new_source is not None: + pymodule = libutils.get_string_module( + self.project, new_source, self.resource + ) + class_scope = pymodule.get_scope().get_inner_scope_for_line( + class_scope.get_start() + ) + indents = sourceutils.get_indent(self.project) * " " + getter = "def {}(self):\n{}return self.{}".format(getter, indents, self.name) + setter = "def {}(self, value):\n{}self.{} = value".format( + setter, + indents, + self.name, + ) + new_source = sourceutils.add_methods(pymodule, class_scope, [getter, setter]) + return new_source + + + +def test_generating_function_in_a_suite_in_a_function(self): + code = dedent("""\ + def f(): + a = 1 + if 1: + g() + """) + self.mod.write(code) + changes = self._get_generate_function(code.index("g()")).get_changes() + self.project.do(changes) + self.assertEqual( + dedent("""\ + def f(): + a = 1 + def g(): + pass + if 1: + g() + """), + self.mod.read(), + ) + + +def test_create_generate_class_with_goal_resource(self): + code = "c = C()\n" + self.mod.write(code) + + result = generate.create_generate( + "class", self.project, self.mod, code.index("C"), goal_resource=self.mod2 + ) + + self.assertTrue(isinstance(result, generate.GenerateClass)) + self.assertEqual(result.goal_resource, self.mod2) + + +def test_create_generate_class_without_goal_resource(self): + code = "c = C()\n" + self.mod.write(code) + + result = generate.create_generate( + "class", self.project, self.mod, code.index("C") + ) + + self.assertTrue(isinstance(result, generate.GenerateClass)) + self.assertIsNone(result.goal_resource) + +@path C:/Repos/ekr-rope/ropetest/contrib/ +import sys + +import unittest + +import ropetest.contrib.autoimporttest +import ropetest.contrib.changestacktest +import ropetest.contrib.codeassisttest +import ropetest.contrib.finderrorstest +import ropetest.contrib.findittest +import ropetest.contrib.fixmodnamestest +import ropetest.contrib.generatetest + + +@others +if __name__ == "__main__": + runner = unittest.TextTestRunner() + result = runner.run(suite()) + sys.exit(not result.wasSuccessful()) +@language python +@tabwidth -4 + +def suite(): + result = unittest.TestSuite() + result.addTests(unittest.makeSuite(ropetest.contrib.generatetest.GenerateTest)) + result.addTests(ropetest.contrib.codeassisttest.suite()) + result.addTests(ropetest.contrib.autoimporttest.suite()) + result.addTests(ropetest.contrib.findittest.suite()) + result.addTests( + unittest.makeSuite(ropetest.contrib.changestacktest.ChangeStackTest) + ) + result.addTests( + unittest.makeSuite(ropetest.contrib.fixmodnamestest.FixModuleNamesTest) + ) + result.addTests(unittest.makeSuite(ropetest.contrib.finderrorstest.FindErrorsTest)) + return result + + + + +@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ +import pathlib + +import pytest + +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +@pytest.fixture +def project(): + project = testutils.sample_project() + yield project + testutils.remove_project(project) + + + +@pytest.fixture +def mod1(project): + mod1 = testutils.create_module(project, "mod1") + yield mod1 + + + +@pytest.fixture +def mod1_path(mod1): + yield pathlib.Path(mod1.real_path) + + + +class GetterSetterRenameInModule: + @others + +@pytest.fixture +def project_path(project): + yield pathlib.Path(project.address) + + + +@pytest.fixture +def typing_path(): + import typing + + yield pathlib.Path(typing.__file__) + + + +@pytest.fixture +def build_env_path(): + from build import env + + yield pathlib.Path(env.__file__) + + + +@pytest.fixture +def build_path(): + import build + + # Uses __init__.py so we need the parent + + yield pathlib.Path(build.__file__).parent + + + +@pytest.fixture +def compiled_lib(): + import _sqlite3 + + yield "_sqlite3", pathlib.Path(_sqlite3.__file__) + +@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ +from unittest import TestCase + +from rope.contrib.autoimport import models + + +@others +@language python +@tabwidth -4 + +class QueryTest(TestCase): + def test_select_non_existent_column(self): + with self.assertRaisesRegex(ValueError, """Unknown column names passed: {['"]doesnotexist['"]}"""): + models.Name.objects.select('doesnotexist')._query + + + +class NameModelTest(TestCase): + @others + +def test_name_objects(self): + self.assertEqual( + models.Name.objects.select_star()._query, + "SELECT * FROM names", + ) + + +def test_query_strings(self): + with self.subTest("objects"): + self.assertEqual( + models.Name.objects.select_star()._query, + 'SELECT * FROM names', + ) + + with self.subTest("search_submodule_like"): + self.assertEqual( + models.Name.search_submodule_like.select_star()._query, + 'SELECT * FROM names WHERE module LIKE ("%." || ?)', + ) + + with self.subTest("search_module_like"): + self.assertEqual( + models.Name.search_module_like.select_star()._query, + 'SELECT * FROM names WHERE module LIKE (?)', + ) + + with self.subTest("import_assist"): + self.assertEqual( + models.Name.import_assist.select_star()._query, + "SELECT * FROM names WHERE name LIKE (? || '%')", + ) + + with self.subTest("search_by_name_like"): + self.assertEqual( + models.Name.search_by_name_like.select_star()._query, + 'SELECT * FROM names WHERE name LIKE (?)', + ) + + with self.subTest("delete_by_module_name"): + self.assertEqual( + models.Name.delete_by_module_name._query, + 'DELETE FROM names WHERE module = ?', + ) + + + +def __init__(self, project, name, pyname, getter, setter): + self.project = project + self.name = name + self.finder = occurrences.create_finder(project, name, pyname) + self.getter = getter + self.setter = setter + + +class PackageModelTest(TestCase): + @others + +def test_query_strings(self): + with self.subTest("objects"): + self.assertEqual( + models.Package.objects.select_star()._query, + 'SELECT * FROM packages', + ) + + with self.subTest("delete_by_package_name"): + self.assertEqual( + models.Package.delete_by_package_name._query, + 'DELETE FROM packages WHERE package = ?', + ) + +@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ +from rope.contrib.autoimport import parse +from rope.contrib.autoimport.defs import Name, NameType, PartialName, Source + + +@others +@language python +@tabwidth -4 + +def test_typing_names(typing_path): + names = list(parse.get_names_from_file(typing_path)) + assert PartialName("Text", NameType.Variable) in names + + + +def test_find_sys(): + names = list(parse.get_names_from_compiled("sys", Source.BUILTIN)) + assert Name("exit", "sys", "sys", Source.BUILTIN, NameType.Function) in names + + + +def test_find_underlined(): + names = list(parse.get_names_from_compiled("os", Source.BUILTIN, underlined=True)) + assert Name("_exit", "os", "os", Source.BUILTIN, NameType.Function) in names + +@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ +"""Tests for autoimport utility functions, written in pytest""" + +from sys import platform + +import pytest + +from rope.contrib.autoimport import utils +from rope.contrib.autoimport.defs import Package, PackageType, Source + + +@others +@language python +@tabwidth -4 + +def test_get_package_source(mod1_path, project): + assert utils.get_package_source(mod1_path, project, "") == Source.PROJECT + + + +def test_get_package_source_not_project(mod1_path): + assert utils.get_package_source(mod1_path, None, "") == Source.UNKNOWN + + + +def test_get_package_source_pytest(build_path): + # pytest is not installed as part of the standard library + # but should be installed into site_packages, + # so it should return Source.SITE_PACKAGE + assert utils.get_package_source(build_path, None, "build") == Source.SITE_PACKAGE + + + +class _Generate: + @others + +def get_changed_module( + self, resource=None, pymodule=None, skip_start=0, skip_end=0 +): + change_finder = _FindChangesForModule( + self, resource, pymodule, skip_start, skip_end + ) + return change_finder.get_changed_module() + + + +def test_get_package_source_typing(typing_path): + + assert utils.get_package_source(typing_path, None, "typing") == Source.STANDARD + + + +def test_get_modname_project_no_add(mod1_path, project_path): + + assert utils.get_modname_from_path(mod1_path, project_path, False) == "mod1" + + + +def test_get_modname_single_file(typing_path): + + assert utils.get_modname_from_path(typing_path, typing_path) == "typing" + + + +def test_get_modname_folder(build_path, build_env_path): + + assert utils.get_modname_from_path(build_env_path, build_path) == "build.env" + + + +def test_get_package_tuple_sample(project_path): + assert Package( + "sample_project", Source.UNKNOWN, project_path, PackageType.STANDARD + ) == utils.get_package_tuple(project_path) + + + +def test_get_package_tuple_typing(typing_path): + + assert Package( + "typing", Source.STANDARD, typing_path, PackageType.SINGLE_FILE + ) == utils.get_package_tuple(typing_path) + + + +def test_get_package_tuple_compiled(compiled_lib): + lib_name, lib_path = compiled_lib + assert Package( + lib_name, Source.STANDARD, lib_path, PackageType.COMPILED + ) == utils.get_package_tuple(lib_path) + + +@path C:/Repos/ekr-rope/ropetest/refactor/ +from textwrap import dedent + +import unittest + +import rope.base.exceptions +from rope.refactor import change_signature +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class ChangeSignatureTest(unittest.TestCase): + @others + +class _FindChangesForModule: + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_normalizing_parameters_for_trivial_case(self): + code = dedent("""\ + def a_func(): + pass + a_func()""") + self.mod.write(code) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) + self.assertEqual(code, self.mod.read()) + + +def test_normalizing_parameters_for_trivial_case2(self): + code = dedent("""\ + def a_func(param): + pass + a_func(2)""") + self.mod.write(code) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) + self.assertEqual(code, self.mod.read()) + + +def test_normalizing_parameters_for_unneeded_keyword(self): + self.mod.write(dedent("""\ + def a_func(param): + pass + a_func(param=1)""")) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) + self.assertEqual( + dedent("""\ + def a_func(param): + pass + a_func(1)"""), + self.mod.read(), + ) + + +def test_normalizing_parameters_for_unneeded_keyword_for_methods(self): + code = dedent("""\ + class A(object): + def a_func(self, param): + pass + a_var = A() + a_var.a_func(param=1) + """) + self.mod.write(code) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) + expected = dedent("""\ + class A(object): + def a_func(self, param): + pass + a_var = A() + a_var.a_func(1) + """) + self.assertEqual(expected, self.mod.read()) + + +def test_normalizing_parameters_for_unsorted_keyword(self): + self.mod.write(dedent("""\ + def a_func(p1, p2): + pass + a_func(p2=2, p1=1)""")) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) + self.assertEqual( + dedent("""\ + def a_func(p1, p2): + pass + a_func(1, 2)"""), + self.mod.read(), + ) + + +def test_raising_exceptions_for_non_functions(self): + self.mod.write("a_var = 10") + with self.assertRaises(rope.base.exceptions.RefactoringError): + change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_var") + 1 + ) + + +def test_normalizing_parameters_for_args_parameter(self): + self.mod.write(dedent("""\ + def a_func(*arg): + pass + a_func(1, 2) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) + self.assertEqual( + dedent("""\ + def a_func(*arg): + pass + a_func(1, 2) + """), + self.mod.read(), + ) + + +def test_normalizing_parameters_for_args_parameter_and_keywords(self): + self.mod.write(dedent("""\ + def a_func(param, *args): + pass + a_func(*[1, 2, 3]) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) + self.assertEqual( + dedent("""\ + def a_func(param, *args): + pass + a_func(*[1, 2, 3]) + """), + self.mod.read(), + ) + + +def __init__(self, finder, resource, pymodule, skip_start, skip_end): + self.project = finder.project + self.finder = finder.finder + self.getter = finder.getter + self.setter = finder.setter + self.resource = resource + self.pymodule = pymodule + self.last_modified = 0 + self.last_set = None + self.set_index = None + self.skip_start = skip_start + self.skip_end = skip_end + + +def test_normalizing_functions_from_other_modules(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + def a_func(param): + pass + """)) + self.mod.write(dedent("""\ + import mod1 + mod1.a_func(param=1) + """)) + signature = change_signature.ChangeSignature( + self.project, mod1, mod1.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) + self.assertEqual( + dedent("""\ + import mod1 + mod1.a_func(1) + """), + self.mod.read(), + ) + + +def test_normalizing_parameters_for_keyword_parameters(self): + self.mod.write(dedent("""\ + def a_func(p1, **kwds): + pass + a_func(p2=2, p1=1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) + self.assertEqual( + dedent("""\ + def a_func(p1, **kwds): + pass + a_func(1, p2=2) + """), + self.mod.read(), + ) + + +def test_removing_arguments(self): + self.mod.write(dedent("""\ + def a_func(p1): + pass + a_func(1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentRemover(0)])) + self.assertEqual( + dedent("""\ + def a_func(): + pass + a_func() + """), + self.mod.read(), + ) + + +def test_removing_arguments_with_multiple_args(self): + self.mod.write(dedent("""\ + def a_func(p1, p2): + pass + a_func(1, 2) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentRemover(0)])) + self.assertEqual( + dedent("""\ + def a_func(p2): + pass + a_func(2) + """), + self.mod.read(), + ) + + +def test_removing_arguments_passed_as_keywords(self): + self.mod.write(dedent("""\ + def a_func(p1): + pass + a_func(p1=1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentRemover(0)])) + self.assertEqual( + dedent("""\ + def a_func(): + pass + a_func() + """), + self.mod.read(), + ) + + +def test_removing_arguments_with_defaults(self): + self.mod.write(dedent("""\ + def a_func(p1=1): + pass + a_func(1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentRemover(0)])) + self.assertEqual( + dedent("""\ + def a_func(): + pass + a_func() + """), + self.mod.read(), + ) + + +def test_removing_arguments_star_args(self): + self.mod.write(dedent("""\ + def a_func(p1, *args): + pass + a_func(1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentRemover(1)])) + self.assertEqual( + dedent("""\ + def a_func(p1): + pass + a_func(1) + """), + self.mod.read(), + ) + + +def test_removing_keyword_arg(self): + self.mod.write(dedent("""\ + def a_func(p1, **kwds): + pass + a_func(1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentRemover(1)])) + self.assertEqual( + dedent("""\ + def a_func(p1): + pass + a_func(1) + """), + self.mod.read(), + ) + + +def test_removing_keyword_arg2(self): + self.mod.write(dedent("""\ + def a_func(p1, *args, **kwds): + pass + a_func(1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentRemover(2)])) + self.assertEqual( + dedent("""\ + def a_func(p1, *args): + pass + a_func(1) + """), + self.mod.read(), + ) + + +# XXX: What to do here for star args? +@unittest.skip("How to deal with start args?") +def xxx_test_removing_arguments_star_args2(self): + self.mod.write(dedent("""\ + def a_func(p1, *args): + pass + a_func(2, 3, p1=1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentRemover(1)])) + self.assertEqual( + dedent("""\ + def a_func(p1): + pass + a_func(p1=1) + """), + self.mod.read(), + ) + + +def get_changed_module(self): + result = [] + for occurrence in self.finder.find_occurrences(self.resource, self.pymodule): + start, end = occurrence.get_word_range() + if self.skip_start <= start < self.skip_end: + continue + self._manage_writes(start, result) + result.append(self.source[self.last_modified : start]) + if self._is_assigned_in_a_tuple_assignment(occurrence): + raise exceptions.RefactoringError( + "Cannot handle tuple assignments in encapsulate field." + ) + if occurrence.is_written(): + assignment_type = self.worder.get_assignment_type(start) + if assignment_type == "=": + result.append(self.setter + "(") + else: + var_name = ( + self.source[occurrence.get_primary_range()[0] : start] + + self.getter + + "()" + ) + result.append( + self.setter + "(" + var_name + " %s " % assignment_type[:-1] + ) + current_line = self.lines.get_line_number(start) + start_line, end_line = self.pymodule.logical_lines.logical_line_in( + current_line + ) + self.last_set = self.lines.get_line_end(end_line) + end = self.source.index("=", end) + 1 + self.set_index = len(result) + else: + result.append(self.getter + "()") + self.last_modified = end + if self.last_modified != 0: + self._manage_writes(len(self.source), result) + result.append(self.source[self.last_modified :]) + return "".join(result) + return None + + +# XXX: What to do here for star args? +def xxx_test_removing_arguments_star_args3(self): + self.mod.write(dedent("""\ + def a_func(p1, *args): + pass + a_func(*[1, 2, 3]) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentRemover(1)])) + self.assertEqual( + dedent("""\ + def a_func(p1): + pass + a_func(*[1, 2, 3]) + """), + self.mod.read(), + ) + + +def test_adding_arguments_for_normal_args_changing_definition(self): + self.mod.write(dedent("""\ + def a_func(): + pass + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do( + signature.get_changes([change_signature.ArgumentAdder(0, "p1")]) + ) + self.assertEqual( + dedent("""\ + def a_func(p1): + pass + """), + self.mod.read(), + ) + + +def test_adding_arguments_for_normal_args_with_defaults(self): + self.mod.write(dedent("""\ + def a_func(): + pass + a_func() + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + adder = change_signature.ArgumentAdder(0, "p1", "None") + self.project.do(signature.get_changes([adder])) + self.assertEqual( + dedent("""\ + def a_func(p1=None): + pass + a_func() + """), + self.mod.read(), + ) + + +def test_adding_arguments_for_normal_args_changing_calls(self): + self.mod.write(dedent("""\ + def a_func(): + pass + a_func() + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + adder = change_signature.ArgumentAdder(0, "p1", "None", "1") + self.project.do(signature.get_changes([adder])) + self.assertEqual( + dedent("""\ + def a_func(p1=None): + pass + a_func(1) + """), + self.mod.read(), + ) + + +def test_adding_arguments_for_norm_args_chang_calls_with_kwords(self): + self.mod.write(dedent("""\ + def a_func(p1=0): + pass + a_func() + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + adder = change_signature.ArgumentAdder(1, "p2", "0", "1") + self.project.do(signature.get_changes([adder])) + self.assertEqual( + dedent("""\ + def a_func(p1=0, p2=0): + pass + a_func(p2=1) + """), + self.mod.read(), + ) + + +def test_adding_arguments_for_norm_args_chang_calls_with_no_value(self): + self.mod.write(dedent("""\ + def a_func(p2=0): + pass + a_func(1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + adder = change_signature.ArgumentAdder(0, "p1", "0", None) + self.project.do(signature.get_changes([adder])) + self.assertEqual( + dedent("""\ + def a_func(p1=0, p2=0): + pass + a_func(p2=1) + """), + self.mod.read(), + ) + + +def test_adding_duplicate_parameter_and_raising_exceptions(self): + self.mod.write(dedent("""\ + def a_func(p1): + pass + """)) + with self.assertRaises(rope.base.exceptions.RefactoringError): + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do( + signature.get_changes([change_signature.ArgumentAdder(1, "p1")]) + ) + + +def test_inlining_default_arguments(self): + self.mod.write(dedent("""\ + def a_func(p1=0): + pass + a_func() + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do( + signature.get_changes([change_signature.ArgumentDefaultInliner(0)]) + ) + self.assertEqual( + dedent("""\ + def a_func(p1=0): + pass + a_func(0) + """), + self.mod.read(), + ) + + +def test_inlining_default_arguments2(self): + self.mod.write(dedent("""\ + def a_func(p1=0): + pass + a_func(1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do( + signature.get_changes([change_signature.ArgumentDefaultInliner(0)]) + ) + self.assertEqual( + dedent("""\ + def a_func(p1=0): + pass + a_func(1) + """), + self.mod.read(), + ) + + +def test_preserving_args_and_keywords_order(self): + self.mod.write(dedent("""\ + def a_func(*args, **kwds): + pass + a_func(3, 1, 2, a=1, c=3, b=2) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) + self.assertEqual( + dedent("""\ + def a_func(*args, **kwds): + pass + a_func(3, 1, 2, a=1, c=3, b=2) + """), + self.mod.read(), + ) + + +def _manage_writes(self, offset, result): + if self.last_set is not None and self.last_set <= offset: + result.append(self.source[self.last_modified : self.last_set]) + set_value = "".join(result[self.set_index :]).strip() + del result[self.set_index :] + result.append(set_value + ")") + self.last_modified = self.last_set + self.last_set = None + + +def test_change_order_for_only_one_parameter(self): + self.mod.write(dedent("""\ + def a_func(p1): + pass + a_func(1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do( + signature.get_changes([change_signature.ArgumentReorderer([0])]) + ) + self.assertEqual( + dedent("""\ + def a_func(p1): + pass + a_func(1) + """), + self.mod.read(), + ) + + +def test_change_order_for_two_parameter(self): + self.mod.write(dedent("""\ + def a_func(p1, p2): + pass + a_func(1, 2) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do( + signature.get_changes([change_signature.ArgumentReorderer([1, 0])]) + ) + self.assertEqual( + dedent("""\ + def a_func(p2, p1): + pass + a_func(2, 1) + """), + self.mod.read(), + ) + + +def test_reordering_multi_line_function_headers(self): + self.mod.write(dedent("""\ + def a_func(p1, + p2): + pass + a_func(1, 2) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do( + signature.get_changes([change_signature.ArgumentReorderer([1, 0])]) + ) + self.assertEqual( + dedent("""\ + def a_func(p2, p1): + pass + a_func(2, 1) + """), + self.mod.read(), + ) + + +def test_changing_order_with_static_params(self): + self.mod.write(dedent("""\ + def a_func(p1, p2=0, p3=0): + pass + a_func(1, 2) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do( + signature.get_changes([change_signature.ArgumentReorderer([0, 2, 1])]) + ) + self.assertEqual( + dedent("""\ + def a_func(p1, p3=0, p2=0): + pass + a_func(1, p2=2) + """), + self.mod.read(), + ) + + +def test_doing_multiple_changes(self): + changers = [] + self.mod.write(dedent("""\ + def a_func(p1): + pass + a_func(1) + """)) + changers.append(change_signature.ArgumentRemover(0)) + changers.append(change_signature.ArgumentAdder(0, "p2", None, None)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + signature.get_changes(changers).do() + self.assertEqual( + dedent("""\ + def a_func(p2): + pass + a_func() + """), + self.mod.read(), + ) + + +def test_doing_multiple_changes2(self): + changers = [] + self.mod.write(dedent("""\ + def a_func(p1, p2): + pass + a_func(p2=2) + """)) + changers.append(change_signature.ArgumentAdder(2, "p3", None, "3")) + changers.append(change_signature.ArgumentReorderer([1, 0, 2])) + changers.append(change_signature.ArgumentRemover(1)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + signature.get_changes(changers).do() + self.assertEqual( + dedent("""\ + def a_func(p2, p3): + pass + a_func(2, 3) + """), + self.mod.read(), + ) + + +def test_changing_signature_in_subclasses(self): + self.mod.write(dedent("""\ + class A(object): + def a_method(self): + pass + class B(A): + def a_method(self): + pass + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_method") + 1 + ) + signature.get_changes( + [change_signature.ArgumentAdder(1, "p1")], in_hierarchy=True + ).do() + self.assertEqual( + dedent("""\ + class A(object): + def a_method(self, p1): + pass + class B(A): + def a_method(self, p1): + pass + """), + self.mod.read(), + ) + + +def test_differentiating_class_accesses_from_instance_accesses(self): + self.mod.write(dedent("""\ + class A(object): + def a_func(self, param): + pass + a_var = A() + A.a_func(a_var, param=1)""")) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("a_func") + 1 + ) + self.project.do(signature.get_changes([change_signature.ArgumentRemover(1)])) + self.assertEqual( + dedent("""\ + class A(object): + def a_func(self): + pass + a_var = A() + A.a_func(a_var)"""), + self.mod.read(), + ) + + +def test_changing_signature_for_constructors(self): + self.mod.write(dedent("""\ + class C(object): + def __init__(self, p): + pass + c = C(1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("C") + 1 + ) + signature.get_changes([change_signature.ArgumentRemover(1)]).do() + self.assertEqual( + dedent("""\ + class C(object): + def __init__(self): + pass + c = C() + """), + self.mod.read(), + ) + + +def test_changing_signature_for_constructors2(self): + self.mod.write(dedent("""\ + class C(object): + def __init__(self, p): + pass + c = C(1) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("__init__") + 1 + ) + signature.get_changes([change_signature.ArgumentRemover(1)]).do() + self.assertEqual( + dedent("""\ + class C(object): + def __init__(self): + pass + c = C() + """), + self.mod.read(), + ) + + +def _is_assigned_in_a_tuple_assignment(self, occurrence): + offset = occurrence.get_word_range()[0] + return self.worder.is_assigned_in_a_tuple_assignment(offset) + + +def test_changing_signature_for_constructors_when_using_super(self): + self.mod.write(dedent("""\ + class A(object): + def __init__(self, p): + pass + class B(A): + def __init__(self, p): + super(B, self).__init__(p) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().index("__init__") + 1 + ) + signature.get_changes([change_signature.ArgumentRemover(1)]).do() + self.assertEqual( + dedent("""\ + class A(object): + def __init__(self): + pass + class B(A): + def __init__(self, p): + super(B, self).__init__() + """), + self.mod.read(), + ) + + +def test_redordering_arguments_reported_by_mft(self): + self.mod.write(dedent("""\ + def f(a, b, c): + pass + f(1, 2, 3) + """)) + signature = change_signature.ChangeSignature( + self.project, self.mod, self.mod.read().rindex("f") + ) + signature.get_changes([change_signature.ArgumentReorderer([1, 2, 0])]).do() + self.assertEqual( + dedent("""\ + def f(b, c, a): + pass + f(2, 3, 1) + """), + self.mod.read(), + ) + + +def test_resources_parameter(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write("def a_func(param):\n pass\n") + self.mod.write(dedent("""\ + import mod1 + mod1.a_func(1) + """)) + signature = change_signature.ChangeSignature( + self.project, mod1, mod1.read().index("a_func") + 1 + ) + signature.get_changes( + [change_signature.ArgumentRemover(0)], resources=[mod1] + ).do() + self.assertEqual( + dedent("""\ + import mod1 + mod1.a_func(1) + """), + self.mod.read(), + ) + self.assertEqual( + dedent("""\ + def a_func(): + pass + """), + mod1.read(), + ) + + +def test_reordering_and_automatic_defaults(self): + code = dedent("""\ + def f(p1, p2=2): + pass + f(1, 2) + """) + self.mod.write(code) + signature = change_signature.ChangeSignature( + self.project, self.mod, code.index("f(") + ) + reorder = change_signature.ArgumentReorderer([1, 0], autodef="1") + signature.get_changes([reorder]).do() + expected = dedent("""\ + def f(p2=2, p1=1): + pass + f(2, 1) + """) + self.assertEqual(expected, self.mod.read()) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +from textwrap import dedent + +import unittest + +import rope.base.codeanalyze +import rope.base.exceptions + +from rope.refactor import extract +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class ExtractMethodTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def do_extract_method(self, source_code, start, end, extracted, **kwds): + testmod = testutils.create_module(self.project, "testmod") + testmod.write(source_code) + extractor = extract.ExtractMethod(self.project, testmod, start, end) + self.project.do(extractor.get_changes(extracted, **kwds)) + return testmod.read() + + +def do_extract_variable(self, source_code, start, end, extracted, **kwds): + testmod = testutils.create_module(self.project, "testmod") + testmod.write(source_code) + extractor = extract.ExtractVariable(self.project, testmod, start, end) + self.project.do(extractor.get_changes(extracted, **kwds)) + return testmod.read() + + +@property +@utils.saveit +def source(self): + if self.resource is not None: + return self.resource.read() + else: + return self.pymodule.source_code + + +def _convert_line_range_to_offset(self, code, start, end): + lines = rope.base.codeanalyze.SourceLinesAdapter(code) + return lines.get_line_start(start), lines.get_line_end(end) + + +def test_simple_extract_function(self): + code = dedent("""\ + def a_func(): + print('one') + print('two') + """) + start, end = self._convert_line_range_to_offset(code, 2, 2) + refactored = self.do_extract_method(code, start, end, "extracted") + expected = dedent("""\ + def a_func(): + extracted() + print('two') + + def extracted(): + print('one') + """) + self.assertEqual(expected, refactored) + + +def test_simple_extract_function_one_line(self): + code = dedent("""\ + def a_func(): + resp = 'one' + print(resp) + """) + selected = "'one'" + start, end = code.index(selected), code.index(selected) + len(selected) + refactored = self.do_extract_method(code, start, end, "extracted") + expected = dedent("""\ + def a_func(): + resp = extracted() + print(resp) + + def extracted(): + return 'one' + """) + self.assertEqual(expected, refactored) + + +def test_extract_function_at_the_end_of_file(self): + code = dedent("""\ + def a_func(): + print('one')""") + start, end = self._convert_line_range_to_offset(code, 2, 2) + refactored = self.do_extract_method(code, start, end, "extracted") + expected = dedent("""\ + def a_func(): + extracted() + def extracted(): + print('one') + """) + self.assertEqual(expected, refactored) + + +def test_extract_function_after_scope(self): + code = dedent("""\ + def a_func(): + print('one') + print('two') + + print('hey') + """) + start, end = self._convert_line_range_to_offset(code, 2, 2) + refactored = self.do_extract_method(code, start, end, "extracted") + expected = dedent("""\ + def a_func(): + extracted() + print('two') + + def extracted(): + print('one') + + print('hey') + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for("3.5") +def test_extract_function_containing_dict_generalized_unpacking(self): + code = dedent("""\ + def a_func(dict1): + dict2 = {} + a_var = {a: b, **dict1, **dict2} + """) + start = code.index("{a") + end = code.index("2}") + len("2}") + refactored = self.do_extract_method(code, start, end, "extracted") + expected = dedent("""\ + def a_func(dict1): + dict2 = {} + a_var = extracted(dict1, dict2) + + def extracted(dict1, dict2): + return {a: b, **dict1, **dict2} + """) + self.assertEqual(expected, refactored) + + +def test_simple_extract_function_with_parameter(self): + code = dedent("""\ + def a_func(): + a_var = 10 + print(a_var) + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + a_var = 10 + new_func(a_var) + + def new_func(a_var): + print(a_var) + """) + self.assertEqual(expected, refactored) + + +def test_not_unread_variables_as_parameter(self): + code = dedent("""\ + def a_func(): + a_var = 10 + print('hey') + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + a_var = 10 + new_func() + + def new_func(): + print('hey') + """) + self.assertEqual(expected, refactored) + + +def test_simple_extract_function_with_two_parameter(self): + code = dedent("""\ + def a_func(): + a_var = 10 + another_var = 20 + third_var = a_var + another_var + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + a_var = 10 + another_var = 20 + new_func(a_var, another_var) + + def new_func(a_var, another_var): + third_var = a_var + another_var + """) + self.assertEqual(expected, refactored) + + +def test_simple_extract_function_with_return_value(self): + code = dedent("""\ + def a_func(): + a_var = 10 + print(a_var) + """) + start, end = self._convert_line_range_to_offset(code, 2, 2) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + a_var = new_func() + print(a_var) + + def new_func(): + a_var = 10 + return a_var + """) + self.assertEqual(expected, refactored) + + +@property +@utils.saveit +def lines(self): + if self.pymodule is None: + self.pymodule = self.project.get_pymodule(self.resource) + return self.pymodule.lines + + +def test_extract_function_with_multiple_return_values(self): + code = dedent("""\ + def a_func(): + a_var = 10 + another_var = 20 + third_var = a_var + another_var + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + a_var, another_var = new_func() + third_var = a_var + another_var + + def new_func(): + a_var = 10 + another_var = 20 + return a_var, another_var + """) + self.assertEqual(expected, refactored) + + +def test_simple_extract_method(self): + code = dedent("""\ + class AClass(object): + + def a_func(self): + print(1) + print(2) + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + class AClass(object): + + def a_func(self): + self.new_func() + print(2) + + def new_func(self): + print(1) + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_args_and_returns(self): + code = dedent("""\ + class AClass(object): + def a_func(self): + a_var = 10 + another_var = a_var * 3 + third_var = a_var + another_var + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + class AClass(object): + def a_func(self): + a_var = 10 + another_var = self.new_func(a_var) + third_var = a_var + another_var + + def new_func(self, a_var): + another_var = a_var * 3 + return another_var + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_self_as_argument(self): + code = dedent("""\ + class AClass(object): + def a_func(self): + print(self) + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + class AClass(object): + def a_func(self): + self.new_func() + + def new_func(self): + print(self) + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_no_self_as_argument(self): + code = dedent("""\ + class AClass(object): + def a_func(): + print(1) + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_extract_method_with_multiple_methods(self): + code = dedent("""\ + class AClass(object): + def a_func(self): + print(self) + + def another_func(self): + pass + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + class AClass(object): + def a_func(self): + self.new_func() + + def new_func(self): + print(self) + + def another_func(self): + pass + """) + self.assertEqual(expected, refactored) + + +def test_extract_function_with_function_returns(self): + code = dedent("""\ + def a_func(): + def inner_func(): + pass + inner_func() + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + inner_func = new_func() + inner_func() + + def new_func(): + def inner_func(): + pass + return inner_func + """) + self.assertEqual(expected, refactored) + + +def test_simple_extract_global_function(self): + code = dedent("""\ + print('one') + print('two') + print('three') + """) + start, end = self._convert_line_range_to_offset(code, 2, 2) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + print('one') + + def new_func(): + print('two') + + new_func() + print('three') + """) + self.assertEqual(expected, refactored) + + +def test_extract_global_function_inside_ifs(self): + code = dedent("""\ + if True: + a = 10 + """) + start, end = self._convert_line_range_to_offset(code, 2, 2) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + + def new_func(): + a = 10 + + if True: + new_func() + """) + self.assertEqual(expected, refactored) + + +def test_extract_function_while_inner_function_reads(self): + code = dedent("""\ + def a_func(): + a_var = 10 + def inner_func(): + print(a_var) + return inner_func + """) + start, end = self._convert_line_range_to_offset(code, 3, 4) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + a_var = 10 + inner_func = new_func(a_var) + return inner_func + + def new_func(a_var): + def inner_func(): + print(a_var) + return inner_func + """) + self.assertEqual(expected, refactored) + + +@property +@utils.saveit +def worder(self): + return worder.Worder(self.source) + +def test_extract_method_bad_range(self): + code = dedent("""\ + def a_func(): + pass + a_var = 10 + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_extract_method_bad_range2(self): + code = dedent("""\ + class AClass(object): + pass + """) + start, end = self._convert_line_range_to_offset(code, 1, 1) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_extract_method_containing_return(self): + code = dedent("""\ + def a_func(arg): + if arg: + return arg * 2 + return 1""") + start, end = self._convert_line_range_to_offset(code, 2, 4) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_extract_method_containing_yield(self): + code = dedent("""\ + def a_func(arg): + yield arg * 2 + """) + start, end = self._convert_line_range_to_offset(code, 2, 2) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_extract_method_containing_uncomplete_lines(self): + code = dedent("""\ + a_var = 20 + another_var = 30 + """) + start = code.index("20") + end = code.index("30") + 2 + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_extract_method_containing_uncomplete_lines2(self): + code = dedent("""\ + a_var = 20 + another_var = 30 + """) + start = code.index("20") + end = code.index("another") + 5 + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_extract_function_and_argument_as_paramenter(self): + code = dedent("""\ + def a_func(arg): + print(arg) + """) + start, end = self._convert_line_range_to_offset(code, 2, 2) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(arg): + new_func(arg) + + def new_func(arg): + print(arg) + """) + self.assertEqual(expected, refactored) + + +def test_extract_function_and_end_as_the_start_of_a_line(self): + code = dedent("""\ + print("hey") + if True: + pass + """) + start = 0 + end = code.index("\n") + 1 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + + def new_func(): + print("hey") + + new_func() + if True: + pass + """) + self.assertEqual(expected, refactored) + + +def test_extract_function_and_indented_blocks(self): + code = dedent("""\ + def a_func(arg): + if True: + if True: + print(arg) + """) + start, end = self._convert_line_range_to_offset(code, 3, 4) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(arg): + if True: + new_func(arg) + + def new_func(arg): + if True: + print(arg) + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_and_multi_line_headers(self): + code = dedent("""\ + def a_func( + arg): + print(arg) + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func( + arg): + new_func(arg) + + def new_func(arg): + print(arg) + """) + self.assertEqual(expected, refactored) + + +@path C:/Repos/ekr-rope/rope/refactor/ +import re +from contextlib import contextmanager +from itertools import chain + +from rope.base import ast, codeanalyze +from rope.base.change import ChangeSet, ChangeContents +from rope.base.exceptions import RefactoringError +from rope.base.utils.datastructures import OrderedSet +from rope.refactor import sourceutils, similarfinder, patchedast, suites, usefunction + + +@others +@language python +@tabwidth -4 + +def test_single_line_extract_function(self): + code = dedent("""\ + a_var = 10 + 20 + """) + start = code.index("10") + end = code.index("20") + 2 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + + def new_func(): + return 10 + 20 + + a_var = new_func() + """) + self.assertEqual(expected, refactored) + + +def test_single_line_extract_function2(self): + code = dedent("""\ + def a_func(): + a = 10 + b = a * 20 + """) + start = code.rindex("a") + end = code.index("20") + 2 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + a = 10 + b = new_func(a) + + def new_func(a): + return a * 20 + """) + self.assertEqual(expected, refactored) + + +def test_single_line_extract_method_and_logical_lines(self): + code = dedent("""\ + a_var = 10 +\\ + 20 + """) + start = code.index("10") + end = code.index("20") + 2 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + + def new_func(): + return 10 + 20 + + a_var = new_func() + """) + self.assertEqual(expected, refactored) + + +def test_single_line_extract_method_and_logical_lines2(self): + code = dedent("""\ + a_var = (10,\\ + 20) + """) + start = code.index("10") - 1 + end = code.index("20") + 3 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + + def new_func(): + return (10, 20) + + a_var = new_func() + """) + self.assertEqual(expected, refactored) + + +def test_single_line_extract_method_with_large_multiline_expression(self): + code = dedent("""\ + a_var = func( + { + "hello": 1, + "world": 2, + }, + blah=foo, + ) + """) + start = code.index("{") - 1 + end = code.index("}") + 1 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + + def new_func(): + return { + "hello": 1, + "world": 2, + } + + a_var = func( + new_func(), + blah=foo, + ) + """) + self.assertEqual(expected, refactored) + + +def test_single_line_extract_method(self): + code = dedent("""\ + class AClass(object): + + def a_func(self): + a = 10 + b = a * a + """) + start = code.rindex("=") + 2 + end = code.rindex("a") + 1 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + class AClass(object): + + def a_func(self): + a = 10 + b = self.new_func(a) + + def new_func(self, a): + return a * a + """) + self.assertEqual(expected, refactored) + + +def test_single_line_extract_function_if_condition(self): + code = dedent("""\ + if True: + pass + """) + start = code.index("True") + end = code.index("True") + 4 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + + def new_func(): + return True + + if new_func(): + pass + """) + self.assertEqual(expected, refactored) + + +def test_unneeded_params(self): + code = dedent("""\ + class A(object): + def a_func(self): + a_var = 10 + a_var += 2 + """) + start = code.rindex("2") + end = code.rindex("2") + 1 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + class A(object): + def a_func(self): + a_var = 10 + a_var += self.new_func() + + def new_func(self): + return 2 + """) + self.assertEqual(expected, refactored) + + +def test_breaks_and_continues_inside_loops(self): + code = dedent("""\ + def a_func(): + for i in range(10): + continue + """) + start = code.index("for") + end = len(code) - 1 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + new_func() + + def new_func(): + for i in range(10): + continue + """) + self.assertEqual(expected, refactored) + + +def test_breaks_and_continues_outside_loops(self): + code = dedent("""\ + def a_func(): + for i in range(10): + a = i + continue + """) + start = code.index("a = i") + end = len(code) - 1 + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def __init__(self, project, resource, offset, goal_resource=None): + self.project = project + self.resource = resource + self.goal_resource = goal_resource + self.info = self._generate_info(project, resource, offset) + self.name = self.info.get_name() + self._check_exceptional_conditions() + + +# Extract refactoring has lots of special cases. I tried to split it +# to smaller parts to make it more manageable: +# +# _ExtractInfo: holds information about the refactoring; it is passed +# to the parts that need to have information about the refactoring +# +# _ExtractCollector: merely saves all of the information necessary for +# performing the refactoring. +# +# _DefinitionLocationFinder: finds where to insert the definition. +# +# _ExceptionalConditionChecker: checks for exceptional conditions in +# which the refactoring cannot be applied. +# +# _ExtractMethodParts: generates the pieces of code (like definition) +# needed for performing extract method. +# +# _ExtractVariableParts: like _ExtractMethodParts for variables. +# +# _ExtractPerformer: Uses above classes to collect refactoring +# changes. +# +# There are a few more helper functions and classes used by above +# classes. +class _ExtractRefactoring: + + kind_prefixes = {} + + @others + +def test_for_loop_variable_scope(self): + code = dedent("""\ + def my_func(): + i = 0 + for dummy in range(10): + i += 1 + print(i) + """) + start, end = self._convert_line_range_to_offset(code, 4, 5) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def my_func(): + i = 0 + for dummy in range(10): + i = new_func(i) + + def new_func(i): + i += 1 + print(i) + return i + """) + self.assertEqual(expected, refactored) + + +def test_for_loop_variable_scope_read_then_write(self): + code = dedent("""\ + def my_func(): + i = 0 + for dummy in range(10): + a = i + 1 + i = a + 1 + """) + start, end = self._convert_line_range_to_offset(code, 4, 5) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def my_func(): + i = 0 + for dummy in range(10): + i = new_func(i) + + def new_func(i): + a = i + 1 + i = a + 1 + return i + """) + self.assertEqual(expected, refactored) + + +def test_for_loop_variable_scope_write_then_read(self): + code = dedent("""\ + def my_func(): + i = 0 + for dummy in range(10): + i = 'hello' + print(i) + """) + start, end = self._convert_line_range_to_offset(code, 4, 5) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def my_func(): + i = 0 + for dummy in range(10): + new_func() + + def new_func(): + i = 'hello' + print(i) + """) + self.assertEqual(expected, refactored) + + +def test_for_loop_variable_scope_write_only(self): + code = dedent("""\ + def my_func(): + i = 0 + for num in range(10): + i = 'hello' + num + print(i) + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def my_func(): + i = 0 + for num in range(10): + i = new_func(num) + print(i) + + def new_func(num): + i = 'hello' + num + return i + """) + self.assertEqual(expected, refactored) + + +def test_variable_writes_followed_by_variable_reads_after_extraction(self): + code = dedent("""\ + def a_func(): + a = 1 + a = 2 + b = a + """) + start = code.index("a = 1") + end = code.index("a = 2") - 1 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + new_func() + a = 2 + b = a + + def new_func(): + a = 1 + """) + self.assertEqual(expected, refactored) + + +def test_var_writes_followed_by_var_reads_inside_extraction(self): + code = dedent("""\ + def a_func(): + a = 1 + a = 2 + b = a + """) + start = code.index("a = 2") + end = len(code) - 1 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + a = 1 + new_func() + + def new_func(): + a = 2 + b = a + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable(self): + code = dedent("""\ + a_var = 10 + 20 + """) + start = code.index("10") + end = code.index("20") + 2 + refactored = self.do_extract_variable(code, start, end, "new_var") + expected = dedent("""\ + new_var = 10 + 20 + a_var = new_var + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.6") +def test_extract_variable_f_string(self): + code = dedent("""\ + foo(f"abc {a_var} def", 10) + """) + start = code.index('f"') + end = code.index('def"') + 4 + refactored = self.do_extract_variable(code, start, end, "new_var") + expected = dedent("""\ + new_var = f"abc {a_var} def" + foo(new_var, 10) + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable_multiple_lines(self): + code = dedent("""\ + a = 1 + b = 2 + """) + start = code.index("1") + end = code.index("1") + 1 + refactored = self.do_extract_variable(code, start, end, "c") + expected = dedent("""\ + c = 1 + a = c + b = 2 + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable_in_the_middle_of_statements(self): + code = dedent("""\ + a = 1 + 2 + """) + start = code.index("1") + end = code.index("1") + 1 + refactored = self.do_extract_variable(code, start, end, "c") + expected = dedent("""\ + c = 1 + a = c + 2 + """) + self.assertEqual(expected, refactored) + + +def __init__(self, project, resource, start_offset, end_offset, variable=False): + self.project = project + self.resource = resource + self.start_offset = self._fix_start(resource.read(), start_offset) + self.end_offset = self._fix_end(resource.read(), end_offset) + + +def test_extract_variable_for_a_tuple(self): + code = dedent("""\ + a = 1, 2 + """) + start = code.index("1") + end = code.index("2") + 1 + refactored = self.do_extract_variable(code, start, end, "c") + expected = dedent("""\ + c = 1, 2 + a = c + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable_for_a_string(self): + code = dedent("""\ + def a_func(): + a = "hey!" + """) + start = code.index('"') + end = code.rindex('"') + 1 + refactored = self.do_extract_variable(code, start, end, "c") + expected = dedent("""\ + def a_func(): + c = "hey!" + a = c + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable_inside_ifs(self): + code = dedent("""\ + if True: + a = 1 + 2 + """) + start = code.index("1") + end = code.rindex("2") + 1 + refactored = self.do_extract_variable(code, start, end, "b") + expected = dedent("""\ + if True: + b = 1 + 2 + a = b + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable_inside_ifs_and_logical_lines(self): + code = dedent("""\ + if True: + a = (3 + + (1 + 2)) + """) + start = code.index("1") + end = code.index("2") + 1 + refactored = self.do_extract_variable(code, start, end, "b") + expected = dedent("""\ + if True: + b = 1 + 2 + a = (3 + + (b)) + """) + self.assertEqual(expected, refactored) + + +# TODO: Handle when extracting a subexpression +def xxx_test_extract_variable_for_a_subexpression(self): + code = dedent("""\ + a = 3 + 1 + 2 + """) + start = code.index("1") + end = code.index("2") + 1 + refactored = self.do_extract_variable(code, start, end, "b") + expected = dedent("""\ + b = 1 + 2 + a = 3 + b + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable_starting_from_the_start_of_the_line(self): + code = dedent("""\ + a_dict = {1: 1} + a_dict.values().count(1) + """) + start = code.rindex("a_dict") + end = code.index("count") - 1 + refactored = self.do_extract_variable(code, start, end, "values") + expected = dedent("""\ + a_dict = {1: 1} + values = a_dict.values() + values.count(1) + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable_on_the_last_line_of_a_function(self): + code = dedent("""\ + def f(): + a_var = {} + a_var.keys() + """) + start = code.rindex("a_var") + end = code.index(".keys") + refactored = self.do_extract_variable(code, start, end, "new_var") + expected = dedent("""\ + def f(): + a_var = {} + new_var = a_var + new_var.keys() + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable_on_the_indented_function_statement(self): + code = dedent("""\ + def f(): + if True: + a_var = 1 + 2 + """) + start = code.index("1") + end = code.index("2") + 1 + refactored = self.do_extract_variable(code, start, end, "new_var") + expected = dedent("""\ + def f(): + if True: + new_var = 1 + 2 + a_var = new_var + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_on_the_last_line_of_a_function(self): + code = dedent("""\ + def f(): + a_var = {} + a_var.keys() + """) + start = code.rindex("a_var") + end = code.index(".keys") + refactored = self.do_extract_method(code, start, end, "new_f") + expected = dedent("""\ + def f(): + a_var = {} + new_f(a_var).keys() + + def new_f(a_var): + return a_var + """) + self.assertEqual(expected, refactored) + + +def test_raising_exception_when_on_incomplete_variables(self): + code = dedent("""\ + a_var = 10 + 20 + """) + start = code.index("10") + 1 + end = code.index("20") + 2 + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def _fix_start(self, source, offset): + while offset < len(source) and source[offset].isspace(): + offset += 1 + return offset + + +def test_raising_exception_when_on_incomplete_variables_on_end(self): + code = dedent("""\ + a_var = 10 + 20 + """) + start = code.index("10") + end = code.index("20") + 1 + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_raising_exception_on_bad_parens(self): + code = dedent("""\ + a_var = (10 + 20) + 30 + """) + start = code.index("20") + end = code.index("30") + 2 + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_raising_exception_on_bad_operators(self): + code = dedent("""\ + a_var = 10 + 20 + 30 + """) + start = code.index("10") + end = code.rindex("+") + 1 + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +# FIXME: Extract method should be more intelligent about bad ranges +def xxx_test_raising_exception_on_function_parens(self): + code = dedent("""\ + a = range(10)""") + start = code.index("(") + end = code.rindex(")") + 1 + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_extract_method_and_extra_blank_lines(self): + code = dedent("""\ + + print(1) + """) + refactored = self.do_extract_method(code, 0, len(code), "new_f") + expected = dedent("""\ + + + def new_f(): + print(1) + + new_f() + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.6") +def test_extract_method_f_string_extract_method(self): + code = dedent("""\ + def func(a_var): + foo(f"abc {a_var}", 10) + """) + start = code.index('f"') + end = code.index('}"') + 2 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def func(a_var): + foo(new_func(a_var), 10) + + def new_func(a_var): + return f"abc {a_var}" + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.6") +def test_extract_method_f_string_extract_method_complex_expression(self): + code = dedent("""\ + def func(a_var): + b_var = int + c_var = 10 + fill = 10 + foo(f"abc {a_var + f'{b_var(a_var)}':{fill}16}" f"{c_var}", 10) + """) + start = code.index('f"') + end = code.index('c_var}"') + 7 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def func(a_var): + b_var = int + c_var = 10 + fill = 10 + foo(new_func(a_var, b_var, c_var, fill), 10) + + def new_func(a_var, b_var, c_var, fill): + return f"abc {a_var + f'{b_var(a_var)}':{fill}16}" f"{c_var}" + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.6") +def test_extract_method_f_string_false_comment(self): + code = dedent("""\ + def func(a_var): + foo(f"abc {a_var} # ", 10) + """) + start = code.index('f"') + end = code.index('# "') + 3 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def func(a_var): + foo(new_func(a_var), 10) + + def new_func(a_var): + return f"abc {a_var} # " + """) + self.assertEqual(expected, refactored) + + +@unittest.expectedFailure +@testutils.only_for_versions_higher("3.6") +def test_extract_method_f_string_false_format_value_in_regular_string(self): + code = dedent("""\ + def func(a_var): + b_var = 1 + foo(f"abc {a_var} " "{b_var}" f"{b_var} def", 10) + """) + start = code.index('f"') + end = code.index('def"') + 4 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def func(a_var): + b_var = 1 + foo(new_func(a_var, b_var), 10) + + def new_func(a_var, b_var): + return f"abc {a_var} " "{b_var}" f"{b_var} def" + """) + self.assertEqual(expected, refactored) + + +def test_variable_writes_in_the_same_line_as_variable_read(self): + code = dedent("""\ + a = 1 + a = 1 + a + """) + start = code.index("\n") + 1 + end = len(code) + refactored = self.do_extract_method(code, start, end, "new_f", global_=True) + expected = dedent("""\ + a = 1 + + def new_f(a): + a = 1 + a + + new_f(a) + """) + self.assertEqual(expected, refactored) + + +def _fix_end(self, source, offset): + while offset > 0 and source[offset - 1].isspace(): + offset -= 1 + return offset + + +def test_variable_writes_in_the_same_line_as_variable_read2(self): + code = dedent("""\ + a = 1 + a += 1 + """) + start = code.index("\n") + 1 + end = len(code) + refactored = self.do_extract_method(code, start, end, "new_f", global_=True) + expected = dedent("""\ + a = 1 + + def new_f(a): + a += 1 + + new_f(a) + """) + self.assertEqual(expected, refactored) + + +def test_variable_writes_in_the_same_line_as_variable_read3(self): + code = dedent("""\ + a = 1 + a += 1 + print(a) + """) + start, end = self._convert_line_range_to_offset(code, 2, 2) + refactored = self.do_extract_method(code, start, end, "new_f") + expected = dedent("""\ + a = 1 + + def new_f(a): + a += 1 + return a + + a = new_f(a) + print(a) + """) + self.assertEqual(expected, refactored) + + +def test_variable_writes_only(self): + code = dedent("""\ + i = 1 + print(i) + """) + start, end = self._convert_line_range_to_offset(code, 1, 1) + refactored = self.do_extract_method(code, start, end, "new_f") + expected = dedent("""\ + + def new_f(): + i = 1 + return i + + i = new_f() + print(i) + """) + self.assertEqual(expected, refactored) + + +def test_variable_and_similar_expressions(self): + code = dedent("""\ + a = 1 + b = 1 + """) + start = code.index("1") + end = start + 1 + refactored = self.do_extract_variable(code, start, end, "one", similar=True) + expected = dedent("""\ + one = 1 + a = one + b = one + """) + self.assertEqual(expected, refactored) + + +def test_definition_should_appear_before_the_first_use(self): + code = dedent("""\ + a = 1 + b = 1 + """) + start = code.rindex("1") + end = start + 1 + refactored = self.do_extract_variable(code, start, end, "one", similar=True) + expected = dedent("""\ + one = 1 + a = one + b = one + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_and_similar_expressions(self): + code = dedent("""\ + a = 1 + b = 1 + """) + start = code.index("1") + end = start + 1 + refactored = self.do_extract_method(code, start, end, "one", similar=True) + expected = dedent("""\ + + def one(): + return 1 + + a = one() + b = one() + """) + self.assertEqual(expected, refactored) + + +def test_simple_extract_method_and_similar_statements(self): + code = dedent("""\ + class AClass(object): + + def func1(self): + a = 1 + 2 + b = a + def func2(self): + a = 1 + 2 + b = a + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "new_func", similar=True) + expected = dedent("""\ + class AClass(object): + + def func1(self): + a = self.new_func() + b = a + + def new_func(self): + a = 1 + 2 + return a + def func2(self): + a = self.new_func() + b = a + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_and_similar_statements2(self): + code = dedent("""\ + class AClass(object): + + def func1(self, p1): + a = p1 + 2 + def func2(self, p2): + a = p2 + 2 + """) + start = code.rindex("p1") + end = code.index("2\n") + 1 + refactored = self.do_extract_method(code, start, end, "new_func", similar=True) + expected = dedent("""\ + class AClass(object): + + def func1(self, p1): + a = self.new_func(p1) + + def new_func(self, p1): + return p1 + 2 + def func2(self, p2): + a = self.new_func(p2) + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_and_similar_sttemnts_return_is_different(self): + code = dedent("""\ + class AClass(object): + + def func1(self, p1): + a = p1 + 2 + def func2(self, p2): + self.attr = p2 + 2 + """) + start = code.rindex("p1") + end = code.index("2\n") + 1 + refactored = self.do_extract_method(code, start, end, "new_func", similar=True) + expected = dedent("""\ + class AClass(object): + + def func1(self, p1): + a = self.new_func(p1) + + def new_func(self, p1): + return p1 + 2 + def func2(self, p2): + self.attr = self.new_func(p2) + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_and_similar_sttemnts_overlapping_regions(self): + code = dedent("""\ + def func(p): + a = p + b = a + c = b + d = c + return d""") + start = code.index("a") + end = code.rindex("a") + 1 + refactored = self.do_extract_method(code, start, end, "new_func", similar=True) + expected = dedent("""\ + def func(p): + b = new_func(p) + d = new_func(b) + return d + def new_func(p): + a = p + b = a + return b + """) + self.assertEqual(expected, refactored) + + +def get_changes(self, extracted_name, similar=False, global_=False, kind=None): + """Get the changes this refactoring makes + + :parameters: + - `extracted_name`: target name, when starts with @ - set kind to + classmethod, $ - staticmethod + - `similar`: if `True`, similar expressions/statements are also + replaced. + - `global_`: if `True`, the extracted method/variable will + be global. + - `kind`: kind of target refactoring to (staticmethod, classmethod) + + """ + extracted_name, kind = self._get_kind_from_name(extracted_name, kind) + + info = _ExtractInfo( + self.project, + self.resource, + self.start_offset, + self.end_offset, + extracted_name, + variable=self._get_kind(kind) == "variable", + similar=similar, + make_global=global_, + ) + info.kind = self._get_kind(kind) + new_contents = _ExtractPerformer(info).extract() + changes = ChangeSet("Extract {} <{}>".format(info.kind, extracted_name)) + changes.add_change(ChangeContents(self.resource, new_contents)) + return changes + + +def test_definition_should_appear_where_it_is_visible(self): + code = dedent("""\ + if True: + a = 1 + else: + b = 1 + """) + start = code.rindex("1") + end = start + 1 + refactored = self.do_extract_variable(code, start, end, "one", similar=True) + expected = dedent("""\ + one = 1 + if True: + a = one + else: + b = one + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable_and_similar_statements_in_classes(self): + code = dedent("""\ + class AClass(object): + + def func1(self): + a = 1 + def func2(self): + b = 1 + """) + start = code.index(" 1") + 1 + refactored = self.do_extract_variable( + code, start, start + 1, "one", similar=True + ) + expected = dedent("""\ + class AClass(object): + + def func1(self): + one = 1 + a = one + def func2(self): + b = 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_in_staticmethods(self): + code = dedent("""\ + class AClass(object): + + @staticmethod + def func2(): + b = 1 + """) + start = code.index(" 1") + 1 + refactored = self.do_extract_method(code, start, start + 1, "one", similar=True) + expected = dedent("""\ + class AClass(object): + + @staticmethod + def func2(): + b = AClass.one() + + @staticmethod + def one(): + return 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_normal_method_with_staticmethods(self): + code = dedent("""\ + class AClass(object): + + @staticmethod + def func1(): + b = 1 + def func2(self): + b = 1 + """) + start = code.rindex(" 1") + 1 + refactored = self.do_extract_method(code, start, start + 1, "one", similar=True) + expected = dedent("""\ + class AClass(object): + + @staticmethod + def func1(): + b = 1 + def func2(self): + b = self.one() + + def one(self): + return 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_variable_with_no_new_lines_at_the_end(self): + code = "a_var = 10" + start = code.index("10") + end = start + 2 + refactored = self.do_extract_variable(code, start, end, "new_var") + expected = dedent("""\ + new_var = 10 + a_var = new_var""") + self.assertEqual(expected, refactored) + + +def test_extract_method_containing_return_in_functions(self): + code = dedent("""\ + def f(arg): + return arg + print(f(1)) + """) + start, end = self._convert_line_range_to_offset(code, 1, 3) + refactored = self.do_extract_method(code, start, end, "a_func") + expected = dedent("""\ + + def a_func(): + def f(arg): + return arg + print(f(1)) + + a_func() + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_and_varying_first_parameter(self): + code = dedent("""\ + class C(object): + def f1(self): + print(str(self)) + def f2(self): + print(str(1)) + """) + start = code.index("print(") + 6 + end = code.index("))\n") + 1 + refactored = self.do_extract_method(code, start, end, "to_str", similar=True) + expected = dedent("""\ + class C(object): + def f1(self): + print(self.to_str()) + + def to_str(self): + return str(self) + def f2(self): + print(str(1)) + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_when_an_attribute_exists_in_function_scope(self): + code = dedent("""\ + class A(object): + def func(self): + pass + a = A() + def f(): + func = a.func() + print(func) + """) + + start, end = self._convert_line_range_to_offset(code, 6, 6) + refactored = self.do_extract_method(code, start, end, "g") + refactored = refactored[refactored.index("A()") + 4 :] + expected = dedent("""\ + def f(): + func = g() + print(func) + + def g(): + func = a.func() + return func + """) + self.assertEqual(expected, refactored) + + +def test_global_option_for_extract_method(self): + code = dedent("""\ + def a_func(): + print(1) + """) + start, end = self._convert_line_range_to_offset(code, 2, 2) + refactored = self.do_extract_method(code, start, end, "extracted", global_=True) + expected = dedent("""\ + def a_func(): + extracted() + + def extracted(): + print(1) + """) + self.assertEqual(expected, refactored) + + +def test_global_extract_method(self): + code = dedent("""\ + class AClass(object): + + def a_func(self): + print(1) + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "new_func", global_=True) + expected = dedent("""\ + class AClass(object): + + def a_func(self): + new_func() + + def new_func(): + print(1) + """) + self.assertEqual(expected, refactored) + + +def _get_kind_from_name(self, extracted_name, kind): + for sign, selected_kind in self.kind_prefixes.items(): + if extracted_name.startswith(sign): + self._validate_kind_prefix(kind, selected_kind) + return extracted_name[1:], selected_kind + return extracted_name, kind + + +def test_global_extract_method_with_multiple_methods(self): + code = dedent("""\ + class AClass(object): + def a_func(self): + print(1) + + def another_func(self): + pass + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "new_func", global_=True) + expected = dedent("""\ + class AClass(object): + def a_func(self): + new_func() + + def another_func(self): + pass + + def new_func(): + print(1) + """) + self.assertEqual(expected, refactored) + + +def test_where_to_seach_when_extracting_global_names(self): + code = dedent("""\ + def a(): + return 1 + def b(): + return 1 + b = 1 + """) + start = code.index("1") + end = start + 1 + refactored = self.do_extract_variable( + code, start, end, "one", similar=True, global_=True + ) + expected = dedent("""\ + def a(): + return one + one = 1 + def b(): + return one + b = one + """) + self.assertEqual(expected, refactored) + + +def test_extracting_pieces_with_distinct_temp_names(self): + code = dedent("""\ + a = 1 + print(a) + b = 1 + print(b) + """) + start = code.index("a") + end = code.index("\nb") + refactored = self.do_extract_method( + code, start, end, "f", similar=True, global_=True + ) + expected = dedent("""\ + + def f(): + a = 1 + print(a) + + f() + f() + """) + self.assertEqual(expected, refactored) + + +def test_extract_methods_in_glob_funcs_should_be_glob(self): + code = dedent("""\ + def f(): + a = 1 + def g(): + b = 1 + """) + start = code.rindex("1") + refactored = self.do_extract_method( + code, start, start + 1, "one", similar=True, global_=False + ) + expected = dedent("""\ + def f(): + a = one() + def g(): + b = one() + + def one(): + return 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_methods_in_glob_funcs_should_be_glob_2(self): + code = dedent("""\ + if 1: + var = 2 + """) + start = code.rindex("2") + refactored = self.do_extract_method( + code, start, start + 1, "two", similar=True, global_=False + ) + expected = dedent("""\ + + def two(): + return 2 + + if 1: + var = two() + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_and_try_blocks(self): + code = dedent("""\ + def f(): + try: + pass + except Exception: + pass + """) + start, end = self._convert_line_range_to_offset(code, 2, 5) + refactored = self.do_extract_method(code, start, end, "g") + expected = dedent("""\ + def f(): + g() + + def g(): + try: + pass + except Exception: + pass + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_and_augmented_assignment_nested_1(self): + code = dedent("""\ + def f(): + my_var = [[0], [1], [2]] + my_var[0][0] += 1 + print(1) + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "g") + expected = dedent("""\ + def f(): + my_var = [[0], [1], [2]] + my_var[0][0] += 1 + g() + + def g(): + print(1) + """) + self.assertEqual(expected, refactored) + +def test_extract_method_and_augmented_assignment_nested_2(self): + code = dedent("""\ + def f(): + my_var = [[0], [1], [2]] + my_var[0][0] += 1 + print(my_var) + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "g") + expected = dedent("""\ + def f(): + my_var = [[0], [1], [2]] + g(my_var) + print(my_var) + + def g(my_var): + my_var[0][0] += 1 + """) + self.assertEqual(expected, refactored) + +def test_extract_method_and_augmented_assignment_var_to_read_in_lhs(self): + code = dedent("""\ + def f(): + var_to_read = 0 + my_var = [0, 1, 2] + my_var[var_to_read] += 1 + print(my_var) + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "g") + expected = dedent("""\ + def f(): + var_to_read = 0 + my_var = [0, 1, 2] + g(my_var, var_to_read) + print(my_var) + + def g(my_var, var_to_read): + my_var[var_to_read] += 1 + """) + self.assertEqual(expected, refactored) + +def test_extract_method_and_augmented_assignment_in_try_block(self): + code = dedent("""\ + def f(): + any_subscriptable = [0] + try: + any_subscriptable[0] += 1 + except Exception: + pass + """) + start, end = self._convert_line_range_to_offset(code, 2, 6) + refactored = self.do_extract_method(code, start, end, "g") + expected = dedent("""\ + def f(): + g() + + def g(): + any_subscriptable = [0] + try: + any_subscriptable[0] += 1 + except Exception: + pass + """) + self.assertEqual(expected, refactored) + + +def test_extract_and_not_passing_global_functions(self): + code = dedent("""\ + def next(p): + return p + 1 + var = next(1) + """) + start = code.rindex("next") + refactored = self.do_extract_method(code, start, len(code) - 1, "two") + expected = dedent("""\ + def next(p): + return p + 1 + + def two(): + return next(1) + + var = two() + """) + self.assertEqual(expected, refactored) + + +def test_extracting_with_only_one_return(self): + code = dedent("""\ + def f(): + var = 1 + return var + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + refactored = self.do_extract_method(code, start, end, "g") + expected = dedent("""\ + def f(): + return g() + + def g(): + var = 1 + return var + """) + self.assertEqual(expected, refactored) + + +def test_extracting_variable_and_implicit_continuations(self): + code = dedent("""\ + s = ("1" + "2") + """) + start = code.index('"') + end = code.rindex('"') + 1 + refactored = self.do_extract_variable(code, start, end, "s2") + expected = dedent("""\ + s2 = "1" "2" + s = (s2) + """) + self.assertEqual(expected, refactored) + + +@staticmethod +def _validate_kind_prefix(kind, selected_kind): + if kind and kind != selected_kind: + raise RefactoringError("Kind and shortcut in name mismatch") + + +def test_extracting_method_and_implicit_continuations(self): + code = dedent("""\ + s = ("1" + "2") + """) + start = code.index('"') + end = code.rindex('"') + 1 + refactored = self.do_extract_method(code, start, end, "f") + expected = dedent("""\ + + def f(): + return "1" "2" + + s = (f()) + """) + self.assertEqual(expected, refactored) + + +def test_passing_conditional_updated_vars_in_extracted(self): + code = dedent("""\ + def f(a): + if 0: + a = 1 + print(a) + """) + start, end = self._convert_line_range_to_offset(code, 2, 4) + refactored = self.do_extract_method(code, start, end, "g") + expected = dedent("""\ + def f(a): + g(a) + + def g(a): + if 0: + a = 1 + print(a) + """) + self.assertEqual(expected, refactored) + + +def test_returning_conditional_updated_vars_in_extracted(self): + code = dedent("""\ + def f(a): + if 0: + a = 1 + print(a) + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + refactored = self.do_extract_method(code, start, end, "g") + expected = dedent("""\ + def f(a): + a = g(a) + print(a) + + def g(a): + if 0: + a = 1 + return a + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_variables_possibly_written_to(self): + code = dedent("""\ + def a_func(b): + if b > 0: + a = 2 + print(a) + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + refactored = self.do_extract_method(code, start, end, "extracted") + expected = dedent("""\ + def a_func(b): + a = extracted(b) + print(a) + + def extracted(b): + if b > 0: + a = 2 + return a + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_list_comprehension(self): + code = dedent("""\ + def foo(): + x = [e for e in []] + f = 23 + + for e, f in []: + def bar(): + e[42] = 1 + """) + start, end = self._convert_line_range_to_offset(code, 4, 7) + refactored = self.do_extract_method(code, start, end, "baz") + expected = dedent("""\ + def foo(): + x = [e for e in []] + f = 23 + + baz() + + def baz(): + for e, f in []: + def bar(): + e[42] = 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_list_comprehension_in_class_method(self): + code = dedent("""\ + class SomeClass: + def method(self): + result = [i for i in range(1)] + print(1) + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "baz", similar=True) + expected = dedent("""\ + class SomeClass: + def method(self): + result = [i for i in range(1)] + self.baz() + + def baz(self): + print(1) + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_list_comprehension_and_iter(self): + code = dedent("""\ + def foo(): + x = [e for e in []] + f = 23 + + for x, f in x: + def bar(): + x[42] = 1 + """) + start, end = self._convert_line_range_to_offset(code, 4, 7) + refactored = self.do_extract_method(code, start, end, "baz") + expected = dedent("""\ + def foo(): + x = [e for e in []] + f = 23 + + baz(x) + + def baz(x): + for x, f in x: + def bar(): + x[42] = 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_list_comprehension_and_orelse(self): + code = dedent("""\ + def foo(): + x = [e for e in []] + f = 23 + + for e, f in []: + def bar(): + e[42] = 1 + """) + start, end = self._convert_line_range_to_offset(code, 4, 7) + refactored = self.do_extract_method(code, start, end, "baz") + expected = dedent("""\ + def foo(): + x = [e for e in []] + f = 23 + + baz() + + def baz(): + for e, f in []: + def bar(): + e[42] = 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_list_comprehension_multiple_targets(self): + code = dedent("""\ + def foo(): + x = [(a, b) for a, b in []] + f = 23 + print("hello") + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "baz") + expected = dedent("""\ + def foo(): + x = [(a, b) for a, b in []] + f = 23 + baz() + + def baz(): + print("hello") + """) + self.assertEqual(expected, refactored) + + +def test_extract_function_with_for_else_statemant(self): + code = dedent("""\ + def a_func(): + for i in range(10): + a = i + else: + a = None + """) + start = code.index("for") + end = len(code) - 1 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + new_func() + + def new_func(): + for i in range(10): + a = i + else: + a = None + """) + self.assertEqual(expected, refactored) + + +@classmethod +def _get_kind(cls, kind): + raise NotImplementedError(f"You have to sublass {cls}") + + + +def test_extract_function_with_for_else_statemant_more(self): + """TODO: fixed code to test passed""" + code = dedent("""\ + def a_func(): + for i in range(10): + a = i + else: + for i in range(5): + b = i + else: + b = None + a = None + """) + + start = code.index("for") + end = len(code) - 1 + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def a_func(): + new_func() + + def new_func(): + for i in range(10): + a = i + else: + for i in range(5): + b = i + else: + b = None + a = None + """) + self.assertEqual(expected, refactored) + + +def test_extract_function_with_for_else_statemant_outside_loops(self): + code = dedent("""\ + def a_func(): + for i in range(10): + a = i + else: + a=None + """) + start = code.index("a = i") + end = len(code) - 1 + with self.assertRaises(rope.base.exceptions.RefactoringError): + self.do_extract_method(code, start, end, "new_func") + + +def test_extract_function_with_inline_assignment_in_method(self): + code = dedent("""\ + def foo(): + i = 1 + i += 1 + print(i) + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def foo(): + i = 1 + i = new_func(i) + print(i) + + def new_func(i): + i += 1 + return i + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.8") +def test_extract_function_statement_with_inline_assignment_in_condition(self): + code = dedent("""\ + def foo(a): + if i := a == 5: + i += 1 + print(i) + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def foo(a): + i = new_func(a) + print(i) + + def new_func(a): + if i := a == 5: + i += 1 + return i + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.8") +def test_extract_function_expression_with_inline_assignment_in_condition(self): + code = dedent("""\ + def foo(a): + if i := a == 5: + i += 1 + print(i) + """) + extract_target = "i := a == 5" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def foo(a): + if i := new_func(a): + i += 1 + print(i) + + def new_func(a): + return (i := a == 5) + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.8") +def test_extract_function_expression_with_inline_assignment_complex(self): + code = dedent("""\ + def foo(a): + if i := a == (c := 5): + i += 1 + c += 1 + print(i) + """) + extract_target = "i := a == (c := 5)" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def foo(a): + if i, c := new_func(a): + i += 1 + c += 1 + print(i) + + def new_func(a): + return (i := a == (c := 5)) + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.8") +def test_extract_function_expression_with_inline_assignment_in_inner_expression( + self, +): + code = dedent("""\ + def foo(a): + if a == (c := 5): + c += 1 + print(i) + """) + extract_target = "a == (c := 5)" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + with self.assertRaisesRegex( + rope.base.exceptions.RefactoringError, + "Extracted piece cannot contain named expression \\(:= operator\\).", + ): + self.do_extract_method(code, start, end, "new_func") + + +def test_extract_exec(self): + code = dedent("""\ + exec("def f(): pass", {}) + """) + start, end = self._convert_line_range_to_offset(code, 1, 1) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + + def new_func(): + exec("def f(): pass", {}) + + new_func() + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_lower("3") +def test_extract_exec_statement(self): + code = dedent("""\ + exec "def f(): pass" in {} + """) + start, end = self._convert_line_range_to_offset(code, 1, 1) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + + def new_func(): + exec "def f(): pass" in {} + + new_func() + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.5") +def test_extract_async_function(self): + code = dedent("""\ + async def my_func(my_list): + for x in my_list: + var = x + 1 + return var + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + async def my_func(my_list): + for x in my_list: + var = new_func(x) + return var + + def new_func(x): + var = x + 1 + return var + """) + self.assertEqual(expected, refactored) + + +class ExtractMethod(_ExtractRefactoring): + kind = "method" + allowed_kinds = ("function", "method", "staticmethod", "classmethod") + kind_prefixes = {"@": "classmethod", "$": "staticmethod"} + + @others + +@testutils.only_for_versions_higher("3.5") +def test_extract_inner_async_function(self): + code = dedent("""\ + def my_func(my_list): + async def inner_func(my_list): + for x in my_list: + var = x + 1 + return inner_func + """) + start, end = self._convert_line_range_to_offset(code, 2, 4) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def my_func(my_list): + inner_func = new_func(my_list) + return inner_func + + def new_func(my_list): + async def inner_func(my_list): + for x in my_list: + var = x + 1 + return inner_func + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.5") +def test_extract_around_inner_async_function(self): + code = dedent("""\ + def my_func(lst): + async def inner_func(obj): + for x in obj: + var = x + 1 + return map(inner_func, lst) + """) + start, end = self._convert_line_range_to_offset(code, 5, 5) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + def my_func(lst): + async def inner_func(obj): + for x in obj: + var = x + 1 + return new_func(inner_func, lst) + + def new_func(inner_func, lst): + return map(inner_func, lst) + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.5") +def test_extract_refactor_around_async_for_loop(self): + code = dedent("""\ + async def my_func(my_list): + async for x in my_list: + var = x + 1 + return var + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + async def my_func(my_list): + async for x in my_list: + var = new_func(x) + return var + + def new_func(x): + var = x + 1 + return var + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.5") +@testutils.only_for_versions_lower("3.8") +def test_extract_refactor_containing_async_for_loop_should_error_before_py38(self): + """ + Refactoring async/await syntaxes is only supported in Python 3.8 and + higher because support for ast.PyCF_ALLOW_TOP_LEVEL_AWAIT was only + added to the standard library in Python 3.8. + """ + code = dedent("""\ + async def my_func(my_list): + async for x in my_list: + var = x + 1 + return var + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + with self.assertRaisesRegex( + rope.base.exceptions.RefactoringError, + "Extracted piece can only have async/await statements if Rope is running on Python 3.8 or higher", + ): + self.do_extract_method(code, start, end, "new_func") + + +@testutils.only_for_versions_higher("3.8") +def test_extract_refactor_containing_async_for_loop_is_supported_after_py38(self): + code = dedent("""\ + async def my_func(my_list): + async for x in my_list: + var = x + 1 + return var + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + async def my_func(my_list): + var = new_func(my_list) + return var + + def new_func(my_list): + async for x in my_list: + var = x + 1 + return var + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.5") +def test_extract_await_expression(self): + code = dedent("""\ + async def my_func(my_list): + for url in my_list: + resp = await request(url) + return resp + """) + selected = "request(url)" + start, end = code.index(selected), code.index(selected) + len(selected) + refactored = self.do_extract_method(code, start, end, "new_func") + expected = dedent("""\ + async def my_func(my_list): + for url in my_list: + resp = await new_func(url) + return resp + + def new_func(url): + return request(url) + """) + self.assertEqual(expected, refactored) + + +def test_extract_to_staticmethod(self): + code = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = a_var + 1 + """) + extract_target = "a_var + 1" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method( + code, start, end, "second_method", kind="staticmethod" + ) + expected = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = A.second_method(a_var) + + @staticmethod + def second_method(a_var): + return a_var + 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_to_staticmethod_when_self_in_body(self): + code = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = self.a_var + 1 + """) + extract_target = "self.a_var + 1" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method( + code, start, end, "second_method", kind="staticmethod" + ) + expected = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = A.second_method(self) + + @staticmethod + def second_method(self): + return self.a_var + 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_from_function_to_staticmethod_raises_exception(self): + code = dedent("""\ + def first_method(): + a_var = 1 + b_var = a_var + 1 + """) + extract_target = "a_var + 1" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + with self.assertRaisesRegex( + rope.base.exceptions.RefactoringError, + "Cannot extract to staticmethod/classmethod outside class", + ): + self.do_extract_method( + code, start, end, "second_method", kind="staticmethod" + ) + + +def test_extract_method_in_classmethods(self): + code = dedent("""\ + class AClass(object): + @classmethod + def func2(cls): + b = 1 + """) + start = code.index(" 1") + 1 + refactored = self.do_extract_method(code, start, start + 1, "one", similar=True) + expected = dedent("""\ + class AClass(object): + @classmethod + def func2(cls): + b = AClass.one() + + @classmethod + def one(cls): + return 1 + """) + self.assertEqual(expected, refactored) + + +@classmethod +def _get_kind(cls, kind): + return kind if kind in cls.allowed_kinds else cls.kind + + + +def test_extract_from_function_to_classmethod_raises_exception(self): + code = dedent("""\ + def first_method(): + a_var = 1 + b_var = a_var + 1 + """) + extract_target = "a_var + 1" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + with self.assertRaisesRegex( + rope.base.exceptions.RefactoringError, + "Cannot extract to staticmethod/classmethod outside class", + ): + self.do_extract_method( + code, start, end, "second_method", kind="classmethod" + ) + + +def test_extract_to_classmethod_when_self_in_body(self): + code = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = self.a_var + 1 + """) + extract_target = "self.a_var + 1" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method( + code, start, end, "second_method", kind="classmethod" + ) + expected = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = A.second_method(self) + + @classmethod + def second_method(cls, self): + return self.a_var + 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_to_classmethod(self): + code = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = a_var + 1 + """) + extract_target = "a_var + 1" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method( + code, start, end, "second_method", kind="classmethod" + ) + expected = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = A.second_method(a_var) + + @classmethod + def second_method(cls, a_var): + return a_var + 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_to_classmethod_when_name_starts_with_at_sign(self): + code = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = a_var + 1 + """) + extract_target = "a_var + 1" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "@second_method") + expected = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = A.second_method(a_var) + + @classmethod + def second_method(cls, a_var): + return a_var + 1 + """) + self.assertEqual(expected, refactored) + + +def test_extract_to_staticmethod_when_name_starts_with_dollar_sign(self): + code = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = a_var + 1 + """) + extract_target = "a_var + 1" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "$second_method") + expected = dedent("""\ + class A: + def first_method(self): + a_var = 1 + b_var = A.second_method(a_var) + + @staticmethod + def second_method(a_var): + return a_var + 1 + """) + self.assertEqual(expected, refactored) + + +def test_raises_exception_when_sign_in_name_and_kind_mismatch(self): + with self.assertRaisesRegex( + rope.base.exceptions.RefactoringError, "Kind and shortcut in name mismatch" + ): + self.do_extract_method("code", 0, 1, "$second_method", kind="classmethod") + + +def test_extracting_from_static_with_function_arg(self): + code = dedent("""\ + class A: + @staticmethod + def first_method(someargs): + b_var = someargs + 1 + """) + + extract_target = "someargs + 1" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "second_method") + expected = dedent("""\ + class A: + @staticmethod + def first_method(someargs): + b_var = A.second_method(someargs) + + @staticmethod + def second_method(someargs): + return someargs + 1 + """) + + self.assertEqual(expected, refactored) + + +def test_extract_with_list_comprehension(self): + code = dedent("""\ + def f(): + y = [1,2,3,4] + a = sum([x for x in y]) + b = sum([x for x in y]) + + print(a, b) + + f() + """) + extract_target = " a = sum([x for x in y])\n" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "_a") + expected = dedent("""\ + def f(): + y = [1,2,3,4] + a = _a(y) + b = sum([x for x in y]) + + print(a, b) + + def _a(y): + a = sum([x for x in y]) + return a + + f() + """) + self.assertEqual(expected, refactored) + + +def test_extract_with_generator(self): + code = dedent("""\ + def f(): + y = [1,2,3,4] + a = sum(x for x in y) + b = sum(x for x in y) + + print(a, b) + + f() + """) + extract_target = " a = sum(x for x in y)\n" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "_a") + expected = dedent("""\ + def f(): + y = [1,2,3,4] + a = _a(y) + b = sum(x for x in y) + + print(a, b) + + def _a(y): + a = sum(x for x in y) + return a + + f() + """) + self.assertEqual(expected, refactored) + + +def test_extract_with_generator_2(self): + code = dedent("""\ + def f(): + y = [1,2,3,4] + a = sum(x for x in y) + """) + extract_target = "x for x in y" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "_a") + expected = dedent("""\ + def f(): + y = [1,2,3,4] + a = sum(_a(y)) + + def _a(y): + return (x for x in y) + """) + self.assertEqual(expected, refactored) + + +def _generate_info(self, project, resource, offset): + return _GenerationInfo(project.pycore, resource, offset, self.goal_resource) + + +class ExtractVariable(_ExtractRefactoring): + @others + +def test_extract_with_set_comprehension(self): + code = dedent("""\ + def f(): + y = [1,2,3,4] + a = sum({x for x in y}) + b = sum({x for x in y}) + + print(a, b) + + f() + """) + extract_target = " a = sum({x for x in y})\n" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "_a") + expected = dedent("""\ + def f(): + y = [1,2,3,4] + a = _a(y) + b = sum({x for x in y}) + + print(a, b) + + def _a(y): + a = sum({x for x in y}) + return a + + f() + """) + self.assertEqual(expected, refactored) + + +def test_extract_with_dict_comprehension(self): + code = dedent("""\ + def f(): + y = [1,2,3,4] + a = sum({x: x for x in y}) + b = sum({x: x for x in y}) + + print(a, b) + + f() + """) + extract_target = " a = sum({x: x for x in y})\n" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "_a") + expected = dedent("""\ + def f(): + y = [1,2,3,4] + a = _a(y) + b = sum({x: x for x in y}) + + print(a, b) + + def _a(y): + a = sum({x: x for x in y}) + return a + + f() + """) + self.assertEqual(expected, refactored) + + +def test_extract_function_expression_with_assignment_to_attribute(self): + code = dedent("""\ + class A(object): + def func(self): + self.var_a = 1 + var_bb = self.var_a + """) + extract_target = "= self.var_a" + start, end = ( + code.index(extract_target) + 2, + code.index(extract_target) + 2 + len(extract_target) - 2, + ) + refactored = self.do_extract_method(code, start, end, "new_func", similar=True) + expected = dedent("""\ + class A(object): + def func(self): + self.var_a = 1 + var_bb = self.new_func() + + def new_func(self): + return self.var_a + """) + + self.assertEqual(expected, refactored) + + +def test_extract_function_expression_with_assignment_index(self): + code = dedent("""\ + class A(object): + def func(self, val): + self[val] = 1 + var_bb = self[val] + """) + extract_target = "= self[val]" + start, end = ( + code.index(extract_target) + 2, + code.index(extract_target) + 2 + len(extract_target) - 2, + ) + refactored = self.do_extract_method(code, start, end, "new_func", similar=True) + expected = dedent("""\ + class A(object): + def func(self, val): + self[val] = 1 + var_bb = self.new_func(val) + + def new_func(self, val): + return self[val] + """) + + self.assertEqual(expected, refactored) + + +def test_extraction_method_with_global_variable(self): + code = dedent("""\ + g = None + + def f(): + global g + + g = 2 + + f() + print(g) + """) + extract_target = "g = 2" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "_g") + expected = dedent("""\ + g = None + + def f(): + global g + + _g() + + def _g(): + global g + g = 2 + + f() + print(g) + """) + self.assertEqual(expected, refactored) + + +def test_extraction_method_with_global_variable_and_global_declaration(self): + code = dedent("""\ + g = None + + def f(): + global g + + g = 2 + + f() + print(g) + """) + start, end = 23, 42 + refactored = self.do_extract_method(code, start, end, "_g") + expected = dedent("""\ + g = None + + def f(): + _g() + + def _g(): + global g + + g = 2 + + f() + print(g) + """) + self.assertEqual(expected, refactored) + + +def test_extraction_one_line_with_global_variable_read_only(self): + code = dedent("""\ + g = None + + def f(): + global g + + a = g + + f() + print(g) + """) + extract_target = "= g" + start, end = code.index(extract_target) + 2, code.index(extract_target) + 3 + refactored = self.do_extract_method(code, start, end, "_g") + expected = dedent("""\ + g = None + + def f(): + global g + + a = _g() + + def _g(): + return g + + f() + print(g) + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.8") +def test_extraction_one_line_with_global_variable(self): + code = dedent("""\ + g = None + + def f(): + global g + + while g := 4: + pass + + f() + print(g) + """) + extract_target = "g := 4" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "_g") + expected = dedent("""\ + g = None + + def f(): + global g + + while _g(): + pass + + def _g(): + global g + return (g := 4) + + f() + print(g) + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.8") +def test_extraction_one_line_with_global_variable_has_postread(self): + code = dedent("""\ + g = None + + def f(): + global g + + while g := 4: + print(g) + + f() + print(g) + """) + extract_target = "g := 4" + start, end = code.index(extract_target), code.index(extract_target) + len( + extract_target + ) + refactored = self.do_extract_method(code, start, end, "_g") + expected = dedent("""\ + g = None + + def f(): + global g + + while g := _g(): + print(g) + + def _g(): + global g + return (g := 4) + + f() + print(g) + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_nested_double_with_as(self): + code = dedent("""\ + with open("test") as file1: + with open("test") as file2: + print(file1, file2) + """) + start, end = self._convert_line_range_to_offset(code, 3, 4) + refactored = self.do_extract_method(code, start, end, "extracted", global_=True) + expected = dedent("""\ + + def extracted(file1, file2): + print(file1, file2) + + with open("test") as file1: + with open("test") as file2: + extracted(file1, file2) + """) + self.assertEqual(expected, refactored) + + +def __init__(self, *args, **kwds): + kwds = dict(kwds) + kwds["variable"] = True + super().__init__(*args, **kwds) + + +def test_extract_method_with_double_with_as(self): + code = dedent("""\ + with open("test") as file1, open("test") as file2: + print(file1, file2) + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + refactored = self.do_extract_method(code, start, end, "extracted", global_=True) + expected = dedent("""\ + + def extracted(file1, file2): + print(file1, file2) + + with open("test") as file1, open("test") as file2: + extracted(file1, file2) + """) + self.assertEqual(expected, refactored) + + +def test_extract_method_with_nested_double_with_as_and_misleading_comment(self): + code = dedent("""\ + with open("test") as file1, open("test") as file2: + # with in comment + bar() + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "extracted", global_=True) + expected = dedent("""\ + + def extracted(): + bar() + + with open("test") as file1, open("test") as file2: + # with in comment + extracted() + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.8") +def test_extract_method_async_with_simple(self): + code = dedent("""\ + async def afunc(): + async with open("test") as file1: + print(file1) + """) + start, end = self._convert_line_range_to_offset(code, 2, 3) + refactored = self.do_extract_method(code, start, end, "extracted", global_=True) + expected = dedent("""\ + async def afunc(): + extracted() + + def extracted(): + async with open("test") as file1: + print(file1) + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.8") +def test_extract_method_containing_async_with(self): + code = dedent("""\ + async def afunc(): + async with open("test") as file1, open("test") as file2: + print(file1, file2) + """) + start, end = self._convert_line_range_to_offset(code, 3, 3) + refactored = self.do_extract_method(code, start, end, "extracted", global_=True) + expected = dedent("""\ + async def afunc(): + async with open("test") as file1, open("test") as file2: + extracted(file1, file2) + + def extracted(file1, file2): + print(file1, file2) + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.10") +def test_extract_method_containing_structural_pattern_match(self): + code = dedent("""\ + match var: + case Foo("xx"): + print(x) + case Foo(x): + print(x) + """) + start, end = self._convert_line_range_to_offset(code, 5, 5) + refactored = self.do_extract_method(code, start, end, "extracted") + expected = dedent("""\ + + def extracted(): + print(x) + + match var: + case Foo("xx"): + print(x) + case Foo(x): + extracted() + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.10") +def test_extract_method_containing_structural_pattern_match_2(self): + code = dedent("""\ + def foo(): + match var: + case Foo(x): + print(x) + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "extracted") + expected = dedent("""\ + def foo(): + match var: + case Foo(x): + extracted(x) + + def extracted(x): + print(x) + """) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.10") +def test_extract_method_containing_structural_pattern_match_3(self): + code = dedent("""\ + def foo(): + match var: + case {"hello": x} as y: + print(x) + """) + start, end = self._convert_line_range_to_offset(code, 4, 4) + refactored = self.do_extract_method(code, start, end, "extracted") + expected = dedent("""\ + def foo(): + match var: + case {"hello": x} as y: + extracted(x) + + def extracted(x): + print(x) + """) + self.assertEqual(expected, refactored) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +import unittest + +from textwrap import dedent + +from rope.refactor.importutils import ImportTools, importinfo, add_import +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class ImportUtilsTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.import_tools = ImportTools(self.project) + + self.mod = testutils.create_module(self.project, "mod") + self.pkg1 = testutils.create_package(self.project, "pkg1") + self.mod1 = testutils.create_module(self.project, "mod1", self.pkg1) + self.pkg2 = testutils.create_package(self.project, "pkg2") + self.mod2 = testutils.create_module(self.project, "mod2", self.pkg2) + self.mod3 = testutils.create_module(self.project, "mod3", self.pkg2) + p1 = testutils.create_package(self.project, "p1") + p2 = testutils.create_package(self.project, "p2", p1) + p3 = testutils.create_package(self.project, "p3", p2) + m1 = testutils.create_module(self.project, "m1", p3) # noqa + l = testutils.create_module(self.project, "l", p3) # noqa + + +kind = "variable" + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_get_import_for_module(self): + mod = self.project.find_module("mod") + import_statement = self.import_tools.get_import(mod) + self.assertEqual("import mod", import_statement.get_import_statement()) + + +def test_get_import_for_module_in_nested_modules(self): + mod = self.project.find_module("pkg1.mod1") + import_statement = self.import_tools.get_import(mod) + self.assertEqual("import pkg1.mod1", import_statement.get_import_statement()) + + +def test_get_import_for_module_in_init_dot_py(self): + init_dot_py = self.pkg1.get_child("__init__.py") + import_statement = self.import_tools.get_import(init_dot_py) + self.assertEqual("import pkg1", import_statement.get_import_statement()) + + +def test_get_from_import_for_module(self): + mod = self.project.find_module("mod") + import_statement = self.import_tools.get_from_import(mod, "a_func") + self.assertEqual( + "from mod import a_func", import_statement.get_import_statement() + ) + + +def test_get_from_import_for_module_in_nested_modules(self): + mod = self.project.find_module("pkg1.mod1") + import_statement = self.import_tools.get_from_import(mod, "a_func") + self.assertEqual( + "from pkg1.mod1 import a_func", import_statement.get_import_statement() + ) + + +def test_get_from_import_for_module_in_init_dot_py(self): + init_dot_py = self.pkg1.get_child("__init__.py") + import_statement = self.import_tools.get_from_import(init_dot_py, "a_func") + self.assertEqual( + "from pkg1 import a_func", import_statement.get_import_statement() + ) + + +def test_get_import_statements(self): + self.mod.write("import pkg1\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.imports + self.assertEqual("import pkg1", imports[0].import_info.get_import_statement()) + + +def test_get_import_statements_with_alias(self): + self.mod.write("import pkg1.mod1 as mod1\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.imports + self.assertEqual( + "import pkg1.mod1 as mod1", imports[0].import_info.get_import_statement() + ) + + +def test_get_import_statements_for_froms(self): + self.mod.write("from pkg1 import mod1\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.imports + self.assertEqual( + "from pkg1 import mod1", imports[0].import_info.get_import_statement() + ) + + +def _get_kind(cls, kind): + return cls.kind + + + +def test_get_multi_line_import_statements_for_froms(self): + self.mod.write("from pkg1 \\\n import mod1\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.imports + self.assertEqual( + "from pkg1 import mod1", imports[0].import_info.get_import_statement() + ) + + +def test_get_import_statements_for_from_star(self): + self.mod.write("from pkg1 import *\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.imports + self.assertEqual( + "from pkg1 import *", imports[0].import_info.get_import_statement() + ) + + +@testutils.only_for("2.5") +def test_get_import_statements_for_new_relatives(self): + self.mod2.write("from .mod3 import x\n") + pymod = self.project.get_module("pkg2.mod2") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.imports + self.assertEqual( + "from .mod3 import x", imports[0].import_info.get_import_statement() + ) + + +def test_ignoring_indented_imports(self): + self.mod.write(dedent("""\ + if True: + import pkg1 + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.imports + self.assertEqual(0, len(imports)) + + +def test_import_get_names(self): + self.mod.write("import pkg1 as pkg\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.imports + context = importinfo.ImportContext(self.project, self.project.root) + self.assertEqual(["pkg"], imports[0].import_info.get_imported_names(context)) + + +def test_import_get_names_with_alias(self): + self.mod.write("import pkg1.mod1\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.imports + context = importinfo.ImportContext(self.project, self.project.root) + self.assertEqual(["pkg1"], imports[0].import_info.get_imported_names(context)) + + +def test_import_get_names_with_alias2(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + """)) + self.mod.write("from pkg1.mod1 import *\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.imports + context = importinfo.ImportContext(self.project, self.project.root) + self.assertEqual(["a_func"], imports[0].import_info.get_imported_names(context)) + + +def test_empty_getting_used_imports(self): + self.mod.write("") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.get_used_imports(pymod) + self.assertEqual(0, len(imports)) + + +def test_empty_getting_used_imports2(self): + self.mod.write("import pkg\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.get_used_imports(pymod) + self.assertEqual(0, len(imports)) + + +def test_simple_getting_used_imports(self): + self.mod.write("import pkg\nprint(pkg)\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.get_used_imports(pymod) + self.assertEqual(1, len(imports)) + self.assertEqual("import pkg", imports[0].get_import_statement()) + + +class _ExtractInfo: + """Holds information about the extract to be performed""" + + @others + +def test_simple_getting_used_imports2(self): + self.mod.write(dedent("""\ + import pkg + def a_func(): + print(pkg) + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.get_used_imports(pymod) + self.assertEqual(1, len(imports)) + self.assertEqual("import pkg", imports[0].get_import_statement()) + + +def test_getting_used_imports_for_nested_scopes(self): + self.mod.write(dedent("""\ + import pkg1 + print(pkg1) + def a_func(): + pass + print(pkg1) + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.get_used_imports(pymod["a_func"].get_object()) + self.assertEqual(0, len(imports)) + + +def test_getting_used_imports_for_nested_scopes2(self): + self.mod.write(dedent("""\ + from pkg1 import mod1 + def a_func(): + print(mod1) + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.get_used_imports(pymod["a_func"].get_object()) + self.assertEqual(1, len(imports)) + self.assertEqual("from pkg1 import mod1", imports[0].get_import_statement()) + + +def test_empty_removing_unused_imports(self): + self.mod.write("import pkg1\nprint(pkg1)\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + "import pkg1\nprint(pkg1)\n", module_with_imports.get_changed_source() + ) + + +def test_simple_removing_unused_imports(self): + self.mod.write("import pkg1\n\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual("", module_with_imports.get_changed_source()) + + +def test_simple_removing_unused_imports_for_froms(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import a_func, another_func + + a_func() + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + from pkg1.mod1 import a_func + + a_func() + """), + module_with_imports.get_changed_source(), + ) + + +def test_simple_removing_unused_imports_for_from_stars(self): + self.mod.write(dedent("""\ + from pkg1.mod1 import * + + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual("", module_with_imports.get_changed_source()) + + +def test_simple_removing_unused_imports_for_nested_modules(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + """)) + self.mod.write(dedent("""\ + import pkg1.mod1 + pkg1.mod1.a_func()""")) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + "import pkg1.mod1\npkg1.mod1.a_func()", + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_and_functions_of_the_same_name(self): + self.mod.write(dedent("""\ + def a_func(): + pass + def a_func(): + pass + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + def a_func(): + pass + def a_func(): + pass + """), + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_for_from_import_with_as(self): + self.mod.write("a_var = 1\n") + self.mod1.write(dedent("""\ + from mod import a_var as myvar + a_var = myvar + """)) + pymod = self.project.get_pymodule(self.mod1) + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + from mod import a_var as myvar + a_var = myvar + """), + module_with_imports.get_changed_source(), + ) + + +def __init__( + self, project, resource, start, end, new_name, variable, similar, make_global +): + self.project = project + self.resource = resource + self.pymodule = project.get_pymodule(resource) + self.global_scope = self.pymodule.get_scope() + self.source = self.pymodule.source_code + self.lines = self.pymodule.lines + self.new_name = new_name + self.variable = variable + self.similar = similar + self._init_parts(start, end) + self.kind = None + self._init_scope() + self.make_global = make_global + + +def test_not_removing_imports_that_conflict_with_class_names(self): + code = dedent("""\ + import pkg1 + class A(object): + pkg1 = 0 + def f(self): + a_var = pkg1 + """) + self.mod.write(code) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual(code, module_with_imports.get_changed_source()) + + +def test_adding_imports(self): + self.mod.write("\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + new_import = self.import_tools.get_import(self.mod1) + module_with_imports.add_import(new_import) + self.assertEqual("import pkg1.mod1\n", module_with_imports.get_changed_source()) + + +def test_adding_imports_no_pull_to_top(self): + self.mod.write(dedent("""\ + import pkg2.mod3 + class A(object): + pass + + import pkg2.mod2 + """)) + pymod = self.project.get_module("mod") + self.project.prefs["pull_imports_to_top"] = False + module_with_imports = self.import_tools.module_imports(pymod) + new_import = self.import_tools.get_import(self.mod1) + module_with_imports.add_import(new_import) + self.assertEqual( + dedent("""\ + import pkg2.mod3 + class A(object): + pass + + import pkg2.mod2 + import pkg1.mod1 + """), + module_with_imports.get_changed_source(), + ) + + +def test_adding_from_imports(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write("from pkg1.mod1 import a_func\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + new_import = self.import_tools.get_from_import(self.mod1, "another_func") + module_with_imports.add_import(new_import) + self.assertEqual( + "from pkg1.mod1 import a_func, another_func\n", + module_with_imports.get_changed_source(), + ) + + +def test_adding_to_star_imports(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write("from pkg1.mod1 import *\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + new_import = self.import_tools.get_from_import(self.mod1, "another_func") + module_with_imports.add_import(new_import) + self.assertEqual( + "from pkg1.mod1 import *\n", module_with_imports.get_changed_source() + ) + + +def test_adding_star_imports(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write("from pkg1.mod1 import a_func\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + new_import = self.import_tools.get_from_import(self.mod1, "*") + module_with_imports.add_import(new_import) + self.assertEqual( + "from pkg1.mod1 import *\n", module_with_imports.get_changed_source() + ) + + +def test_adding_imports_and_preserving_spaces_after_imports(self): + self.mod.write(dedent("""\ + import pkg1 + + + print(pkg1) + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + new_import = self.import_tools.get_import(self.pkg2) + module_with_imports.add_import(new_import) + self.assertEqual( + dedent("""\ + import pkg1 + import pkg2 + + + print(pkg1) + """), + module_with_imports.get_changed_source(), + ) + + +def test_not_changing_the_format_of_unchanged_imports(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import (a_func, + another_func) + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + self.assertEqual( + dedent("""\ + from pkg1.mod1 import (a_func, + another_func) + """), + module_with_imports.get_changed_source(), + ) + + +def test_not_changing_the_format_of_unchanged_imports2(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import (a_func) + a_func() + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + from pkg1.mod1 import (a_func) + a_func() + """), + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_and_reoccuring_names(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import * + from pkg1.mod1 import a_func + a_func() + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + from pkg1.mod1 import * + a_func() + """), + module_with_imports.get_changed_source(), + ) + + +def _init_parts(self, start, end): + self.region = ( + self._choose_closest_line_end(start), + self._choose_closest_line_end(end, end=True), + ) + + start = self.logical_lines.logical_line_in( + self.lines.get_line_number(self.region[0]) + )[0] + end = self.logical_lines.logical_line_in( + self.lines.get_line_number(self.region[1]) + )[1] + self.region_lines = (start, end) + + self.lines_region = ( + self.lines.get_line_start(self.region_lines[0]), + self.lines.get_line_end(self.region_lines[1]), + ) + + +def test_removing_unused_imports_and_reoccuring_names2(self): + self.mod.write(dedent("""\ + import pkg2.mod2 + import pkg2.mod3 + print(pkg2.mod2, pkg2.mod3)""")) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + import pkg2.mod2 + import pkg2.mod3 + print(pkg2.mod2, pkg2.mod3)"""), + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_and_common_packages(self): + self.mod.write(dedent("""\ + import pkg1.mod1 + import pkg1 + print(pkg1, pkg1.mod1) + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + import pkg1.mod1 + print(pkg1, pkg1.mod1) + """), + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_and_common_packages_reversed(self): + self.mod.write(dedent("""\ + import pkg1 + import pkg1.mod1 + print(pkg1, pkg1.mod1) + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_duplicates() + self.assertEqual( + dedent("""\ + import pkg1.mod1 + print(pkg1, pkg1.mod1) + """), + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_and_common_packages2(self): + self.mod.write(dedent("""\ + import pkg1.mod1 + import pkg1.mod2 + print(pkg1) + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + import pkg1.mod1 + print(pkg1) + """), + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_and_froms(self): + self.mod1.write(dedent("""\ + def func1(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import func1 + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual("", module_with_imports.get_changed_source()) + + +def test_removing_unused_imports_and_froms2(self): + self.mod1.write(dedent("""\ + def func1(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import func1 + func1()""")) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + from pkg1.mod1 import func1 + func1()"""), + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_and_froms3(self): + self.mod1.write(dedent("""\ + def func1(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import func1 + def a_func(): + func1() + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + from pkg1.mod1 import func1 + def a_func(): + func1() + """), + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_and_froms4(self): + self.mod1.write(dedent("""\ + def func1(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import func1 + class A(object): + def a_func(self): + func1() + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + from pkg1.mod1 import func1 + class A(object): + def a_func(self): + func1() + """), + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_and_getting_attributes(self): + self.mod1.write(dedent("""\ + class A(object): + def f(self): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import A + var = A().f()""")) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + from pkg1.mod1 import A + var = A().f()"""), + module_with_imports.get_changed_source(), + ) + + +def test_removing_unused_imports_function_parameters(self): + self.mod1.write(dedent("""\ + def func1(): + pass + """)) + self.mod.write(dedent("""\ + import pkg1 + def a_func(pkg1): + my_var = pkg1 + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + def a_func(pkg1): + my_var = pkg1 + """), + module_with_imports.get_changed_source(), + ) + + +@property +def logical_lines(self): + return self.pymodule.logical_lines + + +def test_trivial_expanding_star_imports(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write("from pkg1.mod1 import *\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.expand_stars() + self.assertEqual("", module_with_imports.get_changed_source()) + + +def test_expanding_star_imports(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write("from pkg1.mod1 import *\na_func()\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.expand_stars() + self.assertEqual( + "from pkg1.mod1 import a_func\na_func()\n", + module_with_imports.get_changed_source(), + ) + + +def test_removing_duplicate_imports(self): + self.mod.write("import pkg1\nimport pkg1\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_duplicates() + self.assertEqual("import pkg1\n", module_with_imports.get_changed_source()) + + +def test_removing_duplicates_and_reoccuring_names(self): + self.mod.write("import pkg2.mod2\nimport pkg2.mod3\n") + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_duplicates() + self.assertEqual( + "import pkg2.mod2\nimport pkg2.mod3\n", + module_with_imports.get_changed_source(), + ) + + +def test_removing_duplicate_imports_for_froms(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1 import a_func + from pkg1 import a_func, another_func + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_duplicates() + self.assertEqual( + "from pkg1 import a_func, another_func\n", + module_with_imports.get_changed_source(), + ) + + +def test_transforming_froms_to_normal_changing_imports(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import a_func + print(a_func) + """)) + pymod = self.project.get_module("mod") + changed_module = self.import_tools.froms_to_imports(pymod) + self.assertEqual( + dedent("""\ + import pkg1.mod1 + print(pkg1.mod1.a_func) + """), + changed_module, + ) + + +def test_transforming_froms_to_normal_changing_occurrences(self): + self.mod1.write("def a_func():\n pass\n") + self.mod.write("from pkg1.mod1 import a_func\na_func()") + pymod = self.project.get_module("mod") + changed_module = self.import_tools.froms_to_imports(pymod) + self.assertEqual("import pkg1.mod1\npkg1.mod1.a_func()", changed_module) + + +def test_transforming_froms_to_normal_for_multi_imports(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import * + a_func() + another_func() + """)) + pymod = self.project.get_module("mod") + changed_module = self.import_tools.froms_to_imports(pymod) + self.assertEqual( + dedent("""\ + import pkg1.mod1 + pkg1.mod1.a_func() + pkg1.mod1.another_func() + """), + changed_module, + ) + + +def test_transform_froms_to_norm_for_multi_imports_inside_parens(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + def another_func(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import (a_func, + another_func) + a_func() + another_func() + """)) + pymod = self.project.get_module("mod") + changed_module = self.import_tools.froms_to_imports(pymod) + self.assertEqual( + dedent("""\ + import pkg1.mod1 + pkg1.mod1.a_func() + pkg1.mod1.another_func() + """), + changed_module, + ) + + +def test_transforming_froms_to_normal_from_stars(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import * + a_func() + """)) + pymod = self.project.get_module("mod") + changed_module = self.import_tools.froms_to_imports(pymod) + self.assertEqual( + dedent("""\ + import pkg1.mod1 + pkg1.mod1.a_func() + """), + changed_module, + ) + + +def _init_scope(self): + start_line = self.region_lines[0] + scope = self.global_scope.get_inner_scope_for_line(start_line) + if scope.get_kind() != "Module" and scope.get_start() == start_line: + scope = scope.parent + self.scope = scope + self.scope_region = self._get_scope_region(self.scope) + + +def test_transforming_froms_to_normal_from_stars2(self): + self.mod1.write("a_var = 10") + self.mod.write(dedent("""\ + import pkg1.mod1 + from pkg1.mod1 import a_var + def a_func(): + print(pkg1.mod1, a_var) + """)) + pymod = self.project.get_module("mod") + changed_module = self.import_tools.froms_to_imports(pymod) + self.assertEqual( + dedent("""\ + import pkg1.mod1 + def a_func(): + print(pkg1.mod1, pkg1.mod1.a_var) + """), + changed_module, + ) + + +def test_transforming_froms_to_normal_from_with_alias(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + """)) + self.mod.write(dedent("""\ + from pkg1.mod1 import a_func as another_func + another_func() + """)) + pymod = self.project.get_module("mod") + changed_module = self.import_tools.froms_to_imports(pymod) + self.assertEqual( + dedent("""\ + import pkg1.mod1 + pkg1.mod1.a_func() + """), + changed_module, + ) + + +def test_transforming_froms_to_normal_for_relatives(self): + self.mod2.write(dedent("""\ + def a_func(): + pass + """)) + self.mod3.write(dedent("""\ + from mod2 import * + a_func() + """)) + pymod = self.project.get_pymodule(self.mod3) + changed_module = self.import_tools.froms_to_imports(pymod) + self.assertEqual( + dedent("""\ + import pkg2.mod2 + pkg2.mod2.a_func() + """), + changed_module, + ) + + +def test_transforming_froms_to_normal_for_os_path(self): + self.mod.write("from os import path\npath.exists('.')\n") + pymod = self.project.get_pymodule(self.mod) + changed_module = self.import_tools.froms_to_imports(pymod) + self.assertEqual("import os\nos.path.exists('.')\n", changed_module) + + +def test_transform_relatives_imports_to_abs_imports_doing_nothing(self): + self.mod2.write("from pkg1 import mod1\nimport mod1\n") + pymod = self.project.get_pymodule(self.mod2) + self.assertEqual( + "from pkg1 import mod1\nimport mod1\n", + self.import_tools.relatives_to_absolutes(pymod), + ) + + +def test_transform_relatives_to_absolute_imports_for_normal_imports(self): + self.mod2.write("import mod3\n") + pymod = self.project.get_pymodule(self.mod2) + self.assertEqual( + "import pkg2.mod3\n", self.import_tools.relatives_to_absolutes(pymod) + ) + + +def test_transform_relatives_imports_to_absolute_imports_for_froms(self): + self.mod3.write(dedent("""\ + def a_func(): + pass + """)) + self.mod2.write("from mod3 import a_func\n") + pymod = self.project.get_pymodule(self.mod2) + self.assertEqual( + "from pkg2.mod3 import a_func\n", + self.import_tools.relatives_to_absolutes(pymod), + ) + + +@testutils.only_for("2.5") +def test_transform_rel_imports_to_abs_imports_for_new_relatives(self): + self.mod3.write(dedent("""\ + def a_func(): + pass + """)) + self.mod2.write("from .mod3 import a_func\n") + pymod = self.project.get_pymodule(self.mod2) + self.assertEqual( + "from pkg2.mod3 import a_func\n", + self.import_tools.relatives_to_absolutes(pymod), + ) + + +def test_transform_relatives_to_absolute_imports_for_normal_imports2(self): + self.mod2.write("import mod3\nprint(mod3)") + pymod = self.project.get_pymodule(self.mod2) + self.assertEqual( + "import pkg2.mod3\nprint(pkg2.mod3)", + self.import_tools.relatives_to_absolutes(pymod), + ) + + +def test_transform_relatives_to_absolute_imports_for_aliases(self): + self.mod2.write("import mod3 as mod3\nprint(mod3)") + pymod = self.project.get_pymodule(self.mod2) + self.assertEqual( + "import pkg2.mod3 as mod3\nprint(mod3)", + self.import_tools.relatives_to_absolutes(pymod), + ) + + +def _get_scope_region(self, scope): + return ( + self.lines.get_line_start(scope.get_start()), + self.lines.get_line_end(scope.get_end()) + 1, + ) + + +def test_organizing_imports(self): + self.mod1.write("import mod1\n") + pymod = self.project.get_pymodule(self.mod1) + self.assertEqual("", self.import_tools.organize_imports(pymod)) + + +def test_organizing_imports_without_deduplication(self): + contents = dedent("""\ + from pkg2 import mod2 + from pkg2 import mod3 + """) + self.mod.write(contents) + pymod = self.project.get_pymodule(self.mod) + self.project.prefs["split_imports"] = True + self.assertEqual( + contents, self.import_tools.organize_imports(pymod, unused=False) + ) + + +def test_splitting_imports(self): + self.mod.write(dedent("""\ + from pkg1 import mod1 + from pkg2 import mod2, mod3 + """)) + pymod = self.project.get_pymodule(self.mod) + self.project.prefs["split_imports"] = True + self.assertEqual( + dedent("""\ + from pkg1 import mod1 + from pkg2 import mod2 + from pkg2 import mod3 + """), + self.import_tools.organize_imports(pymod, unused=False), + ) + + +def test_splitting_imports_no_pull_to_top(self): + self.mod.write(dedent("""\ + from pkg2 import mod3, mod4 + from pkg1 import mod2 + from pkg1 import mod1 + """)) + pymod = self.project.get_pymodule(self.mod) + self.project.prefs["split_imports"] = True + self.project.prefs["pull_imports_to_top"] = False + self.assertEqual( + dedent("""\ + from pkg1 import mod2 + from pkg1 import mod1 + from pkg2 import mod3 + from pkg2 import mod4 + """), + self.import_tools.organize_imports(pymod, sort=False, unused=False), + ) + + +def test_splitting_imports_with_filter(self): + self.mod.write(dedent("""\ + from pkg1 import mod1, mod2 + from pkg2 import mod3, mod4 + """)) + pymod = self.project.get_pymodule(self.mod) + self.project.prefs["split_imports"] = True + + def import_filter(stmt): + return stmt.import_info.module_name == "pkg1" + + self.assertEqual( + dedent("""\ + from pkg1 import mod1 + from pkg1 import mod2 + from pkg2 import mod3, mod4 + """), + self.import_tools.organize_imports( + pymod, unused=False, import_filter=import_filter + ), + ) + + +def test_splitting_duplicate_imports(self): + self.mod.write(dedent("""\ + from pkg2 import mod1 + from pkg2 import mod1, mod2 + """)) + pymod = self.project.get_pymodule(self.mod) + self.project.prefs["split_imports"] = True + self.assertEqual( + dedent("""\ + from pkg2 import mod1 + from pkg2 import mod2 + """), + self.import_tools.organize_imports(pymod, unused=False), + ) + + +def test_splitting_duplicate_imports2(self): + self.mod.write(dedent("""\ + from pkg2 import mod1, mod3 + from pkg2 import mod1, mod2 + from pkg2 import mod2, mod3 + """)) + pymod = self.project.get_pymodule(self.mod) + self.project.prefs["split_imports"] = True + self.assertEqual( + dedent("""\ + from pkg2 import mod1 + from pkg2 import mod2 + from pkg2 import mod3 + """), + self.import_tools.organize_imports(pymod, unused=False), + ) + + +def test_removing_self_imports(self): + self.mod.write(dedent("""\ + import mod + mod.a_var = 1 + print(mod.a_var) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + a_var = 1 + print(a_var) + """), + self.import_tools.organize_imports(pymod), + ) + + +def test_removing_self_imports2(self): + self.mod1.write(dedent("""\ + import pkg1.mod1 + pkg1.mod1.a_var = 1 + print(pkg1.mod1.a_var) + """)) + pymod = self.project.get_pymodule(self.mod1) + self.assertEqual( + dedent("""\ + a_var = 1 + print(a_var) + """), + self.import_tools.organize_imports(pymod), + ) + + +def test_removing_self_imports_with_as(self): + self.mod.write(dedent("""\ + import mod as mymod + mymod.a_var = 1 + print(mymod.a_var) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + a_var = 1 + print(a_var) + """), + self.import_tools.organize_imports(pymod), + ) + + +def _check_exceptional_conditions(self): + if self.info.element_already_exists(): + raise exceptions.RefactoringError( + "Element <%s> already exists." % self.name + ) + if not self.info.primary_is_found(): + raise exceptions.RefactoringError( + "Cannot determine the scope <%s> should be defined in." % self.name + ) + + +def _choose_closest_line_end(self, offset, end=False): + lineno = self.lines.get_line_number(offset) + line_start = self.lines.get_line_start(lineno) + line_end = self.lines.get_line_end(lineno) + if self.source[line_start:offset].strip() == "": + if end: + return line_start - 1 + else: + return line_start + elif self.source[offset:line_end].strip() == "": + return min(line_end, len(self.source)) + return offset + + +def test_removing_self_imports_for_froms(self): + self.mod1.write(dedent("""\ + from pkg1 import mod1 + mod1.a_var = 1 + print(mod1.a_var) + """)) + pymod = self.project.get_pymodule(self.mod1) + self.assertEqual( + dedent("""\ + a_var = 1 + print(a_var) + """), + self.import_tools.organize_imports(pymod), + ) + + +def test_removing_self_imports_for_froms_with_as(self): + self.mod1.write(dedent("""\ + from pkg1 import mod1 as mymod + mymod.a_var = 1 + print(mymod.a_var) + """)) + pymod = self.project.get_pymodule(self.mod1) + self.assertEqual( + dedent("""\ + a_var = 1 + print(a_var) + """), + self.import_tools.organize_imports(pymod), + ) + + +def test_removing_self_imports_for_froms2(self): + self.mod.write(dedent("""\ + from mod import a_var + a_var = 1 + print(a_var) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + a_var = 1 + print(a_var) + """), + self.import_tools.organize_imports(pymod), + ) + + +def test_removing_self_imports_for_froms3(self): + self.mod.write(dedent("""\ + from mod import a_var + a_var = 1 + print(a_var) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + a_var = 1 + print(a_var) + """), + self.import_tools.organize_imports(pymod), + ) + + +def test_removing_self_imports_for_froms4(self): + self.mod.write(dedent("""\ + from mod import a_var as myvar + a_var = 1 + print(myvar) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + a_var = 1 + print(a_var) + """), + self.import_tools.organize_imports(pymod), + ) + + +def test_removing_self_imports_with_no_dot_after_mod(self): + self.mod.write(dedent("""\ + import mod + print(mod) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + import mod + + + print(mod) + """), + self.import_tools.organize_imports(pymod), + ) + + +def test_removing_self_imports_with_no_dot_after_mod2(self): + self.mod.write(dedent("""\ + import mod + a_var = 1 + print(mod\\ + \\ + .var) + + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + a_var = 1 + print(var) + + """), + self.import_tools.organize_imports(pymod), + ) + + +def test_removing_self_imports_for_from_import_star(self): + self.mod.write(dedent("""\ + from mod import * + a_var = 1 + print(myvar) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + a_var = 1 + print(myvar) + """), + self.import_tools.organize_imports(pymod), + ) + + +def test_not_removing_future_imports(self): + self.mod.write("from __future__ import division\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + "from __future__ import division\n", + self.import_tools.organize_imports(pymod), + ) + + +def test_sorting_empty_imports(self): + self.mod.write("") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual("", self.import_tools.sort_imports(pymod)) + + +@property +def one_line(self): + return self.region != self.lines_region and ( + self.logical_lines.logical_line_in(self.region_lines[0]) + == self.logical_lines.logical_line_in(self.region_lines[1]) + ) + + +def test_sorting_one_import(self): + self.mod.write("import pkg1.mod1\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual("import pkg1.mod1\n", self.import_tools.sort_imports(pymod)) + + +def test_sorting_imports_alphabetically(self): + self.mod.write("import pkg2.mod2\nimport pkg1.mod1\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + "import pkg1.mod1\nimport pkg2.mod2\n", + self.import_tools.sort_imports(pymod), + ) + + +def test_sorting_imports_purely_alphabetically(self): + self.mod.write(dedent("""\ + from pkg2 import mod3 as mod0 + import pkg2.mod2 + import pkg1.mod1 + """)) + pymod = self.project.get_pymodule(self.mod) + self.project.prefs["sort_imports_alphabetically"] = True + self.assertEqual( + dedent("""\ + import pkg1.mod1 + import pkg2.mod2 + from pkg2 import mod3 as mod0 + """), + self.import_tools.sort_imports(pymod), + ) + + +def test_sorting_imports_and_froms(self): + self.mod.write("import pkg2.mod2\nfrom pkg1 import mod1\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + "import pkg2.mod2\nfrom pkg1 import mod1\n", + self.import_tools.sort_imports(pymod), + ) + + +def test_sorting_imports_and_standard_modules(self): + self.mod.write(dedent("""\ + import pkg1 + import sys + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + import sys + + import pkg1 + """), + self.import_tools.sort_imports(pymod), + ) + + +def test_sorting_imports_and_standard_modules2(self): + self.mod.write(dedent("""\ + import sys + + import time + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + import sys + import time + """), + self.import_tools.sort_imports(pymod), + ) + + +def test_sorting_only_standard_modules(self): + self.mod.write("import sys\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual("import sys\n", self.import_tools.sort_imports(pymod)) + + +def test_sorting_third_party(self): + self.mod.write(dedent("""\ + import pkg1 + import a_third_party + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + import a_third_party + + import pkg1 + """), + self.import_tools.sort_imports(pymod), + ) + + +def test_sorting_only_third_parties(self): + self.mod.write(dedent("""\ + import a_third_party + a_var = 1 + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + import a_third_party + + + a_var = 1 + """), + self.import_tools.sort_imports(pymod), + ) + + +def test_simple_handling_long_imports(self): + self.mod.write(dedent("""\ + import pkg1.mod1 + + + m = pkg1.mod1 + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + import pkg1.mod1 + + + m = pkg1.mod1 + """), + self.import_tools.handle_long_imports(pymod, maxdots=2), + ) + + +@property +def global_(self): + return self.scope.parent is None + + +def test_handling_long_imports_for_many_dots(self): + self.mod.write(dedent("""\ + import p1.p2.p3.m1 + + + m = p1.p2.p3.m1 + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + from p1.p2.p3 import m1 + + + m = m1 + """), + self.import_tools.handle_long_imports(pymod, maxdots=2), + ) + + +def test_handling_long_imports_for_their_length(self): + self.mod.write(dedent("""\ + import p1.p2.p3.m1 + + + m = p1.p2.p3.m1 + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + import p1.p2.p3.m1 + + + m = p1.p2.p3.m1 + """), + self.import_tools.handle_long_imports(pymod, maxdots=3, maxlength=20), + ) + + +def test_handling_long_imports_for_many_dots2(self): + self.mod.write(dedent("""\ + import p1.p2.p3.m1 + + + m = p1.p2.p3.m1 + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + from p1.p2.p3 import m1 + + + m = m1 + """), + self.import_tools.handle_long_imports(pymod, maxdots=3, maxlength=10), + ) + + +def test_handling_long_imports_with_one_letter_last(self): + self.mod.write(dedent("""\ + import p1.p2.p3.l + + + m = p1.p2.p3.l + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + from p1.p2.p3 import l + + + m = l + """), + self.import_tools.handle_long_imports(pymod, maxdots=2), + ) + + +def test_empty_removing_unused_imports_and_eating_blank_lines(self): + self.mod.write(dedent("""\ + import pkg1 + import pkg2 + + + print(pkg1) + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + module_with_imports.remove_unused_imports() + self.assertEqual( + dedent("""\ + import pkg1 + + + print(pkg1) + """), + module_with_imports.get_changed_source(), + ) + + +def test_sorting_imports_moving_to_top(self): + self.mod.write(dedent("""\ + import mod + def f(): + print(mod, pkg1, pkg2) + import pkg1 + import pkg2 + """)) + pymod = self.project.get_module("mod") + self.assertEqual( + dedent("""\ + import mod + import pkg1 + import pkg2 + + + def f(): + print(mod, pkg1, pkg2) + """), + self.import_tools.sort_imports(pymod), + ) + + +def test_sorting_imports_moving_to_top2(self): + self.mod.write(dedent("""\ + def f(): + print(mod) + import mod + """)) + pymod = self.project.get_module("mod") + self.assertEqual( + dedent("""\ + import mod + + + def f(): + print(mod) + """), + self.import_tools.sort_imports(pymod), + ) + + +# Sort pulls imports to the top anyway +def test_sorting_imports_no_pull_to_top(self): + code = dedent("""\ + import pkg2 + def f(): + print(mod, pkg1, pkg2) + import pkg1 + import mod + """) + self.mod.write(code) + pymod = self.project.get_module("mod") + self.project.prefs["pull_imports_to_top"] = False + self.assertEqual( + dedent("""\ + import mod + import pkg1 + import pkg2 + + + def f(): + print(mod, pkg1, pkg2) + """), + self.import_tools.sort_imports(pymod), + ) + + +def test_sorting_imports_moving_to_top_and_module_docs(self): + self.mod.write(dedent('''\ + """ + docs + """ + def f(): + print(mod) + import mod + ''')) + pymod = self.project.get_module("mod") + self.assertEqual( + dedent('''\ + """ + docs + """ + import mod + + + def f(): + print(mod) + '''), + self.import_tools.sort_imports(pymod), + ) + + +def test_sorting_imports_moving_to_top_and_module_docs2(self): + self.mod.write(dedent('''\ + """ + docs + """ + + + import bbb + import aaa + def f(): + print(mod) + import mod + ''')) + pymod = self.project.get_module("mod") + self.assertEqual( + dedent('''\ + """ + docs + """ + + + import aaa + import bbb + + import mod + + + def f(): + print(mod) + '''), + self.import_tools.sort_imports(pymod), + ) + + +@property +def method(self): + return self.scope.parent is not None and self.scope.parent.get_kind() == "Class" + + +def test_get_changed_source_preserves_blank_lines(self): + self.mod.write(dedent("""\ + __author__ = "author" + + import aaa + + import bbb + + def f(): + print(mod) + """)) + pymod = self.project.get_module("mod") + module_with_imports = self.import_tools.module_imports(pymod) + self.assertEqual( + dedent("""\ + import aaa + + import bbb + + __author__ = "author" + + def f(): + print(mod) + """), + module_with_imports.get_changed_source(), + ) + + +def test_sorting_future_imports(self): + self.mod.write(dedent("""\ + import os + from __future__ import devision + """)) + pymod = self.project.get_module("mod") + self.assertEqual( + dedent("""\ + from __future__ import devision + + import os + """), + self.import_tools.sort_imports(pymod), + ) + + +def test_organizing_imports_all_star(self): + code = expected = dedent("""\ + from package import some_name + + + __all__ = ["some_name"] + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_organizing_imports_all_star_with_variables(self): + code = expected = dedent("""\ + from package import name_one, name_two + + + if something(): + foo = 'name_one' + else: + foo = 'name_two' + __all__ = [foo] + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_organizing_imports_all_star_with_inline_if(self): + code = expected = dedent("""\ + from package import name_one, name_two + + + __all__ = ['name_one' if something() else 'name_two'] + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +@testutils.only_for_versions_higher("3") +def test_organizing_imports_all_star_tolerates_non_list_of_str_1(self): + code = expected = dedent("""\ + from package import name_one, name_two + + + foo = 'name_two' + __all__ = [bar, *abc] + mylist + __all__ = [foo, 'name_one', *abc] + __all__ = [it for it in mylist] + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_organizing_imports_all_star_assigned_name_alias(self): + code = expected = dedent("""\ + from package import name_one, name_two + + + foo = ['name_one', 'name_two'] + __all__ = foo + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_organizing_imports_all_star_imported_name_alias(self): + self.mod1.write("foo = ['name_one', 'name_two']") + self.mod2.write("from pkg1.mod1 import foo") + code = expected = dedent("""\ + from package import name_one, name_two + + from pkg2.mod2 import foo + + + __all__ = foo + """) + self.mod3.write(code) + pymod = self.project.get_pymodule(self.mod3) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_organizing_imports_all_star_tolerates_non_list_of_str_2(self): + code = expected = dedent("""\ + from package import name_one, name_two + + + foo = 'name_two' + __all__ = [foo, 3, 'name_one'] + __all__ = [it for it in mylist] + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_organizing_imports_all_star_plusjoin(self): + code = expected = dedent("""\ + from package import name_one, name_two + + + foo = ['name_two'] + __all__ = ['name_one'] + foo + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +@property +def indents(self): + return sourceutils.get_indents(self.pymodule.lines, self.region_lines[0]) + + +def test_organizing_imports_all_star_starjoin(self): + code = expected = dedent("""\ + from package import name_one, name_two + + + foo = ['name_two'] + __all__ = ['name_one', *foo] + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +@testutils.time_limit(60) +def test_organizing_imports_all_star_no_infinite_loop(self): + code = expected = dedent("""\ + from package import name_one, name_two + + + foo = bar + bar = foo + __all__ = [foo, 'name_one', 'name_two'] + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_organizing_imports_all_star_resolve_imported_name(self): + self.mod1.write("foo = 'name_one'") + + code = expected = dedent("""\ + from package import name_one, name_two + + from pkg1.mod1 import foo + + + __all__ = [foo, 'name_two'] + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_organizing_imports_undefined_variable(self): + code = expected = dedent("""\ + from foo import some_name + + + __all__ = ['some_name', undefined_variable] + """) + self.mod1.write(code) + + pymod = self.project.get_pymodule(self.mod1) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_organizing_imports_undefined_variable_with_imported_name(self): + self.mod1.write("") + self.mod2.write("from pkg1.mod1 import undefined_variable") + + code = expected = dedent("""\ + from pkg2.mod2 import undefined_variable + + + __all__ = undefined_variable + """) + self.mod3.write(code) + + pymod = self.project.get_pymodule(self.mod3) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_organizing_indirect_all_star_import(self): + self.mod1.write("some_name = 1") + self.mod2.write(dedent("""\ + __all__ = ['some_name', *imported_all] + """)) + + code = expected = dedent("""\ + from mod1 import some_name + + from mod2 import __all__ + """) + self.mod3.write(code) + + pymod = self.project.get_pymodule(self.mod3) + self.assertEqual(expected, self.import_tools.organize_imports(pymod)) + + +def test_customized_import_organization(self): + self.mod.write(dedent("""\ + import sys + import sys + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + "import sys\n", self.import_tools.organize_imports(pymod, unused=False) + ) + + +def test_customized_import_organization2(self): + self.mod.write("import sys\n") + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + "import sys\n", self.import_tools.organize_imports(pymod, unused=False) + ) + + +def test_customized_import_organization3(self): + self.mod.write(dedent("""\ + import sys + import mod + + + var = 1 + print(mod.var) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + import sys + + + var = 1 + print(var) + """), + self.import_tools.organize_imports(pymod, unused=False), + ) + + +def test_trivial_filtered_expand_stars(self): + self.pkg1.get_child("__init__.py").write("var1 = 1\n") + self.pkg2.get_child("__init__.py").write("var2 = 1\n") + self.mod.write(dedent("""\ + from pkg1 import * + from pkg2 import * + + print(var1, var2) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + from pkg1 import * + from pkg2 import * + + print(var1, var2) + """), + self.import_tools.expand_stars(pymod, lambda stmt: False), + ) + + +@property +def scope_indents(self): + if self.global_: + return 0 + return sourceutils.get_indents(self.pymodule.lines, self.scope.get_start()) + + +def _line_filter(self, lineno): + def import_filter(import_stmt): + return import_stmt.start_line <= lineno < import_stmt.end_line + + return import_filter + + +def test_filtered_expand_stars(self): + self.pkg1.get_child("__init__.py").write("var1 = 1\n") + self.pkg2.get_child("__init__.py").write("var2 = 1\n") + self.mod.write(dedent("""\ + from pkg1 import * + from pkg2 import * + + print(var1, var2) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + from pkg1 import * + from pkg2 import var2 + + print(var1, var2) + """), + self.import_tools.expand_stars(pymod, self._line_filter(2)), + ) + + +def test_filtered_relative_to_absolute(self): + self.mod3.write("var = 1") + self.mod2.write("import mod3\n\nprint(mod3.var)\n") + pymod = self.project.get_pymodule(self.mod2) + self.assertEqual( + dedent("""\ + import mod3 + + print(mod3.var) + """), + self.import_tools.relatives_to_absolutes(pymod, lambda stmt: False), + ) + self.assertEqual( + dedent("""\ + import pkg2.mod3 + + print(pkg2.mod3.var) + """), + self.import_tools.relatives_to_absolutes(pymod, self._line_filter(1)), + ) + + +def test_filtered_froms_to_normals(self): + self.pkg1.get_child("__init__.py").write("var1 = 1\n") + self.pkg2.get_child("__init__.py").write("var2 = 1\n") + self.mod.write(dedent("""\ + from pkg1 import var1 + from pkg2 import var2 + + print(var1, var2) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + from pkg1 import var1 + from pkg2 import var2 + + print(var1, var2) + """), + self.import_tools.expand_stars(pymod, lambda stmt: False), + ) + self.assertEqual( + dedent("""\ + from pkg1 import var1 + import pkg2 + + print(var1, pkg2.var2) + """), + self.import_tools.froms_to_imports(pymod, self._line_filter(2)), + ) + + +def test_filtered_froms_to_normals2(self): + self.pkg1.get_child("__init__.py").write("var1 = 1\n") + self.pkg2.get_child("__init__.py").write("var2 = 1\n") + self.mod.write(dedent("""\ + from pkg1 import * + from pkg2 import * + + print(var1, var2) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + from pkg1 import * + import pkg2 + + print(var1, pkg2.var2) + """), + self.import_tools.froms_to_imports(pymod, self._line_filter(2)), + ) + + +def test_filtered_handle_long_imports(self): + self.mod.write(dedent("""\ + import p1.p2.p3.m1 + import pkg1.mod1 + + + m = p1.p2.p3.m1, pkg1.mod1 + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + import p1.p2.p3.m1 + from pkg1 import mod1 + + + m = p1.p2.p3.m1, mod1 + """), + self.import_tools.handle_long_imports( + pymod, maxlength=5, import_filter=self._line_filter(2) + ), + ) + + +def test_filtering_and_import_actions_with_more_than_one_phase(self): + self.pkg1.get_child("__init__.py").write("var1 = 1\n") + self.pkg2.get_child("__init__.py").write("var2 = 1\n") + self.mod.write(dedent("""\ + from pkg1 import * + from pkg2 import * + + print(var2) + """)) + pymod = self.project.get_pymodule(self.mod) + self.assertEqual( + dedent("""\ + from pkg2 import * + + print(var2) + """), + self.import_tools.expand_stars(pymod, self._line_filter(1)), + ) + + +def test_non_existent_module_and_used_imports(self): + self.mod.write(dedent("""\ + from does_not_exist import func + + func() + """)) + pymod = self.project.get_module("mod") + + module_with_imports = self.import_tools.module_imports(pymod) + imports = module_with_imports.get_used_imports(pymod) + self.assertEqual(1, len(imports)) + + + +class AddImportTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + self.mod1 = testutils.create_module(self.project, "mod1") + self.mod2 = testutils.create_module(self.project, "mod2") + self.pkg = testutils.create_package(self.project, "pkg") + self.mod3 = testutils.create_module(self.project, "mod3", self.pkg) + + +@property +def extracted(self): + return self.source[self.region[0] : self.region[1]] + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_normal_imports(self): + self.mod2.write("myvar = None\n") + self.mod1.write("\n") + pymod = self.project.get_module("mod1") + result, name = add_import(self.project, pymod, "mod2", "myvar") + self.assertEqual("import mod2\n", result) + self.assertEqual("mod2.myvar", name) + + +def test_not_reimporting_a_name(self): + self.mod2.write("myvar = None\n") + self.mod1.write("from mod2 import myvar\n") + pymod = self.project.get_module("mod1") + result, name = add_import(self.project, pymod, "mod2", "myvar") + self.assertEqual("from mod2 import myvar\n", result) + self.assertEqual("myvar", name) + + +def test_adding_import_when_siblings_are_imported(self): + self.mod2.write("var1 = None\nvar2 = None\n") + self.mod1.write("from mod2 import var1\n") + pymod = self.project.get_module("mod1") + result, name = add_import(self.project, pymod, "mod2", "var2") + self.assertEqual("from mod2 import var1, var2\n", result) + self.assertEqual("var2", name) + + +def test_adding_import_when_the_package_is_imported(self): + self.pkg.get_child("__init__.py").write("var1 = None\n") + self.mod3.write("var2 = None\n") + self.mod1.write("from pkg import var1\n") + pymod = self.project.get_module("mod1") + result, name = add_import(self.project, pymod, "pkg.mod3", "var2") + self.assertEqual("from pkg import var1, mod3\n", result) + self.assertEqual("mod3.var2", name) + + +def test_adding_import_for_modules_instead_of_names(self): + self.pkg.get_child("__init__.py").write("var1 = None\n") + self.mod3.write("\n") + self.mod1.write("from pkg import var1\n") + pymod = self.project.get_module("mod1") + result, name = add_import(self.project, pymod, "pkg.mod3", None) + self.assertEqual("from pkg import var1, mod3\n", result) + self.assertEqual("mod3", name) + + +def test_adding_import_for_modules_with_normal_duplicate_imports(self): + self.pkg.get_child("__init__.py").write("var1 = None\n") + self.mod3.write("\n") + self.mod1.write("import pkg.mod3\n") + pymod = self.project.get_module("mod1") + result, name = add_import(self.project, pymod, "pkg.mod3", None) + self.assertEqual("import pkg.mod3\n", result) + self.assertEqual("pkg.mod3", name) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +from textwrap import dedent + +import unittest + +import rope.base.exceptions +from rope.refactor import inline +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class InlineTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + self.mod2 = testutils.create_module(self.project, "mod2") + + +_cached_parsed_extraced = None + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _inline(self, code, offset, **kwds): + self.mod.write(code) + self._inline2(self.mod, offset, **kwds) + return self.mod.read() + + +def _inline2(self, resource, offset, **kwds): + inliner = inline.create_inline(self.project, resource, offset) + changes = inliner.get_changes(**kwds) + self.project.do(changes) + return self.mod.read() + + +def test_simple_case(self): + code = dedent("""\ + a_var = 10 + another_var = a_var + """) + refactored = self._inline(code, code.index("a_var") + 1) + self.assertEqual("another_var = 10\n", refactored) + + +def test_empty_case(self): + code = "a_var = 10\n" + refactored = self._inline(code, code.index("a_var") + 1) + self.assertEqual("", refactored) + + +def test_long_definition(self): + code = dedent("""\ + a_var = 10 + (10 + 10) + another_var = a_var + """) + refactored = self._inline(code, code.index("a_var") + 1) + self.assertEqual("another_var = 10 + (10 + 10)\n", refactored) + + +def test_explicit_continuation(self): + code = dedent("""\ + a_var = (10 + + 10) + another_var = a_var + """) + refactored = self._inline(code, code.index("a_var") + 1) + self.assertEqual( + dedent("""\ + another_var = (10 + + 10) + """), + refactored, + ) + + +def test_implicit_continuation(self): + code = dedent("""\ + a_var = 10 +\\ + 10 + another_var = a_var + """) + refactored = self._inline(code, code.index("a_var") + 1) + self.assertEqual( + dedent("""\ + another_var = 10 +\\ + 10 + """), + refactored, + ) + + +def test_inlining_at_the_end_of_input(self): + code = dedent("""\ + a = 1 + b = a""") + refactored = self._inline(code, code.index("a") + 1) + self.assertEqual("b = 1", refactored) + + +def test_on_classes(self): + code = dedent("""\ + class AClass(object): + pass + """) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self._inline(code, code.index("AClass") + 1) + + +@property +def _parsed_extracted(self): + if self._cached_parsed_extraced is None: + self._cached_parsed_extraced = _parse_text(self.extracted) + return self._cached_parsed_extraced + + +def test_multiple_assignments(self): + code = dedent("""\ + a_var = 10 + a_var = 20 + """) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self._inline(code, code.index("a_var") + 1) + + +def test_tuple_assignments(self): + code = "a_var, another_var = (20, 30)\n" + with self.assertRaises(rope.base.exceptions.RefactoringError): + self._inline(code, code.index("a_var") + 1) + + +def test_on_unknown_vars(self): + code = "a_var = another_var\n" + with self.assertRaises(rope.base.exceptions.RefactoringError): + self._inline(code, code.index("another_var") + 1) + + +def test_attribute_inlining(self): + code = dedent("""\ + class A(object): + def __init__(self): + self.an_attr = 3 + range(self.an_attr) + """) + refactored = self._inline(code, code.index("an_attr") + 1) + expected = dedent("""\ + class A(object): + def __init__(self): + range(3) + """) + self.assertEqual(expected, refactored) + + +def test_attribute_inlining2(self): + code = dedent("""\ + class A(object): + def __init__(self): + self.an_attr = 3 + range(self.an_attr) + a = A() + range(a.an_attr)""") + refactored = self._inline(code, code.index("an_attr") + 1) + expected = dedent("""\ + class A(object): + def __init__(self): + range(3) + a = A() + range(3)""") + self.assertEqual(expected, refactored) + + +def test_a_function_with_no_occurrence(self): + self.mod.write(dedent("""\ + def a_func(): + pass + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("", self.mod.read()) + + +def test_a_function_with_no_occurrence2(self): + self.mod.write(dedent("""\ + a_var = 10 + def a_func(): + pass + print(a_var) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + a_var = 10 + print(a_var) + """), + self.mod.read(), + ) + + +def test_replacing_calls_with_function_definition_in_other_modules(self): + self.mod.write(dedent("""\ + def a_func(): + print(1) + """)) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + import mod + mod.a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + import mod + print(1) + """), + mod1.read(), + ) + + +def test_replacing_calls_with_function_definition_in_other_modules2(self): + self.mod.write(dedent("""\ + def a_func(): + print(1) + """)) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + import mod + if True: + mod.a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + import mod + if True: + print(1) + """), + mod1.read(), + ) + + +def test_replacing_calls_with_method_definition_in_other_modules(self): + self.mod.write(dedent("""\ + class A(object): + var = 10 + def a_func(self): + print(1) + """)) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + import mod + mod.A().a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + import mod + print(1) + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + class A(object): + var = 10 + """), + self.mod.read(), + ) + + +_returned = None + + +def test_replacing_calls_with_function_definition_in_defining_module(self): + self.mod.write(dedent("""\ + def a_func(): + print(1) + a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("print(1)\n", self.mod.read()) + + +def test_replac_calls_with_function_definition_in_defining_module2(self): + self.mod.write(dedent("""\ + def a_func(): + for i in range(10): + print(1) + a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + for i in range(10): + print(1) + """), + self.mod.read(), + ) + + +def test_replacing_calls_with_method_definition_in_defining_modules(self): + self.mod.write(dedent("""\ + class A(object): + var = 10 + def a_func(self): + print(1) + A().a_func()""")) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + class A(object): + var = 10 + print(1) + """), + self.mod.read(), + ) + + +def test_parameters_with_the_same_name_as_passed(self): + self.mod.write(dedent("""\ + def a_func(var): + print(var) + var = 1 + a_func(var) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var = 1 + print(var) + """), + self.mod.read(), + ) + + +def test_parameters_with_the_same_name_as_passed2(self): + self.mod.write(dedent("""\ + def a_func(var): + print(var) + var = 1 + a_func(var=var) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var = 1 + print(var) + """), + self.mod.read(), + ) + + +def test_simple_parameters_renaming(self): + self.mod.write(dedent("""\ + def a_func(param): + print(param) + var = 1 + a_func(var) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var = 1 + print(var) + """), + self.mod.read(), + ) + + +def test_simple_parameters_renaming_for_multiple_params(self): + self.mod.write(dedent("""\ + def a_func(param1, param2): + p = param1 + param2 + var1 = 1 + var2 = 1 + a_func(var1, var2) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var1 = 1 + var2 = 1 + p = var1 + var2 + """), + self.mod.read(), + ) + + +def test_parameters_renaming_for_passed_constants(self): + self.mod.write(dedent("""\ + def a_func(param): + print(param) + a_func(1) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("print(1)\n", self.mod.read()) + + +def test_parameters_renaming_for_passed_statements(self): + self.mod.write(dedent("""\ + def a_func(param): + print(param) + a_func((1 + 2) / 3) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + print((1 + 2) / 3) + """), + self.mod.read(), + ) + + +def test_simple_parameters_renam_for_multiple_params_using_keywords(self): + self.mod.write(dedent("""\ + def a_func(param1, param2): + p = param1 + param2 + var1 = 1 + var2 = 1 + a_func(param2=var1, param1=var2) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var1 = 1 + var2 = 1 + p = var2 + var1 + """), + self.mod.read(), + ) + + +def get_changes(self): + changes = change.ChangeSet( + "Generate {} <{}>".format(self._get_element_kind(), self.name) + ) + indents = self.info.get_scope_indents() + blanks = self.info.get_blank_lines() + base_definition = sourceutils.fix_indentation(self._get_element(), indents) + definition = "\n" * blanks[0] + base_definition + "\n" * blanks[1] + + resource = self.info.get_insertion_resource() + start, end = self.info.get_insertion_offsets() + + collector = codeanalyze.ChangeCollector(resource.read()) + collector.add_change(start, end, definition) + changes.add_change(change.ChangeContents(resource, collector.get_changed())) + if self.goal_resource: + relative_import = _add_relative_import_to_module( + self.project, self.resource, self.goal_resource, self.name + ) + changes.add_change(relative_import) + return changes + + +@property +def returned(self): + """Does the extracted piece contain return statement""" + if self._returned is None: + self._returned = usefunction._returns_last(self._parsed_extracted) + return self._returned + + +def test_simple_params_renam_for_multi_params_using_mixed_keywords(self): + self.mod.write(dedent("""\ + def a_func(param1, param2): + p = param1 + param2 + var1 = 1 + var2 = 1 + a_func(var2, param2=var1) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var1 = 1 + var2 = 1 + p = var2 + var1 + """), + self.mod.read(), + ) + + +def test_simple_putting_in_default_arguments(self): + self.mod.write(dedent("""\ + def a_func(param=None): + print(param) + a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("print(None)\n", self.mod.read()) + + +def test_overriding_default_arguments(self): + self.mod.write(dedent("""\ + def a_func(param1=1, param2=2): + print(param1, param2) + a_func(param2=3) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("print(1, 3)\n", self.mod.read()) + + +def test_arguments_containing_comparisons(self): + self.mod.write(dedent("""\ + def a_func(param1, param2, param3): + param2.name + a_func(2 <= 1, item, True) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("item.name\n", self.mod.read()) + + +def test_badly_formatted_text(self): + self.mod.write(dedent("""\ + def a_func ( param1 = 1 ,param2 = 2 ) : + print(param1, param2) + a_func ( param2 + = 3 ) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("print(1, 3)\n", self.mod.read()) + + +def test_passing_first_arguments_for_methods(self): + a_class = dedent("""\ + class A(object): + def __init__(self): + self.var = 1 + self.a_func(self.var) + def a_func(self, param): + print(param) + """) + self.mod.write(a_class) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + expected = dedent("""\ + class A(object): + def __init__(self): + self.var = 1 + print(self.var) + """) + self.assertEqual(expected, self.mod.read()) + + +def test_passing_first_arguments_for_methods2(self): + a_class = dedent("""\ + class A(object): + def __init__(self): + self.var = 1 + def a_func(self, param): + print(param, self.var) + an_a = A() + an_a.a_func(1) + """) + self.mod.write(a_class) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + expected = dedent("""\ + class A(object): + def __init__(self): + self.var = 1 + an_a = A() + print(1, an_a.var) + """) + self.assertEqual(expected, self.mod.read()) + + +def test_passing_first_arguments_for_methods3(self): + a_class = dedent("""\ + class A(object): + def __init__(self): + self.var = 1 + def a_func(self, param): + print(param, self.var) + an_a = A() + A.a_func(an_a, 1) + """) + self.mod.write(a_class) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + expected = dedent("""\ + class A(object): + def __init__(self): + self.var = 1 + an_a = A() + print(1, an_a.var) + """) + self.assertEqual(expected, self.mod.read()) + + +def test_inlining_staticmethods(self): + a_class = dedent("""\ + class A(object): + @staticmethod + def a_func(param): + print(param) + A.a_func(1) + """) + self.mod.write(a_class) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + expected = dedent("""\ + class A(object): + pass + print(1) + """) + self.assertEqual(expected, self.mod.read()) + + +def test_static_methods2(self): + a_class = dedent("""\ + class A(object): + var = 10 + @staticmethod + def a_func(param): + print(param) + an_a = A() + an_a.a_func(1) + A.a_func(2) + """) + self.mod.write(a_class) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + expected = dedent("""\ + class A(object): + var = 10 + an_a = A() + print(1) + print(2) + """) + self.assertEqual(expected, self.mod.read()) + + +_returning_named_expr = None + + +def test_inlining_classmethods(self): + a_class = dedent("""\ + class A(object): + @classmethod + def a_func(cls, param): + print(param) + A.a_func(1) + """) + self.mod.write(a_class) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + expected = dedent("""\ + class A(object): + pass + print(1) + """) + self.assertEqual(expected, self.mod.read()) + + +def test_inlining_classmethods2(self): + a_class = dedent("""\ + class A(object): + @classmethod + def a_func(cls, param): + return cls + print(A.a_func(1)) + """) + self.mod.write(a_class) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + expected = dedent("""\ + class A(object): + pass + print(A) + """) + self.assertEqual(expected, self.mod.read()) + + +def test_simple_return_values_and_inlining_functions(self): + self.mod.write(dedent("""\ + def a_func(): + return 1 + a = a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("a = 1\n", self.mod.read()) + + +def test_simple_return_values_and_inlining_lonely_functions(self): + self.mod.write(dedent("""\ + def a_func(): + return 1 + a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("1\n", self.mod.read()) + + +def test_empty_returns_and_inlining_lonely_functions(self): + self.mod.write(dedent("""\ + def a_func(): + if True: + return + a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + if True: + pass + """), + self.mod.read(), + ) + + +def test_multiple_returns(self): + self.mod.write(dedent("""\ + def less_than_five(var): + if var < 5: + return True + return False + a = less_than_five(2) + """)) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self._inline2(self.mod, self.mod.read().index("less") + 1) + + +def test_multiple_returns_and_not_using_the_value(self): + self.mod.write(dedent("""\ + def less_than_five(var): + if var < 5: + return True + return False + less_than_five(2) + """)) + self._inline2(self.mod, self.mod.read().index("less") + 1) + self.assertEqual( + dedent("""\ + if 2 < 5: + True + False + """), + self.mod.read(), + ) + + +def test_raising_exception_for_list_arguments(self): + self.mod.write(dedent("""\ + def a_func(*args): + print(args) + a_func(1) + """)) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + + +def test_raising_exception_for_list_keywods(self): + self.mod.write(dedent("""\ + def a_func(**kwds): + print(kwds) + a_func(n=1) + """)) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + + +def test_function_parameters_and_returns_in_other_functions(self): + code = dedent("""\ + def a_func(param1, param2): + return param1 + param2 + range(a_func(20, param2=abs(10))) + """) + self.mod.write(code) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("range(20 + abs(10))\n", self.mod.read()) + + +@property +def returning_named_expr(self): + """Does the extracted piece contains named expression/:= operator)""" + if self._returning_named_expr is None: + self._returning_named_expr = usefunction._namedexpr_last( + self._parsed_extracted + ) + return self._returning_named_expr + + +def test_function_references_other_than_call(self): + self.mod.write(dedent("""\ + def a_func(param): + print(param) + f = a_func + """)) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + + +def test_function_referencing_itself(self): + self.mod.write(dedent("""\ + def a_func(var): + func = a_func + """)) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + + +def test_recursive_functions(self): + self.mod.write(dedent("""\ + def a_func(var): + a_func(var) + """)) + with self.assertRaises(rope.base.exceptions.RefactoringError): + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + + +# TODO: inlining on function parameters +def xxx_test_inlining_function_default_parameters(self): + self.mod.write(dedent("""\ + def a_func(p1=1): + pass + a_func() + """)) + self._inline2(self.mod, self.mod.read().index("p1") + 1) + self.assertEqual( + dedent("""\ + def a_func(p1=1): + pass + a_func() + """), + self.mod.read(), + ) + + +def test_simple_inlining_after_extra_indented_lines(self): + self.mod.write(dedent("""\ + def a_func(): + for i in range(10): + pass + if True: + pass + a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + if True: + pass + for i in range(10): + pass + """), + self.mod.read(), + ) + + +def test_inlining_a_function_with_pydoc(self): + self.mod.write(dedent('''\ + def a_func(): + """docs""" + a = 1 + a_func()''')) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("a = 1\n", self.mod.read()) + + +def test_inlining_methods(self): + self.mod.write(dedent("""\ + class A(object): + name = 'hey' + def get_name(self): + return self.name + a = A() + name = a.get_name() + """)) + self._inline2(self.mod, self.mod.read().rindex("get_name") + 1) + self.assertEqual( + dedent("""\ + class A(object): + name = 'hey' + a = A() + name = a.name + """), + self.mod.read(), + ) + + +def test_simple_returns_with_backslashes(self): + self.mod.write(dedent("""\ + def a_func(): + return 1\\ + + 2 + a = a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + "a = 1\\\n + 2\n", + dedent("""\ + a = 1\\ + + 2 + """), + self.mod.read(), + ) + + +def test_a_function_with_pass_body(self): + self.mod.write(dedent("""\ + def a_func(): + print(1) + a = a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + print(1) + a = None + """), + self.mod.read(), + ) + + +def test_inlining_the_last_method_of_a_class(self): + self.mod.write(dedent("""\ + class A(object): + def a_func(self): + pass + """)) + self._inline2(self.mod, self.mod.read().rindex("a_func") + 1) + self.assertEqual( + dedent("""\ + class A(object): + pass + """), + self.mod.read(), + ) + + +_returning_generator = None + + +def test_adding_needed_imports_in_the_dest_module(self): + self.mod.write(dedent("""\ + import sys + + def ver(): + print(sys.version) + """)) + self.mod2.write(dedent("""\ + import mod + + mod.ver()""")) + self._inline2(self.mod, self.mod.read().index("ver") + 1) + self.assertEqual( + dedent("""\ + import mod + import sys + + print(sys.version) + """), + self.mod2.read(), + ) + + +def test_adding_needed_imports_in_the_dest_module_removing_selfs(self): + self.mod.write(dedent("""\ + import mod2 + + def f(): + print(mod2.var) + """)) + self.mod2.write(dedent("""\ + import mod + + var = 1 + mod.f() + """)) + self._inline2(self.mod, self.mod.read().index("f(") + 1) + self.assertEqual( + dedent("""\ + import mod + + var = 1 + print(var) + """), + self.mod2.read(), + ) + + +def test_handling_relative_imports_when_inlining(self): + pkg = testutils.create_package(self.project, "pkg") + mod3 = testutils.create_module(self.project, "mod3", pkg) + mod4 = testutils.create_module(self.project, "mod4", pkg) + mod4.write("var = 1\n") + mod3.write(dedent("""\ + from . import mod4 + + def f(): + print(mod4.var) + """)) + self.mod.write(dedent("""\ + import pkg.mod3 + + pkg.mod3.f() + """)) + self._inline2(self.mod, self.mod.read().index("f(") + 1) + # Cannot determine the exact import + self.assertTrue("\n\nprint(mod4.var)\n" in self.mod.read()) + + +def test_adding_needed_imports_for_elements_in_source(self): + self.mod.write(dedent("""\ + def f1(): + return f2() + def f2(): + return 1 + """)) + self.mod2.write(dedent("""\ + import mod + + print(mod.f1()) + """)) + self._inline2(self.mod, self.mod.read().index("f1") + 1) + self.assertEqual( + dedent("""\ + import mod + from mod import f2 + + print(f2()) + """), + self.mod2.read(), + ) + + +def test_relative_imports_and_changing_inlining_body(self): + pkg = testutils.create_package(self.project, "pkg") + mod3 = testutils.create_module(self.project, "mod3", pkg) + mod4 = testutils.create_module(self.project, "mod4", pkg) + mod4.write("var = 1\n") + mod3.write(dedent("""\ + import mod4 + + def f(): + print(mod4.var) + """)) + self.mod.write(dedent("""\ + import pkg.mod3 + + pkg.mod3.f() + """)) + self._inline2(self.mod, self.mod.read().index("f(") + 1) + self.assertEqual( + dedent("""\ + import pkg.mod3 + import pkg.mod4 + + print(pkg.mod4.var) + """), + self.mod.read(), + ) + + +def test_inlining_with_different_returns(self): + self.mod.write(dedent("""\ + def f(p): + return p + print(f(1)) + print(f(2)) + print(f(1)) + """)) + self._inline2(self.mod, self.mod.read().index("f(") + 1) + self.assertEqual( + dedent("""\ + print(1) + print(2) + print(1) + """), + self.mod.read(), + ) + + +def test_not_removing_definition_for_variables(self): + code = dedent("""\ + a_var = 10 + another_var = a_var + """) + refactored = self._inline(code, code.index("a_var") + 1, remove=False) + self.assertEqual( + dedent("""\ + a_var = 10 + another_var = 10 + """), + refactored, + ) + + +def test_not_removing_definition_for_methods(self): + code = dedent("""\ + def func(): + print(1) + + func() + """) + refactored = self._inline(code, code.index("func") + 1, remove=False) + self.assertEqual( + dedent("""\ + def func(): + print(1) + + print(1) + """), + refactored, + ) + + +def test_only_current_for_methods(self): + code = dedent("""\ + def func(): + print(1) + + func() + func() + """) + refactored = self._inline( + code, code.rindex("func") + 1, remove=False, only_current=True + ) + self.assertEqual( + dedent("""\ + def func(): + print(1) + + func() + print(1) + """), + refactored, + ) + + +def test_only_current_for_variables(self): + code = dedent("""\ + one = 1 + + a = one + b = one + """) + refactored = self._inline( + code, code.rindex("one") + 1, remove=False, only_current=True + ) + self.assertEqual( + dedent("""\ + one = 1 + + a = one + b = 1 + """), + refactored, + ) + + +@property +def returning_generator_exp(self): + """Does the extracted piece contains a generator expression""" + if self._returning_generator is None: + self._returning_generator = ( + isinstance(self._parsed_extracted, ast.Module) + and isinstance(self._parsed_extracted.body[0], ast.Expr) + and isinstance(self._parsed_extracted.body[0].value, ast.GeneratorExp) + ) + + return self._returning_generator + + + +def test_inlining_one_line_functions(self): + code = dedent("""\ + def f(): return 1 + var = f() + """) + refactored = self._inline(code, code.rindex("f")) + self.assertEqual("var = 1\n", refactored) + + +def test_inlining_one_line_functions_with_breaks(self): + code = dedent("""\ + def f( + p): return p + var = f(1) + """) + refactored = self._inline(code, code.rindex("f")) + self.assertEqual("var = 1\n", refactored) + + +def test_inlining_one_line_functions_with_breaks2(self): + code = dedent("""\ + def f( + ): return 1 + var = f() + """) + refactored = self._inline(code, code.rindex("f")) + self.assertEqual("var = 1\n", refactored) + + +def test_resources_parameter(self): + self.mod.write(dedent("""\ + def a_func(): + print(1) + """)) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + import mod + mod.a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func"), resources=[self.mod]) + self.assertEqual("", self.mod.read()) + self.assertEqual( + dedent("""\ + import mod + mod.a_func() + """), + mod1.read(), + ) + + +def test_inlining_parameters(self): + code = dedent("""\ + def f(p=1): + pass + f() + """) + result = self._inline(code, code.index("p")) + self.assertEqual( + dedent("""\ + def f(p=1): + pass + f(1) + """), + result, + ) + + +def test_inlining_function_with_line_breaks_in_args(self): + code = dedent("""\ + def f(p): return p + var = f(1 + + 1) + """) + refactored = self._inline(code, code.rindex("f")) + self.assertEqual("var = 1 + 1\n", refactored) + + +def test_inlining_variables_before_comparison(self): + code = "start = 1\nprint(start <= 2)\n" + refactored = self._inline(code, code.index("start")) + self.assertEqual("print(1 <= 2)\n", refactored) + + +def test_inlining_variables_in_other_modules(self): + self.mod.write("myvar = 1\n") + self.mod2.write(dedent("""\ + import mod + print(mod.myvar) + """)) + self._inline2(self.mod, 2) + self.assertEqual( + dedent("""\ + import mod + print(1) + """), + self.mod2.read(), + ) + + +def test_inlining_variables_and_back_importing(self): + self.mod.write(dedent("""\ + mainvar = 1 + myvar = mainvar + """)) + self.mod2.write(dedent("""\ + import mod + print(mod.myvar) + """)) + self._inline2(self.mod, self.mod.read().index("myvar")) + expected = dedent("""\ + import mod + from mod import mainvar + print(mainvar) + """) + self.assertEqual(expected, self.mod2.read()) + + +def test_inlining_variables_and_importing_used_imports(self): + self.mod.write(dedent("""\ + import sys + myvar = sys.argv + """)) + self.mod2.write(dedent("""\ + import mod + print(mod.myvar) + """)) + self._inline2(self.mod, self.mod.read().index("myvar")) + expected = dedent("""\ + import mod + import sys + print(sys.argv) + """) + self.assertEqual(expected, self.mod2.read()) + + +class _ExtractCollector: + """Collects information needed for performing the extract""" + + @others + +def test_inlining_variables_and_removing_old_froms(self): + self.mod.write("var = 1\n") + self.mod2.write(dedent("""\ + from mod import var + print(var) + """)) + self._inline2(self.mod2, self.mod2.read().rindex("var")) + self.assertEqual("print(1)\n", self.mod2.read()) + + +def test_inlining_method_and_removing_old_froms(self): + self.mod.write(dedent("""\ + def f(): return 1 + """)) + self.mod2.write(dedent("""\ + from mod import f + print(f()) + """)) + self._inline2(self.mod2, self.mod2.read().rindex("f")) + self.assertEqual("print(1)\n", self.mod2.read()) + + +def test_inlining_functions_in_other_modules_and_only_current(self): + code1 = dedent("""\ + def f(): + return 1 + print(f()) + """) + code2 = dedent("""\ + import mod + print(mod.f()) + print(mod.f()) + """) + self.mod.write(code1) + self.mod2.write(code2) + self._inline2( + self.mod2, self.mod2.read().rindex("f"), remove=False, only_current=True + ) + expected2 = dedent("""\ + import mod + print(mod.f()) + print(1) + """) + self.assertEqual(code1, self.mod.read()) + self.assertEqual(expected2, self.mod2.read()) + + +def test_inlining_variables_in_other_modules_and_only_current(self): + code1 = dedent("""\ + var = 1 + print(var) + """) + code2 = dedent("""\ + import mod + print(mod.var) + print(mod.var) + """) + self.mod.write(code1) + self.mod2.write(code2) + self._inline2( + self.mod2, self.mod2.read().rindex("var"), remove=False, only_current=True + ) + expected2 = "import mod\n" "print(mod.var)\n" "print(1)\n" + self.assertEqual(code1, self.mod.read()) + self.assertEqual(expected2, self.mod2.read()) + + +def test_inlining_does_not_change_string_constants(self): + code = dedent("""\ + var = 1 + print("var\\ + ") + """) + expected = dedent("""\ + var = 1 + print("var\\ + ") + """) + refactored = self._inline( + code, code.rindex("var"), remove=False, only_current=True, docs=False + ) + self.assertEqual(expected, refactored) + + +def test_inlining_does_change_string_constants_if_docs_is_set(self): + code = dedent("""\ + var = 1 + print("var\\ + ") + """) + expected = dedent("""\ + var = 1 + print("1\\ + ") + """) + refactored = self._inline( + code, code.rindex("var"), remove=False, only_current=True, docs=True + ) + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.6") +def test_inlining_into_format_string(self): + code = dedent("""\ + var = 123 + print(f"{var}") + """) + expected = dedent("""\ + print(f"{123}") + """) + + refactored = self._inline(code, code.rindex("var")) + + self.assertEqual(expected, refactored) + + +@testutils.only_for_versions_higher("3.6") +def test_inlining_into_format_string_containing_quotes(self): + code = dedent('''\ + var = 123 + print(f" '{var}' ") + print(f""" "{var}" """) + print(f' "{var}" ') + ''') + expected = dedent('''\ + print(f" '{123}' ") + print(f""" "{123}" """) + print(f' "{123}" ') + ''') + + refactored = self._inline(code, code.rindex("var")) + + self.assertEqual(expected, refactored) + + +def test_parameters_with_the_same_name_as_passed_with_type_hints(self): + self.mod.write(dedent("""\ + def a_func(var: int): + print(var) + var = 1 + a_func(var) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var = 1 + print(var) + """), + self.mod.read(), + ) + + +def test_parameters_with_the_same_name_as_passed_as_kwargs_with_type_hints(self): + self.mod.write(dedent("""\ + def a_func(var: int): + print(var) + var = 1 + a_func(var=var) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var = 1 + print(var) + """), + self.mod.read(), + ) + + +def __init__(self, info): + self.definition = None + self.body_pattern = None + self.checks = {} + self.replacement_pattern = None + self.matches = None + self.replacements = None + self.definition_location = None + + + +def test_simple_parameters_renaming_with_type_hints(self): + self.mod.write(dedent("""\ + def a_func(param: int): + print(param) + var = 1 + a_func(var) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var = 1 + print(var) + """), + self.mod.read(), + ) + + +def test_simple_parameters_renaming_for_multiple_params_with_type_hints(self): + self.mod.write(dedent("""\ + def a_func(param1, param2: int): + p = param1 + param2 + var1 = 1 + var2 = 1 + a_func(var1, var2) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var1 = 1 + var2 = 1 + p = var1 + var2 + """), + self.mod.read(), + ) + + +def test_parameters_renaming_for_passed_constants_with_type_hints(self): + self.mod.write(dedent("""\ + def a_func(param: int): + print(param) + a_func(1) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("print(1)\n", self.mod.read()) + + +def test_parameters_renaming_for_passed_statements_with_type_hints(self): + self.mod.write(dedent("""\ + def a_func(param: int): + print(param) + a_func((1 + 2) / 3) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + print((1 + 2) / 3) + """), + self.mod.read(), + ) + + +def test_simple_parameters_renaming_for_multiple_params_using_keywords_with_type_hints( + self, +): + self.mod.write(dedent("""\ + def a_func(param1, param2: int): + p = param1 + param2 + var1 = 1 + var2 = 1 + a_func(param2=var1, param1=var2) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var1 = 1 + var2 = 1 + p = var2 + var1 + """), + self.mod.read(), + ) + + +def test_simple_params_renaming_for_multi_params_using_mixed_keywords_with_type_hints( + self, +): + self.mod.write(dedent("""\ + def a_func(param1, param2: int): + p = param1 + param2 + var1 = 1 + var2 = 1 + a_func(var2, param2=var1) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual( + dedent("""\ + var1 = 1 + var2 = 1 + p = var2 + var1 + """), + self.mod.read(), + ) + + +def test_simple_putting_in_default_arguments_with_type_hints(self): + self.mod.write(dedent("""\ + def a_func(param: Optional[int] = None): + print(param) + a_func() + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("print(None)\n", self.mod.read()) + + +def test_overriding_default_arguments_with_type_hints(self): + self.mod.write(dedent("""\ + def a_func(param1=1, param2: int = 2): + print(param1, param2) + a_func(param2=3) + """)) + self._inline2(self.mod, self.mod.read().index("a_func") + 1) + self.assertEqual("print(1, 3)\n", self.mod.read()) + +def test_dictionary_with_inline_comment(self): + code = dedent("""\ + myvar = { + "key": "value", # noqa + } + print(myvar) + """) + refactored = self._inline(code, code.index("myvar") + 1) + expected = dedent("""\ + print({ + "key": "value", # noqa + }) + """) + self.assertEqual(expected, refactored) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +from textwrap import dedent + +import unittest + +from rope.base import exceptions +from rope.refactor import move +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class MoveRefactoringTest(unittest.TestCase): + @others + +class _ExtractPerformer: + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.mod1 = testutils.create_module(self.project, "mod1") + self.mod2 = testutils.create_module(self.project, "mod2") + self.mod3 = testutils.create_module(self.project, "mod3") + self.pkg = testutils.create_package(self.project, "pkg") + self.mod4 = testutils.create_module(self.project, "mod4", self.pkg) + self.mod5 = testutils.create_module(self.project, "mod5", self.pkg) + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _move(self, resource, offset, dest_resource): + changes = move.create_move(self.project, resource, offset).get_changes( + dest_resource + ) + self.project.do(changes) + + +def test_move_constant(self): + self.mod1.write("foo = 123\n") + self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2) + self.assertEqual("", self.mod1.read()) + self.assertEqual("foo = 123\n", self.mod2.read()) + + +def test_move_constant_2(self): + self.mod1.write("bar = 321\nfoo = 123\n") + self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2) + self.assertEqual("bar = 321\n", self.mod1.read()) + self.assertEqual("foo = 123\n", self.mod2.read()) + + +def test_move_constant_multiline(self): + self.mod1.write(dedent("""\ + foo = ( + 123 + ) + """)) + self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2) + self.assertEqual("", self.mod1.read()) + self.assertEqual( + dedent("""\ + foo = ( + 123 + ) + """), + self.mod2.read(), + ) + + +def test_move_constant_multiple_statements(self): + self.mod1.write(dedent("""\ + foo = 123 + foo += 3 + foo = 4 + """)) + self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2) + self.assertEqual( + dedent("""\ + import mod2 + mod2.foo += 3 + mod2.foo = 4 + """), + self.mod1.read(), + ) + self.assertEqual("foo = 123\n", self.mod2.read()) + + +def test_simple_moving(self): + self.mod1.write(dedent("""\ + class AClass(object): + pass + """)) + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + self.assertEqual("", self.mod1.read()) + self.assertEqual( + dedent("""\ + class AClass(object): + pass + """), + self.mod2.read(), + ) + + +def test_moving_with_comment_prefix(self): + self.mod1.write(dedent("""\ + a = 1 + # 1 + # 2 + class AClass(object): + pass + """)) + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + self.assertEqual("a = 1\n", self.mod1.read()) + self.assertEqual( + dedent("""\ + # 1 + # 2 + class AClass(object): + pass + """), + self.mod2.read(), + ) + + +def test_moving_with_comment_prefix_imports(self): + self.mod1.write(dedent("""\ + import foo + a = 1 + # 1 + # 2 + class AClass(foo.FooClass): + pass + """)) + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + self.assertEqual("a = 1\n", self.mod1.read()) + self.assertEqual( + dedent("""\ + import foo + + + # 1 + # 2 + class AClass(foo.FooClass): + pass + """), + self.mod2.read(), + ) + + +def __init__(self, info): + self.info = info + _ExceptionalConditionChecker()(self.info) + + +def test_changing_other_modules_replacing_normal_imports(self): + self.mod1.write("class AClass(object):\n pass\n") + self.mod3.write("import mod1\na_var = mod1.AClass()\n") + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + self.assertEqual( + dedent("""\ + import mod2 + a_var = mod2.AClass() + """), + self.mod3.read(), + ) + + +def test_changing_other_modules_adding_normal_imports(self): + self.mod1.write(dedent("""\ + class AClass(object): + pass + def a_function(): + pass + """)) + self.mod3.write(dedent("""\ + import mod1 + a_var = mod1.AClass() + mod1.a_function()""")) + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + self.assertEqual( + dedent("""\ + import mod1 + import mod2 + a_var = mod2.AClass() + mod1.a_function()"""), + self.mod3.read(), + ) + + +def test_adding_imports_prefer_from_module(self): + self.project.prefs["prefer_module_from_imports"] = True + self.mod1.write(dedent("""\ + class AClass(object): + pass + def a_function(): + pass + """)) + self.mod3.write(dedent("""\ + import mod1 + a_var = mod1.AClass() + mod1.a_function()""")) + # Move to mod4 which is in a different package + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod4) + self.assertEqual( + dedent("""\ + import mod1 + from pkg import mod4 + a_var = mod4.AClass() + mod1.a_function()"""), + self.mod3.read(), + ) + + +def test_adding_imports_noprefer_from_module(self): + self.project.prefs["prefer_module_from_imports"] = False + self.mod1.write(dedent("""\ + class AClass(object): + pass + def a_function(): + pass + """)) + self.mod3.write(dedent("""\ + import mod1 + a_var = mod1.AClass() + mod1.a_function()""")) + # Move to mod4 which is in a different package + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod4) + self.assertEqual( + dedent("""\ + import mod1 + import pkg.mod4 + a_var = pkg.mod4.AClass() + mod1.a_function()"""), + self.mod3.read(), + ) + + +def test_adding_imports_prefer_from_module_top_level_module(self): + self.project.prefs["prefer_module_from_imports"] = True + self.mod1.write(dedent("""\ + class AClass(object): + pass + def a_function(): + pass + """)) + self.mod3.write(dedent("""\ + import mod1 + a_var = mod1.AClass() + mod1.a_function()""")) + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + self.assertEqual( + dedent("""\ + import mod1 + import mod2 + a_var = mod2.AClass() + mod1.a_function()"""), + self.mod3.read(), + ) + + +def test_changing_other_modules_removing_from_imports(self): + self.mod1.write(dedent("""\ + class AClass(object): + pass + """)) + self.mod3.write(dedent("""\ + from mod1 import AClass + a_var = AClass() + """)) + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + self.assertEqual( + dedent("""\ + import mod2 + a_var = mod2.AClass() + """), + self.mod3.read(), + ) + + +def test_changing_source_module(self): + self.mod1.write(dedent("""\ + class AClass(object): + pass + a_var = AClass() + """)) + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + self.assertEqual( + dedent("""\ + import mod2 + a_var = mod2.AClass() + """), + self.mod1.read(), + ) + + +def test_changing_destination_module(self): + self.mod1.write(dedent("""\ + class AClass(object): + pass + """)) + self.mod2.write(dedent("""\ + from mod1 import AClass + a_var = AClass() + """)) + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + self.assertEqual( + dedent("""\ + class AClass(object): + pass + a_var = AClass() + """), + self.mod2.read(), + ) + + +def test_folder_destination(self): + folder = self.project.root.create_folder("folder") + self.mod1.write(dedent("""\ + class AClass(object): + pass + """)) + with self.assertRaises(exceptions.RefactoringError): + self._move(self.mod1, self.mod1.read().index("AClass") + 1, folder) + + +def test_raising_exception_for_moving_non_global_elements(self): + self.mod1.write(dedent("""\ + def a_func(): + class AClass(object): + pass + """)) + with self.assertRaises(exceptions.RefactoringError): + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + + +def extract(self): + extract_info = self._collect_info() + content = codeanalyze.ChangeCollector(self.info.source) + definition = extract_info.definition + lineno, indents = extract_info.definition_location + offset = self.info.lines.get_line_start(lineno) + indented = sourceutils.fix_indentation(definition, indents) + content.add_change(offset, offset, indented) + self._replace_occurrences(content, extract_info) + return content.get_changed() + + +def test_raising_an_exception_for_moving_non_global_variable(self): + code = dedent("""\ + class TestClass: + CONSTANT = 5 + """) + self.mod1.write(code) + with self.assertRaises(exceptions.RefactoringError): + mover = move.create_move( + self.project, self.mod1, code.index("CONSTANT") + 1 + ) + + +def test_raising_exception_for_mov_glob_elemnts_to_the_same_module(self): + self.mod1.write("def a_func():\n pass\n") + with self.assertRaises(exceptions.RefactoringError): + self._move(self.mod1, self.mod1.read().index("a_func"), self.mod1) + + +def test_moving_used_imports_to_destination_module(self): + self.mod3.write("a_var = 10") + code = dedent("""\ + import mod3 + from mod3 import a_var + def a_func(): + print(mod3, a_var) + """) + self.mod1.write(code) + self._move(self.mod1, code.index("a_func") + 1, self.mod2) + expected = dedent("""\ + import mod3 + from mod3 import a_var + + + def a_func(): + print(mod3, a_var) + """) + self.assertEqual(expected, self.mod2.read()) + + +def test_moving_used_names_to_destination_module2(self): + code = dedent("""\ + a_var = 10 + def a_func(): + print(a_var) + """) + self.mod1.write(code) + self._move(self.mod1, code.index("a_func") + 1, self.mod2) + self.assertEqual( + dedent("""\ + a_var = 10 + """), + self.mod1.read(), + ) + expected = dedent("""\ + from mod1 import a_var + + + def a_func(): + print(a_var) + """) + self.assertEqual(expected, self.mod2.read()) + + +def test_moving_used_underlined_names_to_destination_module(self): + code = dedent("""\ + _var = 10 + def a_func(): + print(_var) + """) + self.mod1.write(code) + self._move(self.mod1, code.index("a_func") + 1, self.mod2) + expected = dedent("""\ + from mod1 import _var + + + def a_func(): + print(_var) + """) + self.assertEqual(expected, self.mod2.read()) + + +def test_moving_and_used_relative_imports(self): + code = dedent("""\ + import mod5 + def a_func(): + print(mod5) + """) + self.mod4.write(code) + self._move(self.mod4, code.index("a_func") + 1, self.mod1) + expected = dedent("""\ + import pkg.mod5 + + + def a_func(): + print(pkg.mod5) + """) + self.assertEqual(expected, self.mod1.read()) + self.assertEqual("", self.mod4.read()) + + +def test_moving_modules(self): + code = "import mod1\nprint(mod1)" + self.mod2.write(code) + self._move(self.mod2, code.index("mod1") + 1, self.pkg) + expected = "import pkg.mod1\nprint(pkg.mod1)" + self.assertEqual(expected, self.mod2.read()) + self.assertTrue( + not self.mod1.exists() and self.project.find_module("pkg.mod1") is not None + ) + + +def test_moving_modules_and_removing_out_of_date_imports(self): + code = "import pkg.mod4\nprint(pkg.mod4)" + self.mod2.write(code) + self._move(self.mod2, code.index("mod4") + 1, self.project.root) + expected = "import mod4\nprint(mod4)" + self.assertEqual(expected, self.mod2.read()) + self.assertTrue(self.project.find_module("mod4") is not None) + + +def test_moving_modules_and_removing_out_of_date_froms(self): + code = "from pkg import mod4\nprint(mod4)" + self.mod2.write(code) + self._move(self.mod2, code.index("mod4") + 1, self.project.root) + self.assertEqual("import mod4\nprint(mod4)", self.mod2.read()) + + +def test_moving_modules_and_removing_out_of_date_froms2(self): + self.mod4.write("a_var = 10") + code = "from pkg.mod4 import a_var\nprint(a_var)\n" + self.mod2.write(code) + self._move(self.mod2, code.index("mod4") + 1, self.project.root) + expected = "from mod4 import a_var\nprint(a_var)\n" + self.assertEqual(expected, self.mod2.read()) + + +def get_location(self): + return (self.info.get_insertion_resource(), self.info.get_insertion_lineno()) + + +def _replace_occurrences(self, content, extract_info): + for match in extract_info.matches: + replacement = similarfinder.CodeTemplate(extract_info.replacement_pattern) + mapping = {} + for name in replacement.get_names(): + node = match.get_ast(name) + if node: + start, end = patchedast.node_region(match.get_ast(name)) + mapping[name] = self.info.source[start:end] + else: + mapping[name] = name + region = match.get_region() + content.add_change(region[0], region[1], replacement.substitute(mapping)) + + +def test_moving_modules_and_relative_import(self): + self.mod4.write("import mod5\nprint(mod5)\n") + code = "import pkg.mod4\nprint(pkg.mod4)" + self.mod2.write(code) + self._move(self.mod2, code.index("mod4") + 1, self.project.root) + moved = self.project.find_module("mod4") + expected = "import pkg.mod5\nprint(pkg.mod5)\n" + self.assertEqual(expected, moved.read()) + + +def test_moving_module_kwarg_same_name_as_old(self): + self.mod1.write("def foo(mod1=0):\n pass") + code = "import mod1\nmod1.foo(mod1=1)" + self.mod2.write(code) + self._move(self.mod1, None, self.pkg) + moved = self.project.find_module("mod2") + expected = "import pkg.mod1\npkg.mod1.foo(mod1=1)" + self.assertEqual(expected, moved.read()) + + +def test_moving_packages(self): + pkg2 = testutils.create_package(self.project, "pkg2") + code = "import pkg.mod4\nprint(pkg.mod4)" + self.mod1.write(code) + self._move(self.mod1, code.index("pkg") + 1, pkg2) + self.assertFalse(self.pkg.exists()) + self.assertTrue(self.project.find_module("pkg2.pkg.mod4") is not None) + self.assertTrue(self.project.find_module("pkg2.pkg.mod4") is not None) + self.assertTrue(self.project.find_module("pkg2.pkg.mod5") is not None) + expected = "import pkg2.pkg.mod4\nprint(pkg2.pkg.mod4)" + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_modules_with_self_imports(self): + self.mod1.write("import mod1\nprint(mod1)\n") + self.mod2.write("import mod1\n") + self._move(self.mod2, self.mod2.read().index("mod1") + 1, self.pkg) + moved = self.project.find_module("pkg.mod1") + self.assertEqual( + dedent("""\ + import pkg.mod1 + print(pkg.mod1) + """), + moved.read(), + ) + + +def test_moving_modules_with_from_imports(self): + pkg2 = testutils.create_package(self.project, "pkg2") + code = dedent("""\ + from pkg import mod4 + print(mod4)""") + self.mod1.write(code) + self._move(self.mod1, code.index("pkg") + 1, pkg2) + self.assertFalse(self.pkg.exists()) + self.assertTrue(self.project.find_module("pkg2.pkg.mod4") is not None) + self.assertTrue(self.project.find_module("pkg2.pkg.mod5") is not None) + expected = dedent("""\ + from pkg2.pkg import mod4 + print(mod4)""") + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_modules_with_from_import(self): + pkg2 = testutils.create_package(self.project, "pkg2") + pkg3 = testutils.create_package(self.project, "pkg3", pkg2) + pkg4 = testutils.create_package(self.project, "pkg4", pkg3) + code = dedent("""\ + from pkg import mod4 + print(mod4)""") + self.mod1.write(code) + self._move(self.mod4, None, pkg4) + self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) + expected = dedent("""\ + from pkg2.pkg3.pkg4 import mod4 + print(mod4)""") + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_modules_with_multi_from_imports(self): + pkg2 = testutils.create_package(self.project, "pkg2") + pkg3 = testutils.create_package(self.project, "pkg3", pkg2) + pkg4 = testutils.create_package(self.project, "pkg4", pkg3) + code = dedent("""\ + from pkg import mod4, mod5 + print(mod4)""") + self.mod1.write(code) + self._move(self.mod4, None, pkg4) + self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) + expected = dedent("""\ + from pkg import mod5 + from pkg2.pkg3.pkg4 import mod4 + print(mod4)""") + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_modules_with_from_and_normal_imports(self): + pkg2 = testutils.create_package(self.project, "pkg2") + pkg3 = testutils.create_package(self.project, "pkg3", pkg2) + pkg4 = testutils.create_package(self.project, "pkg4", pkg3) + code = dedent("""\ + from pkg import mod4 + import pkg.mod4 + print(mod4) + print(pkg.mod4)""") + self.mod1.write(code) + self._move(self.mod4, None, pkg4) + self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) + expected = dedent("""\ + import pkg2.pkg3.pkg4.mod4 + from pkg2.pkg3.pkg4 import mod4 + print(mod4) + print(pkg2.pkg3.pkg4.mod4)""") + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_modules_with_normal_and_from_imports(self): + pkg2 = testutils.create_package(self.project, "pkg2") + pkg3 = testutils.create_package(self.project, "pkg3", pkg2) + pkg4 = testutils.create_package(self.project, "pkg4", pkg3) + code = dedent("""\ + import pkg.mod4 + from pkg import mod4 + print(mod4) + print(pkg.mod4)""") + self.mod1.write(code) + self._move(self.mod4, None, pkg4) + self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) + expected = dedent("""\ + import pkg2.pkg3.pkg4.mod4 + from pkg2.pkg3.pkg4 import mod4 + print(mod4) + print(pkg2.pkg3.pkg4.mod4)""") + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_modules_from_import_variable(self): + pkg2 = testutils.create_package(self.project, "pkg2") + pkg3 = testutils.create_package(self.project, "pkg3", pkg2) + pkg4 = testutils.create_package(self.project, "pkg4", pkg3) + code = dedent("""\ + from pkg.mod4 import foo + print(foo)""") + self.mod1.write(code) + self._move(self.mod4, None, pkg4) + self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) + expected = dedent("""\ + from pkg2.pkg3.pkg4.mod4 import foo + print(foo)""") + self.assertEqual(expected, self.mod1.read()) + + +def _collect_info(self): + extract_collector = _ExtractCollector(self.info) + self._find_definition(extract_collector) + self._find_matches(extract_collector) + self._find_definition_location(extract_collector) + return extract_collector + + +def test_moving_modules_normal_import(self): + pkg2 = testutils.create_package(self.project, "pkg2") + pkg3 = testutils.create_package(self.project, "pkg3", pkg2) + pkg4 = testutils.create_package(self.project, "pkg4", pkg3) + code = dedent("""\ + import pkg.mod4 + print(pkg.mod4)""") + self.mod1.write(code) + self._move(self.mod4, None, pkg4) + self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) + expected = dedent("""\ + import pkg2.pkg3.pkg4.mod4 + print(pkg2.pkg3.pkg4.mod4)""") + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_package_with_from_and_normal_imports(self): + pkg2 = testutils.create_package(self.project, "pkg2") + code = dedent("""\ + from pkg import mod4 + import pkg.mod4 + print(pkg.mod4) + print(mod4)""") + self.mod1.write(code) + self._move(self.mod1, code.index("pkg") + 1, pkg2) + self.assertFalse(self.pkg.exists()) + self.assertTrue(self.project.find_module("pkg2.pkg.mod4") is not None) + self.assertTrue(self.project.find_module("pkg2.pkg.mod5") is not None) + expected = dedent("""\ + from pkg2.pkg import mod4 + import pkg2.pkg.mod4 + print(pkg2.pkg.mod4) + print(mod4)""") + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_package_with_from_and_normal_imports2(self): + pkg2 = testutils.create_package(self.project, "pkg2") + code = dedent("""\ + import pkg.mod4 + from pkg import mod4 + print(pkg.mod4) + print(mod4)""") + self.mod1.write(code) + self._move(self.mod1, code.index("pkg") + 1, pkg2) + self.assertFalse(self.pkg.exists()) + self.assertTrue(self.project.find_module("pkg2.pkg.mod4") is not None) + self.assertTrue(self.project.find_module("pkg2.pkg.mod5") is not None) + expected = dedent("""\ + import pkg2.pkg.mod4 + from pkg2.pkg import mod4 + print(pkg2.pkg.mod4) + print(mod4)""") + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_package_and_retaining_blank_lines(self): + pkg2 = testutils.create_package(self.project, "pkg2", self.pkg) + code = dedent('''\ + """Docstring followed by blank lines.""" + + import pkg.mod4 + + from pkg import mod4 + from x import y + from y import z + from a import b + from b import c + print(pkg.mod4) + print(mod4)''') + self.mod1.write(code) + self._move(self.mod4, None, pkg2) + expected = dedent('''\ + """Docstring followed by blank lines.""" + + import pkg.pkg2.mod4 + + from x import y + from y import z + from a import b + from b import c + from pkg.pkg2 import mod4 + print(pkg.pkg2.mod4) + print(mod4)''') + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_functions_to_imported_module(self): + code = dedent("""\ + import mod1 + def a_func(): + var = mod1.a_var + """) + self.mod1.write("a_var = 1\n") + self.mod2.write(code) + self._move(self.mod2, code.index("a_func") + 1, self.mod1) + expected = dedent("""\ + def a_func(): + var = a_var + a_var = 1 + """) + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_resources_using_move_module_refactoring(self): + self.mod1.write("a_var = 1") + self.mod2.write(dedent("""\ + import mod1 + my_var = mod1.a_var + """)) + mover = move.create_move(self.project, self.mod1) + mover.get_changes(self.pkg).do() + expected = dedent("""\ + import pkg.mod1 + my_var = pkg.mod1.a_var + """) + self.assertEqual(expected, self.mod2.read()) + self.assertTrue(self.pkg.get_child("mod1.py") is not None) + + +def test_moving_resources_using_move_module_for_packages(self): + self.mod1.write(dedent("""\ + import pkg + my_pkg = pkg""")) + pkg2 = testutils.create_package(self.project, "pkg2") + mover = move.create_move(self.project, self.pkg) + mover.get_changes(pkg2).do() + expected = dedent("""\ + import pkg2.pkg + my_pkg = pkg2.pkg""") + self.assertEqual(expected, self.mod1.read()) + self.assertTrue(pkg2.get_child("pkg") is not None) + + +def test_moving_resources_using_move_module_for_init_dot_py(self): + self.mod1.write(dedent("""\ + import pkg + my_pkg = pkg""")) + pkg2 = testutils.create_package(self.project, "pkg2") + init = self.pkg.get_child("__init__.py") + mover = move.create_move(self.project, init) + mover.get_changes(pkg2).do() + self.assertEqual( + dedent("""\ + import pkg2.pkg + my_pkg = pkg2.pkg"""), + self.mod1.read(), + ) + self.assertTrue(pkg2.get_child("pkg") is not None) + + +def test_moving_module_and_star_imports(self): + self.mod1.write("a_var = 1") + self.mod2.write(dedent("""\ + from mod1 import * + a = a_var + """)) + mover = move.create_move(self.project, self.mod1) + mover.get_changes(self.pkg).do() + self.assertEqual( + dedent("""\ + from pkg.mod1 import * + a = a_var + """), + self.mod2.read(), + ) + + +def test_moving_module_and_not_removing_blanks_after_imports(self): + self.mod4.write("a_var = 1") + self.mod2.write(dedent("""\ + from pkg import mod4 + import os + + + print(mod4.a_var) + """)) + mover = move.create_move(self.project, self.mod4) + mover.get_changes(self.project.root).do() + self.assertEqual( + dedent("""\ + import os + import mod4 + + + print(mod4.a_var) + """), + self.mod2.read(), + ) + + +def _find_matches(self, collector): + regions = self._where_to_search() + finder = similarfinder.SimilarFinder(self.info.pymodule) + matches = [] + for start, end in regions: + region_matches = finder.get_matches( + collector.body_pattern, collector.checks, start, end + ) + # Don't extract overlapping regions + last_match_end = -1 + for region_match in region_matches: + if self.info.one_line and self._is_assignment(region_match): + continue + start, end = region_match.get_region() + if last_match_end < start: + matches.append(region_match) + last_match_end = end + collector.matches = matches + + +def test_moving_module_refactoring_and_nonexistent_destinations(self): + self.mod4.write("a_var = 1") + self.mod2.write(dedent("""\ + from pkg import mod4 + import os + + + print(mod4.a_var) + """)) + with self.assertRaises(exceptions.RefactoringError): + mover = move.create_move(self.project, self.mod4) + mover.get_changes(None).do() + + +def test_moving_methods_choosing_the_correct_class(self): + code = dedent("""\ + class A(object): + def a_method(self): + pass + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + self.assertTrue(isinstance(mover, move.MoveMethod)) + + +def test_moving_methods_getting_new_method_for_empty_methods(self): + code = dedent("""\ + class A(object): + def a_method(self): + pass + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + self.assertEqual( + dedent("""\ + def new_method(self): + pass + """), + mover.get_new_method("new_method"), + ) + + +def test_moving_methods_getting_new_method_for_constant_methods(self): + code = dedent("""\ + class A(object): + def a_method(self): + return 1 + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + self.assertEqual( + dedent("""\ + def new_method(self): + return 1 + """), + mover.get_new_method("new_method"), + ) + + +def test_moving_methods_getting_new_method_passing_simple_paremters(self): + code = dedent("""\ + class A(object): + def a_method(self, p): + return p + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + self.assertEqual( + dedent("""\ + def new_method(self, p): + return p + """), + mover.get_new_method("new_method"), + ) + + +def test_moving_methods_getting_new_method_using_main_object(self): + code = dedent("""\ + class A(object): + attr = 1 + def a_method(host): + return host.attr + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + self.assertEqual( + dedent("""\ + def new_method(self, host): + return host.attr + """), + mover.get_new_method("new_method"), + ) + + +def test_moving_methods_getting_new_method_renaming_main_object(self): + code = dedent("""\ + class A(object): + attr = 1 + def a_method(self): + return self.attr + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + self.assertEqual( + dedent("""\ + def new_method(self, host): + return host.attr + """), + mover.get_new_method("new_method"), + ) + + +def test_moving_methods_gettin_new_method_with_keyword_arguments(self): + code = dedent("""\ + class A(object): + attr = 1 + def a_method(self, p=None): + return p + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + self.assertEqual( + dedent("""\ + def new_method(self, p=None): + return p + """), + mover.get_new_method("new_method"), + ) + + +def test_moving_methods_gettin_new_method_with_many_kinds_arguments(self): + code = dedent("""\ + class A(object): + attr = 1 + def a_method(self, p1, *args, **kwds): + return self.attr + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + expected = dedent("""\ + def new_method(self, host, p1, *args, **kwds): + return host.attr + """) + self.assertEqual(expected, mover.get_new_method("new_method")) + + +def test_moving_methods_getting_new_method_for_multi_line_methods(self): + code = dedent("""\ + class A(object): + def a_method(self): + a = 2 + return a + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + self.assertEqual( + dedent("""\ + def new_method(self): + a = 2 + return a + """), + mover.get_new_method("new_method"), + ) + + +@staticmethod +def _is_assignment(region_match): + return isinstance( + region_match.ast, (ast.Attribute, ast.Subscript) + ) and isinstance(region_match.ast.ctx, ast.Store) + + +def test_moving_methods_getting_old_method_for_constant_methods(self): + self.mod2.write("class B(object):\n pass\n") + code = dedent("""\ + import mod2 + + class A(object): + attr = mod2.B() + def a_method(self): + return 1 + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + mover.get_changes("attr", "new_method").do() + expected = dedent("""\ + import mod2 + + class A(object): + attr = mod2.B() + def a_method(self): + return self.attr.new_method() + """) + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_methods_getting_getting_changes_for_goal_class(self): + self.mod2.write("class B(object):\n var = 1\n") + code = dedent("""\ + import mod2 + + class A(object): + attr = mod2.B() + def a_method(self): + return 1 + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + mover.get_changes("attr", "new_method").do() + expected = dedent("""\ + class B(object): + var = 1 + + + def new_method(self): + return 1 + """) + self.assertEqual(expected, self.mod2.read()) + + +def test_moving_methods_getting_getting_changes_for_goal_class2(self): + code = dedent("""\ + class B(object): + var = 1 + + class A(object): + attr = B() + def a_method(self): + return 1 + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + mover.get_changes("attr", "new_method").do() + self.assertEqual( + dedent("""\ + class B(object): + var = 1 + + + def new_method(self): + return 1 + + class A(object): + attr = B() + def a_method(self): + return self.attr.new_method() + """), + self.mod1.read(), + ) + + +def test_moving_methods_and_nonexistent_attributes(self): + code = dedent("""\ + class A(object): + def a_method(self): + return 1 + """) + self.mod1.write(code) + with self.assertRaises(exceptions.RefactoringError): + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + mover.get_changes("x", "new_method") + + +def test_unknown_attribute_type(self): + code = dedent("""\ + class A(object): + attr = 1 + def a_method(self): + return 1 + """) + self.mod1.write(code) + with self.assertRaises(exceptions.RefactoringError): + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + mover.get_changes("attr", "new_method") + + +def test_moving_methods_and_moving_used_imports(self): + self.mod2.write("class B(object):\n var = 1\n") + code = dedent("""\ + import sys + import mod2 + + class A(object): + attr = mod2.B() + def a_method(self): + return sys.version + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + mover.get_changes("attr", "new_method").do() + code = dedent("""\ + import sys + class B(object): + var = 1 + + + def new_method(self): + return sys.version + """) + self.assertEqual(code, self.mod2.read()) + + +def test_moving_methods_getting_getting_changes_for_goal_class3(self): + self.mod2.write(dedent("""\ + class B(object): + pass + """)) + code = dedent("""\ + import mod2 + + class A(object): + attr = mod2.B() + def a_method(self): + return 1 + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + mover.get_changes("attr", "new_method").do() + expected = dedent("""\ + class B(object): + + def new_method(self): + return 1 + """) + self.assertEqual(expected, self.mod2.read()) + + +def test_moving_methods_and_source_class_with_parameters(self): + self.mod2.write("class B(object):\n pass\n") + code = dedent("""\ + import mod2 + + class A(object): + attr = mod2.B() + def a_method(self, p): + return p + """) + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("a_method")) + mover.get_changes("attr", "new_method").do() + expected1 = dedent("""\ + import mod2 + + class A(object): + attr = mod2.B() + def a_method(self, p): + return self.attr.new_method(p) + """) + self.assertEqual(expected1, self.mod1.read()) + expected2 = dedent("""\ + class B(object): + + def new_method(self, p): + return p + """) + self.assertEqual(expected2, self.mod2.read()) + + +def test_moving_globals_to_a_module_with_only_docstrings(self): + self.mod1.write(dedent("""\ + import sys + + + def f(): + print(sys.version) + """)) + self.mod2.write(dedent('''\ + """doc + + More docs ... + + """ + ''')) + mover = move.create_move( + self.project, self.mod1, self.mod1.read().index("f()") + 1 + ) + self.project.do(mover.get_changes(self.mod2)) + self.assertEqual( + dedent('''\ + """doc + + More docs ... + + """ + import sys + + + def f(): + print(sys.version) + '''), + self.mod2.read(), + ) + + +def test_moving_globals_to_a_module_with_only_docstrings2(self): + code = dedent("""\ + import os + import sys + + + def f(): + print(sys.version, os.path) + """) + self.mod1.write(code) + self.mod2.write('"""doc\n\nMore docs ...\n\n"""\n') + mover = move.create_move( + self.project, self.mod1, self.mod1.read().index("f()") + 1 + ) + self.project.do(mover.get_changes(self.mod2)) + expected = dedent('''\ + """doc + + More docs ... + + """ + import os + import sys + + + def f(): + print(sys.version, os.path) + ''') + self.assertEqual(expected, self.mod2.read()) + + +def _where_to_search(self): + if self.info.similar: + if self.info.make_global or self.info.global_: + return [(0, len(self.info.pymodule.source_code))] + if self.info.method and not self.info.variable: + class_scope = self.info.scope.parent + regions = [] + method_kind = _get_function_kind(self.info.scope) + for scope in class_scope.get_scopes(): + if ( + method_kind == "method" + and _get_function_kind(scope) != "method" + ): + continue + start = self.info.lines.get_line_start(scope.get_start()) + end = self.info.lines.get_line_end(scope.get_end()) + regions.append((start, end)) + return regions + else: + if self.info.variable: + return [self.info.scope_region] + else: + return [self.info._get_scope_region(self.info.scope.parent)] + else: + return [self.info.region] + + +def test_moving_a_global_when_it_is_used_after_a_multiline_str(self): + code = dedent('''\ + def f(): + pass + s = """\\ + """ + r = f() + ''') + self.mod1.write(code) + mover = move.create_move(self.project, self.mod1, code.index("f()") + 1) + self.project.do(mover.get_changes(self.mod2)) + expected = dedent('''\ + import mod2 + s = """\\ + """ + r = mod2.f() + ''') + self.assertEqual(expected, self.mod1.read()) + + +def test_raising_an_exception_when_moving_non_package_folders(self): + dir = self.project.root.create_folder("dir") + with self.assertRaises(exceptions.RefactoringError): + move.create_move(self.project, dir) + + +def test_moving_to_a_module_with_encoding_cookie(self): + code1 = "# -*- coding: utf-8 -*-" + self.mod1.write(code1) + code2 = dedent("""\ + def f(): pass + """) + self.mod2.write(code2) + mover = move.create_move(self.project, self.mod2, code2.index("f()") + 1) + self.project.do(mover.get_changes(self.mod1)) + expected = "%s\n%s" % (code1, code2) + self.assertEqual(expected, self.mod1.read()) + + +def test_moving_decorated_function(self): + self.mod1.write(dedent("""\ + def hello(func): + return func + @hello + def foo(): + pass + """)) + self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2) + self.assertEqual("def hello(func):\n return func\n", self.mod1.read()) + self.assertEqual( + dedent("""\ + from mod1 import hello + + + @hello + def foo(): + pass + """), + self.mod2.read(), + ) + + +def test_moving_decorated_class(self): + self.mod1.write(dedent("""\ + from dataclasses import dataclass + @dataclass + class AClass: + pass + """)) + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) + self.assertEqual("", self.mod1.read()) + self.assertEqual( + dedent("""\ + from dataclasses import dataclass + + + @dataclass + class AClass: + pass + """), + self.mod2.read(), + ) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +from textwrap import dedent + +import unittest + +from rope.refactor import multiproject, rename, move +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class MultiProjectRefactoringTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project1 = testutils.sample_project(foldername="testproject1") + self.project2 = testutils.sample_project(foldername="testproject2") + self.mod1 = self.project1.root.create_file("mod1.py") + self.other = self.project1.root.create_file("other.py") + self.mod2 = self.project2.root.create_file("mod2.py") + + +def tearDown(self): + testutils.remove_project(self.project1) + testutils.remove_project(self.project2) + super().tearDown() + + +def test_trivial_rename(self): + self.mod1.write("var = 1\n") + refactoring = multiproject.MultiProjectRefactoring(rename.Rename, []) + renamer = refactoring(self.project1, self.mod1, 1) + multiproject.perform(renamer.get_all_changes("newvar")) + self.assertEqual("newvar = 1\n", self.mod1.read()) + + +def _find_definition_location(self, collector): + matched_lines = [] + for match in collector.matches: + start = self.info.lines.get_line_number(match.get_region()[0]) + start_line = self.info.logical_lines.logical_line_in(start)[0] + matched_lines.append(start_line) + location_finder = _DefinitionLocationFinder(self.info, matched_lines) + collector.definition_location = ( + location_finder.find_lineno(), + location_finder.find_indents(), + ) + + +def test_rename(self): + self.mod1.write("var = 1\n") + self.mod2.write(dedent("""\ + import mod1 + myvar = mod1.var + """)) + refactoring = multiproject.MultiProjectRefactoring( + rename.Rename, [self.project2] + ) + renamer = refactoring(self.project1, self.mod1, 1) + multiproject.perform(renamer.get_all_changes("newvar")) + self.assertEqual("newvar = 1\n", self.mod1.read()) + self.assertEqual( + dedent("""\ + import mod1 + myvar = mod1.newvar + """), + self.mod2.read(), + ) + + +def test_move(self): + self.mod1.write(dedent("""\ + def a_func(): + pass + """)) + self.mod2.write(dedent("""\ + import mod1 + myvar = mod1.a_func() + """)) + refactoring = multiproject.MultiProjectRefactoring( + move.create_move, [self.project2] + ) + renamer = refactoring(self.project1, self.mod1, self.mod1.read().index("_func")) + multiproject.perform(renamer.get_all_changes(self.other)) + self.assertEqual("", self.mod1.read()) + self.assertEqual( + dedent("""\ + def a_func(): + pass + """), + self.other.read(), + ) + self.assertEqual( + dedent("""\ + import other + myvar = other.a_func() + """), + self.mod2.read(), + ) + + +def test_rename_from_the_project_not_containing_the_change(self): + self.project2.get_prefs().add("python_path", self.project1.address) + self.mod1.write("var = 1\n") + self.mod2.write(dedent("""\ + import mod1 + myvar = mod1.var + """)) + refactoring = multiproject.MultiProjectRefactoring( + rename.Rename, [self.project1] + ) + renamer = refactoring(self.project2, self.mod2, self.mod2.read().rindex("var")) + multiproject.perform(renamer.get_all_changes("newvar")) + self.assertEqual( + dedent("""\ + newvar = 1 + """), + self.mod1.read(), + ) + self.assertEqual( + dedent("""\ + import mod1 + myvar = mod1.newvar + """), + self.mod2.read(), + ) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +import unittest +import sys +from textwrap import dedent + +from rope.base import ast +from rope.refactor import patchedast +from ropetest import testutils + +try: + basestring +except NameError: + basestring = (str, bytes) + +NameConstant = "Name" if sys.version_info <= (3, 8) else "NameConstant" +Bytes = "Bytes" if (3, 0) <= sys.version_info <= (3, 8) else "Str" + + +@others +@language python +@tabwidth -4 + +class PatchedASTTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + + +def tearDown(self): + super().tearDown() + + +def assert_single_case_match_block(self, checker, match_type): + checker.check_children("Match", [ + "match", + " ", + "Name", + "", + ":", + "\n ", + "match_case", + ]) + checker.check_children("match_case", [ + "case", + " ", + match_type, + "", + ":", + "\n ", + "Expr", + ]) + + +def test_bytes_string(self): + source = '1 + b"("\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + str_fragment = 'b"("' + start = source.index(str_fragment) + checker.check_region(Bytes, start, start + len(str_fragment)) + checker.check_children(Bytes, [str_fragment]) + + +def test_integer_literals_and_region(self): + source = "a = 10\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.index("10") + checker.check_region("Num", start, start + 2) + + +def _find_definition(self, collector): + if self.info.variable: + parts = _ExtractVariableParts(self.info) + else: + parts = _ExtractMethodParts(self.info) + collector.definition = parts.get_definition() + collector.body_pattern = parts.get_body_pattern() + collector.replacement_pattern = parts.get_replacement_pattern() + collector.checks = parts.get_checks() + + + +def test_negative_integer_literals_and_region(self): + source = "a = -10\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.index("-10") + 1 + end = start + 2 + # Python 3 parses as UnaryOp(op=USub(), operand=Num(n=10)) + checker.check_region("Num", start, end) + + +def test_scientific_integer_literals_and_region(self): + source = "a = -1.0e-3\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.index("-1.0e-3") + 1 + end = start + 6 + # Python 3 parses as UnaryOp(op=USub(), operand=Num(n=10)) + checker.check_region("Num", start, end) + + +def test_hex_integer_literals_and_region(self): + source = "a = 0x1\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.index("0x1") + checker.check_region("Num", start, start + 3) + + +@testutils.only_for_versions_lower("3") +def test_long_literals_and_region(self): + source = "a = 0x1L\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.index("0x1L") + checker.check_region("Num", start, start + 4) + + +def test_octal_integer_literals_and_region(self): + source = "a = -0125e1\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.index("-0125e1") + 1 + end = start + 6 + # Python 3 parses as UnaryOp(op=USub(), operand=Num(n=10)) + checker.check_region("Num", start, end) + + +def test_integer_literals_and_sorted_children(self): + source = "a = 10\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Num", ["10"]) + + +def test_ellipsis(self): + source = "a[...]\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.index("...") + checker.check_region("Ellipsis", start, start + len("...")) + + +def test_ass_name_node(self): + source = "a = 10\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.index("a") + checker.check_region("Name", start, start + 1) + checker.check_children("Name", ["a"]) + + +def test_assign_node(self): + source = "a = 10\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Assign", 0, len(source) - 1) + checker.check_children("Assign", ["Name", " ", "=", " ", "Num"]) + + +@testutils.only_for_versions_higher("3.6") +def test_ann_assign_node_without_target(self): + source = "a: List[int]\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("AnnAssign", 0, len(source) - 1) + checker.check_children("AnnAssign", ["Name", "", ":", " ", "Subscript"]) + + +class _DefinitionLocationFinder: + @others + +@testutils.only_for_versions_higher("3.6") +def test_ann_assign_node_with_target(self): + source = "a: int = 10\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("AnnAssign", 0, len(source) - 1) + checker.check_children( + "AnnAssign", ["Name", "", ":", " ", "Name", " ", "=", " ", "Num"] + ) + + +def test_add_node(self): + source = "1 + 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("BinOp", 0, len(source) - 1) + checker.check_children("BinOp", ["Num", " ", "+", " ", "Num"]) + + +def test_lshift_node(self): + source = "1 << 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("BinOp", 0, len(source) - 1) + checker.check_children("BinOp", ["Num", " ", "<<", " ", "Num"]) + + +def test_and_node(self): + source = "True and True\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("BoolOp", 0, len(source) - 1) + checker.check_children("BoolOp", [NameConstant, " ", "and", " ", NameConstant]) + + +def test_matmult_node(self): + source = "a @ b\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("BinOp", ["Name", " ", "@", " ", "Name"]) + + +def test_basic_closing_parens(self): + source = "1 + (2)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("BinOp", 0, len(source) - 1) + checker.check_children("BinOp", ["Num", " ", "+", " (", "Num", ")"]) + + +def test_basic_opening_parens(self): + source = "(1) + 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("BinOp", 0, len(source) - 1) + checker.check_children("BinOp", ["(", "Num", ") ", "+", " ", "Num"]) + + +def test_basic_opening_biway(self): + source = "(1) + (2)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("BinOp", 0, len(source) - 1) + checker.check_children("BinOp", ["(", "Num", ") ", "+", " (", "Num", ")"]) + + +def test_basic_opening_double(self): + source = "1 + ((2))\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("BinOp", 0, len(source) - 1) + checker.check_children("BinOp", ["Num", " ", "+", " ((", "Num", "))"]) + + +def test_handling_comments(self): + source = "(1 + #(\n2)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("BinOp", ["Num", " ", "+", " #(\n", "Num"]) + + +def __init__(self, info, matched_lines): + self.info = info + self.matched_lines = matched_lines + # This only happens when subexpressions cannot be matched + if not matched_lines: + self.matched_lines.append(self.info.region_lines[0]) + + +def test_handling_parens_with_spaces(self): + source = "1 + (2\n )\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("BinOp", ["Num", " ", "+", " (", "Num", "\n )"]) + + +def test_handling_strings(self): + source = '1 + "("\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("BinOp", ["Num", " ", "+", " ", "Str"]) + + +def test_handling_implicit_string_concatenation(self): + source = "a = '1''2'" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Assign", ["Name", " ", "=", " ", "Str"]) + checker.check_children("Str", ["'1''2'"]) + + +def test_handling_implicit_string_concatenation_line_breaks(self): + source = dedent("""\ + a = '1' \\ + '2'""") + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Assign", ["Name", " ", "=", " ", "Str"]) + checker.check_children("Str", ["'1' \\\n'2'"]) + + +def test_handling_explicit_string_concatenation_line_breaks(self): + source = "a = ('1' \n'2')" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Assign", ["Name", " ", "=", " (", "Str", ")"]) + checker.check_children("Str", ["'1' \n'2'"]) + + +def test_not_concatenating_strings_on_separate_lines(self): + source = dedent("""\ + '1' + '2' + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Module", ["", "Expr", "\n", "Expr", "\n"]) + + +def test_handling_raw_strings(self): + source = 'r"abc"\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Str", ['r"abc"']) + + +@testutils.only_for_versions_higher("3.6") +def test_handling_format_strings_basic(self): + source = '1 + f"abc{a}"\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("JoinedStr", ['f"', "abc", "FormattedValue", "", '"']) + checker.check_children("FormattedValue", ["{", "", "Name", "", "}"]) + + +@testutils.only_for_versions_higher("3.6") +def test_handling_format_strings_with_implicit_join(self): + source = '''"1" + rf'abc{a}' f"""xxx{b} """\n''' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "JoinedStr", + ["rf'", "abc", "FormattedValue", '\' f"""xxx', "FormattedValue", " ", '"""',], + ) + checker.check_children("FormattedValue", ["{", "", "Name", "", "}"]) + + +@testutils.only_for_versions_higher("3.6") +def test_handling_format_strings_with_format_spec(self): + source = 'f"abc{a:01}"\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("JoinedStr", ['f"', "abc", "FormattedValue", "", '"']) + checker.check_children( + "FormattedValue", ["{", "", "Name", "", ":", "", "01", "", "}"] + ) + + +def find_lineno(self): + if self.info.variable and not self.info.make_global: + return self._get_before_line() + if self.info.global_: + toplevel = self._find_toplevel(self.info.scope) + ast = self.info.pymodule.get_ast() + newlines = sorted(self.matched_lines + [toplevel.get_end() + 1]) + return suites.find_visible(ast, newlines) + if self.info.make_global: + toplevel = self._find_toplevel(self.info.scope) + return toplevel.get_end() + 1 + return self._get_after_scope() + + +@testutils.only_for_versions_higher("3.6") +def test_handling_format_strings_with_inner_format_spec(self): + source = 'f"abc{a:{length}01}"\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("JoinedStr", ['f"', "abc", "FormattedValue", "", '"']) + checker.check_children( + "FormattedValue", + ["{", "", "Name", "", ":", "{", "Name", "}", "01", "", "}"], + ) + + +@testutils.only_for_versions_higher("3.6") +def test_handling_format_strings_with_expression(self): + source = 'f"abc{a + b}"\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("JoinedStr", ['f"', "abc", "FormattedValue", "", '"']) + checker.check_children("FormattedValue", ["{", "", "BinOp", "", "}"]) + + +@testutils.only_for_versions_lower("3") +def test_long_integer_literals(self): + source = "0x1L + a" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("BinOp", ["Num", " ", "+", " ", "Name"]) + checker.check_children("Num", ["0x1L"]) + + +def test_complex_number_literals(self): + source = "1.0e2j + a" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("BinOp", ["Num", " ", "+", " ", "Name"]) + checker.check_children("Num", ["1.0e2j"]) + + +def test_ass_attr_node(self): + source = "a.b = 1\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Attribute", 0, source.index("=") - 1) + checker.check_children("Attribute", ["Name", "", ".", "", "b"]) + + +def test_ass_list_node(self): + source = "[a, b] = 1, 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("List", 0, source.index("]") + 1) + checker.check_children("List", ["[", "", "Name", "", ",", " ", "Name", "", "]"]) + + +def test_ass_tuple(self): + source = "a, b = range(2)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Tuple", 0, source.index("=") - 1) + checker.check_children("Tuple", ["Name", "", ",", " ", "Name"]) + + +def test_ass_tuple2(self): + source = "(a, b) = range(2)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Tuple", 0, source.index("=") - 1) + checker.check_children( + "Tuple", ["(", "", "Name", "", ",", " ", "Name", "", ")"] + ) + + +def test_assert(self): + source = "assert True\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Assert", 0, len(source) - 1) + checker.check_children("Assert", ["assert", " ", NameConstant]) + + +def test_assert2(self): + source = 'assert True, "error"\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Assert", 0, len(source) - 1) + checker.check_children( + "Assert", ["assert", " ", NameConstant, "", ",", " ", "Str"] + ) + + +def _get_element_kind(self): + raise NotImplementedError() + + +def _find_toplevel(self, scope): + toplevel = scope + if toplevel.parent is not None: + while toplevel.parent.parent is not None: + toplevel = toplevel.parent + return toplevel + + +def test_aug_assign_node(self): + source = "a += 1\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.index("a") + checker.check_region("AugAssign", 0, len(source) - 1) + checker.check_children("AugAssign", ["Name", " ", "+", "", "=", " ", "Num"]) + self.assertTrue(start is not None) + + +@testutils.only_for_versions_lower("3") +def test_back_quotenode(self): + source = "`1`\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Repr", 0, len(source) - 1) + checker.check_children("Repr", ["`", "", "Num", "", "`"]) + + +def test_bitand(self): + source = "1 & 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("BinOp", 0, len(source) - 1) + checker.check_children("BinOp", ["Num", " ", "&", " ", "Num"]) + + +def test_bitor(self): + source = "1 | 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("BinOp", ["Num", " ", "|", " ", "Num"]) + + +def test_call_func(self): + source = "f(1, 2)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Call", 0, len(source) - 1) + checker.check_children( + "Call", ["Name", "", "(", "", "Num", "", ",", " ", "Num", "", ")"] + ) + + +def test_call_func_and_keywords(self): + source = "f(1, p=2)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", ["Name", "", "(", "", "Num", "", ",", " ", "keyword", "", ")"] + ) + + +@testutils.only_for_versions_lower("3.5") +def test_call_func_and_star_args(self): + source = "f(1, *args)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", ["Name", "", "(", "", "Num", "", ",", " ", "*", "", "Name", "", ")"] + ) + + +@testutils.only_for("3.5") +def test_call_func_and_star_argspython35(self): + source = "f(1, *args)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", ["Name", "", "(", "", "Num", "", ",", " *", "Starred", "", ")"] + ) + + +@testutils.only_for_versions_lower("3.5") +def test_call_func_and_only_dstar_args(self): + source = "f(**kwds)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Call", ["Name", "", "(", "", "**", "", "Name", "", ")"]) + + +@testutils.only_for("3.5") +def test_call_func_and_only_dstar_args_python35(self): + source = "f(**kwds)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Call", ["Name", "", "(", "**", "keyword", "", ")"]) + + +def find_indents(self): + if self.info.variable and not self.info.make_global: + return sourceutils.get_indents(self.info.lines, self._get_before_line()) + else: + if self.info.global_ or self.info.make_global: + return 0 + return self.info.scope_indents + + +@testutils.only_for_versions_lower("3.5") +def test_call_func_and_both_varargs_and_kwargs(self): + source = "f(*args, **kwds)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", + ["Name", "", "(", "", "*", "", "Name", "", ",", " ", "**", "", "Name", "", ")"], + ) + + +@testutils.only_for("3.5") +def test_call_func_and_both_varargs_and_kwargs_python35(self): + source = "f(*args, **kwds)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", + ["Name", "", "(", "*", "Starred", "", ",", " **", "keyword", "", ")"], + ) + + +def test_class_node(self): + source = dedent('''\ + class A(object): + """class docs""" + pass + ''') + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Class", 0, len(source) - 1) + checker.check_children( + "Class", + ["class", " ", "A", "", "(", "", "Name", "", ")", "", ":", "\n ", "Expr", "\n ", "Pass"], + ) + + +def test_class_with_no_bases(self): + source = dedent("""\ + class A: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Class", 0, len(source) - 1) + checker.check_children("Class", ["class", " ", "A", "", ":", "\n ", "Pass"]) + + +def test_simple_compare(self): + source = "1 < 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Compare", 0, len(source) - 1) + checker.check_children("Compare", ["Num", " ", "<", " ", "Num"]) + + +def test_multiple_compare(self): + source = "1 < 2 <= 3\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Compare", 0, len(source) - 1) + checker.check_children( + "Compare", ["Num", " ", "<", " ", "Num", " ", "<=", " ", "Num"] + ) + + +def test_decorators_node(self): + source = dedent("""\ + @d + def f(): + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("FunctionDef", 0, len(source) - 1) + checker.check_children( + "FunctionDef", + ["@", "", "Name", "\n", "def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Pass"], + ) + + +@testutils.only_for("2.6") +def test_decorators_for_classes(self): + source = dedent("""\ + @d + class C(object): + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("ClassDef", 0, len(source) - 1) + checker.check_children( + "ClassDef", + ["@", "", "Name", "\n", "class", " ", "C", "", "(", "", "Name", "", ")", "", ":", "\n ", "Pass"], + ) + + +def test_both_varargs_and_kwargs(self): + source = dedent("""\ + def f(*args, **kwds): + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "arguments", ["*", "", "args", "", ",", " ", "**", "", "kwds"] + ) + + +def test_function_node(self): + source = dedent("""\ + def f(): + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Function", 0, len(source) - 1) + checker.check_children( + "Function", + ["def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Pass"], + ) + + +def _get_before_line(self): + ast = self.info.scope.pyobject.get_ast() + return suites.find_visible(ast, self.matched_lines) + + +@testutils.only_for_versions_higher("3.5") +def test_async_function_node(self): + source = dedent("""\ + async def f(): + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("AsyncFunction", 0, len(source) - 1) + checker.check_children( + "AsyncFunction", + ["async", " ", "def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Pass"], + ) + + +def test_function_node2(self): + source = dedent('''\ + def f(p1, **p2): + """docs""" + pass + ''') + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Function", 0, len(source) - 1) + checker.check_children( + "Function", + ["def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Expr", "\n ", "Pass"], + ) + expected_child = ast.arg.__name__ + checker.check_children( + "arguments", [expected_child, "", ",", " ", "**", "", "p2"] + ) + + +@testutils.only_for_versions_lower("3") +def test_function_node_and_tuple_parameters(self): + source = dedent("""\ + def f(a, (b, c)): + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Function", 0, len(source) - 1) + checker.check_children( + "Function", + ["def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Pass"], + ) + checker.check_children("arguments", ["Name", "", ",", " ", "Tuple"]) + + +def test_dict_node(self): + source = "{1: 2, 3: 4}\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Dict", 0, len(source) - 1) + checker.check_children( + "Dict", + ["{", "", "Num", "", ":", " ", "Num", "", ",", " ", "Num", "", ":", " ", "Num", "", "}"], + ) + + +@testutils.only_for("3.5") +def test_dict_node_with_unpacking(self): + source = "{**dict1, **dict2}\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Dict", 0, len(source) - 1) + checker.check_children( + "Dict", ["{", "", "**", "", "Name", "", ",", " ", "**", "", "Name", "", "}"] + ) + + +def test_div_node(self): + source = "1 / 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("BinOp", 0, len(source) - 1) + checker.check_children("BinOp", ["Num", " ", "/", " ", "Num"]) + + +@testutils.only_for_versions_lower("3") +def test_simple_exec_node(self): + source = 'exec ""\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Exec", 0, len(source) - 1) + checker.check_children("Exec", ["exec", "", "", " ", "Str", "", ""]) + + +@testutils.only_for_versions_lower("3") +def test_exec_node(self): + source = 'exec "" in locals(), globals()\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Exec", 0, len(source) - 1) + checker.check_children( + "Exec", + ["exec", "", "", " ", "Str", " ", "in", " ", "Call", "", ",", " ", "Call", "", ""], + ) + + +@testutils.only_for_versions_lower("3") +def test_exec_node_with_parens(self): + source = 'exec("", locals(), globals())\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Exec", 0, len(source) - 1) + checker.check_children( + "Exec", + ["exec", "", "(", "", "Str", "", ",", " ", "Call", "", ",", " ", "Call", "", ")"], + ) + + +def test_for_node(self): + source = dedent("""\ + for i in range(1): + pass + else: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("For", 0, len(source) - 1) + checker.check_children( + "For", + ["for", " ", "Name", " ", "in", " ", "Call", "", ":", "\n ", "Pass", "\n", "else", "", ":", "\n ", "Pass"], + ) + + +def _get_after_scope(self): + return self.info.scope.get_end() + 1 + + + +@testutils.only_for_versions_higher("3.5") +def test_async_for_node(self): + source = dedent("""\ + async def foo(): + async for i in range(1): + pass + else: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("AsyncFor", source.index("async for"), len(source) - 1) + checker.check_children( + "AsyncFor", + ["async", " ", "for", " ", "Name", " ", "in", " ", "Call", "", ":", "\n ", "Pass", "\n ", "else", "", ":", "\n ", "Pass"], + ) + + +@testutils.only_for_versions_higher("3.8") +def test_named_expr_node(self): + source = dedent("""\ + if a := 10 == 10: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.index("a") + checker.check_region("NamedExpr", start, start + 13) + checker.check_children("NamedExpr", ["Name", " ", ":=", " ", "Compare"]) + + +def test_normal_from_node(self): + source = "from x import y\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("ImportFrom", 0, len(source) - 1) + checker.check_children( + "ImportFrom", ["from", " ", "x", " ", "import", " ", "alias"] + ) + checker.check_children("alias", ["y"]) + + +@testutils.only_for("2.5") +def test_from_node(self): + source = "from ..x import y as z\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("ImportFrom", 0, len(source) - 1) + checker.check_children( + "ImportFrom", ["from", " ", "..", "", "x", " ", "import", " ", "alias"] + ) + checker.check_children("alias", ["y", " ", "as", " ", "z"]) + + +@testutils.only_for("2.5") +def test_from_node_relative_import(self): + source = "from . import y as z\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("ImportFrom", 0, len(source) - 1) + checker.check_children( + "ImportFrom", ["from", " ", ".", "", "", " ", "import", " ", "alias"] + ) + checker.check_children("alias", ["y", " ", "as", " ", "z"]) + + +def test_simple_gen_expr_node(self): + source = "zip(i for i in x)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("GeneratorExp", 4, len(source) - 2) + checker.check_children("GeneratorExp", ["Name", " ", "comprehension"]) + checker.check_children( + "comprehension", ["for", " ", "Name", " ", "in", " ", "Name"] + ) + + +def test_gen_expr_node_handling_surrounding_parens(self): + source = "(i for i in x)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("GeneratorExp", 0, len(source) - 1) + checker.check_children( + "GeneratorExp", ["(", "", "Name", " ", "comprehension", "", ")"] + ) + + +def test_gen_expr_node2(self): + source = "zip(i for i in range(1) if i == 1)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "comprehension", + ["for", " ", "Name", " ", "in", " ", "Call", " ", "if", " ", "Compare"], + ) + + +def test_get_attr_node(self): + source = "a.b\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Attribute", 0, len(source) - 1) + checker.check_children("Attribute", ["Name", "", ".", "", "b"]) + + +def test_global_node(self): + source = "global a, b\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Global", 0, len(source) - 1) + checker.check_children("Global", ["global", " ", "a", "", ",", " ", "b"]) + + +class _ExceptionalConditionChecker: + @others + +def test_if_node(self): + source = "if True:\n pass\nelse:\n pass\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("If", 0, len(source) - 1) + checker.check_children( + "If", + ["if", " ", NameConstant, "", ":", "\n ", "Pass", "\n", "else", "", ":", "\n ", "Pass"], + ) + + +def test_if_node2(self): + source = dedent("""\ + if True: + pass + elif False: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("If", 0, len(source) - 1) + checker.check_children( + "If", ["if", " ", NameConstant, "", ":", "\n ", "Pass", "\n", "If"] + ) + + +def test_if_node3(self): + source = dedent("""\ + if True: + pass + else: + if True: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("If", 0, len(source) - 1) + checker.check_children( + "If", + ["if", " ", NameConstant, "", ":", "\n ", "Pass", "\n", "else", "", ":", "\n ", "If"], + ) + + +def test_import_node(self): + source = "import a, b as c\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Import", 0, len(source) - 1) + checker.check_children( + "Import", ["import", " ", "alias", "", ",", " ", "alias"] + ) + + +def test_lambda_node(self): + source = "lambda a, b=1, *z: None\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Lambda", 0, len(source) - 1) + checker.check_children( + "Lambda", ["lambda", " ", "arguments", "", ":", " ", NameConstant] + ) + expected_child = ast.arg.__name__ + checker.check_children( + "arguments", + [expected_child, "", ",", " ", expected_child, "", "=", "", "Num", "", ",", " ", "*", "", "z"], + ) + + +def test_list_node(self): + source = "[1, 2]\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("List", 0, len(source) - 1) + checker.check_children("List", ["[", "", "Num", "", ",", " ", "Num", "", "]"]) + + +def test_list_comp_node(self): + source = "[i for i in range(1) if True]\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("ListComp", 0, len(source) - 1) + checker.check_children( + "ListComp", ["[", "", "Name", " ", "comprehension", "", "]"] + ) + checker.check_children( + "comprehension", + ["for", " ", "Name", " ", "in", " ", "Call", " ", "if", " ", NameConstant], + ) + + +def test_list_comp_node_with_multiple_comprehensions(self): + source = "[i for i in range(1) for j in range(1) if True]\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("ListComp", 0, len(source) - 1) + checker.check_children( + "ListComp", + ["[", "", "Name", " ", "comprehension", " ", "comprehension", "", "]"], + ) + checker.check_children( + "comprehension", + ["for", " ", "Name", " ", "in", " ", "Call", " ", "if", " ", NameConstant], + ) + + +def test_set_node(self): + # make sure we are in a python version with set literals + source = "{1, 2}\n" + + try: + eval(source) + except SyntaxError: + return + + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Set", 0, len(source) - 1) + checker.check_children("Set", ["{", "", "Num", "", ",", " ", "Num", "", "}"]) + + +def test_set_comp_node(self): + # make sure we are in a python version with set comprehensions + source = "{i for i in range(1) if True}\n" + + try: + eval(source) + except SyntaxError: + return + + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("SetComp", 0, len(source) - 1) + checker.check_children( + "SetComp", ["{", "", "Name", " ", "comprehension", "", "}"] + ) + checker.check_children( + "comprehension", + ["for", " ", "Name", " ", "in", " ", "Call", " ", "if", " ", NameConstant], + ) + + +def __call__(self, info): + self.base_conditions(info) + if info.one_line: + self.one_line_conditions(info) + else: + self.multi_line_conditions(info) + + +def test_dict_comp_node(self): + # make sure we are in a python version with dict comprehensions + source = "{i:i for i in range(1) if True}\n" + + try: + eval(source) + except SyntaxError: + return + + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("DictComp", 0, len(source) - 1) + checker.check_children( + "DictComp", + ["{", "", "Name", "", ":", "", "Name", " ", "comprehension", "", "}"], + ) + checker.check_children( + "comprehension", + ["for", " ", "Name", " ", "in", " ", "Call", " ", "if", " ", NameConstant], + ) + + +def test_ext_slice_node(self): + source = "x = xs[0,:]\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + if sys.version_info >= (3, 9): + checker.check_region("Tuple", 7, len(source) - 2) + checker.check_children("Tuple", ["Num", "", ",", "", "Slice"]) + else: + checker.check_region("ExtSlice", 7, len(source) - 2) + checker.check_children("ExtSlice", ["Index", "", ",", "", "Slice"]) + + +def test_simple_module_node(self): + source = "pass\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Module", 0, len(source)) + checker.check_children("Module", ["", "Pass", "\n"]) + + +def test_module_node(self): + source = dedent('''\ + """docs""" + pass + ''') + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Module", 0, len(source)) + checker.check_children("Module", ["", "Expr", "\n", "Pass", "\n"]) + checker.check_children("Str", ['"""docs"""']) + + +def test_not_and_or_nodes(self): + source = "not True or False\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Expr", ["BoolOp"]) + checker.check_children("BoolOp", ["UnaryOp", " ", "or", " ", NameConstant]) + + +@testutils.only_for_versions_lower("3") +def test_print_node(self): + source = "print >>out, 1,\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Print", 0, len(source) - 1) + checker.check_children( + "Print", ["print", " ", ">>", "", "Name", "", ",", " ", "Num", "", ","] + ) + + +@testutils.only_for_versions_lower("3") +def test_printnl_node(self): + source = "print 1\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Print", 0, len(source) - 1) + checker.check_children("Print", ["print", " ", "Num"]) + + +@testutils.only_for_versions_lower("3") +def test_raise_node_for_python2(self): + source = "raise x, y, z\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Raise", 0, len(source) - 1) + checker.check_children( + "Raise", ["raise", " ", "Name", "", ",", " ", "Name", "", ",", " ", "Name"] + ) + + +# @#testutils.only_for('3') +@unittest.skipIf(sys.version < "3", "This is wrong") +def test_raise_node_for_python3(self): + source = "raise x(y)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_region("Raise", 0, len(source) - 1) + checker.check_children("Raise", ["raise", " ", "Call"]) + + +def test_return_node(self): + source = dedent("""\ + def f(): + return None + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Return", ["return", " ", NameConstant]) + + +def base_conditions(self, info): + if info.region[1] > info.scope_region[1]: + raise RefactoringError("Bad region selected for extract method") + end_line = info.region_lines[1] + end_scope = info.global_scope.get_inner_scope_for_line(end_line) + if end_scope != info.scope and end_scope.get_end() != end_line: + raise RefactoringError("Bad region selected for extract method") + try: + extracted = info.extracted + if info.one_line: + extracted = "(%s)" % extracted + if _UnmatchedBreakOrContinueFinder.has_errors(extracted): + raise RefactoringError( + "A break/continue without having a matching for/while loop." + ) + except SyntaxError: + raise RefactoringError( + "Extracted piece should contain complete statements." + ) + + +def test_empty_return_node(self): + source = dedent("""\ + def f(): + return + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Return", ["return"]) + + +def test_simple_slice_node(self): + source = "a[1:2]\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Subscript", ["Name", "", "[", "", "Slice", "", "]"]) + checker.check_children("Slice", ["Num", "", ":", "", "Num"]) + + +def test_slice_node2(self): + source = "a[:]\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Subscript", ["Name", "", "[", "", "Slice", "", "]"]) + checker.check_children("Slice", [":"]) + + +def test_simple_subscript(self): + source = "a[1]\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + if sys.version_info >= (3, 9): + checker.check_children("Subscript", ["Name", "", "[", "", "Num", "", "]"]) + else: + checker.check_children("Subscript", ["Name", "", "[", "", "Index", "", "]"]) + checker.check_children("Index", ["Num"]) + + +def test_tuple_node(self): + source = "(1, 2)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Tuple", ["(", "", "Num", "", ",", " ", "Num", "", ")"]) + + +def test_tuple_node2(self): + source = "#(\n1, 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Tuple", ["Num", "", ",", " ", "Num"]) + + +def test_tuple_with_complex_parentheses1(self): + source = "a = ( # (he\n ((((), None))))\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Tuple", ["(", "", "Tuple", "", ",", " ", NameConstant, "", ")"] + ) + + +def test_tuple_with_complex_parentheses2(self): + source = "a = ( # (he\n ((((('a')), ('b')))))\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Tuple", ["(", "", "((", "Str", "))", ",", " (", "Str", ")", "", ")"] + ) + + +def test_tuple_with_complex_parentheses3(self): + source = "a = ((), (([],), []),)" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Tuple", ["(", "", "Tuple", "", ",", " ", "Tuple", ",", ")"] + ) + + +def test_one_item_tuple_node(self): + source = "(1,)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Tuple", ["(", "", "Num", ",", ")"]) + + +def one_line_conditions(self, info): + if self._is_region_on_a_word(info): + raise RefactoringError("Should extract complete statements.") + if info.variable and not info.one_line: + raise RefactoringError("Extract variable should not span multiple lines.") + if usefunction._named_expr_count( + info._parsed_extracted + ) - usefunction._namedexpr_last(info._parsed_extracted): + raise RefactoringError( + "Extracted piece cannot contain named expression (:= operator)." + ) + + +def test_empty_tuple_node(self): + source = "()\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Tuple", ["()"]) + + +def test_empty_tuple_node2(self): + source = "a = ((), None)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Tuple", ["(", "", "Tuple", "", ",", " ", NameConstant, "", ")"] + ) + + +def test_empty_tuple_node3(self): + source = "a = (), None\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Tuple", ["Tuple", "", ",", " ", NameConstant] + ) + + +def test_yield_node(self): + source = dedent("""\ + def f(): + yield None + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Yield", ["yield", " ", NameConstant]) + + +@testutils.only_for_versions_higher("3.3") +def test_yield_from_node(self): + source = dedent("""\ + def f(lst): + yield from lst + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("YieldFrom", ["yield", " ", "from", " ", "Name"]) + + +def test_while_node(self): + source = dedent("""\ + while True: + pass + else: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "While", + ["while", " ", NameConstant, "", ":", "\n ", "Pass", "\n", "else", "", ":", "\n ", "Pass"], + ) + + +@testutils.only_for("2.5") +def test_with_node(self): + source = dedent("""\ + from __future__ import with_statement + with a as b: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "With", + ["with", " ", "Name", " ", "as", " ", "Name", "", ":", "\n ", "Pass"], + ) + + +@testutils.only_for("3.5") +def test_async_with_node(self): + source = dedent("""\ + async def afunc(): + async with a as b: + pass\n + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "AsyncWith", + ["async", " ", "with", " ", "Name", " ", "as", " ", "Name", "", ":", "\n ", "Pass"], + ) + + +def test_try_finally_node(self): + source = dedent("""\ + try: + pass + finally: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + node_to_test = "Try" + expected_children = ["try", "", ":", "\n ", "Pass", "\n", "finally", "", ":", "\n ", "Pass"] + checker.check_children(node_to_test, expected_children) + + +@testutils.only_for_versions_lower("3") +def test_try_except_node(self): + source = dedent("""\ + try: + pass + except Exception, e: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "TryExcept", + ["try", "", ":", "\n ", "Pass", "\n", ("excepthandler", "ExceptHandler")], + ) + checker.check_children( + ("excepthandler", "ExceptHandler"), + ["except", " ", "Name", "", ",", " ", "Name", "", ":", "\n ", "Pass"], + ) + + +def multi_line_conditions(self, info): + node = _parse_text(info.source[info.region[0] : info.region[1]]) + count = usefunction._return_count(node) + extracted = info.extracted + if count > 1: + raise RefactoringError( + "Extracted piece can have only one return statement." + ) + if usefunction._yield_count(node): + raise RefactoringError("Extracted piece cannot have yield statements.") + if not hasattr( + ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT" + ) and _AsyncStatementFinder.has_errors(extracted): + raise RefactoringError( + "Extracted piece can only have async/await " + "statements if Rope is running on Python " + "3.8 or higher" + ) + if count == 1 and not usefunction._returns_last(node): + raise RefactoringError("Return should be the last statement.") + if info.region != info.lines_region: + raise RefactoringError( + "Extracted piece should contain complete statements." + ) + + +def test_try_except_node__with_as_syntax(self): + source = dedent("""\ + try: + pass + except Exception as e: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + node_to_test = "Try" + checker.check_children( + node_to_test, + ["try", "", ":", "\n ", "Pass", "\n", ("excepthandler", "ExceptHandler")], + ) + expected_child = "e" + checker.check_children( + ("excepthandler", "ExceptHandler"), + ["except", " ", "Name", " ", "as", " ", expected_child, "", ":", "\n ", "Pass"], + ) + + +@testutils.only_for("2.5") +def test_try_except_and_finally_node(self): + source = dedent("""\ + try: + pass + except: + pass + finally: + pass + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + node_to_test = "Try" + expected_children = ["try", "", ":", "\n ", "Pass", "\n", "ExceptHandler", "\n", "finally", "", ":", "\n ", "Pass"] + checker.check_children(node_to_test, expected_children) + + +def test_ignoring_comments(self): + source = "#1\n1\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + start = source.rindex("1") + checker.check_region("Num", start, start + 1) + + +def test_simple_sliceobj(self): + source = "a[1::3]\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Slice", ["Num", "", ":", "", ":", "", "Num"]) + + +def test_ignoring_strings_that_start_with_a_char(self): + source = 'r"""("""\n1\n' + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Module", ["", "Expr", "\n", "Expr", "\n"]) + + +@testutils.only_for_versions_lower("3") +def test_how_to_handle_old_not_equals(self): + source = "1 <> 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Compare", ["Num", " ", "<>", " ", "Num"]) + + +def test_semicolon(self): + source = "1;\n" + patchedast.get_patched_ast(source, True) + + +@testutils.only_for("2.5") +def test_if_exp_node(self): + source = "1 if True else 2\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "IfExp", ["Num", " ", "if", " ", NameConstant, " ", "else", " ", "Num"] + ) + + +def test_delete_node(self): + source = "del a, b\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Delete", ["del", " ", "Name", "", ",", " ", "Name"]) + + +@testutils.only_for_versions_lower("3.5") +def test_starargs_before_keywords_legacy(self): + source = "foo(*args, a=1)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", + ["Name", "", "(", "", "*", "", "Name", "", ",", " ", "keyword", "", ")"], + ) + + +def _is_region_on_a_word(self, info): + if ( + info.region[0] > 0 + and self._is_on_a_word(info, info.region[0] - 1) + or self._is_on_a_word(info, info.region[1] - 1) + ): + return True + + +@testutils.only_for_versions_lower("3.5") +def test_starargs_in_keywords_legacy(self): + source = "foo(a=1, *args, b=2)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", + ["Name", "", "(", "", "keyword", "", ",", " ", "*", "", "Name", "", ",", " ", "keyword", "", ")"], + ) + + +@testutils.only_for_versions_lower("3.5") +def test_starargs_after_keywords_legacy(self): + source = "foo(a=1, *args)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", + ["Name", "", "(", "", "keyword", "", ",", " ", "*", "", "Name", "", ")"], + ) + + +@testutils.only_for("3.5") +def test_starargs_before_keywords(self): + source = "foo(*args, a=1)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", ["Name", "", "(", "*", "Starred", "", ",", " ", "keyword", "", ")"] + ) + + +@testutils.only_for("3.5") +def test_starargs_in_keywords(self): + source = "foo(a=1, *args, b=2)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", + ["Name", "", "(", "", "keyword", "", ",", " *", "Starred", "", ",", " ", "keyword", "", ")"], + ) + + +@testutils.only_for("3.5") +def test_starargs_in_positional(self): + source = "foo(a, *b, c)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", + ["Name", "", "(", "", "Name", "", ",", " *", "Starred", "", ",", " ", "Name", "", ")"], + ) + + +@testutils.only_for("3.5") +def test_starargs_after_keywords(self): + source = "foo(a=1, *args)\n" + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children( + "Call", ["Name", "", "(", "", "keyword", "", ",", " *", "Starred", "", ")"] + ) + + +@testutils.only_for_versions_higher("3.5") +def test_await_node(self): + source = dedent("""\ + async def f(): + await sleep() + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Await", ["await", " ", "Call"]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_constant_match_value(self): + source = dedent("""\ + match x: + case 1: + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchValue") + checker.check_children("MatchValue", [ + "Constant" + ]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_match_case_with_guard(self): + source = dedent("""\ + match x: + case int(n) if x < 10: + print(n) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + checker.check_children("Match", [ + "match", + " ", + "Name", + "", + ":", + "\n ", + "match_case", + ]) + checker.check_children("match_case", [ + "case", + " ", + "MatchClass", + " ", + "if", + " ", + "Compare", + "", + ":", + "\n ", + "Expr", + ]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_class(self): + source = dedent("""\ + match x: + case Foo(1): + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchClass") + checker.check_children("MatchClass", [ + "Name", + "", + "(", + "", + "MatchValue", + "", + ")", + ]) + checker.check_children("MatchValue", [ + "Constant" + ]) + + +@utils.saveit +def get_pymodule(self): + """Get a `PyModule`""" + msg = None + code = self.code + tries = 0 + while True: + try: + if ( + tries == 0 + and self.resource is not None + and self.resource.read() == code + ): + return self.project.get_pymodule(self.resource, force_errors=True) + return libutils.get_string_module( + self.project, code, resource=self.resource, force_errors=True + ) + except exceptions.ModuleSyntaxError as e: + if msg is None: + msg = "{}:{} {}".format(e.filename, e.lineno, e.message_) + if tries < self.maxfixes: + tries += 1 + self.commenter.comment(e.lineno) + code = "\n".join(self.commenter.lines) + else: + raise exceptions.ModuleSyntaxError( + e.filename, e.lineno, f"Failed to fix error: {msg}" + ) + + +def _get_element(self): + raise NotImplementedError() + + + +def _is_on_a_word(self, info, offset): + prev = info.source[offset] + if not (prev.isalnum() or prev == "_") or offset + 1 == len(info.source): + return False + next = info.source[offset + 1] + return next.isalnum() or next == "_" + + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_wildcard(self): + source = dedent("""\ + match x: + case _: + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "_" + ]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_as_capture_pattern(self): + source = dedent("""\ + match x: + case myval: + print(myval) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "myval" + ]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_as_capture_pattern_with_explicit_name(self): + source = dedent("""\ + match x: + case "foo" as myval: + print(myval) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "MatchValue", + " ", + "as", + " ", + "myval", + ]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_class_simple_match_as_capture_pattern(self): + source = dedent("""\ + match x: + case Foo(x): + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchClass") + checker.check_children("MatchClass", [ + "Name", + "", + "(", + "", + "MatchAs", + "", + ")", + ]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_class_named_argument(self): + source = dedent("""\ + match x: + case Foo(x=10, y="20"): + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchClass") + checker.check_children("MatchClass", [ + "Name", + "", + "(", + "", + "x", + "", + "=", + "", + "MatchValue", + "", + ",", + " ", + "y", + "", + "=", + "", + "MatchValue", + "", + ")", + ]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name(self): + source = dedent("""\ + match x: + case Foo(x) as b: + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "MatchClass", + " ", + "as", + " ", + "b", + ]) + checker.check_children("MatchClass", [ + "Name", + "", + "(", + "", + "MatchAs", + "", + ")", + ]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_mapping_match_as(self): + source = dedent("""\ + match x: + case {"a": b} as c: + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "MatchMapping", + " ", + "as", + " ", + "c", + ]) + checker.check_children("MatchMapping", [ + "{", + "", + "Constant", + "", + ":", + " ", + "MatchAs", + "", + "}", + ]) + + + +class _ResultChecker: + @others + +def __init__(self, test_case, ast): + self.test_case = test_case + self.ast = ast + + +def check_region(self, text, start, end): + node = self._find_node(text) + if node is None: + self.test_case.fail("Node <%s> cannot be found" % text) + self.test_case.assertEqual((start, end), node.region) + + +def _find_node(self, text): + goal = text + if not isinstance(text, (tuple, list)): + goal = [text] + + class Search: + result = None + + @others + search = Search() + ast.call_for_nodes(self.ast, search, recursive=True) + return search.result + + +class _ExtractMethodParts: + @others + +def __call__(self, node): + for text in goal: + if sys.version_info >= (3, 8) and text in [ + "Num", + "Str", + "NameConstant", + "Ellipsis", + ]: + text = "Constant" + if str(node).startswith(text): + self.result = node + break + if node.__class__.__name__.startswith(text): + self.result = node + break + return self.result is not None + + +def check_children(self, text, children): + node = self._find_node(text) + if node is None: + self.test_case.fail("Node <%s> cannot be found" % text) + result = list(node.sorted_children) + self.test_case.assertEqual(len(children), len(result)) + for expected, child in zip(children, result): + goals = expected + if not isinstance(expected, (tuple, list)): + goals = [expected] + for goal in goals: + if goal == "" or isinstance(child, basestring): + self.test_case.assertEqual(goal, child) + break + else: + self.test_case.assertNotEqual("", text, "probably ignoring some node") + if sys.version_info >= (3, 8) and expected in [ + "Num", + "Str", + "NameConstant", + "Ellipsis", + ]: + expected = "Constant" + self.test_case.assertTrue( + child.__class__.__name__.startswith(expected), + msg="Expected <%s> but was <%s>" + % (expected, child.__class__.__name__), + ) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +import sys +from textwrap import dedent + +import unittest + +import rope.base.codeanalyze +import rope.refactor.occurrences +from rope.refactor import rename +from rope.refactor.rename import Rename +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class RenameRefactoringTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _local_rename(self, source_code, offset, new_name): + testmod = testutils.create_module(self.project, "testmod") + testmod.write(source_code) + changes = Rename(self.project, testmod, offset).get_changes( + new_name, resources=[testmod] + ) + self.project.do(changes) + return testmod.read() + + +def _rename(self, resource, offset, new_name, **kwds): + changes = Rename(self.project, resource, offset).get_changes(new_name, **kwds) + self.project.do(changes) + + +def test_local_variable_but_not_parameter(self): + code = dedent("""\ + a = 10 + foo = dict(a=a) + """) + + refactored = self._local_rename(code, 1, "new_a") + self.assertEqual( + dedent("""\ + new_a = 10 + foo = dict(a=new_a) + """), + refactored, + ) + + +def test_simple_global_variable_renaming(self): + refactored = self._local_rename("a_var = 20\n", 2, "new_var") + self.assertEqual("new_var = 20\n", refactored) + + +def __init__(self, info): + self.info = info + self.info_collector = self._create_info_collector() + self.info.kind = self._get_kind_by_scope() + self._check_constraints() + + +def test_variable_renaming_only_in_its_scope(self): + refactored = self._local_rename( + dedent("""\ + a_var = 20 + def a_func(): + a_var = 10 + """), + 32, + "new_var", + ) + self.assertEqual( + dedent("""\ + a_var = 20 + def a_func(): + new_var = 10 + """), + refactored, + ) + + +def test_not_renaming_dot_name(self): + refactored = self._local_rename( + dedent("""\ + replace = True + 'aaa'.replace('a', 'b') + """), + 1, + "new_var", + ) + self.assertEqual( + dedent("""\ + new_var = True + 'aaa'.replace('a', 'b') + """), + refactored, + ) + + +def test_renaming_multiple_names_in_the_same_line(self): + refactored = self._local_rename( + dedent("""\ + a_var = 10 + a_var = 10 + a_var / 2 + """), + 2, + "new_var", + ) + self.assertEqual( + dedent("""\ + new_var = 10 + new_var = 10 + new_var / 2 + """), + refactored, + ) + + +def test_renaming_names_when_getting_some_attribute(self): + refactored = self._local_rename( + dedent("""\ + a_var = 'a b c' + a_var.split('\\n') + """), + 2, + "new_var", + ) + self.assertEqual( + dedent("""\ + new_var = 'a b c' + new_var.split('\\n') + """), + refactored, + ) + + +def test_renaming_names_when_getting_some_attribute2(self): + refactored = self._local_rename( + dedent("""\ + a_var = 'a b c' + a_var.split('\\n') + """), + 20, + "new_var", + ) + self.assertEqual( + dedent("""\ + new_var = 'a b c' + new_var.split('\\n') + """), + refactored, + ) + + +def test_renaming_function_parameters1(self): + refactored = self._local_rename( + dedent("""\ + def f(a_param): + print(a_param) + """), + 8, + "new_param", + ) + self.assertEqual( + dedent("""\ + def f(new_param): + print(new_param) + """), + refactored, + ) + + +def test_renaming_function_parameters2(self): + refactored = self._local_rename( + dedent("""\ + def f(a_param): + print(a_param) + """), + 30, + "new_param", + ) + self.assertEqual( + dedent("""\ + def f(new_param): + print(new_param) + """), + refactored, + ) + + +def test_renaming_occurrences_inside_functions(self): + code = dedent("""\ + def a_func(p1): + a = p1 + a_func(1) + """) + refactored = self._local_rename(code, code.index("p1") + 1, "new_param") + self.assertEqual( + dedent("""\ + def a_func(new_param): + a = new_param + a_func(1) + """), + refactored, + ) + + +def test_renaming_comprehension_loop_variables(self): + code = "[b_var for b_var, c_var in d_var if b_var == c_var]" + refactored = self._local_rename(code, code.index("b_var") + 1, "new_var") + self.assertEqual( + "[new_var for new_var, c_var in d_var if new_var == c_var]", refactored + ) + + +def test_renaming_list_comprehension_loop_variables_in_assignment(self): + code = "a_var = [b_var for b_var, c_var in d_var if b_var == c_var]" + refactored = self._local_rename(code, code.index("b_var") + 1, "new_var") + self.assertEqual( + "a_var = [new_var for new_var, c_var in d_var if new_var == c_var]", + refactored, + ) + + +def _get_kind_by_scope(self): + if self._extacting_from_staticmethod(): + return "staticmethod" + elif self._extracting_from_classmethod(): + return "classmethod" + return self.info.kind + + +def test_renaming_generator_comprehension_loop_variables(self): + code = "a_var = (b_var for b_var, c_var in d_var if b_var == c_var)" + refactored = self._local_rename(code, code.index("b_var") + 1, "new_var") + self.assertEqual( + "a_var = (new_var for new_var, c_var in d_var if new_var == c_var)", + refactored, + ) + + +def test_renaming_comprehension_loop_variables_scope(self): + code = dedent("""\ + [b_var for b_var, c_var in d_var if b_var == c_var] + b_var = 10 + """) + refactored = self._local_rename(code, code.index("b_var") + 1, "new_var") + self.assertEqual( + dedent("""\ + [new_var for new_var, c_var in d_var if new_var == c_var] + b_var = 10 + """), + refactored, + ) + + +@testutils.only_for_versions_higher("3.8") +def test_renaming_inline_assignment(self): + code = dedent("""\ + while a_var := next(foo): + print(a_var) + """) + refactored = self._local_rename(code, code.index("a_var") + 1, "new_var") + self.assertEqual( + dedent("""\ + while new_var := next(foo): + print(new_var) + """), + refactored, + ) + + +def test_renaming_arguments_for_normal_args_changing_calls(self): + code = dedent("""\ + def a_func(p1=None, p2=None): + pass + a_func(p2=1) + """) + refactored = self._local_rename(code, code.index("p2") + 1, "p3") + self.assertEqual( + dedent("""\ + def a_func(p1=None, p3=None): + pass + a_func(p3=1) + """), + refactored, + ) + + +def test_renaming_function_parameters_of_class_init(self): + code = dedent("""\ + class A(object): + def __init__(self, a_param): + pass + a_var = A(a_param=1) + """) + refactored = self._local_rename(code, code.index("a_param") + 1, "new_param") + expected = dedent("""\ + class A(object): + def __init__(self, new_param): + pass + a_var = A(new_param=1) + """) + self.assertEqual(expected, refactored) + + +def test_rename_functions_parameters_and_occurences_in_other_modules(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write(dedent("""\ + def a_func(a_param): + print(a_param) + """)) + mod2.write(dedent("""\ + from mod1 import a_func + a_func(a_param=10) + """)) + self._rename(mod1, mod1.read().index("a_param") + 1, "new_param") + self.assertEqual( + dedent("""\ + def a_func(new_param): + print(new_param) + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + from mod1 import a_func + a_func(new_param=10) + """), + mod2.read(), + ) + + +def test_renaming_with_backslash_continued_names(self): + refactored = self._local_rename( + "replace = True\n'ali'.\\\nreplace\n", 2, "is_replace" + ) + self.assertEqual("is_replace = True\n'ali'.\\\nreplace\n", refactored) + + +@testutils.only_for("3.6") +def test_renaming_occurrence_in_f_string(self): + code = dedent("""\ + a_var = 20 + a_string=f'value: {a_var}' + """) + expected = dedent("""\ + new_var = 20 + a_string=f'value: {new_var}' + """) + refactored = self._local_rename(code, 2, "new_var") + self.assertEqual(expected, refactored) + + +@testutils.only_for("3.6") +def test_renaming_occurrence_in_nested_f_string(self): + code = dedent("""\ + a_var = 20 + a_string=f'{f"{a_var}"}' + """) + expected = dedent("""\ + new_var = 20 + a_string=f'{f"{new_var}"}' + """) + refactored = self._local_rename(code, 2, "new_var") + self.assertEqual(expected, refactored) + + +@testutils.only_for("3.6") +def test_not_renaming_string_contents_in_f_string(self): + refactored = self._local_rename( + "a_var = 20\na_string=f'{\"a_var\"}'\n", 2, "new_var" + ) + self.assertEqual( + dedent("""\ + new_var = 20 + a_string=f'{"a_var"}' + """), + refactored, + ) + + +def _check_constraints(self): + if self._extracting_staticmethod() or self._extracting_classmethod(): + if not self.info.method: + raise RefactoringError( + "Cannot extract to staticmethod/classmethod outside class" + ) + + +def test_not_renaming_string_contents(self): + refactored = self._local_rename("a_var = 20\na_string='a_var'\n", 2, "new_var") + self.assertEqual( + dedent("""\ + new_var = 20 + a_string='a_var' + """), + refactored, + ) + + +def test_not_renaming_comment_contents(self): + refactored = self._local_rename("a_var = 20\n# a_var\n", 2, "new_var") + self.assertEqual( + dedent("""\ + new_var = 20 + # a_var + """), + refactored, + ) + + +def test_renaming_all_occurrences_in_containing_scope(self): + code = dedent("""\ + if True: + a_var = 1 + else: + a_var = 20 + """) + refactored = self._local_rename(code, 16, "new_var") + self.assertEqual( + dedent("""\ + if True: + new_var = 1 + else: + new_var = 20 + """), + refactored, + ) + + +def test_renaming_a_variable_with_arguement_name(self): + code = dedent("""\ + a_var = 10 + def a_func(a_var): + print(a_var) + """) + refactored = self._local_rename(code, 1, "new_var") + self.assertEqual( + dedent("""\ + new_var = 10 + def a_func(a_var): + print(a_var) + """), + refactored, + ) + + +def test_renaming_an_arguement_with_variable_name(self): + code = dedent("""\ + a_var = 10 + def a_func(a_var): + print(a_var) + """) + refactored = self._local_rename(code, len(code) - 3, "new_var") + self.assertEqual( + dedent("""\ + a_var = 10 + def a_func(new_var): + print(new_var) + """), + refactored, + ) + + +def test_renaming_function_with_local_variable_name(self): + code = dedent("""\ + def a_func(): + a_func=20 + a_func()""") + refactored = self._local_rename(code, len(code) - 3, "new_func") + self.assertEqual( + dedent("""\ + def new_func(): + a_func=20 + new_func()"""), + refactored, + ) + + +def test_renaming_functions(self): + code = dedent("""\ + def a_func(): + pass + a_func() + """) + refactored = self._local_rename(code, len(code) - 5, "new_func") + self.assertEqual( + dedent("""\ + def new_func(): + pass + new_func() + """), + refactored, + ) + + +@testutils.only_for("3.5") +def test_renaming_async_function(self): + code = dedent("""\ + async def a_func(): + pass + a_func()""") + refactored = self._local_rename(code, len(code) - 5, "new_func") + self.assertEqual( + dedent("""\ + async def new_func(): + pass + new_func()"""), + refactored, + ) + + +@testutils.only_for("3.5") +def test_renaming_await(self): + code = dedent("""\ + async def b_func(): + pass + async def a_func(): + await b_func()""") + refactored = self._local_rename(code, len(code) - 5, "new_func") + self.assertEqual( + dedent("""\ + async def new_func(): + pass + async def a_func(): + await new_func()"""), + refactored, + ) + + +def test_renaming_functions_across_modules(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + def a_func(): + pass + a_func() + """)) + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + import mod1 + mod1.a_func() + """)) + self._rename(mod1, len(mod1.read()) - 5, "new_func") + self.assertEqual( + dedent("""\ + def new_func(): + pass + new_func() + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + import mod1 + mod1.new_func() + """), + mod2.read(), + ) + + +def _extacting_from_staticmethod(self): + return ( + self.info.method and _get_function_kind(self.info.scope) == "staticmethod" + ) + + +def test_renaming_functions_across_modules_from_import(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + def a_func(): + pass + a_func() + """)) + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + from mod1 import a_func + a_func() + """)) + self._rename(mod1, len(mod1.read()) - 5, "new_func") + self.assertEqual( + dedent("""\ + def new_func(): + pass + new_func() + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + from mod1 import new_func + new_func() + """), + mod2.read(), + ) + + +def test_renaming_functions_from_another_module(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + def a_func(): + pass + a_func() + """)) + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + import mod1 + mod1.a_func() + """)) + self._rename(mod2, len(mod2.read()) - 5, "new_func") + self.assertEqual( + dedent("""\ + def new_func(): + pass + new_func() + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + import mod1 + mod1.new_func() + """), + mod2.read(), + ) + + +def test_applying_all_changes_together(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + import mod2 + mod2.a_func() + """)) + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + def a_func(): + pass + a_func() + """)) + self._rename(mod2, len(mod2.read()) - 5, "new_func") + self.assertEqual( + dedent("""\ + import mod2 + mod2.new_func() + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + def new_func(): + pass + new_func() + """), + mod2.read(), + ) + + +def test_renaming_modules(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + def a_func(): + pass + """)) + mod2 = testutils.create_module(self.project, "mod2") + mod2.write("from mod1 import a_func\n") + self._rename(mod2, mod2.read().index("mod1") + 1, "newmod") + self.assertTrue( + not mod1.exists() and self.project.find_module("newmod") is not None + ) + self.assertEqual("from newmod import a_func\n", mod2.read()) + + +def test_renaming_modules_aliased(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + def a_func(): + pass + """)) + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + import mod1 as m + m.a_func() + """)) + self._rename(mod1, None, "newmod") + self.assertTrue( + not mod1.exists() and self.project.find_module("newmod") is not None + ) + self.assertEqual("import newmod as m\nm.a_func()\n", mod2.read()) + + +def test_renaming_packages(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod1.write(dedent("""\ + def a_func(): + pass + """)) + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod2.write("from pkg.mod1 import a_func\n") + self._rename(mod2, 6, "newpkg") + self.assertTrue(self.project.find_module("newpkg.mod1") is not None) + new_mod2 = self.project.find_module("newpkg.mod2") + self.assertEqual("from newpkg.mod1 import a_func\n", new_mod2.read()) + + +def test_module_dependencies(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + class AClass(object): + pass + """)) + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + import mod1 + a_var = mod1.AClass() + """)) + self.project.get_pymodule(mod2).get_attributes()["mod1"] + mod1.write(dedent("""\ + def AClass(): + return 0 + """)) + + self._rename(mod2, len(mod2.read()) - 3, "a_func") + self.assertEqual( + dedent("""\ + def a_func(): + return 0 + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + import mod1 + a_var = mod1.a_func() + """), + mod2.read(), + ) + + +def test_renaming_class_attributes(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + class AClass(object): + def __init__(self): + self.an_attr = 10 + """)) + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + import mod1 + a_var = mod1.AClass() + another_var = a_var.an_attr""")) + + self._rename(mod1, mod1.read().index("an_attr"), "attr") + self.assertEqual( + dedent("""\ + class AClass(object): + def __init__(self): + self.attr = 10 + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + import mod1 + a_var = mod1.AClass() + another_var = a_var.attr"""), + mod2.read(), + ) + + +def test_renaming_class_attributes2(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + class AClass(object): + def __init__(self): + an_attr = 10 + self.an_attr = 10 + """)) + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + import mod1 + a_var = mod1.AClass() + another_var = a_var.an_attr""")) + + self._rename(mod1, mod1.read().rindex("an_attr"), "attr") + self.assertEqual( + dedent("""\ + class AClass(object): + def __init__(self): + an_attr = 10 + self.attr = 10 + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + import mod1 + a_var = mod1.AClass() + another_var = a_var.attr"""), + mod2.read(), + ) + + +def test_renaming_methods_in_subclasses(self): + mod = testutils.create_module(self.project, "mod1") + mod.write(dedent("""\ + class A(object): + def a_method(self): + pass + class B(A): + def a_method(self): + pass + """)) + + self._rename( + mod, mod.read().rindex("a_method") + 1, "new_method", in_hierarchy=True + ) + self.assertEqual( + dedent("""\ + class A(object): + def new_method(self): + pass + class B(A): + def new_method(self): + pass + """), + mod.read(), + ) + + +def _extracting_from_classmethod(self): + return self.info.method and _get_function_kind(self.info.scope) == "classmethod" + + +def test_renaming_methods_in_sibling_classes(self): + mod = testutils.create_module(self.project, "mod1") + mod.write(dedent("""\ + class A(object): + def a_method(self): + pass + class B(A): + def a_method(self): + pass + class C(A): + def a_method(self): + pass + """)) + + self._rename( + mod, mod.read().rindex("a_method") + 1, "new_method", in_hierarchy=True + ) + self.assertEqual( + dedent("""\ + class A(object): + def new_method(self): + pass + class B(A): + def new_method(self): + pass + class C(A): + def new_method(self): + pass + """), + mod.read(), + ) + + +def test_not_renaming_methods_in_hierarchies(self): + mod = testutils.create_module(self.project, "mod1") + mod.write(dedent("""\ + class A(object): + def a_method(self): + pass + class B(A): + def a_method(self): + pass + """)) + + self._rename( + mod, mod.read().rindex("a_method") + 1, "new_method", in_hierarchy=False + ) + self.assertEqual( + dedent("""\ + class A(object): + def a_method(self): + pass + class B(A): + def new_method(self): + pass + """), + mod.read(), + ) + + +def test_undoing_refactorings(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + def a_func(): + pass + a_func() + """)) + self._rename(mod1, len(mod1.read()) - 5, "new_func") + self.project.history.undo() + self.assertEqual( + dedent("""\ + def a_func(): + pass + a_func() + """), + mod1.read(), + ) + + +def test_undoing_renaming_modules(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + def a_func(): + pass + """)) + mod2 = testutils.create_module(self.project, "mod2") + mod2.write("from mod1 import a_func\n") + self._rename(mod2, 6, "newmod") + self.project.history.undo() + self.assertEqual("mod1.py", mod1.path) + self.assertEqual("from mod1 import a_func\n", mod2.read()) + + +def test_rename_in_module_renaming_one_letter_names_for_expressions(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write("a = 10\nprint(1+a)\n") + pymod = self.project.get_module("mod1") + old_pyname = pymod["a"] + finder = rope.refactor.occurrences.create_finder(self.project, "a", old_pyname) + refactored = rename.rename_in_module( + finder, "new_var", pymodule=pymod, replace_primary=True + ) + self.assertEqual( + dedent("""\ + new_var = 10 + print(1+new_var) + """), + refactored, + ) + + +def test_renaming_for_loop_variable(self): + code = dedent("""\ + for var in range(10): + print(var) + """) + refactored = self._local_rename(code, code.find("var") + 1, "new_var") + self.assertEqual( + dedent("""\ + for new_var in range(10): + print(new_var) + """), + refactored, + ) + + +@testutils.only_for("3.5") +def test_renaming_async_for_loop_variable(self): + code = dedent("""\ + async def func(): + async for var in range(10): + print(var) + """) + refactored = self._local_rename(code, code.find("var") + 1, "new_var") + self.assertEqual( + dedent("""\ + async def func(): + async for new_var in range(10): + print(new_var) + """), + refactored, + ) + + +@testutils.only_for("3.5") +def test_renaming_async_with_context_manager(self): + code = dedent("""\ + def a_cm(): pass + async def a_func(): + async with a_cm() as x: pass""") + refactored = self._local_rename(code, code.find("a_cm") + 1, "another_cm") + expected = dedent("""\ + def another_cm(): pass + async def a_func(): + async with another_cm() as x: pass""") + self.assertEqual(refactored, expected) + + +@testutils.only_for("3.5") +def test_renaming_async_with_as_variable(self): + code = dedent("""\ + async def func(): + async with a_func() as var: + print(var) + """) + refactored = self._local_rename(code, code.find("var") + 1, "new_var") + self.assertEqual( + dedent("""\ + async def func(): + async with a_func() as new_var: + print(new_var) + """), + refactored, + ) + + +def test_renaming_parameters(self): + code = dedent("""\ + def a_func(param): + print(param) + a_func(param=hey) + """) + refactored = self._local_rename(code, code.find("param") + 1, "new_param") + self.assertEqual( + dedent("""\ + def a_func(new_param): + print(new_param) + a_func(new_param=hey) + """), + refactored, + ) + + +def get_definition(self): + if self.info.global_: + return "\n%s\n" % self._get_function_definition() + else: + return "\n%s" % self._get_function_definition() + + +def test_renaming_assigned_parameters(self): + code = dedent("""\ + def f(p): + p = p + 1 + return p + f(p=1) + """) + refactored = self._local_rename(code, code.find("p"), "arg") + self.assertEqual( + dedent("""\ + def f(arg): + arg = arg + 1 + return arg + f(arg=1) + """), + refactored, + ) + + +def test_renaming_parameters_not_renaming_others(self): + code = dedent("""\ + def a_func(param): + print(param) + param=10 + a_func(param) + """) + refactored = self._local_rename(code, code.find("param") + 1, "new_param") + self.assertEqual( + dedent("""\ + def a_func(new_param): + print(new_param) + param=10 + a_func(param) + """), + refactored, + ) + + +def test_renaming_parameters_not_renaming_others2(self): + code = dedent("""\ + def a_func(param): + print(param) + param=10 + a_func(param=param)""") + refactored = self._local_rename(code, code.find("param") + 1, "new_param") + self.assertEqual( + dedent("""\ + def a_func(new_param): + print(new_param) + param=10 + a_func(new_param=param)"""), + refactored, + ) + + +def test_renaming_parameters_with_multiple_params(self): + code = dedent("""\ + def a_func(param1, param2): + print(param1) + a_func(param1=1, param2=2) + """) + refactored = self._local_rename(code, code.find("param1") + 1, "new_param") + self.assertEqual( + dedent("""\ + def a_func(new_param, param2): + print(new_param) + a_func(new_param=1, param2=2) + """), + refactored, + ) + + +def test_renaming_parameters_with_multiple_params2(self): + code = dedent("""\ + def a_func(param1, param2): + print(param1) + a_func(param1=1, param2=2) + """) + refactored = self._local_rename(code, code.rfind("param2") + 1, "new_param") + self.assertEqual( + dedent("""\ + def a_func(param1, new_param): + print(param1) + a_func(param1=1, new_param=2) + """), + refactored, + ) + + +def test_renaming_parameters_on_calls(self): + code = dedent("""\ + def a_func(param): + print(param) + a_func(param = hey) + """) + refactored = self._local_rename(code, code.rfind("param") + 1, "new_param") + self.assertEqual( + dedent("""\ + def a_func(new_param): + print(new_param) + a_func(new_param = hey) + """), + refactored, + ) + + +def test_renaming_parameters_spaces_before_call(self): + code = dedent("""\ + def a_func(param): + print(param) + a_func (param=hey) + """) + refactored = self._local_rename(code, code.rfind("param") + 1, "new_param") + self.assertEqual( + dedent("""\ + def a_func(new_param): + print(new_param) + a_func (new_param=hey) + """), + refactored, + ) + + +def test_renaming_parameter_like_objects_after_keywords(self): + code = dedent("""\ + def a_func(param): + print(param) + dict(param=hey) + """) + refactored = self._local_rename(code, code.find("param") + 1, "new_param") + self.assertEqual( + dedent("""\ + def a_func(new_param): + print(new_param) + dict(param=hey) + """), + refactored, + ) + + +def test_renaming_variables_in_init_dot_pys(self): + pkg = testutils.create_package(self.project, "pkg") + init_dot_py = pkg.get_child("__init__.py") + init_dot_py.write("a_var = 10\n") + mod = testutils.create_module(self.project, "mod") + mod.write("import pkg\nprint(pkg.a_var)\n") + self._rename(mod, mod.read().index("a_var") + 1, "new_var") + self.assertEqual("new_var = 10\n", init_dot_py.read()) + self.assertEqual("import pkg\nprint(pkg.new_var)\n", mod.read()) + + +def test_renaming_variables_in_init_dot_pys2(self): + pkg = testutils.create_package(self.project, "pkg") + init_dot_py = pkg.get_child("__init__.py") + init_dot_py.write("a_var = 10\n") + mod = testutils.create_module(self.project, "mod") + mod.write("import pkg\nprint(pkg.a_var)\n") + self._rename(init_dot_py, init_dot_py.read().index("a_var") + 1, "new_var") + self.assertEqual("new_var = 10\n", init_dot_py.read()) + self.assertEqual("import pkg\nprint(pkg.new_var)\n", mod.read()) + + +def get_replacement_pattern(self): + variables = [] + variables.extend(self._find_function_arguments()) + variables.extend(self._find_function_returns()) + return similarfinder.make_pattern(self._get_call(), variables) + + +def test_renaming_variables_in_init_dot_pys3(self): + pkg = testutils.create_package(self.project, "pkg") + init_dot_py = pkg.get_child("__init__.py") + init_dot_py.write("a_var = 10\n") + mod = testutils.create_module(self.project, "mod") + mod.write("import pkg\nprint(pkg.a_var)\n") + self._rename(mod, mod.read().index("a_var") + 1, "new_var") + self.assertEqual("new_var = 10\n", init_dot_py.read()) + self.assertEqual("import pkg\nprint(pkg.new_var)\n", mod.read()) + + +def test_renaming_resources_using_rename_module_refactoring(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("a_var = 1") + mod2.write("import mod1\nmy_var = mod1.a_var\n") + renamer = rename.Rename(self.project, mod1) + renamer.get_changes("newmod").do() + self.assertEqual("import newmod\nmy_var = newmod.a_var\n", mod2.read()) + + +def test_renam_resources_using_rename_module_refactor_for_packages(self): + mod1 = testutils.create_module(self.project, "mod1") + pkg = testutils.create_package(self.project, "pkg") + mod1.write("import pkg\nmy_pkg = pkg") + renamer = rename.Rename(self.project, pkg) + renamer.get_changes("newpkg").do() + self.assertEqual("import newpkg\nmy_pkg = newpkg", mod1.read()) + + +def test_renam_resources_use_rename_module_refactor_for_init_dot_py(self): + mod1 = testutils.create_module(self.project, "mod1") + pkg = testutils.create_package(self.project, "pkg") + mod1.write("import pkg\nmy_pkg = pkg") + renamer = rename.Rename(self.project, pkg.get_child("__init__.py")) + renamer.get_changes("newpkg").do() + self.assertEqual("import newpkg\nmy_pkg = newpkg", mod1.read()) + + +def test_renaming_global_variables(self): + code = dedent("""\ + a_var = 1 + def a_func(): + global a_var + var = a_var + """) + refactored = self._local_rename(code, code.index("a_var"), "new_var") + self.assertEqual( + dedent("""\ + new_var = 1 + def a_func(): + global new_var + var = new_var + """), + refactored, + ) + + +def test_renaming_global_variables2(self): + code = dedent("""\ + a_var = 1 + def a_func(): + global a_var + var = a_var + """) + refactored = self._local_rename(code, code.rindex("a_var"), "new_var") + self.assertEqual( + dedent("""\ + new_var = 1 + def a_func(): + global new_var + var = new_var + """), + refactored, + ) + + +def test_renaming_when_unsure(self): + code = dedent("""\ + class C(object): + def a_func(self): + pass + def f(arg): + arg.a_func() + """) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(code) + self._rename(mod1, code.index("a_func"), "new_func", unsure=self._true) + self.assertEqual( + dedent("""\ + class C(object): + def new_func(self): + pass + def f(arg): + arg.new_func() + """), + mod1.read(), + ) + + +def _true(self, *args): + return True + + +def test_renaming_when_unsure_with_confirmation(self): + def confirm(occurrence): + return False + + code = dedent("""\ + class C(object): + def a_func(self): + pass + def f(arg): + arg.a_func() + """) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(code) + self._rename(mod1, code.index("a_func"), "new_func", unsure=confirm) + self.assertEqual( + dedent("""\ + class C(object): + def new_func(self): + pass + def f(arg): + arg.a_func() + """), + mod1.read(), + ) + + +def test_renaming_when_unsure_not_renaming_knowns(self): + code = dedent("""\ + class C1(object): + def a_func(self): + pass + class C2(object): + def a_func(self): + pass + c1 = C1() + c1.a_func() + c2 = C2() + c2.a_func() + """) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(code) + self._rename(mod1, code.index("a_func"), "new_func", unsure=self._true) + self.assertEqual( + dedent("""\ + class C1(object): + def new_func(self): + pass + class C2(object): + def a_func(self): + pass + c1 = C1() + c1.new_func() + c2 = C2() + c2.a_func() + """), + mod1.read(), + ) + + +def get_body_pattern(self): + variables = [] + variables.extend(self._find_function_arguments()) + variables.extend(self._find_function_returns()) + variables.extend(self._find_temps()) + return similarfinder.make_pattern(self._get_body(), variables) + + +def test_renaming_in_strings_and_comments(self): + code = dedent("""\ + a_var = 1 + # a_var + """) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(code) + self._rename(mod1, code.index("a_var"), "new_var", docs=True) + self.assertEqual( + dedent("""\ + new_var = 1 + # new_var + """), + mod1.read(), + ) + + +def test_not_renaming_in_strings_and_comments_where_not_visible(self): + code = dedent("""\ + def f(): + a_var = 1 + # a_var + """) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(code) + self._rename(mod1, code.index("a_var"), "new_var", docs=True) + self.assertEqual( + dedent("""\ + def f(): + new_var = 1 + # a_var + """), + mod1.read(), + ) + + +def test_not_renaming_all_text_occurrences_in_strings_and_comments(self): + code = dedent("""\ + a_var = 1 + # a_vard _a_var + """) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(code) + self._rename(mod1, code.index("a_var"), "new_var", docs=True) + self.assertEqual( + dedent("""\ + new_var = 1 + # a_vard _a_var + """), + mod1.read(), + ) + + +def test_renaming_occurrences_in_overwritten_scopes(self): + refactored = self._local_rename( + dedent("""\ + a_var = 20 + def f(): + print(a_var) + def f(): + print(a_var) + """), + 2, + "new_var", + ) + self.assertEqual( + dedent("""\ + new_var = 20 + def f(): + print(new_var) + def f(): + print(new_var) + """), + refactored, + ) + + +def test_renaming_occurrences_in_overwritten_scopes2(self): + code = dedent("""\ + def f(): + a_var = 1 + print(a_var) + def f(): + a_var = 1 + print(a_var) + """) + refactored = self._local_rename(code, code.index("a_var") + 1, "new_var") + self.assertEqual(code.replace("a_var", "new_var", 2), refactored) + + +@testutils.only_for_versions_higher("3.5") +def test_renaming_in_generalized_dict_unpacking(self): + code = dedent("""\ + a_var = {**{'stuff': 'can'}, **{'stuff': 'crayon'}} + + if "stuff" in a_var: + print("ya") + """) + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(code) + refactored = self._local_rename(code, code.index("a_var") + 1, "new_var") + expected = dedent("""\ + new_var = {**{'stuff': 'can'}, **{'stuff': 'crayon'}} + + if "stuff" in new_var: + print("ya") + """) + self.assertEqual(expected, refactored) + + +def test_dos_line_ending_and_renaming(self): + code = "\r\na = 1\r\n\r\nprint(2 + a + 2)\r\n" + offset = code.replace("\r\n", "\n").rindex("a") + refactored = self._local_rename(code, offset, "b") + self.assertEqual( + "\nb = 1\n\nprint(2 + b + 2)\n", refactored.replace("\r\n", "\n") + ) + + +def test_multi_byte_strs_and_renaming(self): + s = "{LATIN SMALL LETTER I WITH DIAERESIS}" * 4 + code = "# -*- coding: utf-8 -*-\n# " + s + "\na = 1\nprint(2 + a + 2)\n" + refactored = self._local_rename(code, code.rindex("a"), "b") + self.assertEqual( + "# -*- coding: utf-8 -*-\n# " + s + "\nb = 1\nprint(2 + b + 2)\n", + refactored, + ) + + +def test_resources_parameter(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write(dedent("""\ + def f(): + pass + """)) + mod2.write(dedent("""\ + import mod1 + mod1.f() + """)) + self._rename(mod1, mod1.read().rindex("f"), "g", resources=[mod1]) + self.assertEqual( + dedent("""\ + def g(): + pass + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + import mod1 + mod1.f() + """), + mod2.read(), + ) + + +def test_resources_parameter_not_changing_defining_module(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write(dedent("""\ + def f(): + pass + """)) + mod2.write(dedent("""\ + import mod1 + mod1.f() + """)) + self._rename(mod1, mod1.read().rindex("f"), "g", resources=[mod2]) + self.assertEqual( + dedent("""\ + def f(): + pass + """), + mod1.read(), + ) + self.assertEqual( + dedent("""\ + import mod1 + mod1.g() + """), + mod2.read(), + ) + + +class GenerateFunction(_Generate): + @others + +def _get_body(self): + result = sourceutils.fix_indentation(self.info.extracted, 0) + if self.info.one_line: + result = "(%s)" % result + return result + + +# XXX: with variables should not leak +@testutils.only_for("2.5") +def xxx_test_with_statement_variables_should_not_leak(self): + code = dedent("""\ + f = 1 + with open("1.txt") as f: + print(f) + """) + if sys.version_info < (2, 6, 0): + code = "from __future__ import with_statement\n" + code + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(code) + self._rename(mod1, code.rindex("f"), "file") + expected = dedent("""\ + f = 1 + with open("1.txt") as file: + print(file) + """) + self.assertEqual(expected, mod1.read()) + + +def test_rename_in_list_comprehension(self): + code = dedent("""\ + some_var = 1 + compr = [some_var for some_var in range(10)] + """) + offset = code.index("some_var") + refactored = self._local_rename(code, offset, "new_var") + expected = dedent("""\ + new_var = 1 + compr = [some_var for some_var in range(10)] + """) + self.assertEqual(refactored, expected) + + +def test_renaming_modules_aliased_with_dots(self): + pkg = testutils.create_package(self.project, "json") + mod1 = testutils.create_module(self.project, "utils", pkg) + + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + import json.utils as stdlib_json_utils + """)) + self._rename(pkg, None, "new_json") + self.assertTrue( + not mod1.exists() and self.project.find_module("new_json.utils") is not None + ) + self.assertEqual("import new_json.utils as stdlib_json_utils\n", mod2.read()) + + +def test_renaming_modules_aliased_many_dots(self): + pkg = testutils.create_package(self.project, "json") + mod1 = testutils.create_module(self.project, "utils", pkg) + + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + import json.utils.a as stdlib_json_utils + """)) + self._rename(pkg, None, "new_json") + self.assertTrue( + not mod1.exists() and self.project.find_module("new_json.utils") is not None + ) + self.assertEqual("import new_json.utils.a as stdlib_json_utils\n", mod2.read()) + + + +class ChangeOccurrencesTest(unittest.TestCase): + @others + +def setUp(self): + self.project = testutils.sample_project() + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_case(self): + self.mod.write(dedent("""\ + a_var = 1 + print(a_var) + """)) + changer = rename.ChangeOccurrences( + self.project, self.mod, self.mod.read().index("a_var") + ) + changer.get_changes("new_var").do() + self.assertEqual( + dedent("""\ + new_var = 1 + print(new_var) + """), + self.mod.read(), + ) + + +def test_only_performing_inside_scopes(self): + self.mod.write(dedent("""\ + a_var = 1 + new_var = 2 + def f(): + print(a_var) + """)) + changer = rename.ChangeOccurrences( + self.project, self.mod, self.mod.read().rindex("a_var") + ) + changer.get_changes("new_var").do() + self.assertEqual( + dedent("""\ + a_var = 1 + new_var = 2 + def f(): + print(new_var) + """), + self.mod.read(), + ) + + +def test_only_performing_on_calls(self): + self.mod.write(dedent("""\ + def f1(): + pass + def f2(): + pass + g = f1 + a = f1() + """)) + changer = rename.ChangeOccurrences( + self.project, self.mod, self.mod.read().rindex("f1") + ) + changer.get_changes("f2", only_calls=True).do() + self.assertEqual( + dedent("""\ + def f1(): + pass + def f2(): + pass + g = f1 + a = f2() + """), + self.mod.read(), + ) + + +def _find_temps(self): + return usefunction.find_temps(self.info.project, self._get_body()) + + +def test_only_performing_on_reads(self): + self.mod.write(dedent("""\ + a = 1 + b = 2 + print(a) + """)) + changer = rename.ChangeOccurrences( + self.project, self.mod, self.mod.read().rindex("a") + ) + changer.get_changes("b", writes=False).do() + self.assertEqual( + dedent("""\ + a = 1 + b = 2 + print(b) + """), + self.mod.read(), + ) + + + +class ImplicitInterfacesTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project(validate_objectdb=True) + self.pycore = self.project.pycore + self.mod1 = testutils.create_module(self.project, "mod1") + self.mod2 = testutils.create_module(self.project, "mod2") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _rename(self, resource, offset, new_name, **kwds): + changes = Rename(self.project, resource, offset).get_changes(new_name, **kwds) + self.project.do(changes) + + +def test_performing_rename_on_parameters(self): + self.mod1.write("def f(arg):\n arg.run()\n") + self.mod2.write(dedent("""\ + import mod1 + + + class A(object): + def run(self): + pass + class B(object): + def run(self): + pass + mod1.f(A()) + mod1.f(B()) + """)) + self.pycore.analyze_module(self.mod2) + self._rename(self.mod1, self.mod1.read().index("run"), "newrun") + self.assertEqual("def f(arg):\n arg.newrun()\n", self.mod1.read()) + self.assertEqual( + dedent("""\ + import mod1 + + + class A(object): + def newrun(self): + pass + class B(object): + def newrun(self): + pass + mod1.f(A()) + mod1.f(B()) + """), + self.mod2.read(), + ) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +from textwrap import dedent + +from rope.refactor import restructure +from ropetest import testutils + +import unittest + + +@others +@language python +@tabwidth -4 + +class RestructureTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def get_checks(self): + if self.info.method and not self.info.make_global: + if _get_function_kind(self.info.scope) == "method": + class_name = similarfinder._pydefined_to_str( + self.info.scope.parent.pyobject + ) + return {self._get_self_name(): "type=" + class_name} + return {} + + +def test_trivial_case(self): + refactoring = restructure.Restructure(self.project, "a = 1", "a = 0") + self.mod.write("b = 1\n") + self.project.do(refactoring.get_changes()) + self.assertEqual("b = 1\n", self.mod.read()) + + +def test_replacing_simple_patterns(self): + refactoring = restructure.Restructure(self.project, "a = 1", "a = int(1)") + self.mod.write("a = 1\nb = 1\n") + self.project.do(refactoring.get_changes()) + self.assertEqual("a = int(1)\nb = 1\n", self.mod.read()) + + +def test_replacing_patterns_with_normal_names(self): + refactoring = restructure.Restructure( + self.project, "${a} = 1", "${a} = int(1)", args={"a": "exact"} + ) + self.mod.write("a = 1\nb = 1\n") + self.project.do(refactoring.get_changes()) + self.assertEqual("a = int(1)\nb = 1\n", self.mod.read()) + + +def test_replacing_patterns_with_any_names(self): + refactoring = restructure.Restructure(self.project, "${a} = 1", "${a} = int(1)") + self.mod.write("a = 1\nb = 1\n") + self.project.do(refactoring.get_changes()) + self.assertEqual("a = int(1)\nb = int(1)\n", self.mod.read()) + + +def test_replacing_patterns_with_any_names2(self): + refactoring = restructure.Restructure(self.project, "${x} + ${x}", "${x} * 2") + self.mod.write("a = 1 + 1\n") + self.project.do(refactoring.get_changes()) + self.assertEqual("a = 1 * 2\n", self.mod.read()) + + +def test_replacing_patterns_with_checks(self): + self.mod.write(dedent("""\ + def f(p=1): + return p + g = f + g() + """)) + refactoring = restructure.Restructure( + self.project, "${f}()", "${f}(2)", args={"f": "object=mod.f"} + ) + self.project.do(refactoring.get_changes()) + self.assertEqual( + dedent("""\ + def f(p=1): + return p + g = f + g(2) + """), + self.mod.read(), + ) + + +def test_replacing_assignments_with_sets(self): + refactoring = restructure.Restructure( + self.project, "${a} = ${b}", "${a}.set(${b})" + ) + self.mod.write("a = 1\nb = 1\n") + self.project.do(refactoring.get_changes()) + self.assertEqual("a.set(1)\nb.set(1)\n", self.mod.read()) + + +def test_replacing_sets_with_assignments(self): + refactoring = restructure.Restructure( + self.project, "${a}.set(${b})", "${a} = ${b}" + ) + self.mod.write("a.set(1)\nb.set(1)\n") + self.project.do(refactoring.get_changes()) + self.assertEqual( + dedent("""\ + a = 1 + b = 1 + """), + self.mod.read(), + ) + + +def test_using_make_checks(self): + self.mod.write(dedent("""\ + def f(p=1): + return p + g = f + g() + """)) + refactoring = restructure.Restructure( + self.project, "${f}()", "${f}(2)", args={"f": "object=mod.f"} + ) + self.project.do(refactoring.get_changes()) + self.assertEqual( + dedent("""\ + def f(p=1): + return p + g = f + g(2) + """), + self.mod.read(), + ) + + +def test_using_make_checking_builtin_types(self): + self.mod.write("a = 1 + 1\n") + refactoring = restructure.Restructure( + self.project, "${i} + ${i}", "${i} * 2", args={"i": "type=__builtin__.int"} + ) + self.project.do(refactoring.get_changes()) + self.assertEqual("a = 1 * 2\n", self.mod.read()) + + +def _create_info_collector(self): + zero = self.info.scope.get_start() - 1 + start_line = self.info.region_lines[0] - zero + end_line = self.info.region_lines[1] - zero + info_collector = _FunctionInformationCollector( + start_line, end_line, self.info.global_ + ) + body = self.info.source[self.info.scope_region[0] : self.info.scope_region[1]] + node = _parse_text(body) + ast.walk(node, info_collector) + return info_collector + + +def test_auto_indentation_when_no_indentation(self): + self.mod.write("a = 2\n") + refactoring = restructure.Restructure( + self.project, "${a} = 2", "${a} = 1\n${a} += 1" + ) + self.project.do(refactoring.get_changes()) + self.assertEqual( + dedent("""\ + a = 1 + a += 1 + """), + self.mod.read(), + ) + + +def test_auto_indentation(self): + self.mod.write(dedent("""\ + def f(): + a = 2 + """)) + refactoring = restructure.Restructure( + self.project, "${a} = 2", "${a} = 1\n${a} += 1" + ) + self.project.do(refactoring.get_changes()) + self.assertEqual( + dedent("""\ + def f(): + a = 1 + a += 1 + """), + self.mod.read(), + ) + + +def test_auto_indentation_and_not_indenting_blanks(self): + self.mod.write("def f():\n a = 2\n") + refactoring = restructure.Restructure( + self.project, "${a} = 2", "${a} = 1\n\n${a} += 1" + ) + self.project.do(refactoring.get_changes()) + self.assertEqual("def f():\n a = 1\n\n a += 1\n", self.mod.read()) + + +def test_importing_names(self): + self.mod.write("a = 2\n") + refactoring = restructure.Restructure( + self.project, "${a} = 2", "${a} = myconsts.two", imports=["import myconsts"] + ) + self.project.do(refactoring.get_changes()) + self.assertEqual( + dedent("""\ + import myconsts + a = myconsts.two + """), + self.mod.read(), + ) + + +def test_not_importing_names_when_there_are_no_changes(self): + self.mod.write("a = True\n") + refactoring = restructure.Restructure( + self.project, "${a} = 2", "${a} = myconsts.two", imports=["import myconsts"] + ) + self.project.do(refactoring.get_changes()) + self.assertEqual("a = True\n", self.mod.read()) + + +def test_handling_containing_matches(self): + self.mod.write("a = 1 / 2 / 3\n") + refactoring = restructure.Restructure( + self.project, "${a} / ${b}", "${a} // ${b}" + ) + self.project.do(refactoring.get_changes()) + self.assertEqual("a = 1 // 2 // 3\n", self.mod.read()) + + +def test_handling_overlapping_matches(self): + self.mod.write("a = 1\na = 1\na = 1\n") + refactoring = restructure.Restructure(self.project, "a = 1\na = 1\n", "b = 1") + self.project.do(refactoring.get_changes()) + self.assertEqual("b = 1\na = 1\n", self.mod.read()) + + +def test_preventing_stack_overflow_when_matching(self): + self.mod.write("1\n") + refactoring = restructure.Restructure(self.project, "${a}", "${a}") + self.project.do(refactoring.get_changes()) + self.assertEqual("1\n", self.mod.read()) + + +def test_performing_a_restructuring_to_all_modules(self): + mod2 = testutils.create_module(self.project, "mod2") + self.mod.write("a = 1\n") + mod2.write("b = 1\n") + refactoring = restructure.Restructure(self.project, "1", "2 / 1") + self.project.do(refactoring.get_changes()) + self.assertEqual("a = 2 / 1\n", self.mod.read()) + self.assertEqual("b = 2 / 1\n", mod2.read()) + + +def test_performing_a_restructuring_to_selected_modules(self): + mod2 = testutils.create_module(self.project, "mod2") + self.mod.write("a = 1\n") + mod2.write("b = 1\n") + refactoring = restructure.Restructure(self.project, "1", "2 / 1") + self.project.do(refactoring.get_changes(resources=[mod2])) + self.assertEqual("a = 1\n", self.mod.read()) + self.assertEqual("b = 2 / 1\n", mod2.read()) + + +def _get_function_definition(self): + args = self._find_function_arguments() + returns = self._find_function_returns() + + result = [] + self._append_decorators(result) + result.append("def %s:\n" % self._get_function_signature(args)) + unindented_body = self._get_unindented_function_body(returns) + indents = sourceutils.get_indent(self.info.project) + function_body = sourceutils.indent_lines(unindented_body, indents) + result.append(function_body) + definition = "".join(result) + + return definition + "\n" + + +def test_unsure_argument_of_default_wildcard(self): + self.mod.write(dedent("""\ + def f(p): + return p * 2 + x = "" * 2 + i = 1 * 2 + """)) + refactoring = restructure.Restructure( + self.project, + "${s} * 2", + "dup(${s})", + args={"s": {"type": "__builtins__.str", "unsure": True}}, + ) + self.project.do(refactoring.get_changes()) + self.assertEqual( + dedent("""\ + def f(p): + return dup(p) + x = dup("") + i = 1 * 2 + """), + self.mod.read(), + ) + + +def test_statement_after_string_and_column(self): + mod_text = dedent("""\ + def f(x): + if a == "a": raise Exception("test") + """) + self.mod.write(mod_text) + refactoring = restructure.Restructure(self.project, "${a}", "${a}") + self.project.do(refactoring.get_changes()) + self.assertEqual(mod_text, self.mod.read()) + + +@testutils.only_for_versions_higher("3.3") +def test_yield_from(self): + mod_text = dedent("""\ + def f(lst): + yield from lst + """) + self.mod.write(mod_text) + refactoring = restructure.Restructure( + self.project, + "yield from ${a}", + dedent("""\ + for it in ${a}: + yield it"""), + ) + self.project.do(refactoring.get_changes()) + self.assertEqual( + dedent("""\ + def f(lst): + for it in lst: + yield it + """), + self.mod.read(), + ) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +from textwrap import dedent + +import unittest + +from rope.refactor import similarfinder +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class SimilarFinderTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _create_finder(self, source, **kwds): + self.mod.write(source) + pymodule = self.project.get_pymodule(self.mod) + return similarfinder.SimilarFinder(pymodule, **kwds) + + +def test_trivial_case(self): + finder = self._create_finder("") + self.assertEqual([], list(finder.get_match_regions("10"))) + + +def test_constant_integer(self): + source = "a = 10\n" + finder = self._create_finder(source) + result = [(source.index("10"), source.index("10") + 2)] + self.assertEqual(result, list(finder.get_match_regions("10"))) + + +def _append_decorators(self, result): + if self._extracting_staticmethod(): + result.append("@staticmethod\n") + elif self._extracting_classmethod(): + result.append("@classmethod\n") + + +def test_bool_is_not_similar_to_integer(self): + source = dedent("""\ + a = False + b = 0""") + finder = self._create_finder(source) + result = [(source.index("False"), source.index("False") + len("False"))] + self.assertEqual(result, list(finder.get_match_regions("False"))) + + +def test_simple_addition(self): + source = "a = 1 + 2\n" + finder = self._create_finder(source) + result = [(source.index("1"), source.index("2") + 1)] + self.assertEqual(result, list(finder.get_match_regions("1 + 2"))) + + +def test_simple_addition2(self): + source = "a = 1 +2\n" + finder = self._create_finder(source) + result = [(source.index("1"), source.index("2") + 1)] + self.assertEqual(result, list(finder.get_match_regions("1 + 2"))) + + +def test_simple_assign_statements(self): + source = "a = 1 + 2\n" + finder = self._create_finder(source) + self.assertEqual( + [(0, len(source) - 1)], list(finder.get_match_regions("a = 1 + 2")) + ) + + +def test_simple_multiline_statements(self): + source = dedent("""\ + a = 1 + b = 2 + """) + finder = self._create_finder(source) + self.assertEqual( + [(0, len(source) - 1)], list(finder.get_match_regions("a = 1\nb = 2")) + ) + + +def test_multiple_matches(self): + source = "a = 1 + 1\n" + finder = self._create_finder(source) + result = list(finder.get_match_regions("1")) + self.assertEqual(2, len(result)) + start1 = source.index("1") + self.assertEqual((start1, start1 + 1), result[0]) + start2 = source.rindex("1") + self.assertEqual((start2, start2 + 1), result[1]) + + +def test_multiple_matches2(self): + source = dedent("""\ + a = 1 + b = 2 + + a = 1 + b = 2 + """) + finder = self._create_finder(source) + self.assertEqual(2, len(list(finder.get_match_regions("a = 1\nb = 2")))) + + +def test_restricting_the_region_to_search(self): + source = "1\n\n1\n" + finder = self._create_finder(source) + result = list(finder.get_match_regions("1", start=2)) + start = source.rfind("1") + self.assertEqual([(start, start + 1)], result) + + +def test_matching_basic_patterns(self): + source = "b = a\n" + finder = self._create_finder(source) + result = list(finder.get_match_regions("${a}", args={"a": "exact"})) + start = source.rfind("a") + self.assertEqual([(start, start + 1)], result) + + +def test_match_get_ast(self): + source = "b = a\n" + finder = self._create_finder(source) + result = list(finder.get_matches("${a}", args={"a": "exact"})) + self.assertEqual("a", result[0].get_ast("a").id) + + +def _extracting_classmethod(self): + return self.info.kind == "classmethod" + + +def test_match_get_ast_for_statements(self): + source = "b = a\n" + finder = self._create_finder(source) + result = list(finder.get_matches("b = ${a}")) + self.assertEqual("a", result[0].get_ast("a").id) + + +def test_matching_multiple_patterns(self): + source = "c = a + b\n" + finder = self._create_finder(source) + result = list(finder.get_matches("${a} + ${b}")) + self.assertEqual("a", result[0].get_ast("a").id) + self.assertEqual("b", result[0].get_ast("b").id) + + +def test_matching_any_patterns(self): + source = "b = a\n" + finder = self._create_finder(source) + result = list(finder.get_matches("b = ${x}")) + self.assertEqual("a", result[0].get_ast("x").id) + + +def test_matching_any_patterns_repeating(self): + source = "b = 1 + 1\n" + finder = self._create_finder(source) + result = list(finder.get_matches("b = ${x} + ${x}")) + self.assertEqual(1, result[0].get_ast("x").n) + + +def test_matching_any_patterns_not_matching_different_nodes(self): + source = "b = 1 + 2\n" + finder = self._create_finder(source) + result = list(finder.get_matches("b = ${x} + ${x}")) + self.assertEqual(0, len(result)) + + +def test_matching_normal_names_and_assname(self): + source = "a = 1\n" + finder = self._create_finder(source) + result = list(finder.get_matches("${a} = 1")) + self.assertEqual("a", result[0].get_ast("a").id) + + +def test_matching_normal_names_and_assname2(self): + source = "a = 1\n" + finder = self._create_finder(source) + result = list(finder.get_matches("${a}", args={"a": "exact"})) + self.assertEqual(1, len(result)) + + +def test_matching_normal_names_and_attributes(self): + source = "x.a = 1\n" + finder = self._create_finder(source) + result = list(finder.get_matches("${a} = 1", args={"a": "exact"})) + self.assertEqual(0, len(result)) + + +def test_functions_not_matching_when_only_first_parameters(self): + source = "f(1, 2)\n" + finder = self._create_finder(source) + self.assertEqual(0, len(list(finder.get_matches("f(1)")))) + + +def test_matching_nested_try_finally(self): + source = dedent("""\ + if 1: + try: + pass + except: + pass + """) + pattern = dedent("""\ + try: + pass + except: + pass + """) + finder = self._create_finder(source) + self.assertEqual(1, len(list(finder.get_matches(pattern)))) + + +def _extracting_staticmethod(self): + return self.info.kind == "staticmethod" + + +def test_matching_dicts_inside_functions(self): + source = dedent("""\ + def f(p): + d = {1: p.x} + """) + pattern = "{1: ${a}.x}" + finder = self._create_finder(source) + self.assertEqual(1, len(list(finder.get_matches(pattern)))) + + + +class CheckingFinderTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.mod1 = testutils.create_module(self.project, "mod1") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_trivial_case(self): + self.mod1.write("") + pymodule = self.project.get_pymodule(self.mod1) + finder = similarfinder.SimilarFinder(pymodule) + self.assertEqual([], list(finder.get_matches("10", {}))) + + +def test_simple_finding(self): + self.mod1.write(dedent("""\ + class A(object): + pass + a = A() + """)) + pymodule = self.project.get_pymodule(self.mod1) + finder = similarfinder.SimilarFinder(pymodule) + result = list(finder.get_matches("${anything} = ${A}()", {})) + self.assertEqual(1, len(result)) + + +def test_not_matching_when_the_name_does_not_match(self): + self.mod1.write(dedent("""\ + class A(object): + pass + a = list() + """)) + pymodule = self.project.get_pymodule(self.mod1) + finder = similarfinder.SimilarFinder(pymodule) + result = list(finder.get_matches("${anything} = ${C}()", {"C": "name=mod1.A"})) + self.assertEqual(0, len(result)) + + +def test_not_matching_unknowns_finding(self): + self.mod1.write(dedent("""\ + class A(object): + pass + a = unknown() + """)) + pymodule = self.project.get_pymodule(self.mod1) + finder = similarfinder.SimilarFinder(pymodule) + result = list(finder.get_matches("${anything} = ${C}()", {"C": "name=mod1.A"})) + self.assertEqual(0, len(result)) + + +def test_finding_and_matching_pyobjects(self): + source = dedent("""\ + class A(object): + pass + NewA = A + a = NewA() + """) + self.mod1.write(source) + pymodule = self.project.get_pymodule(self.mod1) + finder = similarfinder.SimilarFinder(pymodule) + result = list( + finder.get_matches("${anything} = ${A}()", {"A": "object=mod1.A"}) + ) + self.assertEqual(1, len(result)) + start = source.rindex("a =") + self.assertEqual((start, len(source) - 1), result[0].get_region()) + + +def test_finding_and_matching_types(self): + source = dedent("""\ + class A(object): + def f(self): + pass + a = A() + b = a.f() + """) + self.mod1.write(source) + pymodule = self.project.get_pymodule(self.mod1) + finder = similarfinder.SimilarFinder(pymodule) + result = list( + finder.get_matches("${anything} = ${inst}.f()", {"inst": "type=mod1.A"}) + ) + self.assertEqual(1, len(result)) + start = source.rindex("b") + self.assertEqual((start, len(source) - 1), result[0].get_region()) + + +def _get_function_signature(self, args): + args = list(args) + prefix = "" + if self._extracting_method() or self._extracting_classmethod(): + self_name = self._get_self_name() + if self_name is None: + raise RefactoringError( + "Extracting a method from a function with no self argument." + ) + if self_name in args: + args.remove(self_name) + args.insert(0, self_name) + return prefix + self.info.new_name + "(%s)" % self._get_comma_form(args) + + +def test_checking_the_type_of_an_ass_name_node(self): + self.mod1.write(dedent("""\ + class A(object): + pass + an_a = A() + """)) + pymodule = self.project.get_pymodule(self.mod1) + finder = similarfinder.SimilarFinder(pymodule) + result = list(finder.get_matches("${a} = ${assigned}", {"a": "type=mod1.A"})) + self.assertEqual(1, len(result)) + + +def test_checking_instance_of_an_ass_name_node(self): + self.mod1.write(dedent("""\ + class A(object): + pass + class B(A): + pass + b = B() + """)) + pymodule = self.project.get_pymodule(self.mod1) + finder = similarfinder.SimilarFinder(pymodule) + result = list( + finder.get_matches("${a} = ${assigned}", {"a": "instance=mod1.A"}) + ) + self.assertEqual(1, len(result)) + + +def test_checking_equality_of_imported_pynames(self): + mod2 = testutils.create_module(self.project, "mod2") + mod2.write(dedent("""\ + class A(object): + pass + """)) + self.mod1.write(dedent("""\ + from mod2 import A + an_a = A() + """)) + pymod1 = self.project.get_pymodule(self.mod1) + finder = similarfinder.SimilarFinder(pymod1) + result = list(finder.get_matches("${a_class}()", {"a_class": "name=mod2.A"})) + self.assertEqual(1, len(result)) + + + +class TemplateTest(unittest.TestCase): + @others + +def test_simple_templates(self): + template = similarfinder.CodeTemplate("${a}\n") + self.assertEqual({"a"}, set(template.get_names())) + + +def test_ignoring_matches_in_comments(self): + template = similarfinder.CodeTemplate("#${a}\n") + self.assertEqual({}.keys(), template.get_names()) + + +def test_ignoring_matches_in_strings(self): + template = similarfinder.CodeTemplate("'${a}'\n") + self.assertEqual({}.keys(), template.get_names()) + + +def test_simple_substitution(self): + template = similarfinder.CodeTemplate("${a}\n") + self.assertEqual("b\n", template.substitute({"a": "b"})) + + +def test_substituting_multiple_names(self): + template = similarfinder.CodeTemplate("${a}, ${b}\n") + self.assertEqual("1, 2\n", template.substitute({"a": "1", "b": "2"})) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +from textwrap import dedent + +import unittest + +from rope.base import ast +from rope.refactor import suites +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +def _extracting_method(self): + return not self._extracting_staticmethod() and ( + self.info.method + and not self.info.make_global + and _get_function_kind(self.info.scope) == "method" + ) + + +class SuiteTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + + +def tearDown(self): + super().tearDown() + + +def test_trivial_case(self): + root = source_suite_tree("") + self.assertEqual(1, root.get_start()) + self.assertEqual(0, len(root.get_children())) + + +def test_simple_ifs(self): + root = source_suite_tree(dedent("""\ + if True: + pass""")) + self.assertEqual(1, len(root.get_children())) + + +def test_simple_else(self): + root = source_suite_tree(dedent("""\ + if True: + pass + else: + pass + """)) + self.assertEqual(2, len(root.get_children())) + self.assertEqual(1, root.get_children()[1].get_start()) + + +def test_for(self): + root = source_suite_tree(dedent("""\ + + for i in range(10): + pass + else: + pass + """)) + self.assertEqual(2, len(root.get_children())) + self.assertEqual(2, root.get_children()[1].get_start()) + + +def test_while(self): + root = source_suite_tree(dedent("""\ + while True: + pass + """)) + self.assertEqual(1, len(root.get_children())) + self.assertEqual(1, root.get_children()[0].get_start()) + + +def test_with(self): + root = source_suite_tree(dedent("""\ + from __future__ import with_statement + with file(x): pass + """)) + self.assertEqual(1, len(root.get_children())) + self.assertEqual(2, root.get_children()[0].get_start()) + + +def test_try_finally(self): + root = source_suite_tree(dedent("""\ + try: + pass + finally: + pass + """)) + self.assertEqual(2, len(root.get_children())) + self.assertEqual(1, root.get_children()[0].get_start()) + + +def _generate_info(self, project, resource, offset): + return _FunctionGenerationInfo(project.pycore, resource, offset) + + +def _get_self_name(self): + if self._extracting_classmethod(): + return "cls" + return self._get_scope_self_name() + + +def test_try_except(self): + root = source_suite_tree(dedent("""\ + try: + pass + except: + pass + else: + pass + """)) + self.assertEqual(3, len(root.get_children())) + self.assertEqual(1, root.get_children()[2].get_start()) + + +def test_try_except_finally(self): + root = source_suite_tree(dedent("""\ + try: + pass + except: + pass + finally: + pass + """)) + self.assertEqual(3, len(root.get_children())) + self.assertEqual(1, root.get_children()[2].get_start()) + + +def test_local_start_and_end(self): + root = source_suite_tree(dedent("""\ + if True: + pass + else: + pass + """)) + self.assertEqual(1, root.local_start()) + self.assertEqual(4, root.local_end()) + if_suite = root.get_children()[0] + self.assertEqual(2, if_suite.local_start()) + self.assertEqual(2, if_suite.local_end()) + else_suite = root.get_children()[1] + self.assertEqual(4, else_suite.local_start()) + self.assertEqual(4, else_suite.local_end()) + + +def test_find_suite(self): + root = source_suite_tree("\n") + self.assertEqual(root, root.find_suite(1)) + + +def test_find_suite_for_ifs(self): + root = source_suite_tree(dedent("""\ + if True: + pass + """)) + if_suite = root.get_children()[0] + self.assertEqual(if_suite, root.find_suite(2)) + + +def test_find_suite_for_between_suites(self): + root = source_suite_tree(dedent("""\ + if True: + pass + print(1) + if True: + pass + """)) + if_suite1 = root.get_children()[0] + if_suite2 = root.get_children()[1] + self.assertEqual(if_suite1, root.find_suite(2)) + self.assertEqual(if_suite2, root.find_suite(5)) + self.assertEqual(root, root.find_suite(3)) + + +def test_simple_find_visible(self): + root = source_suite_tree("a = 1\n") + self.assertEqual(1, suites.find_visible_for_suite(root, [1])) + + +def test_simple_find_visible_ifs(self): + root = source_suite_tree(dedent("""\ + + if True: + a = 1 + b = 2 + """)) + self.assertEqual(root.find_suite(3), root.find_suite(4)) + self.assertEqual(3, suites.find_visible_for_suite(root, [3, 4])) + + +def test_simple_find_visible_for_else(self): + root = source_suite_tree(dedent("""\ + + if True: + pass + else: pass + """)) + self.assertEqual(2, suites.find_visible_for_suite(root, [2, 4])) + + +def test_simple_find_visible_for_different_suites(self): + root = source_suite_tree(dedent("""\ + if True: + pass + a = 1 + if False: + pass + """)) + self.assertEqual(1, suites.find_visible_for_suite(root, [2, 3])) + self.assertEqual(5, suites.find_visible_for_suite(root, [5])) + self.assertEqual(1, suites.find_visible_for_suite(root, [2, 5])) + + +def _get_scope_self_name(self): + if self.info.scope.pyobject.get_kind() == "staticmethod": + return + param_names = self.info.scope.pyobject.get_param_names() + if param_names: + return param_names[0] + + +def test_not_always_selecting_scope_start(self): + root = source_suite_tree(dedent("""\ + if True: + a = 1 + if True: + pass + else: + pass + """)) + self.assertEqual(3, suites.find_visible_for_suite(root, [4, 6])) + self.assertEqual(3, suites.find_visible_for_suite(root, [3, 5])) + self.assertEqual(3, suites.find_visible_for_suite(root, [4, 5])) + + +def test_ignoring_functions(self): + root = source_suite_tree(dedent("""\ + def f(): + pass + a = 1 + """)) + self.assertEqual(3, suites.find_visible_for_suite(root, [2, 3])) + + +def test_ignoring_classes(self): + root = source_suite_tree(dedent("""\ + a = 1 + class C(): + pass + """)) + self.assertEqual(1, suites.find_visible_for_suite(root, [1, 3])) + + +@testutils.only_for_versions_higher("3.10") +def test_match_case(self): + root = source_suite_tree(dedent("""\ + a = 1 + match var: + case Foo("xx"): + print(x) + case Foo(x): + print(x) + """)) + self.assertEqual(root.find_suite(4), root.find_suite(6)) + self.assertEqual(root.find_suite(3), root.find_suite(6)) + self.assertEqual(2, suites.find_visible_for_suite(root, [2, 4])) + + + +def source_suite_tree(source): + return suites.ast_suite_tree(ast.parse(source)) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +from textwrap import dedent + +import unittest + +from rope.base import exceptions +from ropetest import testutils +from rope.refactor.usefunction import UseFunction + + +@others +@language python +@tabwidth -4 + +class UseFunctionTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.mod1 = testutils.create_module(self.project, "mod1") + self.mod2 = testutils.create_module(self.project, "mod2") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_case(self): + code = dedent("""\ + def f(): + pass + """) + self.mod1.write(code) + user = UseFunction(self.project, self.mod1, code.rindex("f")) + self.project.do(user.get_changes()) + self.assertEqual(code, self.mod1.read()) + + +def _get_function_call(self, args): + return "{prefix}{name}({args})".format( + prefix=self._get_function_call_prefix(args), + name=self.info.new_name, + args=self._get_comma_form(args), + ) + + +def test_simple_function(self): + code = dedent("""\ + def f(p): + print(p) + print(1) + """) + self.mod1.write(code) + user = UseFunction(self.project, self.mod1, code.rindex("f")) + self.project.do(user.get_changes()) + self.assertEqual( + dedent("""\ + def f(p): + print(p) + f(1) + """), + self.mod1.read(), + ) + + +def test_simple_function2(self): + code = dedent("""\ + def f(p): + print(p + 1) + print(1 + 1) + """) + self.mod1.write(code) + user = UseFunction(self.project, self.mod1, code.rindex("f")) + self.project.do(user.get_changes()) + self.assertEqual( + dedent("""\ + def f(p): + print(p + 1) + f(1) + """), + self.mod1.read(), + ) + + +def test_functions_with_multiple_statements(self): + code = dedent("""\ + def f(p): + r = p + 1 + print(r) + r = 2 + 1 + print(r) + """) + self.mod1.write(code) + user = UseFunction(self.project, self.mod1, code.rindex("f")) + self.project.do(user.get_changes()) + self.assertEqual( + dedent("""\ + def f(p): + r = p + 1 + print(r) + f(2) + """), + self.mod1.read(), + ) + + +def test_returning(self): + code = dedent("""\ + def f(p): + return p + 1 + r = 2 + 1 + print(r) + """) + self.mod1.write(code) + user = UseFunction(self.project, self.mod1, code.rindex("f")) + self.project.do(user.get_changes()) + self.assertEqual( + dedent("""\ + def f(p): + return p + 1 + r = f(2) + print(r) + """), + self.mod1.read(), + ) + + +def test_returning_a_single_expression(self): + code = dedent("""\ + def f(p): + return p + 1 + print(2 + 1) + """) + self.mod1.write(code) + user = UseFunction(self.project, self.mod1, code.rindex("f")) + self.project.do(user.get_changes()) + self.assertEqual( + dedent("""\ + def f(p): + return p + 1 + print(f(2)) + """), + self.mod1.read(), + ) + + +def test_occurrences_in_other_modules(self): + code = dedent("""\ + def f(p): + return p + 1 + """) + self.mod1.write(code) + user = UseFunction(self.project, self.mod1, code.rindex("f")) + self.mod2.write("print(2 + 1)\n") + self.project.do(user.get_changes()) + self.assertEqual( + dedent("""\ + import mod1 + print(mod1.f(2)) + """), + self.mod2.read(), + ) + + +def test_when_performing_on_non_functions(self): + code = "var = 1\n" + self.mod1.write(code) + with self.assertRaises(exceptions.RefactoringError): + UseFunction(self.project, self.mod1, code.rindex("var")) + + +def test_differing_in_the_inner_temp_names(self): + code = dedent("""\ + def f(p): + a = p + 1 + print(a) + b = 2 + 1 + print(b) + """) + self.mod1.write(code) + user = UseFunction(self.project, self.mod1, code.rindex("f")) + self.project.do(user.get_changes()) + self.assertEqual( + dedent("""\ + def f(p): + a = p + 1 + print(a) + f(2) + """), + self.mod1.read(), + ) + + +# TODO: probably new options should be added to restructure +def xxx_test_being_a_bit_more_intelligent_when_returning_assigneds(self): + code = dedent("""\ + def f(p): + a = p + 1 + return a + var = 2 + 1 + print(var) + """) + self.mod1.write(code) + user = UseFunction(self.project, self.mod1, code.rindex("f")) + self.project.do(user.get_changes()) + self.assertEqual( + dedent("""\ + def f(p): + a = p + 1 + return a + var = f(p) + print(var) + """), + self.mod1.read(), + ) + + +def test_exception_when_performing_a_function_with_yield(self): + code = dedent("""\ + def func(): + yield 1 + """) + self.mod1.write(code) + with self.assertRaises(exceptions.RefactoringError): + UseFunction(self.project, self.mod1, code.index("func")) + + +def _get_function_call_prefix(self, args): + prefix = "" + if self.info.method and not self.info.make_global: + if self._extracting_staticmethod() or self._extracting_classmethod(): + prefix = self.info.scope.parent.pyobject.get_name() + "." + else: + self_name = self._get_self_name() + if self_name in args: + args.remove(self_name) + prefix = self_name + "." + return prefix + + +def test_exception_when_performing_a_function_two_returns(self): + code = dedent("""\ + def func(): + return 1 + return 2 + """) + self.mod1.write(code) + with self.assertRaises(exceptions.RefactoringError): + UseFunction(self.project, self.mod1, code.index("func")) + + +def test_exception_when_returns_is_not_the_last_statement(self): + code = dedent("""\ + def func(): + return 2 + a = 1 + """) + self.mod1.write(code) + with self.assertRaises(exceptions.RefactoringError): + UseFunction(self.project, self.mod1, code.index("func")) + +@path C:/Repos/ekr-rope/ropetest/refactor/ +from textwrap import dedent + +import unittest + +import rope.base.taskhandle +import rope.refactor.introduce_parameter +import ropetest.refactor.extracttest +import ropetest.refactor.importutilstest +import ropetest.refactor.inlinetest +import ropetest.refactor.movetest +import ropetest.refactor.multiprojecttest +import ropetest.refactor.patchedasttest +import ropetest.refactor.renametest +import ropetest.refactor.restructuretest +import ropetest.refactor.suitestest +import ropetest.refactor.usefunctiontest +from rope.base.exceptions import RefactoringError, InterruptedTaskError +from rope.refactor.encapsulate_field import EncapsulateField +from rope.refactor.introduce_factory import IntroduceFactory +from rope.refactor.localtofield import LocalToField +from rope.refactor.method_object import MethodObject +from ropetest import testutils +from ropetest.refactor import change_signature_test, similarfindertest + + +@others +@language python +@tabwidth -4 + +class MethodObjectTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_empty_method(self): + code = dedent("""\ + def func(): + pass + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __call__(self): + pass + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + +def test_trivial_return(self): + code = dedent("""\ + def func(): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + +def test_multi_line_header(self): + code = dedent("""\ + def func( + ): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + +def test_a_single_parameter(self): + code = dedent("""\ + def func(param): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, param): + self.param = param + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + +def _get_comma_form(self, names): + return ", ".join(names) + + +def test_self_parameter(self): + code = dedent("""\ + def func(self): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, host): + self.self = host + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + +def test_simple_using_passed_parameters(self): + code = dedent("""\ + def func(param): + return param + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, param): + self.param = param + + def __call__(self): + return self.param + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + +def test_self_keywords_and_args_parameters(self): + code = dedent("""\ + def func(arg, *args, **kwds): + result = arg + args[0] + kwds[arg] + return result + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, arg, args, kwds): + self.arg = arg + self.args = args + self.kwds = kwds + + def __call__(self): + result = self.arg + self.args[0] + self.kwds[self.arg] + return result + """) + self.assertEqual(expected, replacer.get_new_class("_New")) + + +def test_performing_on_not_a_function(self): + code = dedent("""\ + my_var = 10 + """) + self.mod.write(code) + with self.assertRaises(RefactoringError): + MethodObject(self.project, self.mod, code.index("my_var")) + + +def test_changing_the_module(self): + code = dedent("""\ + def func(): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + self.project.do(replacer.get_changes("_New")) + expected = dedent("""\ + def func(): + return _New()() + + + class _New(object): + + def __call__(self): + return 1 + """) + self.assertEqual(expected, self.mod.read()) + + +def test_changing_the_module_and_class_methods(self): + code = dedent("""\ + class C(object): + + def a_func(self): + return 1 + + def another_func(self): + pass + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + self.project.do(replacer.get_changes("_New")) + expected = dedent("""\ + class C(object): + + def a_func(self): + return _New(self)() + + def another_func(self): + pass + + + class _New(object): + + def __init__(self, host): + self.self = host + + def __call__(self): + return 1 + """) + self.assertEqual(expected, self.mod.read()) + + + +class IntroduceFactoryTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _introduce_factory(self, resource, offset, *args, **kwds): + factory_introducer = IntroduceFactory(self.project, resource, offset) + changes = factory_introducer.get_changes(*args, **kwds) + self.project.do(changes) + + +def _get_call(self): + args = self._find_function_arguments() + returns = self._find_function_returns() + call_prefix = "" + if returns and (not self.info.one_line or self.info.returning_named_expr): + assignment_operator = " := " if self.info.one_line else " = " + call_prefix = self._get_comma_form(returns) + assignment_operator + if self.info.returned: + call_prefix = "return " + return call_prefix + self._get_function_call(args) + + +def test_adding_the_method(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + +def test_changing_occurrences_in_the_main_module(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + a_var = AClass()""") + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + a_var = AClass.create()""") + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + +def test_changing_occurrences_with_arguments(self): + code = dedent("""\ + class AClass(object): + def __init__(self, arg): + pass + a_var = AClass(10) + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + def __init__(self, arg): + pass + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + a_var = AClass.create(10) + """) + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + +def test_changing_occurrences_in_other_modules(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("import mod1\na_var = mod1.AClass()\n") + self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = dedent("""\ + import mod1 + a_var = mod1.AClass.create() + """) + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + +def test_raising_exception_for_non_classes(self): + mod = testutils.create_module(self.project, "mod") + mod.write("def a_func():\n pass\n") + with self.assertRaises(RefactoringError): + self._introduce_factory(mod, mod.read().index("a_func") + 1, "create") + + +def test_undoing_introduce_factory(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + code1 = dedent("""\ + class AClass(object): + an_attr = 10 + """) + mod1.write(code1) + code2 = dedent("""\ + from mod1 import AClass + a_var = AClass() + """) + mod2.write(code2) + self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") + self.project.history.undo() + self.assertEqual(code1, mod1.read()) + self.assertEqual(code2, mod2.read()) + + +def test_using_on_an_occurrence_outside_the_main_module(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("import mod1\na_var = mod1.AClass()\n") + self._introduce_factory(mod2, mod2.read().index("AClass") + 1, "create") + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = "import mod1\n" "a_var = mod1.AClass.create()\n" + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + +def test_introduce_factory_in_nested_scopes(self): + code = dedent("""\ + def create_var(): + class AClass(object): + an_attr = 10 + return AClass() + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + def create_var(): + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + return AClass.create() + """) + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + +def test_adding_factory_for_global_factories(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + self._introduce_factory( + mod, mod.read().index("AClass") + 1, "create", global_factory=True + ) + self.assertEqual(expected, mod.read()) + + +def test_get_name_for_factories(self): + code = dedent("""\ + class C(object): + pass + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + factory = IntroduceFactory(self.project, mod, mod.read().index("C") + 1) + self.assertEqual("C", factory.get_name()) + + +def _find_function_arguments(self): + # if not make_global, do not pass any global names; they are + # all visible. + if self.info.global_ and not self.info.make_global: + return list( + self.info_collector.read + & self.info_collector.postread + & self.info_collector.written + ) + if not self.info.one_line: + result = self.info_collector.prewritten & self.info_collector.read + result |= ( + self.info_collector.prewritten + & self.info_collector.postread + & (self.info_collector.maybe_written - self.info_collector.written) + ) + return list(result) + start = self.info.region[0] + if start == self.info.lines_region[0]: + start = start + re.search("\\S", self.info.extracted).start() + function_definition = self.info.source[start : self.info.region[1]] + read = _VariableReadsAndWritesFinder.find_reads_for_one_liners( + function_definition + ) + return list(self.info_collector.prewritten.intersection(read)) + + +def test_raising_exception_for_global_factory_for_nested_classes(self): + code = dedent("""\ + def create_var(): + class AClass(object): + an_attr = 10 + return AClass() + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + with self.assertRaises(RefactoringError): + self._introduce_factory( + mod, mod.read().index("AClass") + 1, "create", global_factory=True + ) + + +def test_changing_occurrences_in_the_main_module_for_global_factories(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + a_var = AClass()""") + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + a_var = create()""") + self._introduce_factory( + mod, mod.read().index("AClass") + 1, "create", global_factory=True + ) + self.assertEqual(expected, mod.read()) + + +def test_changing_occurrences_in_other_modules_for_global_factories(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("import mod1\na_var = mod1.AClass()\n") + self._introduce_factory( + mod1, mod1.read().index("AClass") + 1, "create", global_factory=True + ) + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = "import mod1\n" "a_var = mod1.create()\n" + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + +def test_import_if_necessary_in_other_mods_for_global_factories(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("from mod1 import AClass\npair = AClass(), AClass\n") + self._introduce_factory( + mod1, mod1.read().index("AClass") + 1, "create", global_factory=True + ) + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = dedent("""\ + from mod1 import AClass, create + pair = create(), AClass + """) + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + +def test_changing_occurrences_for_renamed_classes(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + a_class = AClass + a_var = a_class()""") + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + a_class = AClass + a_var = a_class()""") + self._introduce_factory(mod, mod.read().index("a_class") + 1, "create") + self.assertEqual(expected, mod.read()) + + +def test_changing_occurrs_in_the_same_module_with_conflict_ranges(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + def create(self): + return C() + """) + mod.write(code) + self._introduce_factory(mod, mod.read().index("C"), "create_c", True) + expected = dedent("""\ + class C(object): + def create(self): + return create_c() + """) + self.assertTrue(mod.read().startswith(expected)) + + +def _transform_module_to_package(self, resource): + self.project.do( + rope.refactor.ModuleToPackage(self.project, resource).get_changes() + ) + + +def test_transform_module_to_package(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write("import mod2\nfrom mod2 import AClass\n") + mod2 = testutils.create_module(self.project, "mod2") + mod2.write("class AClass(object):\n pass\n") + self._transform_module_to_package(mod2) + mod2 = self.project.get_resource("mod2") + root_folder = self.project.root + self.assertFalse(root_folder.has_child("mod2.py")) + self.assertEqual( + "class AClass(object):\n pass\n", + root_folder.get_child("mod2").get_child("__init__.py").read(), + ) + + +def test_transform_module_to_package_undoing(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) + self._transform_module_to_package(mod) + self.assertFalse(pkg.has_child("mod.py")) + self.assertTrue(pkg.get_child("mod").has_child("__init__.py")) + self.project.history.undo() + self.assertTrue(pkg.has_child("mod.py")) + self.assertFalse(pkg.has_child("mod")) + + +def test_transform_module_to_package_with_relative_imports(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod1.write("import mod2\nfrom mod2 import AClass\n") + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod2.write("class AClass(object):\n pass\n") + self._transform_module_to_package(mod1) + new_init = self.project.get_resource("pkg/mod1/__init__.py") + self.assertEqual( + "import pkg.mod2\nfrom pkg.mod2 import AClass\n", new_init.read() + ) + + +def _find_function_returns(self): + if self.info.one_line: + written = self.info_collector.written | self.info_collector.maybe_written + return list(written & self.info_collector.postread) + + if self.info.returned: + return [] + written = self.info_collector.written | self.info_collector.maybe_written + return list(written & self.info_collector.postread) + + +def test_resources_parameter(self): + code = dedent("""\ + class A(object): + an_attr = 10 + """) + code1 = dedent("""\ + import mod + a = mod.A() + """) + mod = testutils.create_module(self.project, "mod") + mod1 = testutils.create_module(self.project, "mod1") + mod.write(code) + mod1.write(code1) + expected = dedent("""\ + class A(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return A(*args, **kwds) + """) + self._introduce_factory( + mod, mod.read().index("A") + 1, "create", resources=[mod] + ) + self.assertEqual(expected, mod.read()) + self.assertEqual(code1, mod1.read()) + + + +class EncapsulateFieldTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + self.mod1 = testutils.create_module(self.project, "mod1") + self.a_class = dedent("""\ + class A(object): + def __init__(self): + self.attr = 1 + """) + self.added_methods = ( + "\n" + " def get_attr(self):\n" + " return self.attr\n\n" + " def set_attr(self, value):\n" + " self.attr = value\n" + ) + self.encapsulated = self.a_class + self.added_methods + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _encapsulate(self, resource, offset, **args): + changes = EncapsulateField(self.project, resource, offset).get_changes(**args) + self.project.do(changes) + + +def test_adding_getters_and_setters(self): + code = self.a_class + self.mod.write(code) + self._encapsulate(self.mod, code.index("attr") + 1) + self.assertEqual(self.encapsulated, self.mod.read()) + + +def test_changing_getters_in_other_modules(self): + code = dedent("""\ + import mod + a_var = mod.A() + range(a_var.attr) + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + range(a_var.get_attr()) + """) + self.assertEqual(expected, self.mod1.read()) + + +def test_changing_setters_in_other_modules(self): + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(1) + """) + self.assertEqual(expected, self.mod1.read()) + + +def test_changing_getters_in_setters(self): + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + a_var.attr + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(1 + a_var.get_attr()) + """) + self.assertEqual(expected, self.mod1.read()) + + +def test_appending_to_class_end(self): + self.mod1.write(self.a_class + "a_var = A()\n") + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + self.assertEqual(self.encapsulated + "a_var = A()\n", self.mod1.read()) + + +def _get_unindented_function_body(self, returns): + if self.info.one_line: + return self._get_single_expression_function_body() + return self._get_multiline_function_body(returns) + + +def test_performing_in_other_modules(self): + code = dedent("""\ + import mod + a_var = mod.A() + range(a_var.attr) + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + self.assertEqual(self.encapsulated, self.mod.read()) + expected = dedent("""\ + import mod + a_var = mod.A() + range(a_var.get_attr()) + """) + self.assertEqual(expected, self.mod1.read()) + + +def test_changing_main_module_occurrences(self): + code = self.a_class + "a_var = A()\n" "a_var.attr = a_var.attr * 2\n" + self.mod1.write(code) + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + expected = ( + self.encapsulated + "a_var = A()\n" "a_var.set_attr(a_var.get_attr() * 2)\n" + ) + self.assertEqual(expected, self.mod1.read()) + + +def test_raising_exception_when_performed_on_non_attributes(self): + self.mod1.write("attr = 10") + with self.assertRaises(RefactoringError): + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + + +def test_raising_exception_on_tuple_assignments(self): + self.mod.write(self.a_class) + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + a_var.attr, b = 1, 2 + """) + self.mod1.write(code) + with self.assertRaises(RefactoringError): + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + + +def test_raising_exception_on_tuple_assignments2(self): + self.mod.write(self.a_class) + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + b, a_var.attr = 1, 2 + """) + self.mod1.write(code) + with self.assertRaises(RefactoringError): + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + + +def test_tuple_assignments_and_function_calls(self): + code = dedent("""\ + import mod + def func(a1=0, a2=0): + pass + a_var = mod.A() + func(a_var.attr, a2=2) + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + def func(a1=0, a2=0): + pass + a_var = mod.A() + func(a_var.get_attr(), a2=2) + """) + self.assertEqual(expected, self.mod1.read()) + + +def test_tuple_assignments(self): + code = dedent("""\ + import mod + a_var = mod.A() + a, b = a_var.attr, 1 + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a, b = a_var.get_attr(), 1 + """) + self.assertEqual(expected, self.mod1.read()) + + +def test_changing_augmented_assignments(self): + code = "import mod\n" "a_var = mod.A()\n" "a_var.attr += 1\n" + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(a_var.get_attr() + 1) + """) + self.assertEqual(expected, self.mod1.read()) + + +def test_changing_augmented_assignments2(self): + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr <<= 1 + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(a_var.get_attr() << 1) + """) + self.assertEqual(expected, self.mod1.read()) + + +def test_changing_occurrences_inside_the_class(self): + new_class = ( + self.a_class + "\n" " def a_func(self):\n" " self.attr = 1\n" + ) + self.mod.write(new_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = ( + self.a_class + "\n" + " def a_func(self):\n" + " self.set_attr(1)\n" + self.added_methods + ) + self.assertEqual(expected, self.mod.read()) + + +def _get_multiline_function_body(self, returns): + unindented_body = sourceutils.fix_indentation(self.info.extracted, 0) + unindented_body = self._insert_globals(unindented_body) + if returns: + unindented_body += "\nreturn %s" % self._get_comma_form(returns) + return unindented_body + + +def test_getter_and_setter_parameters(self): + self.mod.write(self.a_class) + self._encapsulate( + self.mod, + self.mod.read().index("attr") + 1, + getter="getAttr", + setter="setAttr", + ) + new_methods = self.added_methods.replace("get_attr", "getAttr").replace( + "set_attr", "setAttr" + ) + expected = self.a_class + new_methods + self.assertEqual(expected, self.mod.read()) + + +def test_using_resources_parameter(self): + self.mod1.write("import mod\na = mod.A()\nvar = a.attr\n") + self.mod.write(self.a_class) + self._encapsulate( + self.mod, self.mod.read().index("attr") + 1, resources=[self.mod] + ) + self.assertEqual("import mod\na = mod.A()\nvar = a.attr\n", self.mod1.read()) + expected = self.a_class + self.added_methods + self.assertEqual(expected, self.mod.read()) + + + +class LocalToFieldTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _perform_convert_local_variable_to_field(self, resource, offset): + changes = LocalToField(self.project, resource, offset).get_changes() + self.project.do(changes) + + +def test_simple_local_to_field(self): + code = dedent("""\ + class A(object): + def a_func(self): + var = 10 + """) + self.mod.write(code) + self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) + expected = dedent("""\ + class A(object): + def a_func(self): + self.var = 10 + """) + self.assertEqual(expected, self.mod.read()) + + +def test_raising_exception_when_performed_on_a_global_var(self): + self.mod.write("var = 10\n") + with self.assertRaises(RefactoringError): + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().index("var") + 1 + ) + + +def test_raising_exception_when_performed_on_field(self): + code = dedent("""\ + class A(object): + def a_func(self): + self.var = 10 + """) + self.mod.write(code) + with self.assertRaises(RefactoringError): + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().index("var") + 1 + ) + + +def test_raising_exception_when_performed_on_a_parameter(self): + code = dedent("""\ + class A(object): + def a_func(self, var): + a = var + """) + self.mod.write(code) + with self.assertRaises(RefactoringError): + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().index("var") + 1 + ) + + +def _get_element(self): + decorator = "" + args = [] + if self.info.is_static_method(): + decorator = "@staticmethod\n" + if ( + self.info.is_method() + or self.info.is_constructor() + or self.info.is_instance() + ): + args.append("self") + args.extend(self.info.get_passed_args()) + definition = "{}def {}({}):\n pass\n".format( + decorator, + self.name, + ", ".join(args), + ) + return definition + + +def _get_single_expression_function_body(self): + extracted = _get_single_expression_body(self.info.extracted, info=self.info) + body = "return " + extracted + return self._insert_globals(body) + + +# NOTE: This situation happens alot and is normally not an error +# @testutils.assert_raises(RefactoringError) +def test_not_rais_exception_when_there_is_a_field_with_the_same_name(self): + code = dedent("""\ + class A(object): + def __init__(self): + self.var = 1 + def a_func(self): + var = 10 + """) + self.mod.write(code) + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().rindex("var") + 1 + ) + + +def test_local_to_field_with_self_renamed(self): + code = dedent("""\ + class A(object): + def a_func(myself): + var = 10 + """) + self.mod.write(code) + self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) + expected = dedent("""\ + class A(object): + def a_func(myself): + myself.var = 10 + """) + self.assertEqual(expected, self.mod.read()) + + + +class IntroduceParameterTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def _introduce_parameter(self, offset, name): + rope.refactor.introduce_parameter.IntroduceParameter( + self.project, self.mod, offset + ).get_changes(name).do() + + +def test_simple_case(self): + code = dedent("""\ + var = 1 + def f(): + b = var + """) + self.mod.write(code) + offset = self.mod.read().rindex("var") + self._introduce_parameter(offset, "var") + expected = dedent("""\ + var = 1 + def f(var=var): + b = var + """) + self.assertEqual(expected, self.mod.read()) + + +def test_changing_function_body(self): + code = dedent("""\ + var = 1 + def f(): + b = var + """) + self.mod.write(code) + offset = self.mod.read().rindex("var") + self._introduce_parameter(offset, "p1") + expected = dedent("""\ + var = 1 + def f(p1=var): + b = p1 + """) + self.assertEqual(expected, self.mod.read()) + + +def test_unknown_variables(self): + self.mod.write("def f():\n b = var + c\n") + offset = self.mod.read().rindex("var") + with self.assertRaises(RefactoringError): + self._introduce_parameter(offset, "p1") + self.assertEqual("def f(p1=var):\n b = p1 + c\n", self.mod.read()) + + +def test_failing_when_not_inside(self): + self.mod.write("var = 10\nb = var\n") + offset = self.mod.read().rindex("var") + with self.assertRaises(RefactoringError): + self._introduce_parameter(offset, "p1") + + +def _insert_globals(self, unindented_body): + globals_in_body = self._get_globals_in_body(unindented_body) + globals_ = self.info_collector.globals_ & ( + self.info_collector.written | self.info_collector.maybe_written + ) + globals_ = globals_ - globals_in_body + + if globals_: + unindented_body = "global {}\n{}".format( + ", ".join(globals_), unindented_body + ) + return unindented_body + + +def test_attribute_accesses(self): + code = dedent("""\ + class C(object): + a = 10 + c = C() + def f(): + b = c.a + """) + self.mod.write(code) + offset = self.mod.read().rindex("a") + self._introduce_parameter(offset, "p1") + expected = dedent("""\ + class C(object): + a = 10 + c = C() + def f(p1=c.a): + b = p1 + """) + self.assertEqual(expected, self.mod.read()) + + +def test_introducing_parameters_for_methods(self): + code = dedent("""\ + var = 1 + class C(object): + def f(self): + b = var + """) + self.mod.write(code) + offset = self.mod.read().rindex("var") + self._introduce_parameter(offset, "p1") + expected = dedent("""\ + var = 1 + class C(object): + def f(self, p1=var): + b = p1 + """) + self.assertEqual(expected, self.mod.read()) + + + +class _MockTaskObserver: + def __init__(self): + self.called = 0 + + def __call__(self): + self.called += 1 + + + +class TaskHandleTest(unittest.TestCase): + @others + +def test_trivial_case(self): + handle = rope.base.taskhandle.TaskHandle() + self.assertFalse(handle.is_stopped()) + + +def test_stopping(self): + handle = rope.base.taskhandle.TaskHandle() + handle.stop() + self.assertTrue(handle.is_stopped()) + + +def test_job_sets(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset() + self.assertEqual([jobs], handle.get_jobsets()) + + +def test_starting_and_finishing_jobs(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset(name="test job set", count=1) + jobs.started_job("job1") + jobs.finished_job() + + +def test_test_checking_status(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset() + handle.stop() + with self.assertRaises(InterruptedTaskError): + jobs.check_status() + + +def test_test_checking_status_when_starting(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset() + handle.stop() + with self.assertRaises(InterruptedTaskError): + jobs.started_job("job1") + + +@staticmethod +def _get_globals_in_body(unindented_body): + node = _parse_text(unindented_body) + visitor = _GlobalFinder() + ast.walk(node, visitor) + return visitor.globals_ + + + +def test_calling_the_observer_after_stopping(self): + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) + handle.stop() + self.assertEqual(1, observer.called) + + +def test_calling_the_observer_after_creating_job_sets(self): + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) + jobs = handle.create_jobset() # noqa + self.assertEqual(1, observer.called) + + +def test_calling_the_observer_when_starting_and_finishing_jobs(self): + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) + jobs = handle.create_jobset(name="test job set", count=1) + jobs.started_job("job1") + jobs.finished_job() + self.assertEqual(3, observer.called) + + +def test_job_set_get_percent_done(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset(name="test job set", count=2) + self.assertEqual(0, jobs.get_percent_done()) + jobs.started_job("job1") + jobs.finished_job() + self.assertEqual(50, jobs.get_percent_done()) + jobs.started_job("job2") + jobs.finished_job() + self.assertEqual(100, jobs.get_percent_done()) + + +def test_getting_job_name(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset(name="test job set", count=1) + # recommended name/job_name attribute + self.assertEqual("test job set", jobs.name) + self.assertEqual(None, jobs.job_name) + # deprecated getters + self.assertEqual("test job set", jobs.get_name()) + self.assertEqual(None, jobs.get_active_job_name()) + jobs.started_job("job1") + # recommended name/job_name attribute + self.assertEqual("test job set", jobs.get_name()) + # deprecated getters + self.assertEqual("job1", jobs.get_active_job_name()) + +class _ExtractVariableParts: + @others + +def __init__(self, info): + self.info = info + + +def get_definition(self): + extracted = _get_single_expression_body(self.info.extracted, info=self.info) + return self.info.new_name + " = " + extracted + "\n" + + +def get_body_pattern(self): + return "(%s)" % self.info.extracted.strip() + + +def get_replacement_pattern(self): + return self.info.new_name + + +def get_checks(self): + return {} + + + +class _FunctionInformationCollector: + @others + +def _get_element_kind(self): + return "Function" + + + +def __init__(self, start, end, is_global): + self.start = start + self.end = end + self.is_global = is_global + self.prewritten = OrderedSet() + self.maybe_written = OrderedSet() + self.written = OrderedSet() + self.read = OrderedSet() + self.postread = OrderedSet() + self.postwritten = OrderedSet() + self.host_function = True + self.conditional = False + self.globals_ = OrderedSet() + self.surrounded_by_loop = 0 + self.loop_depth = 0 + + +def _read_variable(self, name, lineno): + if self.start <= lineno <= self.end: + if name not in self.written: + if not self.conditional or name not in self.maybe_written: + self.read.add(name) + if self.end < lineno: + if name not in self.postwritten: + self.postread.add(name) + + +def _written_variable(self, name, lineno): + if self.start <= lineno <= self.end: + if self.conditional: + self.maybe_written.add(name) + else: + self.written.add(name) + if self.loop_depth > 0 and name in self.read: + self.postread.add(name) + if self.start > lineno: + self.prewritten.add(name) + if self.end < lineno: + self.postwritten.add(name) + + +def _FunctionDef(self, node): + if not self.is_global and self.host_function: + self.host_function = False + for name in _get_argnames(node.args): + self._written_variable(name, node.lineno) + for child in node.body: + ast.walk(child, self) + else: + self._written_variable(node.name, node.lineno) + visitor = _VariableReadsAndWritesFinder() + for child in node.body: + ast.walk(child, visitor) + for name in visitor.read - visitor.written: + self._read_variable(name, node.lineno) + + +def _Global(self, node): + self.globals_.add(*node.names) + + +def _AsyncFunctionDef(self, node): + self._FunctionDef(node) + + +def _Name(self, node): + if isinstance(node.ctx, (ast.Store, ast.AugStore)): + self._written_variable(node.id, node.lineno) + if not isinstance(node.ctx, ast.Store): + self._read_variable(node.id, node.lineno) + + +def _MatchAs(self, node): + self._written_variable(node.name, node.lineno) + if node.pattern: + ast.walk(node.pattern, self) + + +def _Assign(self, node): + ast.walk(node.value, self) + for child in node.targets: + ast.walk(child, self) + + +def _AugAssign(self, node): + ast.walk(node.value, self) + if isinstance(node.target, ast.Name): + target_id = node.target.id + self._read_variable(target_id, node.target.lineno) + self._written_variable(target_id, node.target.lineno) + else: + ast.walk(node.target, self) + + +class GenerateVariable(_Generate): + def _get_element(self): + return "%s = None\n" % self.name + + def _get_element_kind(self): + return "Variable" + + + +def _ClassDef(self, node): + self._written_variable(node.name, node.lineno) + + +def _ListComp(self, node): + self._comp_exp(node) + + +def _GeneratorExp(self, node): + self._comp_exp(node) + + +def _SetComp(self, node): + self._comp_exp(node) + + +def _DictComp(self, node): + self._comp_exp(node) + + +def _comp_exp(self, node): + read = OrderedSet(self.read) + written = OrderedSet(self.written) + maybe_written = OrderedSet(self.maybe_written) + + for child in ast.get_child_nodes(node): + ast.walk(child, self) + + comp_names = list( + chain.from_iterable( + self._flatten_nested_tuple_of_names(generator.target) + for generator in node.generators + ) + ) + self.read = self.read - comp_names | read + self.written = self.written - comp_names | written + self.maybe_written = self.maybe_written - comp_names | maybe_written + + +def _flatten_nested_tuple_of_names(self, node): + if isinstance(node, ast.Tuple): + for elt in node.elts: + yield self._flatten_nested_tuple_of_names(elt) + elif isinstance(node, ast.Name): + yield node.id + else: + assert False, "Unexpected node type in list comprehension target: %s" % node + + +def _If(self, node): + self._handle_conditional_node(node) + + +def _While(self, node): + with self._handle_loop_context(node): + self._handle_conditional_node(node) + + +def _For(self, node): + with self._handle_loop_context(node), self._handle_conditional_context(node): + # iter has to be checked before the target variables + ast.walk(node.iter, self) + ast.walk(node.target, self) + + for child in node.body: + ast.walk(child, self) + for child in node.orelse: + ast.walk(child, self) + + +class GenerateClass(_Generate): + def _get_element(self): + return "class %s(object):\n pass\n" % self.name + + def _get_element_kind(self): + return "Class" + + + +def _handle_conditional_node(self, node): + with self._handle_conditional_context(node): + for child in ast.get_child_nodes(node): + ast.walk(child, self) + + +@contextmanager +def _handle_conditional_context(self, node): + if self.start <= node.lineno <= self.end: + self.conditional = True + try: + yield + finally: + self.conditional = False + + +@contextmanager +def _handle_loop_context(self, node): + if node.lineno < self.start: + self.loop_depth += 1 + try: + yield + finally: + self.loop_depth -= 1 + + + +def _get_argnames(arguments): + result = [ + node.arg for node in arguments.args if isinstance(node, ast.arg) + ] + if arguments.vararg: + result.append(vararg.arg) + if arguments.kwarg: + result.append(arguments.kwarg.arg) + return result + + + +class _VariableReadsAndWritesFinder: + @others + +def __init__(self): + self.written = set() + self.read = set() + + +def _Name(self, node): + if isinstance(node.ctx, (ast.Store, ast.AugStore)): + self.written.add(node.id) + if not isinstance(node, ast.Store): + self.read.add(node.id) + + +def _FunctionDef(self, node): + self.written.add(node.name) + visitor = _VariableReadsAndWritesFinder() + for child in ast.get_child_nodes(node): + ast.walk(child, visitor) + self.read.update(visitor.read - visitor.written) + + +def _Class(self, node): + self.written.add(node.name) + + +@staticmethod +def find_reads_and_writes(code): + if code.strip() == "": + return set(), set() + node = _parse_text(code) + visitor = _VariableReadsAndWritesFinder() + ast.walk(node, visitor) + return visitor.read, visitor.written + + +class GenerateModule(_Generate): + @others + +@staticmethod +def find_reads_for_one_liners(code): + if code.strip() == "": + return set(), set() + node = _parse_text(code) + visitor = _VariableReadsAndWritesFinder() + ast.walk(node, visitor) + return visitor.read + + + +class _BaseErrorFinder: + @others + +@classmethod +def has_errors(cls, code): + if code.strip() == "": + return False + node = _parse_text(code) + visitor = cls() + ast.walk(node, visitor) + return visitor.error + + + +class _UnmatchedBreakOrContinueFinder(_BaseErrorFinder): + @others + +def __init__(self): + self.error = False + self.loop_count = 0 + + +def _For(self, node): + self.loop_encountered(node) + + +def _While(self, node): + self.loop_encountered(node) + + +def loop_encountered(self, node): + self.loop_count += 1 + for child in node.body: + ast.walk(child, self) + self.loop_count -= 1 + if node.orelse: + if isinstance(node.orelse, (list, tuple)): + for node_ in node.orelse: + ast.walk(node_, self) + else: + ast.walk(node.orelse, self) + + +def _Break(self, node): + self.check_loop() + + +def _Continue(self, node): + self.check_loop() + + +def get_changes(self): + package = self.info.get_package() + changes = change.ChangeSet("Generate Module <%s>" % self.name) + new_resource = self.project.get_file("{}/{}.py".format(package.path, self.name)) + if new_resource.exists(): + raise exceptions.RefactoringError( + "Module <%s> already exists" % new_resource.path + ) + changes.add_change(change.CreateResource(new_resource)) + changes.add_change( + _add_import_to_module(self.project, self.resource, new_resource) + ) + return changes + + +def check_loop(self): + if self.loop_count < 1: + self.error = True + + +def _FunctionDef(self, node): + pass + + +def _ClassDef(self, node): + pass + + + +class _AsyncStatementFinder(_BaseErrorFinder): + @others + +def __init__(self): + self.error = False + + +def _AsyncFor(self, node): + self.error = True + + +def _AsyncWith(self, node): + self.error = True + + +def _FunctionDef(self, node): + pass + + +def _ClassDef(self, node): + pass + + + +class _GlobalFinder: + def __init__(self): + self.globals_ = OrderedSet() + + def _Global(self, node): + self.globals_.add(*node.names) + + + +def get_location(self): + package = self.info.get_package() + return (package.get_child("%s.py" % self.name), 1) + + + +def _get_function_kind(scope): + return scope.pyobject.get_kind() + + + +def _parse_text(body): + body = sourceutils.fix_indentation(body, 0) + try: + node = ast.parse(body) + except SyntaxError: + # needed to parse expression containing := operator + try: + node = ast.parse("(" + body + ")") + except SyntaxError: + node = ast.parse( + "async def __rope_placeholder__():\n" + + sourceutils.fix_indentation(body, 4) + ) + node.body = node.body[0].body + return node + + + +def _join_lines(code): + lines = [] + for line in code.splitlines(): + if line.endswith("\\"): + lines.append(line[:-1].strip()) + else: + lines.append(line.strip()) + return " ".join(lines) + + + +def _get_single_expression_body(extracted, info): + extracted = sourceutils.fix_indentation(extracted, 0) + already_parenthesized = ( + extracted.lstrip()[0] in "({[" and extracted.rstrip()[-1] in ")}]" + ) + large_multiline = extracted.count("\n") >= 2 and already_parenthesized + if not large_multiline: + extracted = _join_lines(extracted) + multiline_expression = "\n" in extracted + if ( + info.returning_named_expr + or info.returning_generator_exp + or (multiline_expression and not large_multiline) + ): + extracted = "(" + extracted + ")" + return extracted + +@path C:/Repos/ekr-rope/rope/refactor/ +import rope.base.exceptions +import rope.base.pyobjects +from rope.base.builtins import Lambda +from rope.base import worder + + +@others +@language python +@tabwidth -4 + +class DefinitionInfo: + @others + +def __init__( + self, function_name, is_method, args_with_defaults, args_arg, keywords_arg +): + self.function_name = function_name + self.is_method = is_method + self.args_with_defaults = args_with_defaults + self.args_arg = args_arg + self.keywords_arg = keywords_arg + + +def to_string(self): + return "{}({})".format(self.function_name, self.arguments_to_string()) + + +def arguments_to_string(self, from_index=0): + params = [] + for arg, default in self.args_with_defaults: + if default is not None: + params.append("{}={}".format(arg, default)) + else: + params.append(arg) + if self.args_arg is not None: + params.append("*" + self.args_arg) + if self.keywords_arg: + params.append("**" + self.keywords_arg) + return ", ".join(params[from_index:]) + + +@staticmethod +def _read(pyfunction, code): + kind = pyfunction.get_kind() + is_method = kind == "method" + is_lambda = kind == "lambda" + info = _FunctionParser(code, is_method, is_lambda) + args, keywords = info.get_parameters() + args_arg = None + keywords_arg = None + if args and args[-1].startswith("**"): + keywords_arg = args[-1][2:] + del args[-1] + if args and args[-1].startswith("*"): + args_arg = args[-1][1:] + del args[-1] + args_with_defaults = [(name, None) for name in args] + args_with_defaults.extend(keywords) + return DefinitionInfo( + info.get_function_name(), + is_method, + args_with_defaults, + args_arg, + keywords_arg, + ) + + +@property +@utils.saveit +def commenter(self): + return _Commenter(self.code) + + +class GeneratePackage(_Generate): + @others + +@staticmethod +def read(pyfunction): + pymodule = pyfunction.get_module() + word_finder = worder.Worder(pymodule.source_code) + lineno = pyfunction.get_ast().lineno + start = pymodule.lines.get_line_start(lineno) + if isinstance(pyfunction, Lambda): + call = word_finder.get_lambda_and_args(start) + else: + call = word_finder.get_function_and_args_in_header(start) + return DefinitionInfo._read(pyfunction, call) + + + +class CallInfo: + @others + +def __init__( + self, + function_name, + args, + keywords, + args_arg, + keywords_arg, + implicit_arg, + constructor, +): + self.function_name = function_name + self.args = args + self.keywords = keywords + self.args_arg = args_arg + self.keywords_arg = keywords_arg + self.implicit_arg = implicit_arg + self.constructor = constructor + + +def to_string(self): + function = self.function_name + if self.implicit_arg: + function = self.args[0] + "." + self.function_name + params = [] + start = 0 + if self.implicit_arg or self.constructor: + start = 1 + if self.args[start:]: + params.extend(self.args[start:]) + if self.keywords: + params.extend( + ["{}={}".format(name, value) for name, value in self.keywords] + ) + if self.args_arg is not None: + params.append("*" + self.args_arg) + if self.keywords_arg: + params.append("**" + self.keywords_arg) + return "{}({})".format(function, ", ".join(params)) + + +@staticmethod +def read(primary, pyname, definition_info, code): + is_method_call = CallInfo._is_method_call(primary, pyname) + is_constructor = CallInfo._is_class(pyname) + is_classmethod = CallInfo._is_classmethod(pyname) + info = _FunctionParser(code, is_method_call or is_classmethod) + args, keywords = info.get_parameters() + args_arg = None + keywords_arg = None + if args and args[-1].startswith("**"): + keywords_arg = args[-1][2:] + del args[-1] + if args and args[-1].startswith("*"): + args_arg = args[-1][1:] + del args[-1] + if is_constructor: + args.insert(0, definition_info.args_with_defaults[0][0]) + return CallInfo( + info.get_function_name(), + args, + keywords, + args_arg, + keywords_arg, + is_method_call or is_classmethod, + is_constructor, + ) + + +@staticmethod +def _is_method_call(primary, pyname): + return ( + primary is not None + and isinstance(primary.get_object().get_type(), rope.base.pyobjects.PyClass) + and CallInfo._is_method(pyname) + ) + + +@staticmethod +def _is_class(pyname): + return pyname is not None and isinstance( + pyname.get_object(), rope.base.pyobjects.PyClass + ) + + +@staticmethod +def _is_method(pyname): + if pyname is not None and isinstance( + pyname.get_object(), rope.base.pyobjects.PyFunction + ): + return pyname.get_object().get_kind() == "method" + return False + + +@staticmethod +def _is_classmethod(pyname): + if pyname is not None and isinstance( + pyname.get_object(), rope.base.pyobjects.PyFunction + ): + return pyname.get_object().get_kind() == "classmethod" + return False + + + +class ArgumentMapping: + @others + +def get_changes(self): + package = self.info.get_package() + changes = change.ChangeSet("Generate Package <%s>" % self.name) + new_resource = self.project.get_folder("{}/{}".format(package.path, self.name)) + if new_resource.exists(): + raise exceptions.RefactoringError( + "Package <%s> already exists" % new_resource.path + ) + changes.add_change(change.CreateResource(new_resource)) + changes.add_change( + _add_import_to_module(self.project, self.resource, new_resource) + ) + child = self.project.get_folder(package.path + "/" + self.name) + changes.add_change(change.CreateFile(child, "__init__.py")) + return changes + + +def __init__(self, definition_info, call_info): + self.call_info = call_info + self.param_dict = {} + self.keyword_args = [] + self.args_arg = [] + for index, value in enumerate(call_info.args): + if index < len(definition_info.args_with_defaults): + name = definition_info.args_with_defaults[index][0] + self.param_dict[name] = value + else: + self.args_arg.append(value) + for name, value in call_info.keywords: + index = -1 + for pair in definition_info.args_with_defaults: + if pair[0] == name: + self.param_dict[name] = value + break + else: + self.keyword_args.append((name, value)) + + +def to_call_info(self, definition_info): + args = [] + keywords = [] + for index in range(len(definition_info.args_with_defaults)): + name = definition_info.args_with_defaults[index][0] + if name in self.param_dict: + args.append(self.param_dict[name]) + else: + for i in range(index, len(definition_info.args_with_defaults)): + name = definition_info.args_with_defaults[i][0] + if name in self.param_dict: + keywords.append((name, self.param_dict[name])) + break + args.extend(self.args_arg) + keywords.extend(self.keyword_args) + return CallInfo( + self.call_info.function_name, + args, + keywords, + self.call_info.args_arg, + self.call_info.keywords_arg, + self.call_info.implicit_arg, + self.call_info.constructor, + ) + + + +class _FunctionParser: + @others + +def __init__(self, call, implicit_arg, is_lambda=False): + self.call = call + self.implicit_arg = implicit_arg + self.word_finder = worder.Worder(self.call) + if is_lambda: + self.last_parens = self.call.rindex(":") + else: + self.last_parens = self.call.rindex(")") + self.first_parens = self.word_finder._find_parens_start(self.last_parens) + + +def get_parameters(self): + args, keywords = self.word_finder.get_parameters( + self.first_parens, self.last_parens + ) + if self.is_called_as_a_method(): + instance = self.call[: self.call.rindex(".", 0, self.first_parens)] + args.insert(0, instance.strip()) + return args, keywords + + +def get_instance(self): + if self.is_called_as_a_method(): + return self.word_finder.get_primary_at( + self.call.rindex(".", 0, self.first_parens) - 1 + ) + + +def get_function_name(self): + if self.is_called_as_a_method(): + return self.word_finder.get_word_at(self.first_parens - 1) + else: + return self.word_finder.get_primary_at(self.first_parens - 1) + + +def is_called_as_a_method(self): + return self.implicit_arg and "." in self.call[: self.first_parens] + +@path C:/Repos/ekr-rope/rope/refactor/ +# Known Bugs when inlining a function/method +# The values passed to function are inlined using _inlined_variable. +# This may cause two problems, illustrated in the examples below +# +# def foo(var1): +# var1 = var1*10 +# return var1 +# +# If a call to foo(20) is inlined, the result of inlined function is 20, +# but it should be 200. +# +# def foo(var1): +# var2 = var1*10 +# return var2 +# +# 2- If a call to foo(10+10) is inlined the result of inlined function is 110 +# but it should be 200. + +import re +from typing import List + +import rope.base.exceptions +import rope.refactor.functionutils +from rope.base import ( + ast, + pynames, + pyobjects, + codeanalyze, + taskhandle, + evaluate, + worder, + utils, + libutils, +) +from rope.base.change import ChangeSet, ChangeContents +from rope.refactor import ( + occurrences, + rename, + sourceutils, + importutils, + move, + change_signature, +) + + +@others +@language python +@tabwidth -4 + +def unique_prefix(): + n = 0 + while True: + yield "__" + str(n) + "__" + n += 1 + + + +def get_location(self): + package = self.info.get_package() + child = package.get_child(self.name) + return (child.get_child("__init__.py"), 1) + + + +def create_inline(project, resource, offset): + """Create a refactoring object for inlining + + Based on `resource` and `offset` it returns an instance of + `InlineMethod`, `InlineVariable` or `InlineParameter`. + + """ + pyname = _get_pyname(project, resource, offset) + message = ( + "Inline refactoring should be performed on " + "a method, local variable or parameter." + ) + if pyname is None: + raise rope.base.exceptions.RefactoringError(message) + if isinstance(pyname, pynames.ImportedName): + pyname = pyname._get_imported_pyname() + if isinstance(pyname, pynames.AssignedName): + return InlineVariable(project, resource, offset) + if isinstance(pyname, pynames.ParameterName): + return InlineParameter(project, resource, offset) + if isinstance(pyname.get_object(), pyobjects.PyFunction): + return InlineMethod(project, resource, offset) + else: + raise rope.base.exceptions.RefactoringError(message) + + + +class _Inliner: + @others + +def __init__(self, project, resource, offset): + self.project = project + self.pyname = _get_pyname(project, resource, offset) + range_finder = worder.Worder(resource.read(), True) + self.region = range_finder.get_primary_range(offset) + self.name = range_finder.get_word_at(offset) + self.offset = offset + self.original = resource + + +def get_changes(self, *args, **kwds): + pass + + +def get_kind(self): + """Return either 'variable', 'method' or 'parameter'""" + + + +class InlineMethod(_Inliner): + @others + +def __init__(self, *args, **kwds): + super().__init__(*args, **kwds) + self.pyfunction = self.pyname.get_object() + self.pymodule = self.pyfunction.get_module() + self.resource = self.pyfunction.get_module().get_resource() + self.occurrence_finder = occurrences.create_finder( + self.project, self.name, self.pyname + ) + self.normal_generator = _DefinitionGenerator(self.project, self.pyfunction) + self._init_imports() + + +def _init_imports(self): + body = sourceutils.get_body(self.pyfunction) + body, imports = move.moving_code_with_imports(self.project, self.resource, body) + self.imports = imports + self.others_generator = _DefinitionGenerator( + self.project, self.pyfunction, body=body + ) + + +def _get_scope_range(self): + scope = self.pyfunction.get_scope() + lines = self.pymodule.lines + start_line = scope.get_start() + if self.pyfunction.decorators: + decorators = self.pyfunction.decorators + if hasattr(decorators[0], "lineno"): + start_line = decorators[0].lineno + start_offset = lines.get_line_start(start_line) + end_offset = min( + lines.get_line_end(scope.end) + 1, len(self.pymodule.source_code) + ) + return (start_offset, end_offset) + + +def get_changes( + self, + remove=True, + only_current=False, + resources=None, + task_handle=taskhandle.NullTaskHandle(), +): + """Get the changes this refactoring makes + + If `remove` is `False` the definition will not be removed. If + `only_current` is `True`, the the current occurrence will be + inlined, only. + """ + changes = ChangeSet("Inline method <%s>" % self.name) + if resources is None: + resources = self.project.get_python_files() + if only_current: + resources = [self.original] + if remove: + resources.append(self.resource) + job_set = task_handle.create_jobset("Collecting Changes", len(resources)) + for file in resources: + job_set.started_job(file.path) + if file == self.resource: + changes.add_change( + self._defining_file_changes( + changes, remove=remove, only_current=only_current + ) + ) + else: + aim = None + if only_current and self.original == file: + aim = self.offset + handle = _InlineFunctionCallsForModuleHandle( + self.project, file, self.others_generator, aim + ) + result = move.ModuleSkipRenamer( + self.occurrence_finder, file, handle + ).get_changed_module() + if result is not None: + result = _add_imports(self.project, result, file, self.imports) + if remove: + result = _remove_from(self.project, self.pyname, result, file) + changes.add_change(ChangeContents(file, result)) + job_set.finished_job() + return changes + + +def _add_import_to_module(project, resource, imported): + pymodule = project.get_pymodule(resource) + import_tools = importutils.ImportTools(project) + module_imports = import_tools.module_imports(pymodule) + module_name = libutils.modname(imported) + new_import = importutils.NormalImport(((module_name, None),)) + module_imports.add_import(new_import) + return change.ChangeContents(resource, module_imports.get_changed_source()) + + + +def _get_removed_range(self): + scope = self.pyfunction.get_scope() + lines = self.pymodule.lines + start, end = self._get_scope_range() + end_line = scope.get_end() + for i in range(end_line + 1, lines.length()): + if lines.get_line(i).strip() == "": + end_line = i + else: + break + end = min(lines.get_line_end(end_line) + 1, len(self.pymodule.source_code)) + return (start, end) + + +def _defining_file_changes(self, changes, remove, only_current): + start_offset, end_offset = self._get_removed_range() + aim = None + if only_current: + if self.resource == self.original: + aim = self.offset + else: + # we don't want to change any of them + aim = len(self.resource.read()) + 100 + handle = _InlineFunctionCallsForModuleHandle( + self.project, self.resource, self.normal_generator, aim_offset=aim + ) + replacement = None + if remove: + replacement = self._get_method_replacement() + result = move.ModuleSkipRenamer( + self.occurrence_finder, + self.resource, + handle, + start_offset, + end_offset, + replacement, + ).get_changed_module() + return ChangeContents(self.resource, result) + + +def _get_method_replacement(self): + if self._is_the_last_method_of_a_class(): + indents = sourceutils.get_indents( + self.pymodule.lines, self.pyfunction.get_scope().get_start() + ) + return " " * indents + "pass\n" + return "" + + +def _is_the_last_method_of_a_class(self): + pyclass = self.pyfunction.parent + if not isinstance(pyclass, pyobjects.PyClass): + return False + class_start, class_end = sourceutils.get_body_region(pyclass) + source = self.pymodule.source_code + func_start, func_end = self._get_scope_range() + return ( + source[class_start:func_start].strip() == "" + and source[func_end:class_end].strip() == "" + ) + + +def get_kind(self): + return "method" + + + +class InlineVariable(_Inliner): + @others + +def __init__(self, *args, **kwds): + super().__init__(*args, **kwds) + self.pymodule = self.pyname.get_definition_location()[0] + self.resource = self.pymodule.get_resource() + self._check_exceptional_conditions() + self._init_imports() + + +def _check_exceptional_conditions(self): + if len(self.pyname.assignments) != 1: + raise rope.base.exceptions.RefactoringError( + "Local variable should be assigned once for inlining." + ) + + +def get_changes( + self, + remove=True, + only_current=False, + resources=None, + docs=False, + task_handle=taskhandle.NullTaskHandle(), +): + if resources is None: + if rename._is_local(self.pyname): + resources = [self.resource] + else: + resources = self.project.get_python_files() + if only_current: + resources = [self.original] + if remove and self.original != self.resource: + resources.append(self.resource) + changes = ChangeSet("Inline variable <%s>" % self.name) + jobset = task_handle.create_jobset("Calculating changes", len(resources)) + + for resource in resources: + jobset.started_job(resource.path) + if resource == self.resource: + source = self._change_main_module(remove, only_current, docs) + changes.add_change(ChangeContents(self.resource, source)) + else: + result = self._change_module(resource, remove, only_current) + if result is not None: + result = _add_imports(self.project, result, resource, self.imports) + changes.add_change(ChangeContents(resource, result)) + jobset.finished_job() + return changes + + +def _change_main_module(self, remove, only_current, docs): + region = None + if only_current and self.original == self.resource: + region = self.region + return _inline_variable( + self.project, + self.pymodule, + self.pyname, + self.name, + remove=remove, + region=region, + docs=docs, + ) + + +def _add_relative_import_to_module(project, resource, imported, name): + pymodule = project.get_pymodule(resource) + import_tools = importutils.ImportTools(project) + module_imports = import_tools.module_imports(pymodule) + new_import = import_tools.get_from_import(imported, name) + module_imports.add_import(new_import) + return change.ChangeContents(resource, module_imports.get_changed_source()) + + + +def _init_imports(self): + vardef = _getvardef(self.pymodule, self.pyname) + self.imported, self.imports = move.moving_code_with_imports( + self.project, self.resource, vardef + ) + + +def _change_module(self, resource, remove, only_current): + filters = [occurrences.NoImportsFilter(), occurrences.PyNameFilter(self.pyname)] + if only_current and resource == self.original: + + @others + filters.insert(0, check_aim) + finder = occurrences.Finder(self.project, self.name, filters=filters) + changed = rename.rename_in_module( + finder, self.imported, resource=resource, replace_primary=True + ) + if changed and remove: + changed = _remove_from(self.project, self.pyname, changed, resource) + return changed + + +def check_aim(occurrence): + start, end = occurrence.get_primary_range() + if self.offset < start or end < self.offset: + return False + + +def get_kind(self): + return "variable" + + + +class InlineParameter(_Inliner): + @others + +def __init__(self, *args, **kwds): + super().__init__(*args, **kwds) + resource, offset = self._function_location() + index = self.pyname.index + self.changers = [change_signature.ArgumentDefaultInliner(index)] + self.signature = change_signature.ChangeSignature( + self.project, resource, offset + ) + + +def _function_location(self): + pymodule, lineno = self.pyname.get_definition_location() + resource = pymodule.get_resource() + start = pymodule.lines.get_line_start(lineno) + word_finder = worder.Worder(pymodule.source_code) + offset = word_finder.find_function_offset(start) + return resource, offset + + +def get_changes(self, **kwds): + """Get the changes needed by this refactoring + + See `rope.refactor.change_signature.ChangeSignature.get_changes()` + for arguments. + """ + return self.signature.get_changes(self.changers, **kwds) + + +def get_kind(self): + return "parameter" + + + +def _join_lines(lines: List[str]) -> str: + return "\n".join(lines) + + +class _ComplexExpressionVisitor: + def __init__(self): + self.is_complex_expression = False + + def _Set(self, node): + self.is_complex_expression = True + + def _List(self, node): + self.is_complex_expression = True + + def _Tuple(self, node): + self.is_complex_expression = True + + def _Dict(self, node): + self.is_complex_expression = True + + + +class _GenerationInfo: + @others + +class _DefinitionGenerator: + unique_prefix = unique_prefix() + + @others + +def __init__(self, project, pyfunction, body=None): + self.project = project + self.pyfunction = pyfunction + self.pymodule = pyfunction.get_module() + self.resource = self.pymodule.get_resource() + self.definition_info = self._get_definition_info() + self.definition_params = self._get_definition_params() + self._calculated_definitions = {} + if body is not None: + self.body = body + else: + self.body = sourceutils.get_body(self.pyfunction) + + +def _get_definition_info(self): + return rope.refactor.functionutils.DefinitionInfo.read(self.pyfunction) + + +def _get_definition_params(self): + definition_info = self.definition_info + paramdict = dict([pair for pair in definition_info.args_with_defaults]) + if ( + definition_info.args_arg is not None + or definition_info.keywords_arg is not None + ): + raise rope.base.exceptions.RefactoringError( + "Cannot inline functions with list and keyword arguements." + ) + if self.pyfunction.get_kind() == "classmethod": + paramdict[ + definition_info.args_with_defaults[0][0] + ] = self.pyfunction.parent.get_name() + return paramdict + + +def get_function_name(self): + return self.pyfunction.get_name() + + +def get_definition(self, primary, pyname, call, host_vars=[], returns=False): + # caching already calculated definitions + return self._calculate_definition(primary, pyname, call, host_vars, returns) + + +def _calculate_header(self, primary, pyname, call): + # A header is created which initializes parameters + # to the values passed to the function. + call_info = rope.refactor.functionutils.CallInfo.read( + primary, pyname, self.definition_info, call + ) + paramdict = self.definition_params + mapping = rope.refactor.functionutils.ArgumentMapping( + self.definition_info, call_info + ) + for param_name, value in mapping.param_dict.items(): + paramdict[param_name] = value + header = "" + to_be_inlined = [] + for name, value in paramdict.items(): + if name != value and value is not None: + header += name + " = " + value.replace("\n", " ") + "\n" + to_be_inlined.append(name) + return header, to_be_inlined + + +def _calculate_definition(self, primary, pyname, call, host_vars, returns): + + header, to_be_inlined = self._calculate_header(primary, pyname, call) + + source = header + self.body + mod = libutils.get_string_module(self.project, source) + name_dict = mod.get_scope().get_names() + all_names = [ + x + for x in name_dict + if not isinstance(name_dict[x], rope.base.builtins.BuiltinName) + ] + + # If there is a name conflict, all variable names + # inside the inlined function are renamed + if len(set(all_names).intersection(set(host_vars))) > 0: + + prefix = next(_DefinitionGenerator.unique_prefix) + guest = libutils.get_string_module(self.project, source, self.resource) + + to_be_inlined = [prefix + item for item in to_be_inlined] + for item in all_names: + pyname = guest[item] + occurrence_finder = occurrences.create_finder( + self.project, item, pyname + ) + source = rename.rename_in_module( + occurrence_finder, prefix + item, pymodule=guest + ) + guest = libutils.get_string_module(self.project, source, self.resource) + + # parameters not reassigned inside the functions are now inlined. + for name in to_be_inlined: + pymodule = libutils.get_string_module(self.project, source, self.resource) + pyname = pymodule[name] + source = _inline_variable(self.project, pymodule, pyname, name) + + return self._replace_returns_with(source, returns) + + +def _replace_returns_with(self, source, returns): + result = [] + returned = None + last_changed = 0 + for match in _DefinitionGenerator._get_return_pattern().finditer(source): + for key, value in match.groupdict().items(): + if value and key == "return": + result.append(source[last_changed : match.start("return")]) + if returns: + self._check_nothing_after_return(source, match.end("return")) + beg_idx = match.end("return") + returned = _join_lines( + source[beg_idx : len(source)].lstrip().splitlines(), + ) + last_changed = len(source) + else: + current = match.end("return") + while current < len(source) and source[current] in " \t": + current += 1 + last_changed = current + if current == len(source) or source[current] == "\n": + result.append("pass") + result.append(source[last_changed:]) + return "".join(result), returned + + +def _check_nothing_after_return(self, source, offset): + lines = codeanalyze.SourceLinesAdapter(source) + lineno = lines.get_line_number(offset) + logical_lines = codeanalyze.LogicalLineFinder(lines) + lineno = logical_lines.logical_line_in(lineno)[1] + if source[lines.get_line_end(lineno) : len(source)].strip() != "": + raise rope.base.exceptions.RefactoringError( + "Cannot inline functions with statements " + "after return statement." + ) + + +def __init__(self, pycore, resource, offset, goal_resource=None): + self.pycore = pycore + self.resource = resource + self.offset = offset + self.goal_resource = goal_resource + self.source_pymodule = self.pycore.project.get_pymodule(resource) + finder = rope.base.evaluate.ScopeNameFinder(self.source_pymodule) + self.primary, self.pyname = finder.get_primary_and_pyname_at(offset) + self._init_fields() + + +@classmethod +def _get_return_pattern(cls): + if not hasattr(cls, "_return_pattern"): + + @others + comment_pattern = named_pattern("comment", [r"#[^\n]*"]) + string_pattern = named_pattern("string", [codeanalyze.get_string_pattern()]) + return_pattern = r"\b(?P<return>return)\b" + cls._return_pattern = re.compile( + comment_pattern + "|" + string_pattern + "|" + return_pattern + ) + return cls._return_pattern + + + +def named_pattern(name, list_): + return "(?P<%s>" % name + "|".join(list_) + ")" + + +class _InlineFunctionCallsForModuleHandle: + @others + +def __init__(self, project, resource, definition_generator, aim_offset=None): + """Inlines occurrences + + If `aim` is not `None` only the occurrences that intersect + `aim` offset will be inlined. + + """ + self.project = project + self.generator = definition_generator + self.resource = resource + self.aim = aim_offset + + +def occurred_inside_skip(self, change_collector, occurrence): + if not occurrence.is_defined(): + raise rope.base.exceptions.RefactoringError( + "Cannot inline functions that reference themselves" + ) + + +def occurred_outside_skip(self, change_collector, occurrence): + start, end = occurrence.get_primary_range() + # we remove out of date imports later + if occurrence.is_in_import_statement(): + return + # the function is referenced outside an import statement + if not occurrence.is_called(): + raise rope.base.exceptions.RefactoringError( + "Reference to inlining function other than function call" + " in <file: %s, offset: %d>" % (self.resource.path, start) + ) + if self.aim is not None and (self.aim < start or self.aim > end): + return + end_parens = self._find_end_parens(self.source, end - 1) + lineno = self.lines.get_line_number(start) + start_line, end_line = self.pymodule.logical_lines.logical_line_in(lineno) + line_start = self.lines.get_line_start(start_line) + line_end = self.lines.get_line_end(end_line) + + returns = ( + self.source[line_start:start].strip() != "" + or self.source[end_parens:line_end].strip() != "" + ) + indents = sourceutils.get_indents(self.lines, start_line) + primary, pyname = occurrence.get_primary_and_pyname() + + host = self.pymodule + scope = host.scope.get_inner_scope_for_line(lineno) + definition, returned = self.generator.get_definition( + primary, + pyname, + self.source[start:end_parens], + scope.get_names(), + returns=returns, + ) + + end = min(line_end + 1, len(self.source)) + change_collector.add_change( + line_start, end, sourceutils.fix_indentation(definition, indents) + ) + if returns: + name = returned + if name is None: + name = "None" + change_collector.add_change( + line_end, + end, + self.source[line_start:start] + name + self.source[end_parens:end], + ) + + +def _find_end_parens(self, source, offset): + finder = worder.Worder(source) + return finder.get_word_parens_range(offset)[1] + + +@property +@utils.saveit +def pymodule(self): + return self.project.get_pymodule(self.resource) + + +@property +@utils.saveit +def source(self): + if self.resource is not None: + return self.resource.read() + else: + return self.pymodule.source_code + + +@property +@utils.saveit +def lines(self): + return self.pymodule.lines + + + +def _init_fields(self): + self.source_scope = self._get_source_scope() + self.goal_scope = self._get_goal_scope() + self.goal_pymodule = self._get_goal_module(self.goal_scope) + + +def _inline_variable( + project, pymodule, pyname, name, remove=True, region=None, docs=False +): + definition = _getvardef(pymodule, pyname) + start, end = _assigned_lineno(pymodule, pyname) + + occurrence_finder = occurrences.create_finder(project, name, pyname, docs=docs) + changed_source = rename.rename_in_module( + occurrence_finder, + definition, + pymodule=pymodule, + replace_primary=True, + writes=False, + region=region, + ) + if changed_source is None: + changed_source = pymodule.source_code + if remove: + lines = codeanalyze.SourceLinesAdapter(changed_source) + source = ( + changed_source[: lines.get_line_start(start)] + + changed_source[lines.get_line_end(end) + 1 :] + ) + else: + source = changed_source + return source + + + +def _getvardef(pymodule, pyname): + assignment = pyname.assignments[0] + lines = pymodule.lines + start, end = _assigned_lineno(pymodule, pyname) + definition_with_assignment = _join_lines( + [lines.get_line(n) for n in range(start, end + 1)], + ) + if assignment.levels: + raise rope.base.exceptions.RefactoringError("Cannot inline tuple assignments.") + definition = definition_with_assignment[ + definition_with_assignment.index("=") + 1 : + ].strip() + return definition + + + +def _assigned_lineno(pymodule, pyname): + definition_line = pyname.assignments[0].ast_node.lineno + return pymodule.logical_lines.logical_line_in(definition_line) + + + +def _add_imports(project, source, resource, imports): + if not imports: + return source + pymodule = libutils.get_string_module(project, source, resource) + module_import = importutils.get_module_imports(project, pymodule) + for import_info in imports: + module_import.add_import(import_info) + source = module_import.get_changed_source() + pymodule = libutils.get_string_module(project, source, resource) + import_tools = importutils.ImportTools(project) + return import_tools.organize_imports(pymodule, unused=False, sort=False) + + + +def _get_pyname(project, resource, offset): + pymodule = project.get_pymodule(resource) + pyname = evaluate.eval_location(pymodule, offset) + if isinstance(pyname, pynames.ImportedName): + pyname = pyname._get_imported_pyname() + return pyname + + + +def _remove_from(project, pyname, source, resource): + pymodule = libutils.get_string_module(project, source, resource) + module_import = importutils.get_module_imports(project, pymodule) + module_import.remove_pyname(pyname) + return module_import.get_changed_source() + +@path C:/Repos/ekr-rope/rope/refactor/ +import rope.base.exceptions +import rope.base.pyobjects +from rope.base import libutils +from rope.base import taskhandle, evaluate +from rope.base.change import ChangeSet, ChangeContents +from rope.refactor import rename, occurrences, sourceutils, importutils + + +@others +IntroduceFactoryRefactoring = IntroduceFactory +@language python +@tabwidth -4 + +class IntroduceFactory: + @others + +def __init__(self, project, resource, offset): + self.project = project + self.offset = offset + + this_pymodule = self.project.get_pymodule(resource) + self.old_pyname = evaluate.eval_location(this_pymodule, offset) + if self.old_pyname is None or not isinstance( + self.old_pyname.get_object(), rope.base.pyobjects.PyClass + ): + raise rope.base.exceptions.RefactoringError( + "Introduce factory should be performed on a class." + ) + self.old_name = self.old_pyname.get_object().get_name() + self.pymodule = self.old_pyname.get_object().get_module() + self.resource = self.pymodule.get_resource() + + +def get_changes( + self, + factory_name, + global_factory=False, + resources=None, + task_handle=taskhandle.NullTaskHandle(), +): + """Get the changes this refactoring makes + + `factory_name` indicates the name of the factory function to + be added. If `global_factory` is `True` the factory will be + global otherwise a static method is added to the class. + + `resources` can be a list of `rope.base.resource.File` that + this refactoring should be applied on; if `None` all python + files in the project are searched. + + """ + if resources is None: + resources = self.project.get_python_files() + changes = ChangeSet("Introduce factory method <%s>" % factory_name) + job_set = task_handle.create_jobset("Collecting Changes", len(resources)) + self._change_module(resources, changes, factory_name, global_factory, job_set) + return changes + + +def _get_goal_scope(self): + if self.primary is None: + if self.goal_resource: + return self.pycore.project.get_pymodule(self.goal_resource).get_scope() + else: + return self._get_source_scope() + pyobject = self.primary.get_object() + if isinstance(pyobject, pyobjects.PyDefinedObject): + return pyobject.get_scope() + elif isinstance(pyobject.get_type(), pyobjects.PyClass): + return pyobject.get_type().get_scope() + + +def get_name(self): + """Return the name of the class""" + return self.old_name + + +def _change_module(self, resources, changes, factory_name, global_, job_set): + if global_: + replacement = "__rope_factory_%s_" % factory_name + else: + replacement = self._new_function_name(factory_name, global_) + + for file_ in resources: + job_set.started_job(file_.path) + if file_ == self.resource: + self._change_resource(changes, factory_name, global_) + job_set.finished_job() + continue + changed_code = self._rename_occurrences(file_, replacement, global_) + if changed_code is not None: + if global_: + new_pymodule = libutils.get_string_module( + self.project, changed_code, self.resource + ) + modname = libutils.modname(self.resource) + changed_code, imported = importutils.add_import( + self.project, new_pymodule, modname, factory_name + ) + changed_code = changed_code.replace(replacement, imported) + changes.add_change(ChangeContents(file_, changed_code)) + job_set.finished_job() + + +def _change_resource(self, changes, factory_name, global_): + class_scope = self.old_pyname.get_object().get_scope() + source_code = self._rename_occurrences( + self.resource, self._new_function_name(factory_name, global_), global_ + ) + if source_code is None: + source_code = self.pymodule.source_code + else: + self.pymodule = libutils.get_string_module( + self.project, source_code, resource=self.resource + ) + lines = self.pymodule.lines + start = self._get_insertion_offset(class_scope, lines) + result = source_code[:start] + result += self._get_factory_method(lines, class_scope, factory_name, global_) + result += source_code[start:] + changes.add_change(ChangeContents(self.resource, result)) + + +def _get_insertion_offset(self, class_scope, lines): + start_line = class_scope.get_end() + if class_scope.get_scopes(): + start_line = class_scope.get_scopes()[-1].get_end() + start = lines.get_line_end(start_line) + 1 + return start + + +def _get_factory_method(self, lines, class_scope, factory_name, global_): + unit_indents = " " * sourceutils.get_indent(self.project) + if global_: + if self._get_scope_indents(lines, class_scope) > 0: + raise rope.base.exceptions.RefactoringError( + "Cannot make global factory method for nested classes." + ) + return "\ndef {}(*args, **kwds):\n{}return {}(*args, **kwds)\n".format( + factory_name, + unit_indents, + self.old_name, + ) + unindented_factory = ( + "@staticmethod\ndef %s(*args, **kwds):\n" % factory_name + + "{}return {}(*args, **kwds)\n".format(unit_indents, self.old_name) + ) + indents = self._get_scope_indents(lines, class_scope) + sourceutils.get_indent( + self.project + ) + return "\n" + sourceutils.indent_lines(unindented_factory, indents) + + +def _get_scope_indents(self, lines, scope): + return sourceutils.get_indents(lines, scope.get_start()) + + +def _new_function_name(self, factory_name, global_): + if global_: + return factory_name + else: + return self.old_name + "." + factory_name + + +def _rename_occurrences(self, file_, changed_name, global_factory): + finder = occurrences.create_finder( + self.project, self.old_name, self.old_pyname, only_calls=True + ) + return rename.rename_in_module( + finder, changed_name, resource=file_, replace_primary=global_factory + ) + + + +@path C:/Repos/ekr-rope/rope/refactor/ +import rope.base.change +from rope.base import exceptions, evaluate, worder, codeanalyze +from rope.refactor import functionutils, sourceutils, occurrences + + +@others +@language python +@tabwidth -4 + +class IntroduceParameter: + """Introduce parameter refactoring + + This refactoring adds a new parameter to a function and replaces + references to an expression in it with the new parameter. + + The parameter finding part is different from finding similar + pieces in extract refactorings. In this refactoring parameters + are found based on the object they reference to. For instance + in:: + + class A(object): + var = None + + class B(object): + a = A() + + b = B() + a = b.a + + def f(a): + x = b.a.var + a.var + + using this refactoring on ``a.var`` with ``p`` as the new + parameter name, will result in:: + + def f(p=a.var): + x = p + p + + """ + + @others + +def _get_goal_module(self, scope): + if scope is None: + return + while scope.parent is not None: + scope = scope.parent + return scope.pyobject + + +def __init__(self, project, resource, offset): + self.project = project + self.resource = resource + self.offset = offset + self.pymodule = self.project.get_pymodule(self.resource) + scope = self.pymodule.get_scope().get_inner_scope_for_offset(offset) + if scope.get_kind() != "Function": + raise exceptions.RefactoringError( + "Introduce parameter should be performed inside functions" + ) + self.pyfunction = scope.pyobject + self.name, self.pyname = self._get_name_and_pyname() + if self.pyname is None: + raise exceptions.RefactoringError( + "Cannot find the definition of <%s>" % self.name + ) + + +def _get_primary(self): + word_finder = worder.Worder(self.resource.read()) + return word_finder.get_primary_at(self.offset) + + +def _get_name_and_pyname(self): + return ( + worder.get_name_at(self.resource, self.offset), + evaluate.eval_location(self.pymodule, self.offset), + ) + + +def get_changes(self, new_parameter): + definition_info = functionutils.DefinitionInfo.read(self.pyfunction) + definition_info.args_with_defaults.append((new_parameter, self._get_primary())) + collector = codeanalyze.ChangeCollector(self.resource.read()) + header_start, header_end = self._get_header_offsets() + body_start, body_end = sourceutils.get_body_region(self.pyfunction) + collector.add_change(header_start, header_end, definition_info.to_string()) + self._change_function_occurrences( + collector, body_start, body_end, new_parameter + ) + changes = rope.base.change.ChangeSet("Introduce parameter <%s>" % new_parameter) + change = rope.base.change.ChangeContents(self.resource, collector.get_changed()) + changes.add_change(change) + return changes + + +def _get_header_offsets(self): + lines = self.pymodule.lines + start_line = self.pyfunction.get_scope().get_start() + end_line = self.pymodule.logical_lines.logical_line_in(start_line)[1] + start = lines.get_line_start(start_line) + end = lines.get_line_end(end_line) + start = self.pymodule.source_code.find("def", start) + 4 + end = self.pymodule.source_code.rfind(":", start, end) + return start, end + + +def _change_function_occurrences( + self, collector, function_start, function_end, new_name +): + finder = occurrences.create_finder(self.project, self.name, self.pyname) + for occurrence in finder.find_occurrences(resource=self.resource): + start, end = occurrence.get_primary_range() + if function_start <= start < function_end: + collector.add_change(start, end, new_name) + +@path C:/Repos/ekr-rope/rope/refactor/ +from rope.base import pynames, evaluate, exceptions, worder +from rope.refactor.rename import Rename + + +@others +@language python +@tabwidth -4 + +class LocalToField: + @others + +def __init__(self, project, resource, offset): + self.project = project + self.resource = resource + self.offset = offset + + +def get_changes(self): + name = worder.get_name_at(self.resource, self.offset) + this_pymodule = self.project.get_pymodule(self.resource) + pyname = evaluate.eval_location(this_pymodule, self.offset) + if not self._is_a_method_local(pyname): + raise exceptions.RefactoringError( + "Convert local variable to field should be performed on \n" + "a local variable of a method." + ) + + pymodule, lineno = pyname.get_definition_location() + function_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) + # Not checking redefinition + # self._check_redefinition(name, function_scope) + + new_name = self._get_field_name(function_scope.pyobject, name) + changes = Rename(self.project, self.resource, self.offset).get_changes( + new_name, resources=[self.resource] + ) + return changes + + +def pyname_at(self, offset): + pymodule = self.get_pymodule() + + def old_pyname(): + word_finder = worder.Worder(self.code, True) + expression = word_finder.get_primary_at(offset) + expression = expression.replace("\\\n", " ").replace("\n", " ") + lineno = self.code.count("\n", 0, offset) + scope = pymodule.get_scope().get_inner_scope_for_line(lineno) + return rope.base.evaluate.eval_str(scope, expression) + + new_code = pymodule.source_code + + def new_pyname(): + newoffset = self.commenter.transfered_offset(offset) + return rope.base.evaluate.eval_location(pymodule, newoffset) + + if new_code.startswith(self.code[: offset + 1]): + return new_pyname() + result = old_pyname() + if result is None: + return new_pyname() + return result + + + +def _get_source_scope(self): + module_scope = self.source_pymodule.get_scope() + lineno = self.source_pymodule.lines.get_line_number(self.offset) + return module_scope.get_inner_scope_for_line(lineno) + + +def _check_redefinition(self, name, function_scope): + class_scope = function_scope.parent + if name in class_scope.pyobject: + raise exceptions.RefactoringError("The field %s already exists" % name) + + +def _get_field_name(self, pyfunction, name): + self_name = pyfunction.get_param_names()[0] + new_name = self_name + "." + name + return new_name + + +def _is_a_method_local(self, pyname): + pymodule, lineno = pyname.get_definition_location() + holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) + parent = holding_scope.parent + return ( + isinstance(pyname, pynames.AssignedName) + and pyname in holding_scope.get_names().values() + and holding_scope.get_kind() == "Function" + and parent is not None + and parent.get_kind() == "Class" + ) + +@path C:/Repos/ekr-rope/rope/refactor/ +import warnings + +from rope.base import libutils +from rope.base import pyobjects, exceptions, change, evaluate, codeanalyze +from rope.refactor import sourceutils, occurrences, rename + + +@others +@language python +@tabwidth -4 + +class MethodObject: + @others + +def __init__(self, project, resource, offset): + self.project = project + this_pymodule = self.project.get_pymodule(resource) + pyname = evaluate.eval_location(this_pymodule, offset) + if pyname is None or not isinstance(pyname.get_object(), pyobjects.PyFunction): + raise exceptions.RefactoringError( + "Replace method with method object refactoring should be " + "performed on a function." + ) + self.pyfunction = pyname.get_object() + self.pymodule = self.pyfunction.get_module() + self.resource = self.pymodule.get_resource() + + +def get_new_class(self, name): + body = sourceutils.fix_indentation( + self._get_body(), sourceutils.get_indent(self.project) * 2 + ) + return "class {}(object):\n\n{}{}def __call__(self):\n{}".format( + name, + self._get_init(), + " " * sourceutils.get_indent(self.project), + body, + ) + + +def get_changes(self, classname=None, new_class_name=None): + if new_class_name is not None: + warnings.warn( + "new_class_name parameter is deprecated; use classname", + DeprecationWarning, + stacklevel=2, + ) + classname = new_class_name + collector = codeanalyze.ChangeCollector(self.pymodule.source_code) + start, end = sourceutils.get_body_region(self.pyfunction) + indents = sourceutils.get_indents( + self.pymodule.lines, self.pyfunction.get_scope().get_start() + ) + sourceutils.get_indent(self.project) + new_contents = " " * indents + "return {}({})()\n".format( + classname, + ", ".join(self._get_parameter_names()), + ) + collector.add_change(start, end, new_contents) + insertion = self._get_class_insertion_point() + collector.add_change( + insertion, insertion, "\n\n" + self.get_new_class(classname) + ) + changes = change.ChangeSet("Replace method with method object refactoring") + changes.add_change( + change.ChangeContents(self.resource, collector.get_changed()) + ) + return changes + + +def _get_class_insertion_point(self): + current = self.pyfunction + while current.parent != self.pymodule: + current = current.parent + end = self.pymodule.lines.get_line_end(current.get_scope().get_end()) + return min(end + 1, len(self.pymodule.source_code)) + + +def _get_body(self): + body = sourceutils.get_body(self.pyfunction) + for param in self._get_parameter_names(): + body = param + " = None\n" + body + pymod = libutils.get_string_module(self.project, body, self.resource) + pyname = pymod[param] + finder = occurrences.create_finder(self.project, param, pyname) + result = rename.rename_in_module(finder, "self." + param, pymodule=pymod) + body = result[result.index("\n") + 1 :] + return body + + +def get_insertion_lineno(self): + lines = self.goal_pymodule.lines + if self.goal_scope == self.source_scope: + line_finder = self.goal_pymodule.logical_lines + lineno = lines.get_line_number(self.offset) + lineno = line_finder.logical_line_in(lineno)[0] + root = suites.ast_suite_tree(self.goal_scope.pyobject.get_ast()) + suite = root.find_suite(lineno) + indents = sourceutils.get_indents(lines, lineno) + while self.get_scope_indents() < indents: + lineno = suite.get_start() + indents = sourceutils.get_indents(lines, lineno) + suite = suite.parent + return lineno + else: + return min(self.goal_scope.get_end() + 1, lines.length()) + + +def _get_init(self): + params = self._get_parameter_names() + indents = " " * sourceutils.get_indent(self.project) + if not params: + return "" + header = indents + "def __init__(self" + body = "" + for arg in params: + new_name = arg + if arg == "self": + new_name = "host" + header += ", %s" % new_name + body += indents * 2 + "self.{} = {}\n".format(arg, new_name) + header += "):" + return "{}\n{}\n".format(header, body) + + +def _get_parameter_names(self): + return self.pyfunction.get_param_names() + +@path C:/Repos/ekr-rope/rope/refactor/ +"""A module containing classes for move refactoring + +`create_move()` is a factory for creating move refactoring objects +based on inputs. + +""" +from rope.base import ( + pyobjects, + codeanalyze, + exceptions, + pynames, + taskhandle, + evaluate, + worder, + libutils, +) +from rope.base.change import ChangeSet, ChangeContents, MoveResource +from rope.refactor import importutils, rename, occurrences, sourceutils, functionutils +from rope.refactor.importutils.module_imports import ( + get_first_decorator_or_function_start_line, +) + + +@others +@language python +@tabwidth -4 + +def create_move(project, resource, offset=None): + """A factory for creating Move objects + + Based on `resource` and `offset`, return one of `MoveModule`, + `MoveGlobal` or `MoveMethod` for performing move refactoring. + + """ + if offset is None: + return MoveModule(project, resource) + this_pymodule = project.get_pymodule(resource) + pyname = evaluate.eval_location(this_pymodule, offset) + if pyname is not None: + pyobject = pyname.get_object() + if isinstance(pyobject, pyobjects.PyModule) or isinstance( + pyobject, pyobjects.PyPackage + ): + return MoveModule(project, pyobject.get_resource()) + if isinstance(pyobject, pyobjects.PyFunction) and isinstance( + pyobject.parent, pyobjects.PyClass + ): + return MoveMethod(project, resource, offset) + if ( + isinstance(pyobject, pyobjects.PyDefinedObject) + and isinstance(pyobject.parent, pyobjects.PyModule) + or isinstance(pyname, pynames.AssignedName) + ): + return MoveGlobal(project, resource, offset) + raise exceptions.RefactoringError( + "Move only works on global classes/functions/variables, modules and methods." + ) + + + +class MoveMethod: + """For moving methods + + It makes a new method in the destination class and changes + the body of the old method to call the new method. You can + inline the old method to change all of its occurrences. + + """ + + @others + +def __init__(self, project, resource, offset): + self.project = project + this_pymodule = self.project.get_pymodule(resource) + pyname = evaluate.eval_location(this_pymodule, offset) + self.method_name = worder.get_name_at(resource, offset) + self.pyfunction = pyname.get_object() + if self.pyfunction.get_kind() != "method": + raise exceptions.RefactoringError("Only normal methods can be moved.") + + +def get_changes( + self, + dest_attr, + new_name=None, + resources=None, + task_handle=taskhandle.NullTaskHandle(), +): + """Return the changes needed for this refactoring + + Parameters: + + - `dest_attr`: the name of the destination attribute + - `new_name`: the name of the new method; if `None` uses + the old name + - `resources` can be a list of `rope.base.resources.File` to + apply this refactoring on. If `None`, the restructuring + will be applied to all python files. + + """ + changes = ChangeSet("Moving method <%s>" % self.method_name) + if resources is None: + resources = self.project.get_python_files() + if new_name is None: + new_name = self.get_method_name() + resource1, start1, end1, new_content1 = self._get_changes_made_by_old_class( + dest_attr, new_name + ) + collector1 = codeanalyze.ChangeCollector(resource1.read()) + collector1.add_change(start1, end1, new_content1) + + resource2, start2, end2, new_content2 = self._get_changes_made_by_new_class( + dest_attr, new_name + ) + if resource1 == resource2: + collector1.add_change(start2, end2, new_content2) + else: + collector2 = codeanalyze.ChangeCollector(resource2.read()) + collector2.add_change(start2, end2, new_content2) + result = collector2.get_changed() + import_tools = importutils.ImportTools(self.project) + new_imports = self._get_used_imports(import_tools) + if new_imports: + goal_pymodule = libutils.get_string_module( + self.project, result, resource2 + ) + result = _add_imports_to_module( + import_tools, goal_pymodule, new_imports + ) + if resource2 in resources: + changes.add_change(ChangeContents(resource2, result)) + + if resource1 in resources: + changes.add_change(ChangeContents(resource1, collector1.get_changed())) + return changes + + +def get_method_name(self): + return self.method_name + + +def _get_used_imports(self, import_tools): + return importutils.get_imports(self.project, self.pyfunction) + + +def _get_changes_made_by_old_class(self, dest_attr, new_name): + pymodule = self.pyfunction.get_module() + indents = self._get_scope_indents(self.pyfunction) + body = "return self.{}.{}({})\n".format( + dest_attr, + new_name, + self._get_passed_arguments_string(), + ) + region = sourceutils.get_body_region(self.pyfunction) + return ( + pymodule.get_resource(), + region[0], + region[1], + sourceutils.fix_indentation(body, indents), + ) + + +def get_insertion_resource(self): + return self.goal_pymodule.get_resource() + + +def _get_scope_indents(self, pyobject): + pymodule = pyobject.get_module() + return sourceutils.get_indents( + pymodule.lines, pyobject.get_scope().get_start() + ) + sourceutils.get_indent(self.project) + + +def _get_changes_made_by_new_class(self, dest_attr, new_name): + old_pyclass = self.pyfunction.parent + if dest_attr not in old_pyclass: + raise exceptions.RefactoringError( + "Destination attribute <%s> not found" % dest_attr + ) + pyclass = old_pyclass[dest_attr].get_object().get_type() + if not isinstance(pyclass, pyobjects.PyClass): + raise exceptions.RefactoringError( + "Unknown class type for attribute <%s>" % dest_attr + ) + pymodule = pyclass.get_module() + resource = pyclass.get_module().get_resource() + start, end = sourceutils.get_body_region(pyclass) + pre_blanks = "\n" + if pymodule.source_code[start:end].strip() != "pass": + pre_blanks = "\n\n" + start = end + indents = self._get_scope_indents(pyclass) + body = pre_blanks + sourceutils.fix_indentation( + self.get_new_method(new_name), indents + ) + return resource, start, end, body + + +def get_new_method(self, name): + return "{}\n{}".format( + self._get_new_header(name), + sourceutils.fix_indentation( + self._get_body(), sourceutils.get_indent(self.project) + ), + ) + + +def _get_unchanged_body(self): + return sourceutils.get_body(self.pyfunction) + + +def _get_body(self, host="host"): + self_name = self._get_self_name() + body = self_name + " = None\n" + self._get_unchanged_body() + pymodule = libutils.get_string_module(self.project, body) + finder = occurrences.create_finder(self.project, self_name, pymodule[self_name]) + result = rename.rename_in_module(finder, host, pymodule=pymodule) + if result is None: + result = body + return result[result.index("\n") + 1 :] + + +def _get_self_name(self): + return self.pyfunction.get_param_names()[0] + + +def _get_new_header(self, name): + header = "def %s(self" % name + if self._is_host_used(): + header += ", host" + definition_info = functionutils.DefinitionInfo.read(self.pyfunction) + others = definition_info.arguments_to_string(1) + if others: + header += ", " + others + return header + "):" + + +def _get_passed_arguments_string(self): + result = "" + if self._is_host_used(): + result = "self" + definition_info = functionutils.DefinitionInfo.read(self.pyfunction) + others = definition_info.arguments_to_string(1) + if others: + if result: + result += ", " + result += others + return result + + +def _is_host_used(self): + return self._get_body("__old_self") != self._get_unchanged_body() + + + +class MoveGlobal: + """For moving global function and classes""" + + @others + +def get_insertion_offsets(self): + if self.goal_scope.get_kind() == "Class": + start, end = sourceutils.get_body_region(self.goal_scope.pyobject) + if self.goal_pymodule.source_code[start:end].strip() == "pass": + return start, end + lines = self.goal_pymodule.lines + start = lines.get_line_start(self.get_insertion_lineno()) + return (start, start) + + +def __init__(self, project, resource, offset): + self.project = project + this_pymodule = self.project.get_pymodule(resource) + self.old_pyname = evaluate.eval_location(this_pymodule, offset) + if self.old_pyname is None: + raise exceptions.RefactoringError( + "Move refactoring should be performed on a class/function/variable." + ) + if self._is_variable(self.old_pyname): + self.old_name = worder.get_name_at(resource, offset) + pymodule = this_pymodule + else: + self.old_name = self.old_pyname.get_object().get_name() + pymodule = self.old_pyname.get_object().get_module() + self._check_exceptional_conditions() + self.source = pymodule.get_resource() + self.tools = _MoveTools( + self.project, self.source, self.old_pyname, self.old_name + ) + self.import_tools = self.tools.import_tools + + +def _import_filter(self, stmt): + module_name = libutils.modname(self.source) + + if isinstance(stmt.import_info, importutils.NormalImport): + # Affect any statement that imports the source module + return any( + module_name == name + for name, alias in stmt.import_info.names_and_aliases + ) + elif isinstance(stmt.import_info, importutils.FromImport): + # Affect statements importing from the source package + if "." in module_name: + package_name, basename = module_name.rsplit(".", 1) + if stmt.import_info.module_name == package_name and any( + basename == name + for name, alias in stmt.import_info.names_and_aliases + ): + return True + return stmt.import_info.module_name == module_name + return False + + +def _check_exceptional_conditions(self): + if self._is_variable(self.old_pyname): + pymodule = self.old_pyname.get_definition_location()[0] + try: + pymodule.get_scope().get_name(self.old_name) + except exceptions.NameNotFoundError: + self._raise_refactoring_error() + elif not ( + isinstance(self.old_pyname.get_object(), pyobjects.PyDefinedObject) + and self._is_global(self.old_pyname.get_object()) + ): + self._raise_refactoring_error() + + +def _raise_refactoring_error(self): + raise exceptions.RefactoringError( + "Move refactoring should be performed on a global class, function " + "or variable." + ) + + +def _is_global(self, pyobject): + return pyobject.get_scope().parent == pyobject.get_module().get_scope() + + +def _is_variable(self, pyname): + return isinstance(pyname, pynames.AssignedName) + + +def get_changes( + self, dest, resources=None, task_handle=taskhandle.NullTaskHandle() +): + if resources is None: + resources = self.project.get_python_files() + if dest is None or not dest.exists(): + raise exceptions.RefactoringError("Move destination does not exist.") + if dest.is_folder() and dest.has_child("__init__.py"): + dest = dest.get_child("__init__.py") + if dest.is_folder(): + raise exceptions.RefactoringError( + "Move destination for non-modules should not be folders." + ) + if self.source == dest: + raise exceptions.RefactoringError( + "Moving global elements to the same module." + ) + return self._calculate_changes(dest, resources, task_handle) + + +def _calculate_changes(self, dest, resources, task_handle): + changes = ChangeSet("Moving global <%s>" % self.old_name) + job_set = task_handle.create_jobset("Collecting Changes", len(resources)) + for file_ in resources: + job_set.started_job(file_.path) + if file_ == self.source: + changes.add_change(self._source_module_changes(dest)) + elif file_ == dest: + changes.add_change(self._dest_module_changes(dest)) + elif self.tools.occurs_in_module(resource=file_): + pymodule = self.project.get_pymodule(file_) + # Changing occurrences + placeholder = "__rope_renaming_%s_" % self.old_name + source = self.tools.rename_in_module(placeholder, resource=file_) + should_import = source is not None + # Removing out of date imports + pymodule = self.tools.new_pymodule(pymodule, source) + source = self.import_tools.organize_imports( + pymodule, sort=False, import_filter=self._import_filter + ) + # Adding new import + if should_import: + pymodule = self.tools.new_pymodule(pymodule, source) + source, imported = importutils.add_import( + self.project, pymodule, self._new_modname(dest), self.old_name + ) + source = source.replace(placeholder, imported) + source = self.tools.new_source(pymodule, source) + if source != file_.read(): + changes.add_change(ChangeContents(file_, source)) + job_set.finished_job() + return changes + + +def _source_module_changes(self, dest): + placeholder = "__rope_moving_%s_" % self.old_name + handle = _ChangeMoveOccurrencesHandle(placeholder) + occurrence_finder = occurrences.create_finder( + self.project, self.old_name, self.old_pyname + ) + start, end = self._get_moving_region() + renamer = ModuleSkipRenamer(occurrence_finder, self.source, handle, start, end) + source = renamer.get_changed_module() + pymodule = libutils.get_string_module(self.project, source, self.source) + source = self.import_tools.organize_imports(pymodule, sort=False) + if handle.occurred: + pymodule = libutils.get_string_module(self.project, source, self.source) + # Adding new import + source, imported = importutils.add_import( + self.project, pymodule, self._new_modname(dest), self.old_name + ) + source = source.replace(placeholder, imported) + return ChangeContents(self.source, source) + + +def _new_modname(self, dest): + return libutils.modname(dest) + + +def get_scope_indents(self): + if self.goal_scope.get_kind() == "Module": + return 0 + return ( + sourceutils.get_indents( + self.goal_pymodule.lines, self.goal_scope.get_start() + ) + + 4 + ) + + +def _dest_module_changes(self, dest): + # Changing occurrences + pymodule = self.project.get_pymodule(dest) + source = self.tools.rename_in_module(self.old_name, pymodule) + pymodule = self.tools.new_pymodule(pymodule, source) + + moving, imports = self._get_moving_element_with_imports() + pymodule, has_changed = self._add_imports2(pymodule, imports) + + module_with_imports = self.import_tools.module_imports(pymodule) + source = pymodule.source_code + lineno = 0 + if module_with_imports.imports: + lineno = module_with_imports.imports[-1].end_line - 1 + else: + while lineno < pymodule.lines.length() and pymodule.lines.get_line( + lineno + 1 + ).lstrip().startswith("#"): + lineno += 1 + if lineno > 0: + cut = pymodule.lines.get_line_end(lineno) + 1 + result = source[:cut] + "\n\n" + moving + source[cut:] + else: + result = moving + source + + # Organizing imports + source = result + pymodule = libutils.get_string_module(self.project, source, dest) + source = self.import_tools.organize_imports(pymodule, sort=False, unused=False) + # Remove unused imports of the old module + pymodule = libutils.get_string_module(self.project, source, dest) + source = self.import_tools.organize_imports( + pymodule, + sort=False, + selfs=False, + unused=True, + import_filter=self._import_filter, + ) + return ChangeContents(dest, source) + + +def _get_moving_element_with_imports(self): + return moving_code_with_imports( + self.project, self.source, self._get_moving_element() + ) + + +def _get_module_with_imports(self, source_code, resource): + pymodule = libutils.get_string_module(self.project, source_code, resource) + return self.import_tools.module_imports(pymodule) + + +def _get_moving_element(self): + start, end = self._get_moving_region() + moving = self.source.read()[start:end] + return moving.rstrip() + "\n" + + +def _get_moving_region(self): + pymodule = self.project.get_pymodule(self.source) + lines = pymodule.lines + if self._is_variable(self.old_pyname): + logical_lines = pymodule.logical_lines + lineno = logical_lines.logical_line_in( + self.old_pyname.get_definition_location()[1] + )[0] + start = lines.get_line_start(lineno) + end_line = logical_lines.logical_line_in(lineno)[1] + else: + node = self.old_pyname.get_object().ast_node + start = lines.get_line_start( + get_first_decorator_or_function_start_line(node) + ) + end_line = self.old_pyname.get_object().get_scope().get_end() + + # Include comment lines before the definition + start_line = lines.get_line_number(start) + while start_line > 1 and lines.get_line(start_line - 1).startswith("#"): + start_line -= 1 + start = lines.get_line_start(start_line) + + while end_line < lines.length() and lines.get_line(end_line + 1).strip() == "": + end_line += 1 + end = min(lines.get_line_end(end_line) + 1, len(pymodule.source_code)) + return start, end + + +def _add_imports2(self, pymodule, new_imports): + source = self.tools.add_imports(pymodule, new_imports) + if source is None: + return pymodule, False + else: + resource = pymodule.get_resource() + pymodule = libutils.get_string_module(self.project, source, resource) + return pymodule, True + + + +class MoveModule: + """For moving modules and packages""" + + @others + +def __init__(self, project, resource): + self.project = project + if not resource.is_folder() and resource.name == "__init__.py": + resource = resource.parent + if resource.is_folder() and not resource.has_child("__init__.py"): + raise exceptions.RefactoringError("Cannot move non-package folder.") + dummy_pymodule = libutils.get_string_module(self.project, "") + self.old_pyname = pynames.ImportedModule(dummy_pymodule, resource=resource) + self.source = self.old_pyname.get_object().get_resource() + if self.source.is_folder(): + self.old_name = self.source.name + else: + self.old_name = self.source.name[:-3] + self.tools = _MoveTools( + self.project, self.source, self.old_pyname, self.old_name + ) + self.import_tools = self.tools.import_tools + + +def get_changes( + self, dest, resources=None, task_handle=taskhandle.NullTaskHandle() +): + if resources is None: + resources = self.project.get_python_files() + if dest is None or not dest.is_folder(): + raise exceptions.RefactoringError( + "Move destination for modules should be packages." + ) + return self._calculate_changes(dest, resources, task_handle) + + +def _calculate_changes(self, dest, resources, task_handle): + changes = ChangeSet("Moving module <%s>" % self.old_name) + job_set = task_handle.create_jobset("Collecting changes", len(resources)) + for module in resources: + job_set.started_job(module.path) + if module == self.source: + self._change_moving_module(changes, dest) + else: + source = self._change_occurrences_in_module(dest, resource=module) + if source is not None: + changes.add_change(ChangeContents(module, source)) + job_set.finished_job() + if self.project == self.source.project: + changes.add_change(MoveResource(self.source, dest.path)) + return changes + + +def get_blank_lines(self): + if self.goal_scope.get_kind() == "Module": + base_blanks = 2 + if self.goal_pymodule.source_code.strip() == "": + base_blanks = 0 + if self.goal_scope.get_kind() == "Class": + base_blanks = 1 + if self.goal_scope.get_kind() == "Function": + base_blanks = 0 + if self.goal_scope == self.source_scope: + return (0, base_blanks) + return (base_blanks, 0) + + +def _new_modname(self, dest): + destname = libutils.modname(dest) + if destname: + return destname + "." + self.old_name + return self.old_name + + +def _new_import(self, dest): + return importutils.NormalImport([(self._new_modname(dest), None)]) + + +def _change_moving_module(self, changes, dest): + if not self.source.is_folder(): + pymodule = self.project.get_pymodule(self.source) + source = self.import_tools.relatives_to_absolutes(pymodule) + pymodule = self.tools.new_pymodule(pymodule, source) + source = self._change_occurrences_in_module(dest, pymodule) + source = self.tools.new_source(pymodule, source) + if source != self.source.read(): + changes.add_change(ChangeContents(self.source, source)) + + +def _change_occurrences_in_module(self, dest, pymodule=None, resource=None): + if not self.tools.occurs_in_module(pymodule=pymodule, resource=resource): + return + if pymodule is None: + pymodule = self.project.get_pymodule(resource) + new_name = self._new_modname(dest) + module_imports = importutils.get_module_imports(self.project, pymodule) + changed = False + source = None + if libutils.modname(dest): + changed = self._change_import_statements(dest, new_name, module_imports) + if changed: + source = module_imports.get_changed_source() + source = self.tools.new_source(pymodule, source) + pymodule = self.tools.new_pymodule(pymodule, source) + + new_import = self._new_import(dest) + source = self.tools.rename_in_module( + new_name, + imports=True, + pymodule=pymodule, + resource=resource if not changed else None, + ) + should_import = self.tools.occurs_in_module( + pymodule=pymodule, resource=resource, imports=False + ) + pymodule = self.tools.new_pymodule(pymodule, source) + source = self.tools.remove_old_imports(pymodule) + if should_import: + pymodule = self.tools.new_pymodule(pymodule, source) + source = self.tools.add_imports(pymodule, [new_import]) + source = self.tools.new_source(pymodule, source) + if source is not None and source != pymodule.resource.read(): + return source + return None + + +def _change_import_statements(self, dest, new_name, module_imports): + moving_module = self.source + parent_module = moving_module.parent + + changed = False + for import_stmt in module_imports.imports: + if not any( + name_and_alias[0] == self.old_name + for name_and_alias in import_stmt.import_info.names_and_aliases + ) and not any( + name_and_alias[0] == libutils.modname(self.source) + for name_and_alias in import_stmt.import_info.names_and_aliases + ): + continue + + # Case 1: Look for normal imports of the moving module. + if isinstance(import_stmt.import_info, importutils.NormalImport): + continue + + # Case 2: The moving module is from-imported. + changed = ( + self._handle_moving_in_from_import_stmt( + dest, import_stmt, module_imports, parent_module + ) + or changed + ) + + # Case 3: Names are imported from the moving module. + context = importutils.importinfo.ImportContext(self.project, None) + if ( + not import_stmt.import_info.is_empty() + and import_stmt.import_info.get_imported_resource(context) + == moving_module + ): + import_stmt.import_info = importutils.FromImport( + new_name, + import_stmt.import_info.level, + import_stmt.import_info.names_and_aliases, + ) + changed = True + + return changed + + +def _handle_moving_in_from_import_stmt( + self, dest, import_stmt, module_imports, parent_module +): + changed = False + context = importutils.importinfo.ImportContext(self.project, None) + if import_stmt.import_info.get_imported_resource(context) == parent_module: + imports = import_stmt.import_info.names_and_aliases + new_imports = [] + for name, alias in imports: + # The moving module was imported. + if name == self.old_name: + changed = True + new_import = importutils.FromImport( + libutils.modname(dest), 0, [(self.old_name, alias)] + ) + module_imports.add_import(new_import) + else: + new_imports.append((name, alias)) + + # Update the imports if the imported names were changed. + if new_imports != imports: + changed = True + if new_imports: + import_stmt.import_info = importutils.FromImport( + import_stmt.import_info.module_name, + import_stmt.import_info.level, + new_imports, + ) + else: + import_stmt.empty_import() + return changed + + + +class _ChangeMoveOccurrencesHandle: + @others + +def __init__(self, new_name): + self.new_name = new_name + self.occurred = False + + +def occurred_inside_skip(self, change_collector, occurrence): + pass + + +def occurred_outside_skip(self, change_collector, occurrence): + start, end = occurrence.get_primary_range() + change_collector.add_change(start, end, self.new_name) + self.occurred = True + + + +def get_package(self): + primary = self.primary + if self.primary is None: + return self.pycore.project.get_source_folders()[0] + if isinstance(primary.get_object(), pyobjects.PyPackage): + return primary.get_object().get_resource() + raise exceptions.RefactoringError( + "A module/package can be only created in a package." + ) + + +class _MoveTools: + @others + +def __init__(self, project, source, pyname, old_name): + self.project = project + self.source = source + self.old_pyname = pyname + self.old_name = old_name + self.import_tools = importutils.ImportTools(self.project) + + +def remove_old_imports(self, pymodule): + old_source = pymodule.source_code + module_with_imports = self.import_tools.module_imports(pymodule) + + class CanSelect: + changed = False + old_name = self.old_name + old_pyname = self.old_pyname + + @others + can_select = CanSelect() + module_with_imports.filter_names(can_select) + new_source = module_with_imports.get_changed_source() + if old_source != new_source: + return new_source + + +def __call__(self, name): + try: + if ( + name == self.old_name + and pymodule[name].get_object() == self.old_pyname.get_object() + ): + self.changed = True + return False + except exceptions.AttributeNotFoundError: + pass + return True + + +def rename_in_module(self, new_name, pymodule=None, imports=False, resource=None): + occurrence_finder = self._create_finder(imports) + source = rename.rename_in_module( + occurrence_finder, + new_name, + replace_primary=True, + pymodule=pymodule, + resource=resource, + ) + return source + + +def occurs_in_module(self, pymodule=None, resource=None, imports=True): + finder = self._create_finder(imports) + for occurrence in finder.find_occurrences(pymodule=pymodule, resource=resource): + return True + return False + + +def _create_finder(self, imports): + return occurrences.create_finder( + self.project, + self.old_name, + self.old_pyname, + imports=imports, + keywords=False, + ) + + +def new_pymodule(self, pymodule, source): + if source is not None: + return libutils.get_string_module( + self.project, source, pymodule.get_resource() + ) + return pymodule + + +def new_source(self, pymodule, source): + if source is None: + return pymodule.source_code + return source + + +def add_imports(self, pymodule, new_imports): + return _add_imports_to_module(self.import_tools, pymodule, new_imports) + + + +def primary_is_found(self): + return self.goal_scope is not None + + +def _add_imports_to_module(import_tools, pymodule, new_imports): + module_with_imports = import_tools.module_imports(pymodule) + for new_import in new_imports: + module_with_imports.add_import(new_import) + return module_with_imports.get_changed_source() + + + +def moving_code_with_imports(project, resource, source): + import_tools = importutils.ImportTools(project) + pymodule = libutils.get_string_module(project, source, resource) + + # Strip comment prefix, if any. These need to stay before the moving + # section, but imports would be added between them. + lines = codeanalyze.SourceLinesAdapter(source) + start = 1 + while start < lines.length() and lines.get_line(start).startswith("#"): + start += 1 + moving_prefix = source[: lines.get_line_start(start)] + pymodule = libutils.get_string_module( + project, source[lines.get_line_start(start) :], resource + ) + + origin = project.get_pymodule(resource) + + imports = [stmt.import_info for stmt in import_tools.module_imports(origin).imports] + + back_names = [name for name in origin if name not in pymodule] + imports.append(import_tools.get_from_import(resource, back_names)) + + source = _add_imports_to_module(import_tools, pymodule, imports) + pymodule = libutils.get_string_module(project, source, resource) + + source = import_tools.relatives_to_absolutes(pymodule) + pymodule = libutils.get_string_module(project, source, resource) + source = import_tools.organize_imports(pymodule, selfs=False) + pymodule = libutils.get_string_module(project, source, resource) + + # extracting imports after changes + module_imports = import_tools.module_imports(pymodule) + imports = [import_stmt.import_info for import_stmt in module_imports.imports] + start = 1 + if module_imports.imports: + start = module_imports.imports[-1].end_line + lines = codeanalyze.SourceLinesAdapter(source) + while start < lines.length() and not lines.get_line(start).strip(): + start += 1 + + # Reinsert the prefix which was removed at the beginning + moving = moving_prefix + source[lines.get_line_start(start) :] + return moving, imports + + + +class ModuleSkipRenamerHandle: + def occurred_outside_skip(self, change_collector, occurrence): + pass + + def occurred_inside_skip(self, change_collector, occurrence): + pass + + + +class ModuleSkipRenamer: + """Rename occurrences in a module + + This class can be used when you want to treat a region in a file + separately from other parts when renaming. + + """ + + @others + +def __init__( + self, + occurrence_finder, + resource, + handle=None, + skip_start=0, + skip_end=0, + replacement="", +): + """Constructor + + if replacement is `None` the region is not changed. Otherwise + it is replaced with `replacement`. + + """ + self.occurrence_finder = occurrence_finder + self.resource = resource + self.skip_start = skip_start + self.skip_end = skip_end + self.replacement = replacement + self.handle = handle + if self.handle is None: + self.handle = ModuleSkipRenamerHandle() + + +def get_changed_module(self): + source = self.resource.read() + change_collector = codeanalyze.ChangeCollector(source) + if self.replacement is not None: + change_collector.add_change( + self.skip_start, self.skip_end, self.replacement + ) + for occurrence in self.occurrence_finder.find_occurrences(self.resource): + start, end = occurrence.get_primary_range() + if self.skip_start <= start < self.skip_end: + self.handle.occurred_inside_skip(change_collector, occurrence) + else: + self.handle.occurred_outside_skip(change_collector, occurrence) + result = change_collector.get_changed() + if result is not None and result != source: + return result + +@path C:/Repos/ekr-rope/rope/refactor/ +"""This module can be used for performing cross-project refactorings + +See the "cross-project refactorings" section of ``docs/library.rst`` +file. + +""" + +from rope.base import resources, libutils + + +@others +@language python +@tabwidth -4 + +class MultiProjectRefactoring: + @others + +def __init__(self, refactoring, projects, addpath=True): + """Create a multiproject proxy for the main refactoring + + `projects` are other project. + + """ + self.refactoring = refactoring + self.projects = projects + self.addpath = addpath + + +def __call__(self, project, *args, **kwds): + """Create the refactoring""" + return _MultiRefactoring( + self.refactoring, self.projects, self.addpath, project, *args, **kwds + ) + + + +def element_already_exists(self): + if self.pyname is None or isinstance(self.pyname, pynames.UnboundName): + return False + return self.get_name() in self.goal_scope.get_defined_names() + + +class _MultiRefactoring: + @others + +def __init__(self, refactoring, other_projects, addpath, project, *args, **kwds): + self.refactoring = refactoring + self.projects = [project] + other_projects + for other_project in other_projects: + for folder in self.project.get_source_folders(): + other_project.get_prefs().add("python_path", folder.real_path) + self.refactorings = [] + for other in self.projects: + args, kwds = self._resources_for_args(other, args, kwds) + self.refactorings.append(self.refactoring(other, *args, **kwds)) + + +def get_all_changes(self, *args, **kwds): + """Get a project to changes dict""" + result = [] + for project, refactoring in zip(self.projects, self.refactorings): + args, kwds = self._resources_for_args(project, args, kwds) + result.append((project, refactoring.get_changes(*args, **kwds))) + return result + + +def __getattr__(self, name): + return getattr(self.main_refactoring, name) + + +def _resources_for_args(self, project, args, kwds): + newargs = [self._change_project_resource(project, arg) for arg in args] + newkwds = { + name: self._change_project_resource(project, value) + for name, value in kwds.items() + } + return newargs, newkwds + + +def _change_project_resource(self, project, obj): + if isinstance(obj, resources.Resource) and obj.project != project: + return libutils.path_to_resource(project, obj.real_path) + return obj + + +@property +def project(self): + return self.projects[0] + + +@property +def main_refactoring(self): + return self.refactorings[0] + + + +def perform(project_changes): + for project, changes in project_changes: + project.do(changes) + +@path C:/Repos/ekr-rope/rope/refactor/ +"""Find occurrences of a name in a project. + +This module consists of a `Finder` that finds all occurrences of a name +in a project. The `Finder.find_occurrences()` method is a generator that +yields `Occurrence` instances for each occurrence of the name. To create +a `Finder` object, use the `create_finder()` function: + + finder = occurrences.create_finder(project, 'foo', pyname) + for occurrence in finder.find_occurrences(): + pass + +It's possible to filter the occurrences. They can be specified when +calling the `create_finder()` function. + + * `only_calls`: If True, return only those instances where the name is + a function that's being called. + + * `imports`: If False, don't return instances that are in import + statements. + + * `unsure`: If a predicate function, return instances where we don't + know what the name references. It also filters based on the + predicate function. + + * `docs`: If True, it will search for occurrences in regions normally + ignored. E.g., strings and comments. + + * `in_hierarchy`: If True, it will find occurrences if the name is in + the class's hierarchy. + + * `instance`: Used only when you want implicit interfaces to be + considered. + + * `keywords`: If False, don't return instances that are the names of keyword + arguments +""" + +import ast +import re + +from rope.base import codeanalyze +from rope.base import evaluate +from rope.base import exceptions +from rope.base import pynames +from rope.base import pyobjects +from rope.base import utils +from rope.base import worder + + +@others +@language python +@tabwidth -4 + +def get_name(self): + return worder.get_name_at(self.resource, self.offset) + + + +class Finder: + """For finding occurrences of a name + + The constructor takes a `filters` argument. It should be a list + of functions that take a single argument. For each possible + occurrence, these functions are called in order with the an + instance of `Occurrence`: + + * If it returns `None` other filters are tried. + * If it returns `True`, the occurrence will be a match. + * If it returns `False`, the occurrence will be skipped. + * If all of the filters return `None`, it is skipped also. + + """ + + @others + +def __init__(self, project, name, filters=[lambda o: True], docs=False): + self.project = project + self.name = name + self.docs = docs + self.filters = filters + self._textual_finder = _TextualFinder(name, docs=docs) + + +def find_occurrences(self, resource=None, pymodule=None): + """Generate `Occurrence` instances""" + tools = _OccurrenceToolsCreator( + self.project, resource=resource, pymodule=pymodule, docs=self.docs + ) + for offset in self._textual_finder.find_offsets(tools.source_code): + occurrence = Occurrence(tools, offset) + for filter in self.filters: + result = filter(occurrence) + if result is None: + continue + if result: + yield occurrence + break + + + +def create_finder( + project, + name, + pyname, + only_calls=False, + imports=True, + unsure=None, + docs=False, + instance=None, + in_hierarchy=False, + keywords=True, +): + """A factory for `Finder` + + Based on the arguments it creates a list of filters. `instance` + argument is needed only when you want implicit interfaces to be + considered. + + """ + pynames_ = {pyname} + filters = [] + if only_calls: + filters.append(CallsFilter()) + if not imports: + filters.append(NoImportsFilter()) + if not keywords: + filters.append(NoKeywordsFilter()) + if isinstance(instance, pynames.ParameterName): + for pyobject in instance.get_objects(): + try: + pynames_.add(pyobject[name]) + except exceptions.AttributeNotFoundError: + pass + for pyname in pynames_: + filters.append(PyNameFilter(pyname)) + if in_hierarchy: + filters.append(InHierarchyFilter(pyname)) + if unsure: + filters.append(UnsureFilter(unsure)) + return Finder(project, name, filters=filters, docs=docs) + + + +class Occurrence: + @others + +def __init__(self, tools, offset): + self.tools = tools + self.offset = offset + self.resource = tools.resource + + +@utils.saveit +def get_word_range(self): + return self.tools.word_finder.get_word_range(self.offset) + + +@utils.saveit +def get_primary_range(self): + return self.tools.word_finder.get_primary_range(self.offset) + + +@utils.saveit +def get_pyname(self): + try: + return self.tools.name_finder.get_pyname_at(self.offset) + except exceptions.BadIdentifierError: + pass + + +@utils.saveit +def get_primary_and_pyname(self): + try: + return self.tools.name_finder.get_primary_and_pyname_at(self.offset) + except exceptions.BadIdentifierError: + pass + + +class _Commenter: + @others + +class _FunctionGenerationInfo(_GenerationInfo): + @others + +@utils.saveit +def is_in_import_statement(self): + return self.tools.word_finder.is_from_statement( + self.offset + ) or self.tools.word_finder.is_import_statement(self.offset) + + +def is_called(self): + return self.tools.word_finder.is_a_function_being_called(self.offset) + + +def is_defined(self): + return self.tools.word_finder.is_a_class_or_function_name_in_header(self.offset) + + +def is_a_fixed_primary(self): + return self.tools.word_finder.is_a_class_or_function_name_in_header( + self.offset + ) or self.tools.word_finder.is_a_name_after_from_import(self.offset) + + +def is_written(self): + return self.tools.word_finder.is_assigned_here(self.offset) + + +def is_unsure(self): + return unsure_pyname(self.get_pyname()) + + +def is_function_keyword_parameter(self): + return self.tools.word_finder.is_function_keyword_parameter(self.offset) + + +@property +@utils.saveit +def lineno(self): + offset = self.get_word_range()[0] + return self.tools.pymodule.lines.get_line_number(offset) + + + +def same_pyname(expected, pyname): + """Check whether `expected` and `pyname` are the same""" + if expected is None or pyname is None: + return False + if expected == pyname: + return True + if type(expected) not in (pynames.ImportedModule, pynames.ImportedName) and type( + pyname + ) not in (pynames.ImportedModule, pynames.ImportedName): + return False + return ( + expected.get_definition_location() == pyname.get_definition_location() + and expected.get_object() == pyname.get_object() + ) + + + +def unsure_pyname(pyname, unbound=True): + """Return `True` if we don't know what this name references""" + if pyname is None: + return True + if unbound and not isinstance(pyname, pynames.UnboundName): + return False + if pyname.get_object() == pyobjects.get_unknown(): + return True + + + +def _get_goal_scope(self): + if self.is_constructor(): + return self.pyname.get_object().get_scope() + if self.is_instance(): + return self.pyname.get_object().get_type().get_scope() + if self.primary is None: + return self._get_source_scope() + pyobject = self.primary.get_object() + if isinstance(pyobject, pyobjects.PyDefinedObject): + return pyobject.get_scope() + elif isinstance(pyobject.get_type(), pyobjects.PyClass): + return pyobject.get_type().get_scope() + + +class PyNameFilter: + """For finding occurrences of a name.""" + + @others + +def __init__(self, pyname): + self.pyname = pyname + + +def __call__(self, occurrence): + if same_pyname(self.pyname, occurrence.get_pyname()): + return True + + + +class InHierarchyFilter: + """Finds the occurrence if the name is in the class's hierarchy.""" + + @others + +def __init__(self, pyname, implementations_only=False): + self.pyname = pyname + self.impl_only = implementations_only + self.pyclass = self._get_containing_class(pyname) + if self.pyclass is not None: + self.name = pyname.get_object().get_name() + self.roots = self._get_root_classes(self.pyclass, self.name) + else: + self.roots = None + + +def __call__(self, occurrence): + if self.roots is None: + return + pyclass = self._get_containing_class(occurrence.get_pyname()) + if pyclass is not None: + roots = self._get_root_classes(pyclass, self.name) + if self.roots.intersection(roots): + return True + + +def _get_containing_class(self, pyname): + if isinstance(pyname, pynames.DefinedName): + scope = pyname.get_object().get_scope() + parent = scope.parent + if parent is not None and parent.get_kind() == "Class": + return parent.pyobject + + +def _get_root_classes(self, pyclass, name): + if self.impl_only and pyclass == self.pyclass: + return {pyclass} + result = set() + for superclass in pyclass.get_superclasses(): + if name in superclass: + result.update(self._get_root_classes(superclass, name)) + if not result: + return {pyclass} + return result + + + +class UnsureFilter: + """Occurrences where we don't knoow what the name references.""" + + @others + +def __init__(self, unsure): + self.unsure = unsure + + +def element_already_exists(self): + if self.pyname is None or isinstance(self.pyname, pynames.UnboundName): + return False + return self.get_name() in self.goal_scope.get_defined_names() + + +def __call__(self, occurrence): + if occurrence.is_unsure() and self.unsure(occurrence): + return True + + + +class NoImportsFilter: + """Don't include import statements as occurrences.""" + + def __call__(self, occurrence): + if occurrence.is_in_import_statement(): + return False + + + +class CallsFilter: + """Filter out non-call occurrences.""" + + def __call__(self, occurrence): + if not occurrence.is_called(): + return False + + + +class NoKeywordsFilter: + """Filter out keyword parameters.""" + + def __call__(self, occurrence): + if occurrence.is_function_keyword_parameter(): + return False + + + +class _TextualFinder: + @others + +def __init__(self, name, docs=False): + self.name = name + self.docs = docs + self.comment_pattern = _TextualFinder.any("comment", [r"#[^\n]*"]) + self.string_pattern = _TextualFinder.any( + "string", [codeanalyze.get_string_pattern()] + ) + self.f_string_pattern = _TextualFinder.any( + "fstring", [codeanalyze.get_formatted_string_pattern()] + ) + self.pattern = self._get_occurrence_pattern(self.name) + + +def find_offsets(self, source): + if not self._fast_file_query(source): + return + if self.docs: + searcher = self._normal_search + else: + searcher = self._re_search + yield from searcher(source) + + +def _re_search(self, source): + for match in self.pattern.finditer(source): + if match.groupdict()["occurrence"]: + yield match.start("occurrence") + elif match.groupdict()["fstring"]: + f_string = match.groupdict()["fstring"] + for occurrence_node in self._search_in_f_string(f_string): + yield match.start("fstring") + occurrence_node.col_offset + + +def _search_in_f_string(self, f_string): + tree = ast.parse(f_string) + for node in ast.walk(tree): + if isinstance(node, ast.Name) and node.id == self.name: + yield node + + +def _normal_search(self, source): + current = 0 + while True: + try: + found = source.index(self.name, current) + current = found + len(self.name) + if (found == 0 or not self._is_id_char(source[found - 1])) and ( + current == len(source) or not self._is_id_char(source[current]) + ): + yield found + except ValueError: + break + + +def is_static_method(self): + return self.primary is not None and isinstance( + self.primary.get_object(), pyobjects.PyClass + ) + + +def _is_id_char(self, c): + return c.isalnum() or c == "_" + + +def _fast_file_query(self, source): + try: + source.index(self.name) + return True + except ValueError: + return False + + +def _get_source(self, resource, pymodule): + if resource is not None: + return resource.read() + else: + return pymodule.source_code + + +def _get_occurrence_pattern(self, name): + occurrence_pattern = _TextualFinder.any("occurrence", ["\\b" + name + "\\b"]) + pattern = re.compile( + occurrence_pattern + + "|" + + self.comment_pattern + + "|" + + self.string_pattern + + "|" + + self.f_string_pattern + ) + return pattern + + +@staticmethod +def any(name, list_): + return "(?P<%s>" % name + "|".join(list_) + ")" + + + +class _OccurrenceToolsCreator: + @others + +def __init__(self, project, resource=None, pymodule=None, docs=False): + self.project = project + self.__resource = resource + self.__pymodule = pymodule + self.docs = docs + + +@property +@utils.saveit +def name_finder(self): + return evaluate.ScopeNameFinder(self.pymodule) + + +@property +@utils.saveit +def source_code(self): + return self.pymodule.source_code + + +@property +@utils.saveit +def word_finder(self): + return worder.Worder(self.source_code, self.docs) + + +def is_method(self): + return self.primary is not None and isinstance( + self.primary.get_object().get_type(), pyobjects.PyClass + ) + + +@property +@utils.saveit +def resource(self): + if self.__resource is not None: + return self.__resource + if self.__pymodule is not None: + return self.__pymodule.resource + + +@property +@utils.saveit +def pymodule(self): + if self.__pymodule is not None: + return self.__pymodule + return self.project.get_pymodule(self.resource) + +@path C:/Repos/ekr-rope/rope/refactor/ +import collections +import numbers +import re +import warnings +from itertools import chain + +from rope.base import ast, codeanalyze, exceptions + +### +try: + basestring +except NameError: + basestring = (str, bytes) + +COMMA_IN_WITH_PATTERN = re.compile(r"\(.*?\)|(,)") + + +@others +@language python +@tabwidth -4 + +def get_patched_ast(source, sorted_children=False): + """Adds ``region`` and ``sorted_children`` fields to nodes + + Adds ``sorted_children`` field only if `sorted_children` is True. + + """ + return patch_ast(ast.parse(source), source, sorted_children) + + + +def patch_ast(node, source, sorted_children=False): + """Patches the given node + + After calling, each node in `node` will have a new field named + `region` that is a tuple containing the start and end offsets + of the code that generated it. + + If `sorted_children` is true, a `sorted_children` field will + be created for each node, too. It is a list containing child + nodes as well as whitespaces and comments that occur between + them. + + """ + if hasattr(node, "region"): + return node + walker = _PatchingASTWalker(source, children=sorted_children) + ast.call_for_nodes(node, walker) + return node + + + +def node_region(patched_ast_node): + """Get the region of a patched ast node""" + return patched_ast_node.region + + + +def write_ast(patched_ast_node): + """Extract source form a patched AST node with `sorted_children` field + + If the node is patched with sorted_children turned off you can use + `node_region` function for obtaining code using module source code. + """ + result = [] + for child in patched_ast_node.sorted_children: + if isinstance(child, ast.AST): + result.append(write_ast(child)) + else: + result.append(child) + return "".join(result) + + + +class MismatchedTokenError(exceptions.RopeError): + pass + + + +class _PatchingASTWalker: + @others + +def __init__(self, source, children=False): + self.source = _Source(source) + self.children = children + self.lines = codeanalyze.SourceLinesAdapter(source) + self.children_stack = [] + + +def is_constructor(self): + return self.pyname is not None and isinstance( + self.pyname.get_object(), pyobjects.PyClass + ) + + +Number = object() +String = object() +semicolon_or_as_in_except = object() +exec_open_paren_or_space = object() +exec_close_paren_or_space = object() +exec_in_or_comma = object() +with_or_comma_context_manager = object() +empty_tuple = object() + + +def __call__(self, node): + method = getattr(self, "_" + node.__class__.__name__, None) + if method is not None: + return method(node) + # ???: Unknown node; what should we do here? + warnings.warn( + "Unknown node type <%s>; please report!" % node.__class__.__name__, + RuntimeWarning, + ) + node.region = (self.source.offset, self.source.offset) + if self.children: + node.sorted_children = ast.get_children(node) + + +def _handle(self, node, base_children, eat_parens=False, eat_spaces=False): + if hasattr(node, "region"): + # ???: The same node was seen twice; what should we do? + warnings.warn( + "Node <%s> has been already patched; please report!" + % node.__class__.__name__, + RuntimeWarning, + ) + return + + base_children = collections.deque(base_children) + self.children_stack.append(base_children) + children = collections.deque() + formats = [] + suspected_start = self.source.offset + start = suspected_start + first_token = True + while base_children: + child = base_children.popleft() + if child is None: + continue + offset = self.source.offset + if isinstance(child, ast.AST): + ast.call_for_nodes(child, self) + token_start = child.region[0] + else: + if child is self.String: + region = self.source.consume_string( + end=self._find_next_statement_start() + ) + elif child is self.Number: + region = self.source.consume_number() + elif child == self.empty_tuple: + region = self.source.consume_empty_tuple() + elif child == "!=": + # INFO: This has been added to handle deprecated ``<>`` + region = self.source.consume_not_equal() + elif child == self.semicolon_or_as_in_except: + # INFO: This has been added to handle deprecated + # semicolon in except + region = self.source.consume_except_as_or_semicolon() + elif child == self.exec_open_paren_or_space: + # These three cases handle the differences between + # the deprecated exec statement and the exec + # function. + region = self.source.consume_exec_open_paren_or_space() + elif child == self.exec_in_or_comma: + region = self.source.consume_exec_in_or_comma() + elif child == self.exec_close_paren_or_space: + region = self.source.consume_exec_close_paren_or_space() + elif child == self.with_or_comma_context_manager: + region = self.source.consume_with_or_comma_context_manager() + else: + if hasattr(ast, "JoinedStr") and isinstance( + node, (ast.JoinedStr, ast.FormattedValue) + ): + region = self.source.consume_joined_string(child) + else: + region = self.source.consume(child) + child = self.source[region[0] : region[1]] + token_start = region[0] + if not first_token: + formats.append(self.source[offset:token_start]) + if self.children: + children.append(self.source[offset:token_start]) + else: + first_token = False + start = token_start + if self.children: + children.append(child) + start = self._handle_parens(children, start, formats) + if eat_parens: + start = self._eat_surrounding_parens(children, suspected_start, start) + if eat_spaces: + if self.children: + children.appendleft(self.source[0:start]) + end_spaces = self.source[self.source.offset :] + self.source.consume(end_spaces) + if self.children: + children.append(end_spaces) + start = 0 + if self.children: + node.sorted_children = children + node.region = (start, self.source.offset) + self.children_stack.pop() + + +def _handle_parens(self, children, start, formats): + """Changes `children` and returns new start""" + opens, closes = self._count_needed_parens(formats) + old_end = self.source.offset + new_end = None + for i in range(closes): + new_end = self.source.consume(")")[1] + if new_end is not None: + if self.children: + children.append(self.source[old_end:new_end]) + new_start = start + for i in range(opens): + new_start = self.source.rfind_token("(", 0, new_start) + if new_start != start: + if self.children: + children.appendleft(self.source[new_start:start]) + start = new_start + return start + + +def _eat_surrounding_parens(self, children, suspected_start, start): + index = self.source.rfind_token("(", suspected_start, start) + if index is not None: + old_start = start + old_offset = self.source.offset + start = index + if self.children: + children.appendleft(self.source[start + 1 : old_start]) + children.appendleft("(") + token_start, token_end = self.source.consume(")") + if self.children: + children.append(self.source[old_offset:token_start]) + children.append(")") + return start + + +def _count_needed_parens(self, children): + start = 0 + opens = 0 + for child in children: + if not isinstance(child, basestring): + continue + if child == "" or child[0] in "'\"": + continue + index = 0 + while index < len(child): + if child[index] == ")": + if opens > 0: + opens -= 1 + else: + start += 1 + if child[index] == "(": + opens += 1 + if child[index] == "#": + try: + index = child.index("\n", index) + except ValueError: + break + index += 1 + return start, opens + + +def _find_next_statement_start(self): + for children in reversed(self.children_stack): + for child in children: + if isinstance(child, ast.stmt): + return child.col_offset + self.lines.get_line_start(child.lineno) + return len(self.source.source) + + +def _join(self, iterable, separator): + iterable = iter(iterable) + try: + yield next(iterable) + except StopIteration: + return + for child in iterable: + yield separator + yield child + + +def _flatten_keywords(self, iterable): + iterable = ([attr, "=", pattern] for attr, pattern in iterable) + iterable = self._join(iterable, separator=[","]) + return chain.from_iterable(iterable) + + +def _child_nodes(self, nodes, separator): + return list(self._join(nodes, separator=separator)) + + +def is_instance(self): + if self.pyname is None: + return False + pyobject = self.pyname.get_object() + return isinstance(pyobject.get_type(), pyobjects.PyClass) + + +_operators = { + "And": "and", + "Or": "or", + "Add": "+", + "Sub": "-", + "Mult": "*", + "Div": "/", + "Mod": "%", + "Pow": "**", + "MatMult": "@", + "LShift": "<<", + "RShift": ">>", + "BitOr": "|", + "BitAnd": "&", + "BitXor": "^", + "FloorDiv": "//", + "Invert": "~", + "Not": "not", + "UAdd": "+", + "USub": "-", + "Eq": "==", + "NotEq": "!=", + "Lt": "<", + "LtE": "<=", + "Gt": ">", + "GtE": ">=", + "Is": "is", + "IsNot": "is not", + "In": "in", + "NotIn": "not in", +} + + +def _get_op(self, node): + return self._operators[node.__class__.__name__].split(" ") + + +def _Attribute(self, node): + self._handle(node, [node.value, ".", node.attr]) + + +def _Assert(self, node): + children = ["assert", node.test] + if node.msg: + children.append(",") + children.append(node.msg) + self._handle(node, children) + + +def _Assign(self, node): + children = self._child_nodes(node.targets, "=") + children.append("=") + children.append(node.value) + self._handle(node, children) + + +def _AugAssign(self, node): + children = [node.target] + children.extend(self._get_op(node.op)) + children.extend(["=", node.value]) + self._handle(node, children) + + +def _AnnAssign(self, node): + children = [node.target, ":", node.annotation] + if node.value is not None: + children.append("=") + children.append(node.value) + self._handle(node, children) + + +def _Repr(self, node): + self._handle(node, ["`", node.value, "`"]) + + +def _BinOp(self, node): + children = [node.left] + self._get_op(node.op) + [node.right] + self._handle(node, children) + + +def _BoolOp(self, node): + self._handle(node, self._child_nodes(node.values, self._get_op(node.op)[0])) + + +def get_name(self): + if self.is_constructor(): + return "__init__" + if self.is_instance(): + return "__call__" + return worder.get_name_at(self.resource, self.offset) + + +def _Break(self, node): + self._handle(node, ["break"]) + + +def _Call(self, node): + def _arg_sort_key(node): + if isinstance(node, ast.keyword): + return (node.value.lineno, node.value.col_offset) + return (node.lineno, node.col_offset) + + children = [node.func, "("] + args = sorted([*node.args, *node.keywords], key=_arg_sort_key) + children.extend(self._child_nodes(args, ",")) + children.append(")") + self._handle(node, children) + + +def _ClassDef(self, node): + children = [] + if getattr(node, "decorator_list", None): + for decorator in node.decorator_list: + children.append("@") + children.append(decorator) + children.extend(["class", node.name]) + if node.bases: + children.append("(") + children.extend(self._child_nodes(node.bases, ",")) + children.append(")") + children.append(":") + children.extend(node.body) + self._handle(node, children) + + +def _Compare(self, node): + children = [] + children.append(node.left) + for op, expr in zip(node.ops, node.comparators): + children.extend(self._get_op(op)) + children.append(expr) + self._handle(node, children) + + +def _Delete(self, node): + self._handle(node, ["del"] + self._child_nodes(node.targets, ",")) + + +def _Constant(self, node): + if isinstance(node.value, basestring): + self._handle(node, [self.String]) + return + + if any(node.value is v for v in [True, False, None]): + self._handle(node, [str(node.value)]) + return + + if isinstance(node.value, numbers.Number): + self._handle(node, [self.Number]) + return + + if node.value is Ellipsis: + self._handle(node, ["..."]) + return + + assert False + + +def _Num(self, node): + self._handle(node, [self.Number]) + + +def _Str(self, node): + self._handle(node, [self.String]) + + +def _Bytes(self, node): + self._handle(node, [self.String]) + + +def _JoinedStr(self, node): + def start_quote_char(): + possible_quotes = [ + (self.source.source.find(q, start, end), q) for q in QUOTE_CHARS + ] + quote_pos, quote_char = min( + (pos, q) for pos, q in possible_quotes if pos != -1 + ) + return self.source[start : quote_pos + len(quote_char)] + + def end_quote_char(): + possible_quotes = [ + (self.source.source.rfind(q, start, end), q) + for q in reversed(QUOTE_CHARS) + ] + _, quote_pos, quote_char = max( + (len(q), pos, q) for pos, q in possible_quotes if pos != -1 + ) + return self.source[end - len(quote_char) : end] + + QUOTE_CHARS = ['"""', "'''", '"', "'"] + offset = self.source.offset + start, end = self.source.consume_string( + end=self._find_next_statement_start(), + ) + self.source.offset = offset + + children = [] + children.append(start_quote_char()) + for part in node.values: + if isinstance(part, ast.FormattedValue): + children.append(part) + children.append(end_quote_char()) + self._handle(node, children) + + +def get_passed_args(self): + result = [] + source = self.source_pymodule.source_code + finder = worder.Worder(source) + if finder.is_a_function_being_called(self.offset): + start, end = finder.get_primary_range(self.offset) + parens_start, parens_end = finder.get_word_parens_range(end - 1) + call = source[start:parens_end] + parser = functionutils._FunctionParser(call, False) + args, keywords = parser.get_parameters() + for arg in args: + if self._is_id(arg): + result.append(arg) + else: + result.append("arg%d" % len(result)) + for name, value in keywords: + result.append(name) + return result + + +def _FormattedValue(self, node): + children = [] + children.append("{") + children.append(node.value) + if node.format_spec: + children.append(":") + for val in node.format_spec.values: + if isinstance(val, ast.FormattedValue): + children.append(val.value) + else: + children.append(val.s) + children.append("}") + self._handle(node, children) + + +def _Continue(self, node): + self._handle(node, ["continue"]) + + +def _Dict(self, node): + children = [] + children.append("{") + if node.keys: + for index, (key, value) in enumerate(zip(node.keys, node.values)): + if key is None: + # PEP-448 dict unpacking: {a: b, **unpack} + children.extend(["**", value]) + else: + children.extend([key, ":", value]) + if index < len(node.keys) - 1: + children.append(",") + children.append("}") + self._handle(node, children) + + +def _Ellipsis(self, node): + self._handle(node, ["..."]) + + +def _Expr(self, node): + self._handle(node, [node.value]) + + +def _NamedExpr(self, node): + children = [node.target, ":=", node.value] + self._handle(node, children) + + +def _Exec(self, node): + children = ["exec", self.exec_open_paren_or_space, node.body] + if node.globals: + children.extend([self.exec_in_or_comma, node.globals]) + if node.locals: + children.extend([",", node.locals]) + children.append(self.exec_close_paren_or_space) + self._handle(node, children) + + +def _ExtSlice(self, node): + children = [] + for index, dim in enumerate(node.dims): + if index > 0: + children.append(",") + children.append(dim) + self._handle(node, children) + + +def _handle_for_loop_node(self, node, is_async): + if is_async: + children = ["async", "for"] + else: + children = ["for"] + children.extend([node.target, "in", node.iter, ":"]) + children.extend(node.body) + if node.orelse: + children.extend(["else", ":"]) + children.extend(node.orelse) + self._handle(node, children) + + +def _For(self, node): + self._handle_for_loop_node(node, is_async=False) + + +def _is_id(self, arg): + def id_or_underline(c): + return c.isalpha() or c == "_" + + for c in arg: + if not id_or_underline(c) and not c.isdigit(): + return False + return id_or_underline(arg[0]) + +def _AsyncFor(self, node): + self._handle_for_loop_node(node, is_async=True) + + +def _ImportFrom(self, node): + children = ["from"] + if node.level: + children.append("." * node.level) + # see comment at rope.base.ast.walk + children.extend([node.module or "", "import"]) + children.extend(self._child_nodes(node.names, ",")) + self._handle(node, children) + + +def _alias(self, node): + children = [node.name] + if node.asname: + children.extend(["as", node.asname]) + self._handle(node, children) + + +def _handle_function_def_node(self, node, is_async): + children = [] + try: + decorators = getattr(node, "decorator_list") + except AttributeError: + decorators = getattr(node, "decorators", None) + if decorators: + for decorator in decorators: + children.append("@") + children.append(decorator) + if is_async: + children.extend(["async", "def"]) + else: + children.extend(["def"]) + children.extend([node.name, "(", node.args]) + children.extend([")", ":"]) + children.extend(node.body) + self._handle(node, children) + + +def _FunctionDef(self, node): + self._handle_function_def_node(node, is_async=False) + + +def _AsyncFunctionDef(self, node): + self._handle_function_def_node(node, is_async=True) + + +def _arguments(self, node): + children = [] + args = list(node.args) + defaults = [None] * (len(args) - len(node.defaults)) + list(node.defaults) + for index, (arg, default) in enumerate(zip(args, defaults)): + if index > 0: + children.append(",") + self._add_args_to_children(children, arg, default) + if node.vararg is not None: + if args: + children.append(",") + children.extend(["*", node.vararg.arg]) + if node.kwarg is not None: + if args or node.vararg is not None: + children.append(",") + children.extend(["**", node.kwarg.arg]) + self._handle(node, children) + + +def _add_args_to_children(self, children, arg, default): + if isinstance(arg, (list, tuple)): + self._add_tuple_parameter(children, arg) + else: + children.append(arg) + if default is not None: + children.append("=") + children.append(default) + + +def _add_tuple_parameter(self, children, arg): + children.append("(") + for index, token in enumerate(arg): + if index > 0: + children.append(",") + if isinstance(token, (list, tuple)): + self._add_tuple_parameter(children, token) + else: + children.append(token) + children.append(")") + + +def _GeneratorExp(self, node): + children = [node.elt] + children.extend(node.generators) + self._handle(node, children, eat_parens=True) + + +def __init__(self, code): + self.code = code + self.lines = self.code.split("\n") + self.lines.append("\n") + self.origs = list(range(len(self.lines) + 1)) + self.diffs = [0] * (len(self.lines) + 1) + + +@path C:/Repos/ekr-rope/rope/contrib/ +"""rope IDE tools package + +This package contains modules that can be used in IDEs +but do not depend on the UI. So these modules will be used +by `rope.ui` modules. + +""" +@language python +@tabwidth -4 + +def _comprehension(self, node): + children = ["for", node.target, "in", node.iter] + if node.ifs: + for if_ in node.ifs: + children.append("if") + children.append(if_) + self._handle(node, children) + + +def _Global(self, node): + children = self._child_nodes(node.names, ",") + children.insert(0, "global") + self._handle(node, children) + + +def _If(self, node): + if self._is_elif(node): + children = ["elif"] + else: + children = ["if"] + children.extend([node.test, ":"]) + children.extend(node.body) + if node.orelse: + if len(node.orelse) == 1 and self._is_elif(node.orelse[0]): + pass + else: + children.extend(["else", ":"]) + children.extend(node.orelse) + self._handle(node, children) + + +def _is_elif(self, node): + if not isinstance(node, ast.If): + return False + offset = self.lines.get_line_start(node.lineno) + node.col_offset + word = self.source[offset : offset + 4] + # XXX: This is a bug; the offset does not point to the first + alt_word = self.source[offset - 5 : offset - 1] + return "elif" in (word, alt_word) + + +def _IfExp(self, node): + return self._handle(node, [node.body, "if", node.test, "else", node.orelse]) + + +def _Import(self, node): + children = ["import"] + children.extend(self._child_nodes(node.names, ",")) + self._handle(node, children) + + +def _keyword(self, node): + children = [] + if node.arg is None: + children.append(node.value) + else: + children.extend([node.arg, "=", node.value]) + self._handle(node, children) + + +def _Lambda(self, node): + self._handle(node, ["lambda", node.args, ":", node.body]) + + +def _List(self, node): + self._handle(node, ["["] + self._child_nodes(node.elts, ",") + ["]"]) + + +def _ListComp(self, node): + children = ["[", node.elt] + children.extend(node.generators) + children.append("]") + self._handle(node, children) + + + +def _Set(self, node): + if node.elts: + self._handle(node, ["{"] + self._child_nodes(node.elts, ",") + ["}"]) + return + # Python doesn't have empty set literals + warnings.warn( + "Tried to handle empty <Set> literal; please report!", RuntimeWarning + ) + self._handle(node, ["set(", ")"]) + + +def _SetComp(self, node): + children = ["{", node.elt] + children.extend(node.generators) + children.append("}") + self._handle(node, children) + + +def _DictComp(self, node): + children = ["{"] + children.extend([node.key, ":", node.value]) + children.extend(node.generators) + children.append("}") + self._handle(node, children) + + +def _Module(self, node): + self._handle(node, list(node.body), eat_spaces=True) + + +def _Name(self, node): + self._handle(node, [node.id]) + + +def _NameConstant(self, node): + self._handle(node, [str(node.value)]) + + +def _arg(self, node): + self._handle(node, [node.arg]) + + +def _Pass(self, node): + self._handle(node, ["pass"]) + + +def _Print(self, node): + children = ["print"] + if node.dest: + children.extend([">>", node.dest]) + if node.values: + children.append(",") + children.extend(self._child_nodes(node.values, ",")) + if not node.nl: + children.append(",") + self._handle(node, children) + + +def _Raise(self, node): + children = ["raise"] + if node.exc: + children.append(node.exc) + if node.cause: + children.append(node.cause) + self._handle(node, children) + + +@path C:/Repos/ekr-rope/rope/contrib/autoimport/ +"""Definitions of types for the Autoimport program.""" +import pathlib +from enum import Enum +from typing import NamedTuple, Optional + + +@others +@language python +@tabwidth -4 + +def _Return(self, node): + children = ["return"] + if node.value: + children.append(node.value) + self._handle(node, children) + + +def _Sliceobj(self, node): + children = [] + for index, slice in enumerate(node.nodes): + if index > 0: + children.append(":") + if slice: + children.append(slice) + self._handle(node, children) + + +def _Index(self, node): + self._handle(node, [node.value]) + + +def _Subscript(self, node): + self._handle(node, [node.value, "[", node.slice, "]"]) + + +def _Slice(self, node): + children = [] + if node.lower: + children.append(node.lower) + children.append(":") + if node.upper: + children.append(node.upper) + if node.step: + children.append(":") + children.append(node.step) + self._handle(node, children) + + +def _TryFinally(self, node): + # @todo fixme + is_there_except_handler = False + not_empty_body = True + if len(node.finalbody) == 1: + try: + is_there_except_handler = isinstance( + node.handlers[0], ast.ExceptHandler + ) + not_empty_body = True + except IndexError: + pass + children = [] + if not_empty_body or not is_there_except_handler: + children.extend(["try", ":"]) + children.extend(node.body) + children.extend(node.handlers) + children.extend(["finally", ":"]) + children.extend(node.finalbody) + self._handle(node, children) + + +def _TryExcept(self, node): + children = ["try", ":"] + children.extend(node.body) + children.extend(node.handlers) + if node.orelse: + children.extend(["else", ":"]) + children.extend(node.orelse) + self._handle(node, children) + + +def _Try(self, node): + if len(node.finalbody): + self._TryFinally(node) + else: + self._TryExcept(node) + + +def _ExceptHandler(self, node): + self._excepthandler(node) + + +def _excepthandler(self, node): + # self._handle(node, [self.semicolon_or_as_in_except]) + children = ["except"] + if node.type: + children.append(node.type) + if node.name: + children.append(self.semicolon_or_as_in_except) + children.append(node.name) + children.append(":") + children.extend(node.body) + + self._handle(node, children) + + +class Source(Enum): + """Describes the source of the package, for sorting purposes.""" + + PROJECT = 0 # Obviously any project packages come first + MANUAL = 1 # Placeholder since Autoimport classifies manually added modules + BUILTIN = 2 + STANDARD = 3 # We want to favor standard library items + SITE_PACKAGE = 4 + UNKNOWN = 5 + + # modified_time + + + +def _Tuple(self, node): + if node.elts: + self._handle(node, self._child_nodes(node.elts, ","), eat_parens=True) + else: + self._handle(node, [self.empty_tuple]) + + +def _UnaryOp(self, node): + children = self._get_op(node.op) + children.append(node.operand) + self._handle(node, children) + + +def _Await(self, node): + children = ["await"] + if node.value: + children.append(node.value) + self._handle(node, children) + + +def _Yield(self, node): + children = ["yield"] + if node.value: + children.append(node.value) + self._handle(node, children) + + +def _YieldFrom(self, node): + children = ["yield", "from", node.value] + self._handle(node, children) + + +def _While(self, node): + children = ["while", node.test, ":"] + children.extend(node.body) + if node.orelse: + children.extend(["else", ":"]) + children.extend(node.orelse) + self._handle(node, children) + + +def _handle_with_node(self, node, is_async): + children = [] + + if is_async: + children.extend(["async"]) + for item in node.items: + children.extend([self.with_or_comma_context_manager, item.context_expr]) + if item.optional_vars: + children.extend(["as", item.optional_vars]) + children.append(":") + children.extend(node.body) + self._handle(node, children) + + +def _With(self, node): + self._handle_with_node(node, is_async=False) + + +def _AsyncWith(self, node): + self._handle_with_node(node, is_async=True) + + +def _Starred(self, node): + self._handle(node, [node.value]) + + +class ModuleInfo(NamedTuple): + """Descriptor of information to get names from a module.""" + + filepath: Optional[pathlib.Path] + modname: str + underlined: bool + process_imports: bool + + + +def _Match(self, node): + children = ["match", node.subject, ":"] + children.extend(node.cases) + self._handle(node, children) + + +def _match_case(self, node): + children = ["case", node.pattern] + if node.guard: + children.extend(["if", node.guard]) + children.append(":") + children.extend(node.body) + self._handle(node, children) + + +def _MatchAs(self, node): + if node.pattern: + children = [node.pattern, "as", node.name] + elif node.name is None: + children = ["_"] + else: + children = [node.name] + self._handle(node, children) + + +def _MatchClass(self, node): + children = [] + children.extend([node.cls, "("]) + children.extend(self._child_nodes(node.patterns, ",")) + children.extend(self._flatten_keywords(zip(node.kwd_attrs, node.kwd_patterns))) + children.append(")") + self._handle(node, children) + + +def _MatchValue(self, node): + self._handle(node, [node.value]) + +def _MatchMapping(self, node): + children = [] + children.append("{") + for index, (key, value) in enumerate(zip(node.keys, node.patterns)): + children.extend([key, ":", value]) + if index < len(node.keys) - 1: + children.append(",") + children.append("}") + self._handle(node, children) + + + +class _Source: + @others + _string_pattern = None + _number_pattern = None + _not_equals_pattern = None + +def __init__(self, source): + self.source = source + self.offset = 0 + + +def consume(self, token, skip_comment=True): + try: + while True: + new_offset = self.source.index(token, self.offset) + if self._good_token(token, new_offset) or not skip_comment: + break + else: + self._skip_comment() + except (ValueError, TypeError) as e: + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) + self.offset = new_offset + len(token) + return (new_offset, self.offset) + + +def consume_joined_string(self, token): + new_offset = self.source.index(token, self.offset) + self.offset = new_offset + len(token) + return (new_offset, self.offset) + + +def consume_string(self, end=None): + if _Source._string_pattern is None: + string_pattern = codeanalyze.get_string_pattern() + formatted_string_pattern = codeanalyze.get_formatted_string_pattern() + original = r"(?:{})|(?:{})".format(string_pattern, formatted_string_pattern) + pattern = r"({})((\s|\\\n|#[^\n]*\n)*({}))*".format(original, original) + _Source._string_pattern = re.compile(pattern) + repattern = _Source._string_pattern + return self._consume_pattern(repattern, end) + + +class ModuleFile(ModuleInfo): + """Descriptor of information to get names from a file using ast.""" + + filepath: pathlib.Path + modname: str + underlined: bool + process_imports: bool + + + +def consume_number(self): + if _Source._number_pattern is None: + _Source._number_pattern = re.compile(self._get_number_pattern()) + repattern = _Source._number_pattern + return self._consume_pattern(repattern) + + +def consume_empty_tuple(self): + return self._consume_pattern(re.compile(r"\(\s*\)")) + + +def consume_not_equal(self): + if _Source._not_equals_pattern is None: + _Source._not_equals_pattern = re.compile(r"<>|!=") + repattern = _Source._not_equals_pattern + return self._consume_pattern(repattern) + + +def consume_except_as_or_semicolon(self): + repattern = re.compile(r"as|,") + return self._consume_pattern(repattern) + + +def consume_exec_open_paren_or_space(self): + repattern = re.compile(r"\(|") + return self._consume_pattern(repattern) + + +def consume_exec_in_or_comma(self): + repattern = re.compile(r"in|,") + return self._consume_pattern(repattern) + + +def consume_exec_close_paren_or_space(self): + repattern = re.compile(r"\)|") + return self._consume_pattern(repattern) + + +def consume_with_or_comma_context_manager(self): + repattern = re.compile(r"with|,") + return self._consume_pattern(repattern) + + +def _good_token(self, token, offset, start=None): + """Checks whether consumed token is in comments""" + if start is None: + start = self.offset + try: + comment_index = self.source.rindex("#", start, offset) + except ValueError: + return True + try: + new_line_index = self.source.rindex("\n", start, offset) + except ValueError: + return False + return comment_index < new_line_index + + +def _skip_comment(self): + self.offset = self.source.index("\n", self.offset + 1) + + +class ModuleCompiled(ModuleInfo): + """Descriptor of information to get names using imports.""" + + filepath = None + modname: str + underlined: bool + process_imports: bool + + + +def _get_location(self): + lines = self.source[: self.offset].split("\n") + return (len(lines), len(lines[-1])) + + +def _consume_pattern(self, repattern, end=None): + while True: + if end is None: + end = len(self.source) + match = repattern.search(self.source, self.offset, end) + if self._good_token(match.group(), match.start()): + break + else: + self._skip_comment() + self.offset = match.end() + return match.start(), match.end() + + +def till_token(self, token): + new_offset = self.source.index(token, self.offset) + return self[self.offset : new_offset] + + +def rfind_token(self, token, start, end): + index = start + while True: + try: + index = self.source.rindex(token, start, end) + if self._good_token(token, index, start=start): + return index + else: + end = index + except ValueError: + return None + + +def from_offset(self, offset): + return self[offset : self.offset] + + +def find_backwards(self, pattern, offset): + return self.source.rindex(pattern, 0, offset) + + +def __getitem__(self, index): + return self.source[index] + + +def __getslice__(self, i, j): + return self.source[i:j] + + +def _get_number_pattern(self): + # HACK: It is merely an approaximation and does the job + integer = r"\-?(0x[\da-fA-F]+|\d+)[lL]?" + return r"(%s(\.\d*)?|(\.\d+))([eE][-+]?\d+)?[jJ]?" % integer + + +@path C:/Repos/ekr-rope/rope/refactor/ +import warnings + +from rope.base import ( + exceptions, + pyobjects, + pynames, + taskhandle, + evaluate, + worder, + codeanalyze, + libutils, +) +from rope.base.change import ChangeSet, ChangeContents, MoveResource +from rope.refactor import occurrences + + +@others +@language python +@tabwidth -4 + +class PackageType(Enum): + """Describes the type of package, to determine how to get the names from it.""" + + BUILTIN = 0 # No file exists, compiled into python. IE: Sys + STANDARD = 1 # Just a folder + COMPILED = 2 # .so module + SINGLE_FILE = 3 # a .py file + + + +class Rename: + """A class for performing rename refactoring + + It can rename everything: classes, functions, modules, packages, + methods, variables and keyword arguments. + + """ + + @others + +def __init__(self, project, resource, offset=None): + """If `offset` is None, the `resource` itself will be renamed""" + self.project = project + self.resource = resource + if offset is not None: + self.old_name = worder.get_name_at(self.resource, offset) + this_pymodule = self.project.get_pymodule(self.resource) + self.old_instance, self.old_pyname = evaluate.eval_location2( + this_pymodule, offset + ) + if self.old_pyname is None: + raise exceptions.RefactoringError( + "Rename refactoring should be performed" + " on resolvable python identifiers." + ) + else: + if not resource.is_folder() and resource.name == "__init__.py": + resource = resource.parent + dummy_pymodule = libutils.get_string_module(self.project, "") + self.old_instance = None + self.old_pyname = pynames.ImportedModule(dummy_pymodule, resource=resource) + if resource.is_folder(): + self.old_name = resource.name + else: + self.old_name = resource.name[:-3] + + +def get_old_name(self): + return self.old_name + + +def get_changes( + self, + new_name, + in_file=None, + in_hierarchy=False, + unsure=None, + docs=False, + resources=None, + task_handle=taskhandle.NullTaskHandle(), +): + """Get the changes needed for this refactoring + + Parameters: + + - `in_hierarchy`: when renaming a method this keyword forces + to rename all matching methods in the hierarchy + - `docs`: when `True` rename refactoring will rename + occurrences in comments and strings where the name is + visible. Setting it will make renames faster, too. + - `unsure`: decides what to do about unsure occurrences. + If `None`, they are ignored. Otherwise `unsure` is + called with an instance of `occurrence.Occurrence` as + parameter. If it returns `True`, the occurrence is + considered to be a match. + - `resources` can be a list of `rope.base.resources.File` to + apply this refactoring on. If `None`, the restructuring + will be applied to all python files. + - `in_file`: this argument has been deprecated; use + `resources` instead. + + """ + if unsure in (True, False): + warnings.warn( + "unsure parameter should be a function that returns " "True or False", + DeprecationWarning, + stacklevel=2, + ) + + @others + unsure = unsure_func + if in_file is not None: + warnings.warn( + "`in_file` argument has been deprecated; use `resources` " "instead. ", + DeprecationWarning, + stacklevel=2, + ) + if in_file: + resources = [self.resource] + if _is_local(self.old_pyname): + resources = [self.resource] + if resources is None: + resources = self.project.get_python_files() + changes = ChangeSet("Renaming <{}> to <{}>".format(self.old_name, new_name)) + finder = occurrences.create_finder( + self.project, + self.old_name, + self.old_pyname, + unsure=unsure, + docs=docs, + instance=self.old_instance, + in_hierarchy=in_hierarchy and self.is_method(), + ) + job_set = task_handle.create_jobset("Collecting Changes", len(resources)) + for file_ in resources: + job_set.started_job(file_.path) + new_content = rename_in_module(finder, new_name, resource=file_) + if new_content is not None: + changes.add_change(ChangeContents(file_, new_content)) + job_set.finished_job() + if self._is_renaming_a_module(): + resource = self.old_pyname.get_object().get_resource() + if self._is_allowed_to_move(resources, resource): + self._rename_module(resource, new_name, changes) + return changes + + +def unsure_func(value=unsure): + return value + + +def _is_allowed_to_move(self, resources, resource): + if resource.is_folder(): + try: + return resource.get_child("__init__.py") in resources + except exceptions.ResourceNotFoundError: + return False + else: + return resource in resources + + +def _is_renaming_a_module(self): + return isinstance(self.old_pyname.get_object(), pyobjects.AbstractModule) + + +def is_method(self): + pyname = self.old_pyname + return ( + isinstance(pyname, pynames.DefinedName) + and isinstance(pyname.get_object(), pyobjects.PyFunction) + and isinstance(pyname.get_object().parent, pyobjects.PyClass) + ) + + +def _rename_module(self, resource, new_name, changes): + if not resource.is_folder(): + new_name = new_name + ".py" + parent_path = resource.parent.path + if parent_path == "": + new_location = new_name + else: + new_location = parent_path + "/" + new_name + changes.add_change(MoveResource(resource, new_location)) + + + +class ChangeOccurrences: + """A class for changing the occurrences of a name in a scope + + This class replaces the occurrences of a name. Note that it only + changes the scope containing the offset passed to the constructor. + What's more it does not have any side-effects. That is for + example changing occurrences of a module does not rename the + module; it merely replaces the occurrences of that module in a + scope with the given expression. This class is useful for + performing many custom refactorings. + + """ + + @others + +class NameType(Enum): + """Describes the type of Name for lsp completions. Taken from python lsp server.""" + + Text = 1 + Method = 2 + Function = 3 + Constructor = 4 + Field = 5 + Variable = 6 + Class = 7 + Interface = 8 + Module = 9 + Property = 10 + Unit = 11 + Value = 12 + Enum = 13 + Keyword = 14 + Snippet = 15 + Color = 16 + File = 17 + Reference = 18 + Folder = 19 + EnumMember = 20 + Constant = 21 + Struct = 22 + Event = 23 + Operator = 24 + TypeParameter = 25 + + + +def __init__(self, project, resource, offset): + self.project = project + self.resource = resource + self.offset = offset + self.old_name = worder.get_name_at(resource, offset) + self.pymodule = project.get_pymodule(self.resource) + self.old_pyname = evaluate.eval_location(self.pymodule, offset) + + +def get_old_name(self): + word_finder = worder.Worder(self.resource.read()) + return word_finder.get_primary_at(self.offset) + + +def _get_scope_offset(self): + scope = self.pymodule.get_scope().get_inner_scope_for_offset(self.offset) + return scope.get_region() + + +def get_changes(self, new_name, only_calls=False, reads=True, writes=True): + changes = ChangeSet( + "Changing <{}> occurrences to <{}>".format(self.old_name, new_name) + ) + scope_start, scope_end = self._get_scope_offset() + finder = occurrences.create_finder( + self.project, + self.old_name, + self.old_pyname, + imports=False, + only_calls=only_calls, + ) + new_contents = rename_in_module( + finder, + new_name, + pymodule=self.pymodule, + replace_primary=True, + region=(scope_start, scope_end), + reads=reads, + writes=writes, + ) + if new_contents is not None: + changes.add_change(ChangeContents(self.resource, new_contents)) + return changes + + + +def rename_in_module( + occurrences_finder, + new_name, + resource=None, + pymodule=None, + replace_primary=False, + region=None, + reads=True, + writes=True, +): + """Returns the changed source or `None` if there is no changes""" + if resource is not None: + source_code = resource.read() + else: + source_code = pymodule.source_code + change_collector = codeanalyze.ChangeCollector(source_code) + for occurrence in occurrences_finder.find_occurrences(resource, pymodule): + if replace_primary and occurrence.is_a_fixed_primary(): + continue + if replace_primary: + start, end = occurrence.get_primary_range() + else: + start, end = occurrence.get_word_range() + if (not reads and not occurrence.is_written()) or ( + not writes and occurrence.is_written() + ): + continue + if region is None or region[0] <= start < region[1]: + change_collector.add_change(start, end, new_name) + return change_collector.get_changed() + + + +def _is_local(pyname): + module, lineno = pyname.get_definition_location() + if lineno is None: + return False + scope = module.get_scope().get_inner_scope_for_line(lineno) + if isinstance(pyname, pynames.DefinedName) and scope.get_kind() in ( + "Function", + "Class", + ): + scope = scope.parent + return ( + scope.get_kind() == "Function" + and pyname in scope.get_names().values() + and isinstance(pyname, pynames.AssignedName) + ) + +@path C:/Repos/ekr-rope/rope/refactor/ +import warnings + +from rope.base import change, taskhandle, builtins, ast, codeanalyze +from rope.base import libutils +from rope.refactor import patchedast, similarfinder, sourceutils +from rope.refactor.importutils import module_imports + + +@others +@language python +@tabwidth -4 + +class Restructure: + """A class to perform python restructurings + + A restructuring transforms pieces of code matching `pattern` to + `goal`. In the `pattern` wildcards can appear. Wildcards match + some piece of code based on their kind and arguments that are + passed to them through `args`. + + `args` is a dictionary of wildcard names to wildcard arguments. + If the argument is a tuple, the first item of the tuple is + considered to be the name of the wildcard to use; otherwise the + "default" wildcard is used. For getting the list arguments a + wildcard supports, see the pydoc of the wildcard. (see + `rope.refactor.wildcard.DefaultWildcard` for the default + wildcard.) + + `wildcards` is the list of wildcard types that can appear in + `pattern`. See `rope.refactor.wildcards`. If a wildcard does not + specify its kind (by using a tuple in args), the wildcard named + "default" is used. So there should be a wildcard with "default" + name in `wildcards`. + + `imports` is the list of imports that changed modules should + import. Note that rope handles duplicate imports and does not add + the import if it already appears. + + Example #1:: + + pattern ${pyobject}.get_attribute(${name}) + goal ${pyobject}[${name}] + args pyobject: instance=rope.base.pyobjects.PyObject + + Example #2:: + + pattern ${name} in ${pyobject}.get_attributes() + goal ${name} in {pyobject} + args pyobject: instance=rope.base.pyobjects.PyObject + + Example #3:: + + pattern ${pycore}.create_module(${project}.root, ${name}) + goal generate.create_module(${project}, ${name}) + + imports + from rope.contrib import generate + + args + project: type=rope.base.project.Project + + Example #4:: + + pattern ${pow}(${param1}, ${param2}) + goal ${param1} ** ${param2} + args pow: name=mod.pow, exact + + Example #5:: + + pattern ${inst}.longtask(${p1}, ${p2}) + goal + ${inst}.subtask1(${p1}) + ${inst}.subtask2(${p2}) + args + inst: type=mod.A,unsure + + """ + + @others + +def __init__(self, project, pattern, goal, args=None, imports=None, wildcards=None): + """Construct a restructuring + + See class pydoc for more info about the arguments. + + """ + self.project = project + self.pattern = pattern + self.goal = goal + self.args = args + if self.args is None: + self.args = {} + self.imports = imports + if self.imports is None: + self.imports = [] + self.wildcards = wildcards + self.template = similarfinder.CodeTemplate(self.goal) + + +def get_changes( + self, + checks=None, + imports=None, + resources=None, + task_handle=taskhandle.NullTaskHandle(), +): + """Get the changes needed by this restructuring + + `resources` can be a list of `rope.base.resources.File` to + apply the restructuring on. If `None`, the restructuring will + be applied to all python files. + + `checks` argument has been deprecated. Use the `args` argument + of the constructor. The usage of:: + + strchecks = {'obj1.type': 'mod.A', 'obj2': 'mod.B', + 'obj3.object': 'mod.C'} + checks = restructuring.make_checks(strchecks) + + can be replaced with:: + + args = {'obj1': 'type=mod.A', 'obj2': 'name=mod.B', + 'obj3': 'object=mod.C'} + + where obj1, obj2 and obj3 are wildcard names that appear + in restructuring pattern. + + """ + if checks is not None: + warnings.warn( + "The use of checks parameter is deprecated; " + "use the args parameter of the constructor instead.", + DeprecationWarning, + stacklevel=2, + ) + for name, value in checks.items(): + self.args[name] = similarfinder._pydefined_to_str(value) + if imports is not None: + warnings.warn( + "The use of imports parameter is deprecated; " + "use imports parameter of the constructor, instead.", + DeprecationWarning, + stacklevel=2, + ) + self.imports = imports + changes = change.ChangeSet( + "Restructuring <{}> to <{}>".format(self.pattern, self.goal) + ) + if resources is not None: + files = [ + resource + for resource in resources + if libutils.is_python_file(self.project, resource) + ] + else: + files = self.project.get_python_files() + job_set = task_handle.create_jobset("Collecting Changes", len(files)) + for resource in files: + job_set.started_job(resource.path) + pymodule = self.project.get_pymodule(resource) + finder = similarfinder.SimilarFinder(pymodule, wildcards=self.wildcards) + matches = list(finder.get_matches(self.pattern, self.args)) + computer = self._compute_changes(matches, pymodule) + result = computer.get_changed() + if result is not None: + imported_source = self._add_imports(resource, result, self.imports) + changes.add_change(change.ChangeContents(resource, imported_source)) + job_set.finished_job() + return changes + + +class Package(NamedTuple): + """Attributes of a package.""" + + name: str + source: Source + path: Optional[pathlib.Path] + type: PackageType + + + +def _compute_changes(self, matches, pymodule): + return _ChangeComputer( + pymodule.source_code, + pymodule.get_ast(), + pymodule.lines, + self.template, + matches, + ) + + +def _add_imports(self, resource, source, imports): + if not imports: + return source + import_infos = self._get_import_infos(resource, imports) + pymodule = libutils.get_string_module(self.project, source, resource) + imports = module_imports.ModuleImports(self.project, pymodule) + for import_info in import_infos: + imports.add_import(import_info) + return imports.get_changed_source() + + +def _get_import_infos(self, resource, imports): + pymodule = libutils.get_string_module( + self.project, "\n".join(imports), resource + ) + imports = module_imports.ModuleImports(self.project, pymodule) + return [imports.import_info for imports in imports.imports] + + +def make_checks(self, string_checks): + """Convert str to str dicts to str to PyObject dicts + + This function is here to ease writing a UI. + + """ + checks = {} + for key, value in string_checks.items(): + is_pyname = not key.endswith(".object") and not key.endswith(".type") + evaluated = self._evaluate(value, is_pyname=is_pyname) + if evaluated is not None: + checks[key] = evaluated + return checks + + +def _evaluate(self, code, is_pyname=True): + attributes = code.split(".") + pyname = None + if attributes[0] in ("__builtin__", "__builtins__"): + + @others + pyobject = _BuiltinsStub() + else: + pyobject = self.project.get_module(attributes[0]) + for attribute in attributes[1:]: + pyname = pyobject[attribute] + if pyname is None: + return None + pyobject = pyname.get_object() + return pyname if is_pyname else pyobject + + + +class _BuiltinsStub: + def get_attribute(self, name): + return builtins.builtins[name] + + +def replace(code, pattern, goal): + """used by other refactorings""" + finder = similarfinder.RawSimilarFinder(code) + matches = list(finder.get_matches(pattern)) + ast = patchedast.get_patched_ast(code) + lines = codeanalyze.SourceLinesAdapter(code) + template = similarfinder.CodeTemplate(goal) + computer = _ChangeComputer(code, ast, lines, template, matches) + result = computer.get_changed() + if result is None: + return code + return result + + + +class _ChangeComputer: + @others + +def __init__(self, code, ast, lines, goal, matches): + self.source = code + self.goal = goal + self.matches = matches + self.ast = ast + self.lines = lines + self.matched_asts = {} + self._nearest_roots = {} + if self._is_expression(): + for match in self.matches: + self.matched_asts[match.ast] = match + + +def get_changed(self): + if self._is_expression(): + result = self._get_node_text(self.ast) + if result == self.source: + return None + return result + else: + collector = codeanalyze.ChangeCollector(self.source) + last_end = -1 + for match in self.matches: + start, end = match.get_region() + if start < last_end: + if not self._is_expression(): + continue + last_end = end + replacement = self._get_matched_text(match) + collector.add_change(start, end, replacement) + return collector.get_changed() + + +def comment(self, lineno): + start = _logical_start(self.lines, lineno, check_prev=True) - 1 + # using self._get_stmt_end() instead of self._get_block_end() + # to lower commented lines + end = self._get_stmt_end(start) + indents = _get_line_indents(self.lines[start]) + if 0 < start: + last_lineno = self._last_non_blank(start - 1) + last_line = self.lines[last_lineno] + if last_line.rstrip().endswith(":"): + indents = _get_line_indents(last_line) + 4 + self._set(start, " " * indents + "pass") + for line in range(start + 1, end + 1): + self._set(line, self.lines[start]) + self._fix_incomplete_try_blocks(lineno, indents) + + +class Name(NamedTuple): + """A Name to be added to the database.""" + + name: str + modname: str + package: str + source: Source + name_type: NameType + + + +def _is_expression(self): + return self.matches and isinstance( + self.matches[0], similarfinder.ExpressionMatch + ) + + +def _get_matched_text(self, match): + mapping = {} + for name in self.goal.get_names(): + node = match.get_ast(name) + if node is None: + raise similarfinder.BadNameInCheckError("Unknown name <%s>" % name) + force = self._is_expression() and match.ast == node + mapping[name] = self._get_node_text(node, force) + unindented = self.goal.substitute(mapping) + return self._auto_indent(match.get_region()[0], unindented) + + +def _get_node_text(self, node, force=False): + if not force and node in self.matched_asts: + return self._get_matched_text(self.matched_asts[node]) + start, end = patchedast.node_region(node) + main_text = self.source[start:end] + collector = codeanalyze.ChangeCollector(main_text) + for node in self._get_nearest_roots(node): + sub_start, sub_end = patchedast.node_region(node) + collector.add_change( + sub_start - start, sub_end - start, self._get_node_text(node) + ) + result = collector.get_changed() + if result is None: + return main_text + return result + + +def _auto_indent(self, offset, text): + lineno = self.lines.get_line_number(offset) + indents = sourceutils.get_indents(self.lines, lineno) + result = [] + for index, line in enumerate(text.splitlines(True)): + if index != 0 and line.strip(): + result.append(" " * indents) + result.append(line) + return "".join(result) + + +def _get_nearest_roots(self, node): + if node not in self._nearest_roots: + result = [] + for child in ast.get_child_nodes(node): + if child in self.matched_asts: + result.append(child) + else: + result.extend(self._get_nearest_roots(child)) + self._nearest_roots[node] = result + return self._nearest_roots[node] + +@path C:/Repos/ekr-rope/rope/refactor/ +"""This module can be used for finding similar code""" +import re + +import rope.refactor.wildcards +from rope.base import libutils +from rope.base import codeanalyze, exceptions, ast, builtins +from rope.refactor import patchedast, wildcards + +from rope.refactor.patchedast import MismatchedTokenError + + +@others +@language python +@tabwidth -4 + +class BadNameInCheckError(exceptions.RefactoringError): + pass + + + +class SimilarFinder: + """`SimilarFinder` can be used to find similar pieces of code + + See the notes in the `rope.refactor.restructure` module for more + info. + + """ + + @others + +def __init__(self, pymodule, wildcards=None): + """Construct a SimilarFinder""" + self.source = pymodule.source_code + try: + self.raw_finder = RawSimilarFinder( + pymodule.source_code, pymodule.get_ast(), self._does_match + ) + except MismatchedTokenError: + print("in file %s" % pymodule.resource.path) + raise + self.pymodule = pymodule + if wildcards is None: + self.wildcards = {} + for wildcard in [ + rope.refactor.wildcards.DefaultWildcard(pymodule.pycore.project) + ]: + self.wildcards[wildcard.get_name()] = wildcard + else: + self.wildcards = wildcards + + +def get_matches(self, code, args={}, start=0, end=None): + self.args = args + if end is None: + end = len(self.source) + skip_region = None + if "skip" in args.get("", {}): + resource, region = args[""]["skip"] + if resource == self.pymodule.get_resource(): + skip_region = region + return self.raw_finder.get_matches(code, start=start, end=end, skip=skip_region) + + +class PartialName(NamedTuple): + """Partial information of a Name.""" + + name: str + name_type: NameType + + + +def get_match_regions(self, *args, **kwds): + for match in self.get_matches(*args, **kwds): + yield match.get_region() + + +def _does_match(self, node, name): + arg = self.args.get(name, "") + kind = "default" + if isinstance(arg, (tuple, list)): + kind = arg[0] + arg = arg[1] + suspect = wildcards.Suspect(self.pymodule, node, name) + return self.wildcards[kind].matches(suspect, arg) + + + +class RawSimilarFinder: + """A class for finding similar expressions and statements""" + + @others + +def __init__(self, source, node=None, does_match=None): + if node is None: + try: + node = ast.parse(source) + except SyntaxError: + # needed to parse expression containing := operator + node = ast.parse("(" + source + ")") + if does_match is None: + self.does_match = self._simple_does_match + else: + self.does_match = does_match + self._init_using_ast(node, source) + + +def _simple_does_match(self, node, name): + return isinstance(node, (ast.expr, ast.Name)) + + +def _init_using_ast(self, node, source): + self.source = source + self._matched_asts = {} + if not hasattr(node, "region"): + patchedast.patch_ast(node, source) + self.ast = node + + +def get_matches(self, code, start=0, end=None, skip=None): + """Search for `code` in source and return a list of `Match`-es + + `code` can contain wildcards. ``${name}`` matches normal + names and ``${?name} can match any expression. You can use + `Match.get_ast()` for getting the node that has matched a + given pattern. + + """ + if end is None: + end = len(self.source) + for match in self._get_matched_asts(code): + match_start, match_end = match.get_region() + if start <= match_start and match_end <= end: + if skip is not None and (skip[0] < match_end and skip[1] > match_start): + continue + yield match + + +def _get_matched_asts(self, code): + if code not in self._matched_asts: + wanted = self._create_pattern(code) + matches = _ASTMatcher(self.ast, wanted, self.does_match).find_matches() + self._matched_asts[code] = matches + return self._matched_asts[code] + + +def _create_pattern(self, expression): + expression = self._replace_wildcards(expression) + node = ast.parse(expression) + # Getting Module.Stmt.nodes + nodes = node.body + if len(nodes) == 1 and isinstance(nodes[0], ast.Expr): + # Getting Discard.expr + wanted = nodes[0].value + else: + wanted = nodes + return wanted + + +def _replace_wildcards(self, expression): + ropevar = _RopeVariable() + template = CodeTemplate(expression) + mapping = {} + for name in template.get_names(): + mapping[name] = ropevar.get_var(name) + return template.substitute(mapping) + + + +class SearchResult(NamedTuple): + """Search Result.""" + + import_statement: str + name: str + source: int + itemkind: int + +class _ASTMatcher: + @others + +def __init__(self, body, pattern, does_match): + """Searches the given pattern in the body AST. + + body is an AST node and pattern can be either an AST node or + a list of ASTs nodes + """ + self.body = body + self.pattern = pattern + self.matches = None + self.ropevar = _RopeVariable() + self.matches_callback = does_match + + +def find_matches(self): + if self.matches is None: + self.matches = [] + ast.call_for_nodes(self.body, self._check_node, recursive=True) + return self.matches + + +def _check_node(self, node): + if isinstance(self.pattern, list): + self._check_statements(node) + else: + self._check_expression(node) + + +def _check_expression(self, node): + mapping = {} + if self._match_nodes(self.pattern, node, mapping): + self.matches.append(ExpressionMatch(node, mapping)) + + +def _check_statements(self, node): + for child in ast.get_children(node): + if isinstance(child, (list, tuple)): + self.__check_stmt_list(child) + + +def __check_stmt_list(self, nodes): + for index in range(len(nodes)): + if len(nodes) - index >= len(self.pattern): + current_stmts = nodes[index : index + len(self.pattern)] + mapping = {} + if self._match_stmts(current_stmts, mapping): + self.matches.append(StatementMatch(current_stmts, mapping)) + + +def _match_nodes(self, expected, node, mapping): + if isinstance(expected, ast.Name): + if self.ropevar.is_var(expected.id): + return self._match_wildcard(expected, node, mapping) + if not isinstance(expected, ast.AST): + return expected == node + if expected.__class__ != node.__class__: + return False + + children1 = self._get_children(expected) + children2 = self._get_children(node) + if len(children1) != len(children2): + return False + for child1, child2 in zip(children1, children2): + if isinstance(child1, ast.AST): + if not self._match_nodes(child1, child2, mapping): + return False + elif isinstance(child1, (list, tuple)): + if not isinstance(child2, (list, tuple)) or len(child1) != len(child2): + return False + for c1, c2 in zip(child1, child2): + if not self._match_nodes(c1, c2, mapping): + return False + else: + if type(child1) is not type(child2) or child1 != child2: + return False + return True + + +def _get_children(self, node): + """Return not `ast.expr_context` children of `node`""" + children = ast.get_children(node) + return [child for child in children if not isinstance(child, ast.expr_context)] + + +def _match_stmts(self, current_stmts, mapping): + if len(current_stmts) != len(self.pattern): + return False + for stmt, expected in zip(current_stmts, self.pattern): + if not self._match_nodes(expected, stmt, mapping): + return False + return True + + +@path C:/Repos/ekr-rope/rope/contrib/autoimport/ +from typing import List + + +@others +@language python +@tabwidth -4 + +def _match_wildcard(self, node1, node2, mapping): + name = self.ropevar.get_base(node1.id) + if name not in mapping: + if self.matches_callback(node2, name): + mapping[name] = node2 + return True + return False + else: + return self._match_nodes(mapping[name], node2, {}) + + + +class Match: + @others + +def __init__(self, mapping): + self.mapping = mapping + + +def get_region(self): + """Returns match region""" + + +def get_ast(self, name): + """Return the ast node that has matched rope variables""" + return self.mapping.get(name, None) + + + +class ExpressionMatch(Match): + def __init__(self, ast, mapping): + super().__init__(mapping) + self.ast = ast + + def get_region(self): + return self.ast.region + + + +class StatementMatch(Match): + def __init__(self, ast_list, mapping): + super().__init__(mapping) + self.ast_list = ast_list + + def get_region(self): + return self.ast_list[0].region[0], self.ast_list[-1].region[1] + + + +class CodeTemplate: + @others + +def __init__(self, template): + self.template = template + self._find_names() + + +def _find_names(self): + self.names = {} + for match in CodeTemplate._get_pattern().finditer(self.template): + if "name" in match.groupdict() and match.group("name") is not None: + start, end = match.span("name") + name = self.template[start + 2 : end - 1] + if name not in self.names: + self.names[name] = [] + self.names[name].append((start, end)) + + +class FinalQuery: + def __init__(self, query): + self._query = query + + + +def get_names(self): + return self.names.keys() + + +def substitute(self, mapping): + collector = codeanalyze.ChangeCollector(self.template) + for name, occurrences in self.names.items(): + for region in occurrences: + collector.add_change(region[0], region[1], mapping[name]) + result = collector.get_changed() + if result is None: + return self.template + return result + + +_match_pattern = None + + +@classmethod +def _get_pattern(cls): + if cls._match_pattern is None: + pattern = ( + codeanalyze.get_comment_pattern() + + "|" + + codeanalyze.get_string_pattern() + + "|" + + r"(?P<name>\$\{[^\s\$\}]*\})" + ) + cls._match_pattern = re.compile(pattern) + return cls._match_pattern + + + +class _RopeVariable: + """Transform and identify rope inserted wildcards""" + + _normal_prefix = "__rope__variable_normal_" + _any_prefix = "__rope__variable_any_" + + @others + +def get_var(self, name): + if name.startswith("?"): + return self._get_any(name) + else: + return self._get_normal(name) + + +def is_var(self, name): + return self._is_normal(name) or self._is_var(name) + + +def get_base(self, name): + if self._is_normal(name): + return name[len(self._normal_prefix) :] + if self._is_var(name): + return "?" + name[len(self._any_prefix) :] + + +def _get_normal(self, name): + return self._normal_prefix + name + + +def _get_any(self, name): + return self._any_prefix + name[1:] + + +class Query: + @others + +def _is_normal(self, name): + return name.startswith(self._normal_prefix) + + +def _is_var(self, name): + return name.startswith(self._any_prefix) + + + +def make_pattern(code, variables): + variables = set(variables) + collector = codeanalyze.ChangeCollector(code) + + @others + finder = RawSimilarFinder(code, does_match=does_match) + for variable in variables: + for match in finder.get_matches("${%s}" % variable): + start, end = match.get_region() + collector.add_change(start, end, "${%s}" % variable) + result = collector.get_changed() + return result if result is not None else code + + + +def does_match(node, name): + return isinstance(node, ast.Name) and node.id == name + + +def _pydefined_to_str(pydefined): + address = [] + if isinstance(pydefined, (builtins.BuiltinClass, builtins.BuiltinFunction)): + return "__builtins__." + pydefined.get_name() + else: + while pydefined.parent is not None: + address.insert(0, pydefined.get_name()) + pydefined = pydefined.parent + module_name = libutils.modname(pydefined.resource) + return ".".join(module_name.split(".") + address) + +@path C:/Repos/ekr-rope/rope/refactor/ +from rope.base import codeanalyze + + +@others +@language python +@tabwidth -4 + +def get_indents(lines, lineno): + return codeanalyze.count_line_indents(lines.get_line(lineno)) + + + +def find_minimum_indents(source_code): + result = 80 + lines = source_code.split("\n") + for line in lines: + if line.strip() == "": + continue + result = min(result, codeanalyze.count_line_indents(line)) + return result + + + +def indent_lines(source_code, amount): + if amount == 0: + return source_code + lines = source_code.splitlines(True) + result = [] + for l in lines: + if l.strip() == "": + result.append("\n") + continue + if amount < 0: + indents = codeanalyze.count_line_indents(l) + result.append(max(0, indents + amount) * " " + l.lstrip()) + else: + result.append(" " * amount + l) + return "".join(result) + + + +def fix_indentation(code: str, new_indents: int) -> str: + """Change the indentation of `code` to `new_indents`""" + min_indents = find_minimum_indents(code) + return indent_lines(code, new_indents - min_indents) + + + +def __init__(self, query: str, columns: List[str]): + self.query = query + self.columns = columns + + +def add_methods(pymodule, class_scope, methods_sources): + source_code = pymodule.source_code + lines = pymodule.lines + insertion_line = class_scope.get_end() + if class_scope.get_scopes(): + insertion_line = class_scope.get_scopes()[-1].get_end() + insertion_offset = lines.get_line_end(insertion_line) + methods = "\n\n" + "\n\n".join(methods_sources) + indented_methods = fix_indentation( + methods, + get_indents(lines, class_scope.get_start()) + + get_indent(pymodule.pycore.project), + ) + result = [] + result.append(source_code[:insertion_offset]) + result.append(indented_methods) + result.append(source_code[insertion_offset:]) + return "".join(result) + + + +def get_body(pyfunction): + """Return unindented function body""" + # FIXME scope = pyfunction.get_scope() + pymodule = pyfunction.get_module() + start, end = get_body_region(pyfunction) + return fix_indentation(pymodule.source_code[start:end], 0) + + + +def get_body_region(defined): + """Return the start and end offsets of function body""" + scope = defined.get_scope() + pymodule = defined.get_module() + lines = pymodule.lines + node = defined.get_ast() + start_line = node.lineno + if defined.get_doc() is None: + start_line = node.body[0].lineno + elif len(node.body) > 1: + start_line = node.body[1].lineno + start = lines.get_line_start(start_line) + scope_start = pymodule.logical_lines.logical_line_in(scope.start) + if scope_start[1] >= start_line: + # a one-liner! + # XXX: what if colon appears in a string + start = pymodule.source_code.index(":", start) + 1 + while pymodule.source_code[start].isspace(): + start += 1 + end = min(lines.get_line_end(scope.end) + 1, len(pymodule.source_code)) + return start, end + + + +def get_indent(project): + return project.prefs.get("indent_size", 4) + +@path C:/Repos/ekr-rope/rope/refactor/ +from itertools import chain + +from rope.base import ast + + +@others +@language python +@tabwidth -4 + +def find_visible(node, lines): + """Return the line which is visible from all `lines`""" + root = ast_suite_tree(node) + return find_visible_for_suite(root, lines) + + + +def find_visible_for_suite(root, lines): + if len(lines) == 1: + return lines[0] + line1 = lines[0] + line2 = find_visible_for_suite(root, lines[1:]) + suite1 = root.find_suite(line1) + suite2 = root.find_suite(line2) + + @others + if valid(suite1) and not valid(suite2): + return line1 + if not valid(suite1) and valid(suite2): + return line2 + if not valid(suite1) and not valid(suite2): + return None + while suite1 != suite2 and suite1.parent != suite2.parent: + if suite1._get_level() < suite2._get_level(): + line2 = suite2.get_start() + suite2 = suite2.parent + elif suite1._get_level() > suite2._get_level(): + line1 = suite1.get_start() + suite1 = suite1.parent + else: + line1 = suite1.get_start() + line2 = suite2.get_start() + suite1 = suite1.parent + suite2 = suite2.parent + if suite1 == suite2: + return min(line1, line2) + return min(suite1.get_start(), suite2.get_start()) + + + +def valid(suite): + return suite is not None and not suite.ignored + + +def ast_suite_tree(node): + if hasattr(node, "lineno"): + lineno = node.lineno + else: + lineno = 1 + return Suite(node.body, lineno) + + + +class Suite: + @others + +def select(self, *columns: str): + if not (set(columns) <= set(self.columns)): + raise ValueError( + f"Unknown column names passed: {set(columns) - set(self.columns)}" + ) + + selected_columns = ", ".join(columns) + return FinalQuery(f"SELECT {selected_columns} FROM {self.query}") + + +def __init__(self, child_nodes, lineno, parent=None, ignored=False): + self.parent = parent + self.lineno = lineno + self.child_nodes = child_nodes + self._children = None + self.ignored = ignored + + +def get_start(self): + if self.parent is None: + if self.child_nodes: + return self.local_start() + else: + return 1 + return self.lineno + + +def get_children(self): + if self._children is None: + walker = _SuiteWalker(self) + for child in self.child_nodes: + ast.walk(child, walker) + self._children = walker.suites + return self._children + + +def local_start(self): + return self.child_nodes[0].lineno + + +def local_end(self): + end = self.child_nodes[-1].lineno + if self.get_children(): + end = max(end, self.get_children()[-1].local_end()) + return end + + +def find_suite(self, line): + if line is None: + return None + for child in self.get_children(): + if child.local_start() <= line <= child.local_end(): + return child.find_suite(line) + return self + + +def _get_level(self): + if self.parent is None: + return 0 + return self.parent._get_level() + 1 + + + +class _SuiteWalker: + @others + +def __init__(self, suite): + self.suite = suite + self.suites = [] + + +def _If(self, node): + self._add_if_like_node(node) + + +def select_star(self): + return FinalQuery(f"SELECT * FROM {self.query}") + + +def _For(self, node): + self._add_if_like_node(node) + + +def _While(self, node): + self._add_if_like_node(node) + + +def _With(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite)) + + +def _AsyncWith(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite)) + + +def _Match(self, node): + case_bodies = list( + chain.from_iterable([[case.pattern] + case.body for case in node.cases]) + ) + self.suites.append(Suite(case_bodies, node.lineno, self.suite)) + + +def _TryFinally(self, node): + proceed_to_except_handler = False + if len(node.finalbody) == 1: + try: + proceed_to_except_handler = isinstance( + node.handlers[0], ast.ExceptHandler + ) + except IndexError: + pass + if proceed_to_except_handler: + self._TryExcept(node) + else: + self.suites.append(Suite(node.body, node.lineno, self.suite)) + self.suites.append(Suite(node.finalbody, node.lineno, self.suite)) + + +def _Try(self, node): + if len(node.finalbody) == 1: + self._TryFinally(node) + else: + self._TryExcept(node) + + +def _TryExcept(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite)) + for handler in node.handlers: + self.suites.append(Suite(handler.body, node.lineno, self.suite)) + if node.orelse: + self.suites.append(Suite(node.orelse, node.lineno, self.suite)) + + +def _add_if_like_node(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite)) + if node.orelse: + self.suites.append(Suite(node.orelse, node.lineno, self.suite)) + + +def _FunctionDef(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) + + +def where(self, where_clause: str): + return Query( + f"{self.query} WHERE {where_clause}", + columns=self.columns, + ) + + +def _AsyncFunctionDef(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) + + +def _ClassDef(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) + +@path C:/Repos/ekr-rope/rope/refactor/ +import rope.refactor.importutils +from rope.base.change import ChangeSet, ChangeContents, MoveResource, CreateFolder + + +@others +@language python +@tabwidth -4 + +class ModuleToPackage: + @others + +def __init__(self, project, resource): + self.project = project + self.resource = resource + + +def get_changes(self): + changes = ChangeSet("Transform <%s> module to package" % self.resource.path) + new_content = self._transform_relatives_to_absolute(self.resource) + if new_content is not None: + changes.add_change(ChangeContents(self.resource, new_content)) + parent = self.resource.parent + name = self.resource.name[:-3] + changes.add_change(CreateFolder(parent, name)) + parent_path = parent.path + "/" + if not parent.path: + parent_path = "" + new_path = parent_path + "%s/__init__.py" % name + if self.resource.project == self.project: + changes.add_change(MoveResource(self.resource, new_path)) + return changes + + +def _transform_relatives_to_absolute(self, resource): + pymodule = self.project.get_pymodule(resource) + import_tools = rope.refactor.importutils.ImportTools(self.project) + return import_tools.relatives_to_absolutes(pymodule) + +@path C:/Repos/ekr-rope/rope/refactor/ +from rope.base import change, taskhandle, evaluate, exceptions, pyobjects, pynames, ast +from rope.base import libutils +from rope.refactor import restructure, sourceutils, similarfinder + + +@others +@language python +@tabwidth -4 + +class UseFunction: + """Try to use a function wherever possible""" + + @others + _rope_result = "_rope__result" + _rope_returned = "_rope__returned" + + + +def __init__(self, project, resource, offset): + self.project = project + self.offset = offset + this_pymodule = project.get_pymodule(resource) + pyname = evaluate.eval_location(this_pymodule, offset) + if pyname is None: + raise exceptions.RefactoringError("Unresolvable name selected") + self.pyfunction = pyname.get_object() + if not isinstance(self.pyfunction, pyobjects.PyFunction) or not isinstance( + self.pyfunction.parent, pyobjects.PyModule + ): + raise exceptions.RefactoringError( + "Use function works for global functions, only." + ) + self.resource = self.pyfunction.get_module().get_resource() + self._check_returns() + + +def transfered_offset(self, offset): + lineno = self.code.count("\n", 0, offset) + diff = sum(self.diffs[:lineno]) + return offset + diff + + +def insert_into(self) -> FinalQuery: + columns = ", ".join(self.columns) + placeholders = ", ".join(["?"] * len(self.columns)) + return FinalQuery( + f"INSERT INTO {self.query}({columns}) VALUES ({placeholders})" + ) + + +def _check_returns(self): + node = self.pyfunction.get_ast() + if _yield_count(node): + raise exceptions.RefactoringError( + "Use function should not be used on generatorS." + ) + returns = _return_count(node) + if returns > 1: + raise exceptions.RefactoringError( + "usefunction: Function has more than one return statement." + ) + if returns == 1 and not _returns_last(node): + raise exceptions.RefactoringError( + "usefunction: return should be the last statement." + ) + + +def get_changes(self, resources=None, task_handle=taskhandle.NullTaskHandle()): + if resources is None: + resources = self.project.get_python_files() + changes = change.ChangeSet("Using function <%s>" % self.pyfunction.get_name()) + if self.resource in resources: + newresources = list(resources) + newresources.remove(self.resource) + for c in self._restructure(newresources, task_handle).changes: + changes.add_change(c) + if self.resource in resources: + for c in self._restructure( + [self.resource], task_handle, others=False + ).changes: + changes.add_change(c) + return changes + + +def get_function_name(self): + return self.pyfunction.get_name() + + +def _restructure(self, resources, task_handle, others=True): + pattern = self._make_pattern() + goal = self._make_goal(import_=others) + imports = None + if others: + imports = ["import %s" % self._module_name()] + + body_region = sourceutils.get_body_region(self.pyfunction) + args_value = {"skip": (self.resource, body_region)} + args = {"": args_value} + + restructuring = restructure.Restructure( + self.project, pattern, goal, args=args, imports=imports + ) + return restructuring.get_changes(resources=resources, task_handle=task_handle) + + +def _find_temps(self): + return find_temps(self.project, self._get_body()) + + +def _module_name(self): + return libutils.modname(self.resource) + + +def _make_pattern(self): + params = self.pyfunction.get_param_names() + body = self._get_body() + body = restructure.replace(body, "return", "pass") + wildcards = list(params) + wildcards.extend(self._find_temps()) + if self._does_return(): + if self._is_expression(): + replacement = "${%s}" % self._rope_returned + else: + replacement = "{} = ${{{}}}".format( + self._rope_result, self._rope_returned + ) + body = restructure.replace( + body, "return ${%s}" % self._rope_returned, replacement + ) + wildcards.append(self._rope_result) + return similarfinder.make_pattern(body, wildcards) + + +def _get_body(self): + return sourceutils.get_body(self.pyfunction) + + +def _make_goal(self, import_=False): + params = self.pyfunction.get_param_names() + function_name = self.pyfunction.get_name() + if import_: + function_name = self._module_name() + "." + function_name + goal = "{}({})".format(function_name, ", ".join(("${%s}" % p) for p in params)) + if self._does_return() and not self._is_expression(): + goal = "${{{}}} = {}".format(self._rope_result, goal) + return goal + + +def _does_return(self): + body = self._get_body() + removed_return = restructure.replace(body, "return ${result}", "") + return removed_return != body + + +def drop_table(self) -> FinalQuery: + return FinalQuery(f"DROP TABLE {self.query}") + + +def _is_expression(self): + return len(self.pyfunction.get_ast().body) == 1 + + +def find_temps(project, code): + code = "def f():\n" + sourceutils.indent_lines(code, 4) + pymodule = libutils.get_string_module(project, code) + result = [] + function_scope = pymodule.get_scope().get_scopes()[0] + for name, pyname in function_scope.get_names().items(): + if isinstance(pyname, pynames.AssignedName): + result.append(name) + return result + + + +def _returns_last(node): + return node.body and isinstance(node.body[-1], ast.Return) + + + +def _namedexpr_last(node): + if not hasattr(ast, "NamedExpr"): # python<3.8 + return False + return ( + bool(node.body) + and len(node.body) == 1 + and isinstance(node.body[-1].value, ast.NamedExpr) + ) + + + +def _yield_count(node): + visitor = _ReturnOrYieldFinder() + visitor.start_walking(node) + return visitor.yields + + + +def _return_count(node): + visitor = _ReturnOrYieldFinder() + visitor.start_walking(node) + return visitor.returns + + + +def _named_expr_count(node): + visitor = _ReturnOrYieldFinder() + visitor.start_walking(node) + return visitor.named_expression + + + +class _ReturnOrYieldFinder: + @others + +def __init__(self): + self.returns = 0 + self.named_expression = 0 + self.yields = 0 + + +def _Return(self, node): + self.returns += 1 + + +def delete_from(self) -> FinalQuery: + return FinalQuery(f"DELETE FROM {self.query}") + + + +def _NamedExpr(self, node): + self.named_expression += 1 + + +def _Yield(self, node): + self.yields += 1 + + +def _FunctionDef(self, node): + pass + + +def _ClassDef(self, node): + pass + + +def start_walking(self, node): + nodes = [node] + if isinstance(node, ast.FunctionDef): + nodes = ast.get_child_nodes(node) + for child in nodes: + ast.walk(child, self) + +@path C:/Repos/ekr-rope/rope/refactor/ +from rope.base import ast, evaluate, builtins, pyobjects +from rope.refactor import patchedast, occurrences + + +@others +@language python +@tabwidth -4 + +class Wildcard: + def get_name(self): + """Return the name of this wildcard""" + + def matches(self, suspect, arg): + """Return `True` if `suspect` matches this wildcard""" + + + +class Suspect: + def __init__(self, pymodule, node, name): + self.name = name + self.pymodule = pymodule + self.node = node + + + +class DefaultWildcard: + """The default restructuring wildcard + + The argument passed to this wildcard is in the + ``key1=value1,key2=value2,...`` format. Possible keys are: + + * name - for checking the reference + * type - for checking the type + * object - for checking the object + * instance - for checking types but similar to builtin isinstance + * exact - matching only occurrences with the same name as the wildcard + * unsure - matching unsure occurrences + + """ + + @others + +def __init__(self, project): + self.project = project + + +class Name: + table_name = "names" + columns = [ + "name", + "module", + "package", + "source", + "type", + ] + + @others + objects = Query(table_name, columns) + + search_submodule_like = objects.where('module LIKE ("%." || ?)') + search_module_like = objects.where("module LIKE (?)") + + import_assist = objects.where("name LIKE (? || '%')") + + search_by_name_like = objects.where("name LIKE (?)") + + delete_by_module_name = objects.where("module = ?").delete_from() + + + +def get_name(self): + return "default" + + +def matches(self, suspect, arg=""): + args = parse_arg(arg) + + if not self._check_exact(args, suspect): + return False + if not self._check_object(args, suspect): + return False + return True + + +def _check_object(self, args, suspect): + kind = None + expected = None + unsure = args.get("unsure", False) + for check in ["name", "object", "type", "instance"]: + if check in args: + kind = check + expected = args[check] + if expected is not None: + checker = _CheckObject(self.project, expected, kind, unsure=unsure) + return checker(suspect.pymodule, suspect.node) + return True + + +def _check_exact(self, args, suspect): + node = suspect.node + if args.get("exact"): + if not isinstance(node, ast.Name) or not node.id == suspect.name: + return False + else: + if not isinstance(node, ast.expr): + return False + return True + + + +def parse_arg(arg): + if isinstance(arg, dict): + return arg + result = {} + tokens = arg.split(",") + for token in tokens: + if "=" in token: + parts = token.split("=", 1) + result[parts[0].strip()] = parts[1].strip() + else: + result[token.strip()] = True + return result + + + +class _CheckObject: + @others + +def __init__(self, project, expected, kind="object", unsure=False): + self.project = project + self.kind = kind + self.unsure = unsure + self.expected = self._evaluate(expected) + + +def __call__(self, pymodule, node): + pyname = self._evaluate_node(pymodule, node) + if pyname is None or self.expected is None: + return self.unsure + if self._unsure_pyname(pyname, unbound=self.kind == "name"): + return True + if self.kind == "name": + return self._same_pyname(self.expected, pyname) + else: + pyobject = pyname.get_object() + if self.kind == "object": + objects = [pyobject] + if self.kind == "type": + objects = [pyobject.get_type()] + if self.kind == "instance": + objects = [pyobject] + objects.extend(self._get_super_classes(pyobject)) + objects.extend(self._get_super_classes(pyobject.get_type())) + for pyobject in objects: + if self._same_pyobject(self.expected.get_object(), pyobject): + return True + return False + + +def _get_super_classes(self, pyobject): + result = [] + if isinstance(pyobject, pyobjects.AbstractClass): + for superclass in pyobject.get_superclasses(): + result.append(superclass) + result.extend(self._get_super_classes(superclass)) + return result + + +def _same_pyobject(self, expected, pyobject): + return expected == pyobject + + +@classmethod +def create_table(self, connection): + names_table = ( + "(name TEXT, module TEXT, package TEXT, source INTEGER, type INTEGER)" + ) + connection.execute(f"CREATE TABLE IF NOT EXISTS names{names_table}") + connection.execute("CREATE INDEX IF NOT EXISTS name ON names(name)") + connection.execute("CREATE INDEX IF NOT EXISTS module ON names(module)") + connection.execute("CREATE INDEX IF NOT EXISTS package ON names(package)") + + +def _same_pyname(self, expected, pyname): + return occurrences.same_pyname(expected, pyname) + + +def _unsure_pyname(self, pyname, unbound=True): + return self.unsure and occurrences.unsure_pyname(pyname, unbound) + + +def _split_name(self, name): + parts = name.split(".") + expression, kind = parts[0], parts[-1] + if len(parts) == 1: + kind = "name" + return expression, kind + + +def _evaluate_node(self, pymodule, node): + scope = pymodule.get_scope().get_inner_scope_for_line(node.lineno) + expression = node + if isinstance(expression, ast.Name) and isinstance(expression.ctx, ast.Store): + start, end = patchedast.node_region(expression) + text = pymodule.source_code[start:end] + return evaluate.eval_str(scope, text) + else: + return evaluate.eval_node(scope, expression) + + +def _evaluate(self, code): + attributes = code.split(".") + pyname = None + if attributes[0] in ("__builtin__", "__builtins__"): + + @others + pyobject = _BuiltinsStub() + else: + pyobject = self.project.get_module(attributes[0]) + for attribute in attributes[1:]: + pyname = pyobject[attribute] + if pyname is None: + return None + pyobject = pyname.get_object() + return pyname + +class _BuiltinsStub: + def get_attribute(self, name): + return builtins.builtins[name] + + def __getitem__(self, name): + return builtins.builtins[name] + + def __contains__(self, name): + return name in builtins.builtins + + +@path C:/Repos/ekr-rope/rope/refactor/ +"""rope refactor package + +This package contains modules that perform python refactorings. +Refactoring classes perform refactorings in 4 steps: + +1. Collect some data for performing the refactoring and use them + to construct a refactoring class. Like:: + + renamer = Rename(project, resource, offset) + +2. Some refactorings give you useful information about the + refactoring after their construction. Like:: + + print(renamer.get_old_name()) + +3. Give the refactoring class more information about how to + perform the refactoring and get the changes this refactoring is + going to make. This is done by calling `get_changes` method of the + refactoring class. Like:: + + changes = renamer.get_changes(new_name) + +4. You can commit the changes. Like:: + + project.do(changes) + +These steps are like the steps IDEs usually do for performing a +refactoring. These are the things an IDE does in each step: + +1. Construct a refactoring object by giving it information like + resource, offset and ... . Some of the refactoring problems (like + performing rename refactoring on language keywords) can be reported + here. +2. Print some information about the refactoring and ask the user + about the information that are necessary for completing the + refactoring (like new name). +3. Call the `get_changes` by passing it information asked from + the user (if necessary) and get and preview the changes returned by + it. +4. perform the refactoring. + +From ``0.5m5`` release the `get_changes()` method of some time- +consuming refactorings take an optional `rope.base.taskhandle. +TaskHandle` parameter. You can use this object for stopping or +monitoring the progress of refactorings. + +""" +from rope.refactor.importutils import ImportOrganizer # noqa +from rope.refactor.topackage import ModuleToPackage # noqa + + +__all__ = [ + "rename", + "move", + "inline", + "extract", + "restructure", + "topackage", + "importutils", + "usefunction", + "change_signature", + "encapsulate_field", + "introduce_factory", + "introduce_parameter", + "localtofield", + "method_object", + "multiproject", +] +@language python +@tabwidth -4 + + +@path C:/Repos/ekr-rope/rope/refactor/importutils/ +from rope.base import libutils +from rope.base import pyobjects, exceptions, stdmods +from rope.refactor import occurrences +from rope.refactor.importutils import importinfo + + +@others +@language python +@tabwidth -4 + +class ImportInfoVisitor: + @others + +class Package: + table_name = "packages" + columns = [ + "package", + "path", + ] + + @others + objects = Query(table_name, columns) + + delete_by_package_name = objects.where("package = ?").delete_from() + +def dispatch(self, import_): + try: + method_name = "visit" + import_.import_info.__class__.__name__ + method = getattr(self, method_name) + return method(import_, import_.import_info) + except exceptions.ModuleNotFoundError: + pass + + +def visitEmptyImport(self, import_stmt, import_info): + pass + + +def visitNormalImport(self, import_stmt, import_info): + pass + + +def visitFromImport(self, import_stmt, import_info): + pass + + + +class RelativeToAbsoluteVisitor(ImportInfoVisitor): + @others + +def __init__(self, project, current_folder): + self.to_be_absolute = [] + self.project = project + self.folder = current_folder + self.context = importinfo.ImportContext(project, current_folder) + + +def visitNormalImport(self, import_stmt, import_info): + self.to_be_absolute.extend(self._get_relative_to_absolute_list(import_info)) + new_pairs = [] + for name, alias in import_info.names_and_aliases: + resource = self.project.find_module(name, folder=self.folder) + if resource is None: + new_pairs.append((name, alias)) + continue + absolute_name = libutils.modname(resource) + new_pairs.append((absolute_name, alias)) + if not import_info._are_name_and_alias_lists_equal( + new_pairs, import_info.names_and_aliases + ): + import_stmt.import_info = importinfo.NormalImport(new_pairs) + + +def _get_relative_to_absolute_list(self, import_info): + result = [] + for name, alias in import_info.names_and_aliases: + if alias is not None: + continue + resource = self.project.find_module(name, folder=self.folder) + if resource is None: + continue + absolute_name = libutils.modname(resource) + if absolute_name != name: + result.append((name, absolute_name)) + return result + + +def visitFromImport(self, import_stmt, import_info): + resource = import_info.get_imported_resource(self.context) + if resource is None: + return None + absolute_name = libutils.modname(resource) + if import_info.module_name != absolute_name: + import_stmt.import_info = importinfo.FromImport( + absolute_name, 0, import_info.names_and_aliases + ) + + + +class FilteringVisitor(ImportInfoVisitor): + @others + +@classmethod +def create_table(self, connection): + packages_table = "(package TEXT, path TEXT)" + connection.execute(f"CREATE TABLE IF NOT EXISTS packages{packages_table}") + + +def __init__(self, project, folder, can_select): + self.to_be_absolute = [] + self.project = project + self.can_select = self._transform_can_select(can_select) + self.context = importinfo.ImportContext(project, folder) + + +def _transform_can_select(self, can_select): + def can_select_name_and_alias(name, alias): + imported = name + if alias is not None: + imported = alias + return can_select(imported) + + return can_select_name_and_alias + + +def visitNormalImport(self, import_stmt, import_info): + new_pairs = [ + (name, alias) + for name, alias in import_info.names_and_aliases + if self.can_select(name, alias) + ] + return importinfo.NormalImport(new_pairs) + + +def visitFromImport(self, import_stmt, import_info): + if _is_future(import_info): + return import_info + new_pairs = [] + if import_info.is_star_import(): + for name in import_info.get_imported_names(self.context): + if self.can_select(name, None): + new_pairs.append(import_info.names_and_aliases[0]) + break + else: + for name, alias in import_info.names_and_aliases: + if self.can_select(name, alias): + new_pairs.append((name, alias)) + return importinfo.FromImport( + import_info.module_name, import_info.level, new_pairs + ) + + + +class RemovingVisitor(ImportInfoVisitor): + @others + +def __init__(self, project, folder, can_select): + self.to_be_absolute = [] + self.project = project + self.filtering = FilteringVisitor(project, folder, can_select) + + +def dispatch(self, import_): + result = self.filtering.dispatch(import_) + if result is not None: + import_.import_info = result + + + +class AddingVisitor(ImportInfoVisitor): + """A class for adding imports + + Given a list of `ImportInfo`, it tries to add each import to the + module and returns `True` and gives up when an import can be added + to older ones. + + """ + + @others + +def __init__(self, project, import_list): + self.project = project + self.import_list = import_list + self.import_info = None + + +def dispatch(self, import_): + for import_info in self.import_list: + self.import_info = import_info + if ImportInfoVisitor.dispatch(self, import_): + return True + + +@path C:/Repos/ekr-rope/rope/contrib/autoimport/ +""" +Functions to find importable names. + +Can extract names from source code of a python file, .so object, or builtin module. +""" + +import ast +import inspect +import logging +import pathlib +from importlib import import_module +from typing import Generator, List + +from .defs import ( + ModuleCompiled, + ModuleFile, + ModuleInfo, + Name, + NameType, + Package, + PartialName, + Source, +) + +logger = logging.getLogger(__name__) + + +@others +@language python +@tabwidth -4 + +# TODO: Handle adding relative and absolute imports +def visitNormalImport(self, import_stmt, import_info): + if not isinstance(self.import_info, import_info.__class__): + return False + # Adding ``import x`` and ``import x.y`` that results ``import x.y`` + if ( + len(import_info.names_and_aliases) + == len(self.import_info.names_and_aliases) + == 1 + ): + imported1 = import_info.names_and_aliases[0] + imported2 = self.import_info.names_and_aliases[0] + if imported1[1] == imported2[1] is None: + if imported1[0].startswith(imported2[0] + "."): + return True + if imported2[0].startswith(imported1[0] + "."): + import_stmt.import_info = self.import_info + return True + # Multiple imports using a single import statement is discouraged + # so we won't bother adding them. + if self.import_info._are_name_and_alias_lists_equal( + import_info.names_and_aliases, self.import_info.names_and_aliases + ): + return True + + +def visitFromImport(self, import_stmt, import_info): + if ( + isinstance(self.import_info, import_info.__class__) + and import_info.module_name == self.import_info.module_name + and import_info.level == self.import_info.level + ): + if import_info.is_star_import(): + return True + if self.import_info.is_star_import(): + import_stmt.import_info = self.import_info + return True + if self.project.prefs.get("split_imports"): + return ( + self.import_info.names_and_aliases == import_info.names_and_aliases + ) + new_pairs = list(import_info.names_and_aliases) + for pair in self.import_info.names_and_aliases: + if pair not in new_pairs: + new_pairs.append(pair) + import_stmt.import_info = importinfo.FromImport( + import_info.module_name, import_info.level, new_pairs + ) + return True + + + +class ExpandStarsVisitor(ImportInfoVisitor): + @others + +def __init__(self, project, folder, can_select): + self.project = project + self.filtering = FilteringVisitor(project, folder, can_select) + self.context = importinfo.ImportContext(project, folder) + + +def visitNormalImport(self, import_stmt, import_info): + self.filtering.dispatch(import_stmt) + + +def visitFromImport(self, import_stmt, import_info): + if import_info.is_star_import(): + new_pairs = [ + (name, None) for name in import_info.get_imported_names(self.context) + ] + new_import = importinfo.FromImport( + import_info.module_name, import_info.level, new_pairs + ) + import_stmt.import_info = self.filtering.visitFromImport(None, new_import) + else: + self.filtering.dispatch(import_stmt) + + + +class SelfImportVisitor(ImportInfoVisitor): + @others + +def __init__(self, project, current_folder, resource): + self.project = project + self.folder = current_folder + self.resource = resource + self.to_be_fixed = set() + self.to_be_renamed = set() + self.context = importinfo.ImportContext(project, current_folder) + + +def visitNormalImport(self, import_stmt, import_info): + new_pairs = [] + for name, alias in import_info.names_and_aliases: + resource = self.project.find_module(name, folder=self.folder) + if resource is not None and resource == self.resource: + imported = name + if alias is not None: + imported = alias + self.to_be_fixed.add(imported) + else: + new_pairs.append((name, alias)) + if not import_info._are_name_and_alias_lists_equal( + new_pairs, import_info.names_and_aliases + ): + import_stmt.import_info = importinfo.NormalImport(new_pairs) + + +def visitFromImport(self, import_stmt, import_info): + resource = import_info.get_imported_resource(self.context) + if resource is None: + return + if resource == self.resource: + self._importing_names_from_self(import_info, import_stmt) + return + pymodule = self.project.get_pymodule(resource) + new_pairs = [] + for name, alias in import_info.names_and_aliases: + try: + result = pymodule[name].get_object() + if ( + isinstance(result, pyobjects.PyModule) + and result.get_resource() == self.resource + ): + imported = name + if alias is not None: + imported = alias + self.to_be_fixed.add(imported) + else: + new_pairs.append((name, alias)) + except exceptions.AttributeNotFoundError: + new_pairs.append((name, alias)) + if not import_info._are_name_and_alias_lists_equal( + new_pairs, import_info.names_and_aliases + ): + import_stmt.import_info = importinfo.FromImport( + import_info.module_name, import_info.level, new_pairs + ) + + +def get_type_ast(node: ast.AST) -> NameType: + """Get the lsp type of a node.""" + if isinstance(node, ast.ClassDef): + return NameType.Class + if isinstance(node, ast.FunctionDef): + return NameType.Function + if isinstance(node, ast.Assign): + return NameType.Variable + return NameType.Variable # default value + + + +def _importing_names_from_self(self, import_info, import_stmt): + if not import_info.is_star_import(): + for name, alias in import_info.names_and_aliases: + if alias is not None: + self.to_be_renamed.add((alias, name)) + import_stmt.empty_import() + + + +class SortingVisitor(ImportInfoVisitor): + @others + +def __init__(self, project, current_folder): + self.project = project + self.folder = current_folder + self.standard = set() + self.third_party = set() + self.in_project = set() + self.future = set() + self.context = importinfo.ImportContext(project, current_folder) + + +def visitNormalImport(self, import_stmt, import_info): + if import_info.names_and_aliases: + name, alias = import_info.names_and_aliases[0] + resource = self.project.find_module(name, folder=self.folder) + self._check_imported_resource(import_stmt, resource, name) + + +def visitFromImport(self, import_stmt, import_info): + resource = import_info.get_imported_resource(self.context) + self._check_imported_resource(import_stmt, resource, import_info.module_name) + + +def _check_imported_resource(self, import_stmt, resource, imported_name): + info = import_stmt.import_info + if resource is not None and resource.project == self.project: + self.in_project.add(import_stmt) + elif _is_future(info): + self.future.add(import_stmt) + elif imported_name.split(".")[0] in stdmods.standard_modules(): + self.standard.add(import_stmt) + else: + self.third_party.add(import_stmt) + + + +class LongImportVisitor(ImportInfoVisitor): + @others + +def __init__(self, current_folder, project, maxdots, maxlength): + self.maxdots = maxdots + self.maxlength = maxlength + self.to_be_renamed = set() + self.current_folder = current_folder + self.project = project + self.new_imports = [] + + +def visitNormalImport(self, import_stmt, import_info): + for name, alias in import_info.names_and_aliases: + if alias is None and self._is_long(name): + self.to_be_renamed.add(name) + last_dot = name.rindex(".") + from_ = name[:last_dot] + imported = name[last_dot + 1 :] + self.new_imports.append( + importinfo.FromImport(from_, 0, ((imported, None),)) + ) + + +def _is_long(self, name): + return name.count(".") > self.maxdots or ( + "." in name and len(name) > self.maxlength + ) + + + +def get_names_from_file( + module: pathlib.Path, + package_name: str = "", + underlined: bool = False, + process_imports: bool = False, +) -> Generator[PartialName, None, None]: + """Get all the names from a given file using ast.""" + try: + root_node = ast.parse(module.read_bytes()) + except SyntaxError as error: + print(error) + return + for node in ast.iter_child_nodes(root_node): + if isinstance(node, ast.Assign): + for target in node.targets: + try: + assert isinstance(target, ast.Name) + if underlined or not target.id.startswith("_"): + yield PartialName( + target.id, + get_type_ast(node), + ) + except (AttributeError, AssertionError): + # TODO handle tuple assignment + pass + elif isinstance(node, (ast.FunctionDef, ast.ClassDef)): + if underlined or not node.name.startswith("_"): + yield PartialName( + node.name, + get_type_ast(node), + ) + elif process_imports and isinstance(node, ast.ImportFrom): + # When we process imports, we want to include names in it's own package. + if node.level == 0: + continue + if not node.module or package_name is node.module.split(".")[0]: + continue + for name in node.names: + if isinstance(name, ast.alias): + if name.asname: + real_name = name.asname + else: + real_name = name.name + else: + real_name = name + if underlined or not real_name.startswith("_"): + yield PartialName(real_name, get_type_ast(node)) + + + +class RemovePyNameVisitor(ImportInfoVisitor): + @others + +def __init__(self, project, pymodule, pyname, folder): + self.pymodule = pymodule + self.pyname = pyname + self.context = importinfo.ImportContext(project, folder) + + +def visitFromImport(self, import_stmt, import_info): + new_pairs = [] + if not import_info.is_star_import(): + for name, alias in import_info.names_and_aliases: + try: + pyname = self.pymodule[alias or name] + if occurrences.same_pyname(self.pyname, pyname): + continue + except exceptions.AttributeNotFoundError: + pass + new_pairs.append((name, alias)) + return importinfo.FromImport( + import_info.module_name, import_info.level, new_pairs + ) + + +def dispatch(self, import_): + result = ImportInfoVisitor.dispatch(self, import_) + if result is not None: + import_.import_info = result + + + +def _is_future(info): + return isinstance(info, importinfo.FromImport) and info.module_name == "__future__" + +@path C:/Repos/ekr-rope/rope/refactor/importutils/ +@others +@language python +@tabwidth -4 + +class ImportStatement: + """Represent an import in a module + + `readonly` attribute controls whether this import can be changed + by import actions or not. + + """ + + @others + +def __init__( + self, import_info, start_line, end_line, main_statement=None, blank_lines=0 +): + self.start_line = start_line + self.end_line = end_line + self.readonly = False + self.main_statement = main_statement + self._import_info = None + self.import_info = import_info + self._is_changed = False + self.new_start = None + self.blank_lines = blank_lines + + +def _get_import_info(self): + return self._import_info + + +def _set_import_info(self, new_import): + if ( + not self.readonly + and new_import is not None + and not new_import == self._import_info + ): + self._is_changed = True + self._import_info = new_import + + +@language rest +"""Rope object analysis and inference package + +Rope makes some simplifying assumptions about a python program. It +assumes that a program only performs assignments and function calls. +Tracking assignments is simple and `PyName` objects handle that. The +main problem is function calls. Rope uses these two approaches for +obtaining call information: + +* Static object analysis: `rope.base.pycore.PyCore.analyze_module()` + + It can analyze modules to obtain information about functions. This + is done by analyzing function calls in a module or scope. Currently + SOA analyzes the scopes that are changed while saving or when the + user asks to analyze a module. That is mainly because static + analysis is time-consuming. + +* Dynamic object analysis: `rope.base.pycore.PyCore.run_module()` + + When you run a module or your testsuite, when DOA is enabled, it + collects information about parameters passed to and objects returned + from functions. The main problem with this approach is that it is + quite slow; Not when looking up the information but when collecting + them. + +An instance of `rope.base.oi.objectinfo.ObjectInfoManager` can be used +for accessing these information. It saves the data in a +`rope.base.oi.objectdb.ObjectDB` internally. + +Now if our objectdb does not know anything about a function and we +need the value returned by it, static object inference, SOI, comes +into play. It analyzes function body and tries to infer the object +that is returned from it (we usually need the returned value for the +given parameter objects). + +Rope might collect and store information for other `PyName`, too. +For instance rope stores the object builtin containers hold. + +""" + + + +@language rest +@wrap + +*** git pull upstream master + +*** git diff master..ekr-walk-special-case --name-only + +*** git diff master..ekr-walk-special-case -- rope\base + +Install all required packages: (from contributing.rst) +pip install -e .[dev] + +Run all unit tests: (from contributing.rst) +pytest -v -W ignore::DeprecationWarning + +Run black: python -m black rope + +@language rest +@nosearch + +C:\Repos\rope>python310 -m pip install -e .[dev] + +C:\Repos\rope>C:\Python\Python3.10\python.exe -m pip install -e .[dev] +Obtaining file:///C:/Repos/rope + Installing build dependencies ... done + Checking if build backend supports build_editable ... done + Getting requirements to build editable ... done + Installing backend dependencies ... done + Preparing editable metadata (pyproject.toml) ... done +Collecting pytoolconfig[global]>=1.2.2 + Downloading pytoolconfig-1.2.2-py3-none-any.whl (16 kB) +Requirement already satisfied: +pytest-timeout>=2.1.0 in c:\python\python3.10\lib\site-packages (from rope==1.4.0) (2.1.0) +Requirement already satisfied: +pytest>=7.0.1 in c:\python\python3.10\lib\site-packages (from rope==1.4.0) (7.1.3) +Requirement already satisfied: +build>=0.7.0 in c:\python\python3.10\lib\site-packages (from rope==1.4.0) (0.7.0) +Requirement already satisfied: +tomli>=1.0.0 in c:\python\python3.10\lib\site-packages (from build>=0.7.0->rope==1.4.0) (2.0.1) +Requirement already satisfied: +colorama in c:\python\python3.10\lib\site-packages (from build>=0.7.0->rope==1.4.0) (0.4.5) +Requirement already satisfied: +packaging>=19.0 in c:\python\python3.10\lib\site-packages (from build>=0.7.0->rope==1.4.0) (21.3) +Requirement already satisfied: +pep517>=0.9.1 in c:\python\python3.10\lib\site-packages (from build>=0.7.0->rope==1.4.0) (0.12.0) +Requirement already satisfied: +iniconfig in c:\python\python3.10\lib\site-packages (from pytest>=7.0.1->rope==1.4.0) (1.1.1) +Requirement already satisfied: +pluggy<2.0,>=0.12 in c:\python\python3.10\lib\site-packages (from pytest>=7.0.1->rope==1.4.0) (1.0.0) +Requirement already satisfied: +py>=1.8.2 in c:\python\python3.10\lib\site-packages (from pytest>=7.0.1->rope==1.4.0) (1.11.0) +Requirement already satisfied: +attrs>=19.2.0 in c:\python\python3.10\lib\site-packages (from pytest>=7.0.1->rope==1.4.0) (22.1.0) +Collecting appdirs>=1.4.4 + Downloading appdirs-1.4.4-py2.py3-none-any.whl (9.6 kB) +Requirement already satisfied: +pyparsing!=3.0.5,>=2.0.2 in c:\python\python3.10\lib\site-packages (from packaging>=19.0->build>=0.7.0->rope==1.4.0) (3.0.8) +Building wheels for collected packages: rope + Building editable for rope (pyproject.toml) ... done + Created wheel for rope: filename=rope-1.4.0-0.editable-py3-none-any.whl size=4230 sha256=2c7cdd9e629f640d7aad483db7a304292b53f109a9edf1c74f39d556f5542584 + Stored in directory: C:\Users\Dev\AppData\Local\Temp\pip-ephem-wheel-cache-amm6vn1a\wheels\2d\c8\16\7b23335844cf0cb3ba7735e296d501c516251327f7d24e7766 + +Successfully built rope +Installing collected packages: appdirs, pytoolconfig, rope +Successfully installed appdirs-1.4.4 pytoolconfig-1.2.2 rope-1.4.0 + +**appdirs**: module for determining appropriate platform-specific dirs, e.g. a "user data dir". + +**pytoolconfig**: +- manage configuration for python tools, such as black and rope +- add support for a pyproject.toml configuration file. +c.backup_helper(sub_dir='rope') + + + + +import rope.base.builtins +import rope.base.codeanalyze +import rope.base.evaluate +import rope.base.libutils +import rope.base.oi.soi +import rope.base.pyscopes +from rope.base import ( + pynamesdef as pynames, + exceptions, + ast, + astutils, + pyobjects, + fscommands, + arguments, + utils, +) + + + +@path C:/Repos/ekr-rope/rope/base/ +from rope.base import ast + + +def get_name_levels(node): + """Return a list of ``(name, level)`` tuples for assigned names + + The `level` is `None` for simple assignments and is a list of + numbers for tuple assignments for example in:: + + a, (b, c) = x + + The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for + `c` is ``[1, 1]``. + + """ + visitor = _NodeNameCollector() + ast.walk(node, visitor) + return visitor.names + + +@others +@language python +@tabwidth -4 + + + + + + +class _NodeNameCollector: + @others + +def _Slice(self, node): + self._add_node(node) + +def __init__(self, levels=None): + self.names = [] + self.levels = levels + self.index = 0 + + +def _add_node(self, node): + new_levels = [] + if self.levels is not None: + new_levels = list(self.levels) + new_levels.append(self.index) + self.index += 1 + self._added(node, new_levels) + + +def _added(self, node, levels): + if hasattr(node, "id"): + self.names.append((node.id, levels)) + + +def _Name(self, node): + self._add_node(node) + + +def _ExceptHandler(self, node): + self.names.append((node.name, [])) + + +def _Tuple(self, node): + new_levels = [] + if self.levels is not None: + new_levels = list(self.levels) + new_levels.append(self.index) + self.index += 1 + visitor = _NodeNameCollector(new_levels) + for child in ast.get_child_nodes(node): + ast.walk(child, visitor) + self.names.extend(visitor.names) + + +def _Subscript(self, node): + self._add_node(node) + + +def _Attribute(self, node): + self._add_node(node) + + + + +When checked, the Find and Change commands ignore the case of alphabetic characters when determining matches. + + +@language rest +@wrap + +https://github.com/edreamleo/ekr-rope/pull/5 + +- Remove pylint complaint:consider using decorator instead of class method. +- Use type annotations instead of type comments. + +@language python +@nosearch + + + + + +@language rest +@wrap + +? Remove @multi ? + +@language python +@nosearch + +@nosearch +@nosearch + +# Regex, Head, Body + +# found 49 nodes + +# Fail: test_new_style_relative_imports + +@nosearch +@nosearch + +# Word, Head, Body + +# found 38 nodes + + + + + + +@nosearch + +# Word, Head, Body + +# found 7 nodes +@language rest +@wrap + +ropetest/pycoretest.py::PyCoreInProjectsTest::test_new_style_relative_imports1 + +=== Good + +test_new_style_relative_imports1 mod1 <rope.base.resources.File "pkg/mod1.py" at 0x27909c1e650> +test_new_style_relative_imports1 mod2 <rope.base.resources.File "pkg/mod2.py" at 0x27909c1e860> +test_new_style_relative_imports1 mod1_object <rope.base.pyobjectsdef.PyModule "pkg.mod1" at 0x27909ca08e0> +test_new_style_relative_imports1 mod2_object <rope.base.pyobjectsdef.PyModule "pkg.mod2" at 0x27909c1ebf0> + +*** _ImportFrom: imported_module.module_name: '' + +=== Bad + +test_new_style_relative_imports1 mod1 <rope.base.resources.File "pkg/mod1.py" at 0x20a074224d0> +test_new_style_relative_imports1 mod2 <rope.base.resources.File "pkg/mod2.py" at 0x20a074226e0> +test_new_style_relative_imports1 mod1_object <rope.base.pyobjectsdef.PyModule "pkg.mod1" at 0x20a074a8760> +test_new_style_relative_imports1 mod2_object <rope.base.pyobjectsdef.PyModule "pkg.mod2" at 0x20a07422a70> + +*** _ImportFrom: imported_module.module_name: None + +@nosearch +@nosearch + +# Word, Head, Body + +# found 4 nodes +@nosearch + +# Word, Head, Body + +# found 9 nodes +@path C:/Repos/ekr-rope/rope/base/ +@nopyflakes +import ast +from ast import * + +from rope.base import fscommands + + +@others +@language python +@tabwidth -4 + +def parse(source, filename="<string>"): + # NOTE: the raw string should be given to `compile` function + if isinstance(source, str): + source = fscommands.unicode_to_file_data(source) + if b"\r" in source: + source = source.replace(b"\r\n", b"\n").replace(b"\r", b"\n") + if not source.endswith(b"\n"): + source += b"\n" + try: + return ast.parse(source, filename="<unknown>") + except (TypeError, ValueError) as e: + error = SyntaxError() + error.lineno = 1 + error.filename = filename + error.msg = str(e) + raise error + + + +def walk(node, walker) -> None: + """Walk the syntax tree""" + method_name = "_" + node.__class__.__name__ + method = getattr(walker, method_name, None) + if method is not None: + if isinstance(node, ast.ImportFrom) and node.module is None: + # In python < 2.7 ``node.module == ''`` for relative imports + # but for python 2.7 it is None. Generalizing it to ''. + node.module = "" + method(node) + return + for child in get_child_nodes(node): + walk(child, walker) + + + +def get_child_nodes(node): + if isinstance(node, ast.Module): + return node.body + result = [] + if node._fields is not None: + for name in node._fields: + child = getattr(node, name) + if isinstance(child, list): + for entry in child: + if isinstance(entry, ast.AST): + result.append(entry) + if isinstance(child, ast.AST): + result.append(child) + return result + + + +def call_for_nodes(node, callback, recursive=False): + """If callback returns `True` the child nodes are skipped""" + result = callback(node) + if recursive and not result: + for child in get_child_nodes(node): + call_for_nodes(child, callback, recursive) + + + +def get_children(node): + result = [] + if node._fields is not None: + for name in node._fields: + if name in ["lineno", "col_offset"]: + continue + child = getattr(node, name) + result.append(child) + return result + +@nosearch + +# Word, Head, Body + +# found 8 nodes +@nosearch + +# Word, Head, Body + +# found 23 nodes +@nosearch + +# Word, Body + +# found 8 nodes +@nosearch + +# B007 Loop control variable 'i' not used within the loop body. If this is intended, start the name with an underscore. + +.\rope\base\codeanalyze.py:184:20: B007 Loop control variable 'end' not used within the loop body. + +.\rope\base\history.py:109:13: B007 Loop control variable 'i' not used within the loop body. +.\rope\base\history.py:119:13: B007 Loop control variable 'i' not used within the loop body. + +.\rope\base\project.py:159:13: B007 Loop control variable 'i' not used within the loop body. + +.\rope\base\oi\type_hinting\providers\numpydocstrings.py:22:29: B007 Loop control variable 'p_descr' not used within the loop body. + +.\rope\contrib\changestack.py:35:13: B007 Loop control variable 'i' not used within the loop body. + +.\rope\contrib\generate.py:377:23: B007 Loop control variable 'value' not used within the loop body. + +.\rope\refactor\move.py:709:13: B007 Loop control variable 'occurrence' not used within the loop body. + +.\rope\refactor\patchedast.py:192:13: B007 Loop control variable 'i' not used within the loop body. +.\rope\refactor\patchedast.py:198:13: B007 Loop control variable 'i' not used within the loop body. + +.\rope\refactor\importutils\module_imports.py:577:13: B007 Loop control variable 'index' not used within the loop body. + +# B011 Do not call assert False since python -O removes these calls. Instead callers should raise AssertionError(). +.\rope\refactor\extract.py:906:13: B011 Do not call assert False + +.\rope\refactor\patchedast.py:403:9: B011 Do not call assert False + +# E741 ambiguous variable name + +.\rope\base\pyscopes.py:331:13: E741 ambiguous variable name 'l' +.\rope\refactor\sourceutils.py:23:9: E741 ambiguous variable name 'l' +.\ropetest\builtinstest.py:360:9: E741 ambiguous variable name 'l' + +# All others + +.\rope\base\utils\pycompat.py:2:1: F401 'builtins' imported but unused + +.\rope\base\oi\soa.py:25:9: E731 do not assign a lambda expression, use a def +.\rope\base\oi\soa.py:26:9: E731 do not assign a lambda expression, use a def + +.\rope\base\pynamesdef.py:3:1: F403 'from rope.base.pynames import *' used; unable to detect undefined names +.\rope\base\pynamesdef.py:16:6: F405 'utils' may be undefined, or defined from star imports: rope.base.pynames + +# Disambiguate placeholder classes + +# PR: https://github.com/python-rope/rope/pull/539/ + + +@language rest +@wrap + +PR: https://github.com/python-rope/rope/pull/540 + +To do: create new PR that doesn't change so much. + + +# git-diff-pr won't work at present. +from leo.commands import editFileCommands as efc + +efc.GitDiffController(c).diff_two_revs( + rev1='master', # Old + # rev2='ekr-walk-special-case', # New + rev2='HEAD' +) + +g.cls() +import os +import leo.commands.editFileCommands as efc +path = g.os_path_finalize_join(g.app.loadDir, '..', '..') +print('path:', path) +os.chdir(path) + +# Any revspec is valid as an argument to the "branch1" and "branch2" args. +# See https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection + +efc.GitDiffController(c).diff_two_branches( + branch1='6.6.4', # old branch/rev + branch2='ekr-index', # new branch/rev + fn='leo/plugins/qt_text.py', # Don't use back slashes. +) + +g.cls() + +# Monkey-patched git-diff-pr command. +import leo.commands.editFileCommands as efc + +rev1 = 'master' +rev2 = 'ekr-walk-special-case' +x = efc.GitDiffController(c) + +@others + +# Monkey-patch, with x bound. +x.make_diff_outlines = make_diff_outlines_ignoring_comments +x.diff_two_revs(rev1, rev2) + +def make_diff_outlines_ignoring_comments(c1, c2, fn, rev1='', rev2=''): + """Create an outline-oriented diff from the *hidden* outlines c1 and c2.""" + self = x + added, deleted, changed = self.compute_dicts(c1, c2) + table = ( + (added, 'Added'), + (deleted, 'Deleted'), + (changed, 'Changed')) + for d, kind in table: + if kind.lower() == 'changed': + for key in d: + v1, v2 = d.get(key) + v1.b = strip_comments(v1.b) + v2.b = strip_comments(v2.b) + self.create_compare_node(c1, c2, d, kind, rev1, rev2) + +def strip_comments(aString): + """ + Strip everything that looks like a comment from aString. + It's fine, for now, to ignore strings and docstrings. + """ + result = [] + lines = g.splitLines(aString) + for s in lines: + if s.strip().startswith('#@'): + # Retain everything that looks like a sentinel. + result.append(s) + else: + # Strip the comment, ignoring the end of the line. + i = s.find('#') + if i == -1: + result.append(s) + else: + tail = s[:i] + if tail.strip(): + result.append(tail.rstrip() + '\n') + return ''.join(result) + +from leo.commands import editFileCommands as efc + +efc.GitDiffController(c).diff_two_revs( + rev1='master', # Old + rev2='HEAD' # New +) + +@ignore +@nosearch + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,14 +1,9 @@ +-def walk(node, walker) -> None: ++def walk(node, walker): + """Walk the syntax tree""" + method_name = "_" + node.__class__.__name__ + method = getattr(walker, method_name, None) + if method is not None: +- if isinstance(node, ast.ImportFrom) and node.module is None: +- # In python < 2.7 ``node.module == ''`` for relative imports +- # but for python 2.7 it is None. Generalizing it to ''. +- node.module = "" +- method(node) +- return ++ return method(node) + for child in get_child_nodes(node): + walk(child, walker) + +@language python + +def walk(node, walker) -> None: + """Walk the syntax tree""" + method_name = "_" + node.__class__.__name__ + method = getattr(walker, method_name, None) + if method is not None: + if isinstance(node, ast.ImportFrom) and node.module is None: + # In python < 2.7 ``node.module == ''`` for relative imports + # but for python 2.7 it is None. Generalizing it to ''. + node.module = "" + method(node) + return + for child in get_child_nodes(node): + walk(child, walker) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -22,17 +22,12 @@ + raise error + + +-def walk(node, walker) -> None: ++def walk(node, walker): + """Walk the syntax tree""" + method_name = "_" + node.__class__.__name__ + method = getattr(walker, method_name, None) + if method is not None: +- if isinstance(node, ast.ImportFrom) and node.module is None: +- # In python < 2.7 ``node.module == ''`` for relative imports +- # but for python 2.7 it is None. Generalizing it to ''. +- node.module = "" +- method(node) +- return ++ return method(node) + for child in get_child_nodes(node): + walk(child, walker) +@language python + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -537,6 +537,12 @@ + + def _ImportFrom(self, node): + level = 0 ++ # From walk ++ assert isinstance(node, ast.ImportFrom) ++ if node.module is None: ++ # In python < 2.7 ``node.module == ''`` for relative imports ++ # but for python 2.7 it is None. Generalizing it to ''. ++ node.module = "" + if node.level: + level = node.level + imported_module = pynames.ImportedModule(self.get_module(), node.module, level) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,11 @@ + def _ImportFrom(self, node): + level = 0 ++ # From walk ++ assert isinstance(node, ast.ImportFrom) ++ if node.module is None: ++ # In python < 2.7 ``node.module == ''`` for relative imports ++ # but for python 2.7 it is None. Generalizing it to ''. ++ node.module = "" + if node.level: + level = node.level + imported_module = pynames.ImportedModule(self.get_module(), node.module, level) +@language python + +def _ImportFrom(self, node): + level = 0 + if node.level: + level = node.level + imported_module = pynames.ImportedModule(self.get_module(), node.module, level) + if self._is_ignored_import(imported_module): + return + if len(node.names) == 1 and node.names[0].name == "*": + if isinstance(self.owner_object, PyModule): + self.owner_object.star_imports.append(StarImport(imported_module)) + else: + for imported_name in node.names: + imported = imported_name.name + alias = imported_name.asname + if alias is not None: + imported = alias + self.names[imported] = pynames.ImportedName( + imported_module, imported_name.name + ) + + +@ignore +@nosearch + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,20 +1,19 @@ + @path C:/Repos/ekr-rope/rope/base/ ++import ast + from operator import itemgetter + from typing import Optional, Tuple + ++import rope.base.astutils as au + import rope.base.builtins +-import rope.base.pynames + import rope.base.pyobjects + from rope.base import ( +- ast, +- astutils, ++ arguments, + exceptions, ++ pynames, + pyobjects, + pyobjectsdef, +- arguments, + worder, + ) +- + + BadIdentifierError = exceptions.BadIdentifierError + +@language python + +@path C:/Repos/ekr-rope/rope/base/ +from operator import itemgetter +from typing import Optional, Tuple + +import rope.base.builtins +import rope.base.pynames +import rope.base.pyobjects +from rope.base import ( + ast, + astutils, + exceptions, + pyobjects, + pyobjectsdef, + arguments, + worder, +) + + +BadIdentifierError = exceptions.BadIdentifierError + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def eval_node2(scope, node): + evaluator = StatementEvaluator(scope) +- ast.walk(node, evaluator) ++ au.walk(node, evaluator) + return evaluator.old_result, evaluator.result + + +@language python + +def eval_node2(scope, node): + evaluator = StatementEvaluator(scope) + ast.walk(node, evaluator) + return evaluator.old_result, evaluator.result + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + def eval_str2(holding_scope, name): + try: + # parenthesizing for handling cases like 'a_var.\nattr' +- node = ast.parse("(%s)" % name) ++ node = au.parse("(%s)" % name) + except SyntaxError: + raise BadIdentifierError("Not a resolvable python identifier selected.") + return eval_node2(holding_scope, node) +@language python + +def eval_str2(holding_scope, name): + try: + # parenthesizing for handling cases like 'a_var.\nattr' + node = ast.parse("(%s)" % name) + except SyntaxError: + raise BadIdentifierError("Not a resolvable python identifier selected.") + return eval_node2(holding_scope, node) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + def get_primary_and_pyname_at( + self, + offset: int, +-) -> Tuple[Optional[rope.base.pynames.PyName], Optional[rope.base.pynames.PyName]]: ++) -> Tuple[Optional[pynames.PyName], Optional[pynames.PyName]]: + lineno = self.lines.get_line_number(offset) + holding_scope = self.module_scope.get_inner_scope_for_offset(offset) + # function keyword parameter +@@ -12,7 +12,7 @@ + parameter_name = pyobject.get_parameters().get(keyword_name, None) + return (None, parameter_name) + elif isinstance(pyobject, pyobjects.AbstractFunction): +- parameter_name = rope.base.pynames.ParameterName() ++ parameter_name = pynames.ParameterName() + return (None, parameter_name) + # class body + if self._is_defined_in_class_body(holding_scope, offset, lineno): +@language python + +def get_primary_and_pyname_at( + self, + offset: int, +) -> Tuple[Optional[rope.base.pynames.PyName], Optional[rope.base.pynames.PyName]]: + lineno = self.lines.get_line_number(offset) + holding_scope = self.module_scope.get_inner_scope_for_offset(offset) + # function keyword parameter + if self.worder.is_function_keyword_parameter(offset): + keyword_name = self.worder.get_word_at(offset) + pyobject = self.get_enclosing_function(offset) + if isinstance(pyobject, pyobjectsdef.PyFunction): + parameter_name = pyobject.get_parameters().get(keyword_name, None) + return (None, parameter_name) + elif isinstance(pyobject, pyobjects.AbstractFunction): + parameter_name = rope.base.pynames.ParameterName() + return (None, parameter_name) + # class body + if self._is_defined_in_class_body(holding_scope, offset, lineno): + class_scope = holding_scope + if lineno == holding_scope.get_start(): + class_scope = holding_scope.parent + name = self.worder.get_primary_at(offset).strip() + try: + return (None, class_scope.pyobject[name]) + except rope.base.exceptions.AttributeNotFoundError: + return (None, None) + # function header + if self._is_function_name_in_function_header(holding_scope, offset, lineno): + name = self.worder.get_primary_at(offset).strip() + return (None, holding_scope.parent[name]) + # module in a from statement or an imported name that is aliased + if self.worder.is_from_statement_module( + offset + ) or self.worder.is_import_statement_aliased_module(offset): + module = self.worder.get_primary_at(offset) + module_pyname = self._find_module(module) + return (None, module_pyname) + if self.worder.is_from_aliased(offset): + name = self.worder.get_from_aliased(offset) + else: + name = self.worder.get_primary_at(offset) + return eval_str2(holding_scope, name) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,7 @@ + dots = 0 + while module_name[dots] == ".": + dots += 1 +- return rope.base.pynames.ImportedModule( ++ return pynames.ImportedModule( + self.module_scope.pyobject, module_name[dots:], dots + ) + +@language python + +def _find_module(self, module_name): + dots = 0 + while module_name[dots] == ".": + dots += 1 + return rope.base.pynames.ImportedModule( + self.module_scope.pyobject, module_name[dots:], dots + ) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + def _Attribute(self, node): + pyname = eval_node(self.scope, node.value) + if pyname is None: +- pyname = rope.base.pynames.UnboundName() ++ pyname = pynames.UnboundName() + self.old_result = pyname + if pyname.get_object() != rope.base.pyobjects.get_unknown(): + try: +@language python + +def _Attribute(self, node): + pyname = eval_node(self.scope, node.value) + if pyname is None: + pyname = rope.base.pynames.UnboundName() + self.old_result = pyname + if pyname.get_object() != rope.base.pyobjects.get_unknown(): + try: + self.result = pyname.get_object()[node.attr] + except exceptions.AttributeNotFoundError: + self.result = None + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -14,7 +14,7 @@ + result = _get_returned(new_function) + if result is None or result == rope.base.pyobjects.get_unknown(): + result = rope.base.pyobjects.PyObject(pyobject) +- self.result = rope.base.pynames.UnboundName(pyobject=result) ++ self.result = pynames.UnboundName(pyobject=result) + return + + pyfunction = None +@@ -23,7 +23,7 @@ + elif "__call__" in pyobject: + pyfunction = pyobject["__call__"].get_object() + if pyfunction is not None: +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=_get_returned(pyfunction) + ) + +@language python + +def _Call(self, node): + primary, pyobject = self._get_primary_and_object_for_node(node.func) + if pyobject is None: + return + + def _get_returned(pyobject): + args = arguments.create_arguments(primary, pyobject, node, self.scope) + return pyobject.get_returned_object(args) + + if isinstance(pyobject, rope.base.pyobjects.AbstractClass): + result = None + if "__new__" in pyobject: + new_function = pyobject["__new__"].get_object() + result = _get_returned(new_function) + if result is None or result == rope.base.pyobjects.get_unknown(): + result = rope.base.pyobjects.PyObject(pyobject) + self.result = rope.base.pynames.UnboundName(pyobject=result) + return + + pyfunction = None + if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): + pyfunction = pyobject + elif "__call__" in pyobject: + pyfunction = pyobject["__call__"].get_object() + if pyfunction is not None: + self.result = rope.base.pynames.UnboundName( + pyobject=_get_returned(pyfunction) + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _Str(self, node): +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_str() + ) + +@language python + +def _Str(self, node): + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_str() + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,4 @@ + def _get_builtin_name(self, type_name): + pytype = rope.base.builtins.builtins[type_name].get_object() +- return rope.base.pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) ++ return pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) + +@language python + +def _get_builtin_name(self, type_name): + pytype = rope.base.builtins.builtins[type_name].get_object() + return rope.base.pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _BinOp(self, node): +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + self._get_object_for_node(node.left) + ) + +@language python + +def _BinOp(self, node): + self.result = rope.base.pynames.UnboundName( + self._get_object_for_node(node.left) + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,5 +2,5 @@ + pyobject = self._get_object_for_node(node.values[0]) + if pyobject is None: + pyobject = self._get_object_for_node(node.values[1]) +- self.result = rope.base.pynames.UnboundName(pyobject) ++ self.result = pynames.UnboundName(pyobject) + +@language python + +def _BoolOp(self, node): + pyobject = self._get_object_for_node(node.values[0]) + if pyobject is None: + pyobject = self._get_object_for_node(node.values[1]) + self.result = rope.base.pynames.UnboundName(pyobject) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _UnaryOp(self, node): +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + self._get_object_for_node(node.operand) + ) + +@language python + +def _UnaryOp(self, node): + self.result = rope.base.pynames.UnboundName( + self._get_object_for_node(node.operand) + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -9,7 +9,7 @@ + keys = self._get_object_for_node(keys) + if values: + values = self._get_object_for_node(values) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_dict(keys, values) + ) + +@language python + +def _Dict(self, node): + keys = None + values = None + if node.keys and node.keys[0]: + keys, values = next( + iter(filter(itemgetter(0), zip(node.keys, node.values))), (None, None) + ) + if keys: + keys = self._get_object_for_node(keys) + if values: + values = self._get_object_for_node(values) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_dict(keys, values) + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,7 @@ + holding = None + if node.elts: + holding = self._get_object_for_node(node.elts[0]) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_list(holding) + ) + +@language python + +def _List(self, node): + holding = None + if node.elts: + holding = self._get_object_for_node(node.elts[0]) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_list(holding) + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def _ListComp(self, node): + pyobject = self._what_does_comprehension_hold(node) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_list(pyobject) + ) + +@language python + +def _ListComp(self, node): + pyobject = self._what_does_comprehension_hold(node) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_list(pyobject) + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def _GeneratorExp(self, node): + pyobject = self._what_does_comprehension_hold(node) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_iterator(pyobject) + ) + +@language python + +def _GeneratorExp(self, node): + pyobject = self._what_does_comprehension_hold(node) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_iterator(pyobject) + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,7 +6,7 @@ + objects.append(pyobject) + else: + objects.append(self._get_object_for_node(node.elts[0])) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_tuple(*objects) + ) + +@language python + +def _Tuple(self, node): + objects = [] + if len(node.elts) < 4: + for stmt in node.elts: + pyobject = self._get_object_for_node(stmt) + objects.append(pyobject) + else: + objects.append(self._get_object_for_node(node.elts[0])) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_tuple(*objects) + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -12,7 +12,7 @@ + if other_args: + args += other_args + arguments_ = arguments.Arguments(args, self.scope) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=called.get_returned_object(arguments_) + ) + +@language python + +def _call_function(self, node, function_name, other_args=None): + pyname = eval_node(self.scope, node) + if pyname is not None: + pyobject = pyname.get_object() + else: + return + if function_name in pyobject: + called = pyobject[function_name].get_object() + if not called or not isinstance(called, pyobjects.AbstractFunction): + return + args = [node] + if other_args: + args += other_args + arguments_ = arguments.Arguments(args, self.scope) + self.result = rope.base.pynames.UnboundName( + pyobject=called.get_returned_object(arguments_) + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _Lambda(self, node): +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.Lambda(node, self.scope) + ) + +@language python + +def _Lambda(self, node): + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.Lambda(node, self.scope) + ) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,8 @@ + def _get_evaluated_names(targets, assigned, module, evaluation, lineno): + result = {} +- for name, levels in astutils.get_name_levels(targets): +- assignment = rope.base.pynames.AssignmentValue(assigned, levels, evaluation) +- # XXX: this module should not access `rope.base.pynamesdef`! +- pyname = rope.base.pynamesdef.AssignedName(lineno, module) ++ for name, levels in au.get_name_levels(targets): ++ assignment = pynames.AssignmentValue(assigned, levels, evaluation) ++ pyname = rope.base.pynames.AssignedName(lineno, module) + pyname.assignments.append(assignment) + result[name] = pyname + return result +@language python + +def _get_evaluated_names(targets, assigned, module, evaluation, lineno): + result = {} + for name, levels in astutils.get_name_levels(targets): + assignment = rope.base.pynames.AssignmentValue(assigned, levels, evaluation) + # XXX: this module should not access `rope.base.pynamesdef`! + pyname = rope.base.pynamesdef.AssignedName(lineno, module) + pyname.assignments.append(assignment) + result[name] = pyname + return result + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,8 @@ +-import rope.base.ast ++import ast ++ ++import rope.base.astutils as au + import rope.base.oi.soi +-import rope.base.pynames +-from rope.base import pyobjects, evaluate, astutils, arguments +- ++from rope.base import arguments, evaluate, pyobjects, pynames + + def analyze_module(pycore, pymodule, should_analyze, search_subscopes, followed_calls): + """Analyze `pymodule` for static object inference +@@ -33,8 +33,8 @@ + if not followed_calls: + _follow = None + visitor = SOAVisitor(pycore, pydefined, _follow) +- for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): +- rope.base.ast.walk(child, visitor) ++ for child in au.get_child_nodes(pydefined.get_ast()): ++ au.walk(child, visitor) + + + class SOAVisitor: +@@ -51,8 +51,8 @@ + pass + + def _Call(self, node): +- for child in rope.base.ast.get_child_nodes(node): +- rope.base.ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + primary, pyname = evaluate.eval_node2(self.scope, node.func) + if pyname is None: + return +@@ -63,7 +63,7 @@ + pyclass = pyfunction + if "__init__" in pyfunction: + pyfunction = pyfunction["__init__"].get_object() +- pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass)) ++ pyname = pynames.UnboundName(pyobjects.PyObject(pyclass)) + args = self._args_with_self(primary, pyname, pyfunction, node) + elif "__call__" in pyfunction: + pyfunction = pyfunction["__call__"].get_object() +@@ -99,23 +99,23 @@ + ] + + def _AnnAssign(self, node): +- for child in rope.base.ast.get_child_nodes(node): +- rope.base.ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + visitor = _SOAAssignVisitor() + nodes = [] + +- rope.base.ast.walk(node.target, visitor) ++ au.walk(node.target, visitor) + nodes.extend(visitor.nodes) + + self._evaluate_assign_value(node, nodes, type_hint=node.annotation) + + def _Assign(self, node): +- for child in rope.base.ast.get_child_nodes(node): +- rope.base.ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + visitor = _SOAAssignVisitor() + nodes = [] + for child in node.targets: +- rope.base.ast.walk(child, visitor) ++ au.walk(child, visitor) + nodes.extend(visitor.nodes) + self._evaluate_assign_value(node, nodes) + +@@ -124,12 +124,12 @@ + instance = evaluate.eval_node(self.scope, subscript.value) + args_pynames = [evaluate.eval_node(self.scope, subscript.slice)] + value = rope.base.oi.soi._infer_assignment( +- rope.base.pynames.AssignmentValue( ++ pynames.AssignmentValue( + node.value, levels, type_hint=type_hint + ), + self.pymodule, + ) +- args_pynames.append(rope.base.pynames.UnboundName(value)) ++ args_pynames.append(pynames.UnboundName(value)) + if instance is not None and value is not None: + pyobject = instance.get_object() + if "__setitem__" in pyobject: +@@ -139,13 +139,13 @@ + # IDEA: handle `__setslice__`, too + + +-class _SOAAssignVisitor(astutils._NodeNameCollector): ++class _SOAAssignVisitor(au._NodeNameCollector): + def __init__(self): + super().__init__() + self.nodes = [] + + def _added(self, node, levels): +- if isinstance(node, rope.base.ast.Subscript) and isinstance( +- node.slice, (rope.base.ast.Index, rope.base.ast.expr) ++ if isinstance(node, ast.Subscript) and isinstance( ++ node.slice, (ast.Index, ast.expr) + ): + self.nodes.append((node, levels)) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,9 @@ + @path C:/Repos/ekr-rope/rope/base/oi/ +-import rope.base.ast ++import ast ++ ++import rope.base.astutils as au + import rope.base.oi.soi +-import rope.base.pynames +-from rope.base import pyobjects, evaluate, astutils, arguments +- ++from rope.base import arguments, evaluate, pyobjects, pynames + + @others + @language python +@language python + +@path C:/Repos/ekr-rope/rope/base/oi/ +import rope.base.ast +import rope.base.oi.soi +import rope.base.pynames +from rope.base import pyobjects, evaluate, astutils, arguments + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -17,7 +17,7 @@ + if not followed_calls: + _follow = None + visitor = SOAVisitor(pycore, pydefined, _follow) +- for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): +- rope.base.ast.walk(child, visitor) ++ for child in au.get_child_nodes(pydefined.get_ast()): ++ au.walk(child, visitor) + + +@language python + +def _analyze_node(pycore, pydefined, should_analyze, search_subscopes, followed_calls): + if search_subscopes(pydefined): + for scope in pydefined.get_scope().get_scopes(): + _analyze_node( + pycore, scope.pyobject, should_analyze, search_subscopes, followed_calls + ) + if should_analyze(pydefined): + new_followed_calls = max(0, followed_calls - 1) + return_true = lambda pydefined: True + return_false = lambda pydefined: False + + def _follow(pyfunction): + _analyze_node( + pycore, pyfunction, return_true, return_false, new_followed_calls + ) + + if not followed_calls: + _follow = None + visitor = SOAVisitor(pycore, pydefined, _follow) + for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): + rope.base.ast.walk(child, visitor) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def _Call(self, node): +- for child in rope.base.ast.get_child_nodes(node): +- rope.base.ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + primary, pyname = evaluate.eval_node2(self.scope, node.func) + if pyname is None: + return +@@ -11,7 +11,7 @@ + pyclass = pyfunction + if "__init__" in pyfunction: + pyfunction = pyfunction["__init__"].get_object() +- pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass)) ++ pyname = pynames.UnboundName(pyobjects.PyObject(pyclass)) + args = self._args_with_self(primary, pyname, pyfunction, node) + elif "__call__" in pyfunction: + pyfunction = pyfunction["__call__"].get_object() +@language python + +def _Call(self, node): + for child in rope.base.ast.get_child_nodes(node): + rope.base.ast.walk(child, self) + primary, pyname = evaluate.eval_node2(self.scope, node.func) + if pyname is None: + return + pyfunction = pyname.get_object() + if isinstance(pyfunction, pyobjects.AbstractFunction): + args = arguments.create_arguments(primary, pyfunction, node, self.scope) + elif isinstance(pyfunction, pyobjects.PyClass): + pyclass = pyfunction + if "__init__" in pyfunction: + pyfunction = pyfunction["__init__"].get_object() + pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass)) + args = self._args_with_self(primary, pyname, pyfunction, node) + elif "__call__" in pyfunction: + pyfunction = pyfunction["__call__"].get_object() + args = self._args_with_self(primary, pyname, pyfunction, node) + else: + return + self._call(pyfunction, args) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,10 +1,10 @@ + def _AnnAssign(self, node): +- for child in rope.base.ast.get_child_nodes(node): +- rope.base.ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + visitor = _SOAAssignVisitor() + nodes = [] + +- rope.base.ast.walk(node.target, visitor) ++ au.walk(node.target, visitor) + nodes.extend(visitor.nodes) + + self._evaluate_assign_value(node, nodes, type_hint=node.annotation) +@language python + +def _AnnAssign(self, node): + for child in rope.base.ast.get_child_nodes(node): + rope.base.ast.walk(child, self) + visitor = _SOAAssignVisitor() + nodes = [] + + rope.base.ast.walk(node.target, visitor) + nodes.extend(visitor.nodes) + + self._evaluate_assign_value(node, nodes, type_hint=node.annotation) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,10 +1,10 @@ + def _Assign(self, node): +- for child in rope.base.ast.get_child_nodes(node): +- rope.base.ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + visitor = _SOAAssignVisitor() + nodes = [] + for child in node.targets: +- rope.base.ast.walk(child, visitor) ++ au.walk(child, visitor) + nodes.extend(visitor.nodes) + self._evaluate_assign_value(node, nodes) + +@language python + +def _Assign(self, node): + for child in rope.base.ast.get_child_nodes(node): + rope.base.ast.walk(child, self) + visitor = _SOAAssignVisitor() + nodes = [] + for child in node.targets: + rope.base.ast.walk(child, visitor) + nodes.extend(visitor.nodes) + self._evaluate_assign_value(node, nodes) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -3,12 +3,12 @@ + instance = evaluate.eval_node(self.scope, subscript.value) + args_pynames = [evaluate.eval_node(self.scope, subscript.slice)] + value = rope.base.oi.soi._infer_assignment( +- rope.base.pynames.AssignmentValue( ++ pynames.AssignmentValue( + node.value, levels, type_hint=type_hint + ), + self.pymodule, + ) +- args_pynames.append(rope.base.pynames.UnboundName(value)) ++ args_pynames.append(pynames.UnboundName(value)) + if instance is not None and value is not None: + pyobject = instance.get_object() + if "__setitem__" in pyobject: +@language python + +def _evaluate_assign_value(self, node, nodes, type_hint=False): + for subscript, levels in nodes: + instance = evaluate.eval_node(self.scope, subscript.value) + args_pynames = [evaluate.eval_node(self.scope, subscript.slice)] + value = rope.base.oi.soi._infer_assignment( + rope.base.pynames.AssignmentValue( + node.value, levels, type_hint=type_hint + ), + self.pymodule, + ) + args_pynames.append(rope.base.pynames.UnboundName(value)) + if instance is not None and value is not None: + pyobject = instance.get_object() + if "__setitem__" in pyobject: + pyfunction = pyobject["__setitem__"].get_object() + args = arguments.ObjectArguments([instance] + args_pynames) + self._call(pyfunction, args) + # IDEA: handle `__setslice__`, too + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,2 +1,2 @@ +-class _SOAAssignVisitor(astutils._NodeNameCollector): ++class _SOAAssignVisitor(au._NodeNameCollector): + @others +@language python + +class _SOAAssignVisitor(astutils._NodeNameCollector): + @others + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _added(self, node, levels): +- if isinstance(node, rope.base.ast.Subscript) and isinstance( +- node.slice, (rope.base.ast.Index, rope.base.ast.expr) ++ if isinstance(node, ast.Subscript) and isinstance( ++ node.slice, (ast.Index, ast.expr) + ): + self.nodes.append((node, levels)) +@language python + +def _added(self, node, levels): + if isinstance(node, rope.base.ast.Subscript) and isinstance( + node.slice, (rope.base.ast.Index, rope.base.ast.expr) + ): + self.nodes.append((node, levels)) + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,11 +5,9 @@ + + """ + import rope.base.builtins +-import rope.base.pynames + import rope.base.pyobjects +-from rope.base import evaluate, utils, arguments ++from rope.base import arguments, evaluate, pynames, utils + from rope.base.oi.type_hinting.factory import get_type_hinting_factory +- + + _ignore_inferred = utils.ignore_exception(rope.base.pyobjects.IsBeingInferredError) + +@@ -142,7 +140,6 @@ + + # handling `rope.base.pynames.AssignmentValue` + +- + @_ignore_inferred + def _infer_assignment(assignment, pymodule): + result = _follow_pyname(assignment, pymodule) +@@ -185,7 +182,7 @@ + isinstance(result.get_type(), rope.base.builtins.Property) + and holding_scope.get_kind() == "Class" + ): +- arg = rope.base.pynames.UnboundName( ++ arg = pynames.UnboundName( + rope.base.pyobjects.PyObject(holding_scope.pyobject) + ) + return pyname, result.get_type().get_property_object( +@language python + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ ++ ++import ast + import rope.base.evaluate +-from rope.base import ast +- + + class Arguments: + """A class for evaluating parameters passed to a function +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,11 +6,9 @@ + + """ + import rope.base.builtins +-import rope.base.pynames + import rope.base.pyobjects +-from rope.base import evaluate, utils, arguments ++from rope.base import arguments, evaluate, pynames, utils + from rope.base.oi.type_hinting.factory import get_type_hinting_factory +- + + _ignore_inferred = utils.ignore_exception(rope.base.pyobjects.IsBeingInferredError) + +@language python + +@path C:/Repos/ekr-rope/rope/base/oi/ +"""A module for inferring objects + +For more information see the documentation in `rope.base.oi` +package. + +""" +import rope.base.builtins +import rope.base.pynames +import rope.base.pyobjects +from rope.base import evaluate, utils, arguments +from rope.base.oi.type_hinting.factory import get_type_hinting_factory + + +_ignore_inferred = utils.ignore_exception(rope.base.pyobjects.IsBeingInferredError) + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,4 @@ + # handling `rope.base.pynames.AssignmentValue` +- + + @_ignore_inferred + def _infer_assignment(assignment, pymodule): +@language python + +# handling `rope.base.pynames.AssignmentValue` + + +@_ignore_inferred +def _infer_assignment(assignment, pymodule): + result = _follow_pyname(assignment, pymodule) + if result is None: + return None + pyname, pyobject = result + pyobject = _follow_evaluations(assignment, pyname, pyobject) + if pyobject is None: + return None + return _follow_levels(assignment, pyobject) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -11,7 +11,7 @@ + isinstance(result.get_type(), rope.base.builtins.Property) + and holding_scope.get_kind() == "Class" + ): +- arg = rope.base.pynames.UnboundName( ++ arg = pynames.UnboundName( + rope.base.pyobjects.PyObject(holding_scope.pyobject) + ) + return pyname, result.get_type().get_property_object( +@language python + +@_ignore_inferred +def _follow_pyname(assignment, pymodule, lineno=None): + assign_node = assignment.type_hint or assignment.ast_node + if lineno is None: + lineno = _get_lineno_for_node(assign_node) + holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) + pyname = evaluate.eval_node(holding_scope, assign_node) + if pyname is not None: + result = pyname.get_object() + if ( + isinstance(result.get_type(), rope.base.builtins.Property) + and holding_scope.get_kind() == "Class" + ): + arg = rope.base.pynames.UnboundName( + rope.base.pyobjects.PyObject(holding_scope.pyobject) + ) + return pyname, result.get_type().get_property_object( + arguments.ObjectArguments([arg]) + ) + return pyname, result + + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + @path C:/Repos/ekr-rope/rope/base/ ++ ++import ast + import rope.base.evaluate +-from rope.base import ast +- + + @others + @language python +@language python + +@path C:/Repos/ekr-rope/rope/base/ +import rope.base.evaluate +from rope.base import ast + + +@others +@language python +@tabwidth -4 + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,22 +1,8 @@ +-from rope.base import ast +- +- +-def get_name_levels(node): +- """Return a list of ``(name, level)`` tuples for assigned names +- +- The `level` is `None` for simple assignments and is a list of +- numbers for tuple assignments for example in:: +- +- a, (b, c) = x +- +- The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for +- `c` is ``[1, 1]``. +- +- """ +- visitor = _NodeNameCollector() +- ast.walk(node, visitor) +- return visitor.names +- ++""" ++ast utilities, renamed from base.ast.py. ++""" ++import ast ++from rope.base.fscommands import unicode_to_file_data + + class _NodeNameCollector: + def __init__(self, levels=None): +@@ -49,8 +35,8 @@ + new_levels.append(self.index) + self.index += 1 + visitor = _NodeNameCollector(new_levels) +- for child in ast.get_child_nodes(node): +- ast.walk(child, visitor) ++ for child in get_child_nodes(node): ++ walk(child, visitor) + self.names.extend(visitor.names) + + def _Subscript(self, node): +@@ -61,3 +47,78 @@ + + def _Slice(self, node): + self._add_node(node) ++ ++ ++def call_for_nodes(node, callback, recursive=False): ++ """If callback returns `True` the child nodes are skipped""" ++ result = callback(node) ++ if recursive and not result: ++ for child in get_child_nodes(node): ++ call_for_nodes(child, callback, recursive) ++def get_child_nodes(node): ++ if isinstance(node, ast.Module): ++ return node.body ++ result = [] ++ if node._fields is not None: ++ for name in node._fields: ++ child = getattr(node, name) ++ if isinstance(child, list): ++ for entry in child: ++ if isinstance(entry, ast.AST): ++ result.append(entry) ++ if isinstance(child, ast.AST): ++ result.append(child) ++ return result ++def get_children(node): ++ result = [] ++ if node._fields is not None: ++ for name in node._fields: ++ if name in ["lineno", "col_offset"]: ++ continue ++ child = getattr(node, name) ++ result.append(child) ++ return result ++def get_name_levels(node): ++ """Return a list of ``(name, level)`` tuples for assigned names ++ ++ The `level` is `None` for simple assignments and is a list of ++ numbers for tuple assignments for example in:: ++ ++ a, (b, c) = x ++ ++ The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for ++ `c` is ``[1, 1]``. ++ ++ """ ++ visitor = _NodeNameCollector() ++ walk(node, visitor) ++ return visitor.names ++def parse(source, filename="<string>"): ++ # NOTE: the raw string should be given to `compile` function ++ if isinstance(source, str): ++ source = unicode_to_file_data(source) ++ if b"\r" in source: ++ source = source.replace(b"\r\n", b"\n").replace(b"\r", b"\n") ++ if not source.endswith(b"\n"): ++ source += b"\n" ++ try: ++ return ast.parse(source, filename="<unknown>") ++ except (TypeError, ValueError) as e: ++ error = SyntaxError() ++ error.lineno = 1 ++ error.filename = filename ++ error.msg = str(e) ++ raise error # pylint: disable=raise-missing-from ++ ++def walk(node, walker): # pylint: disable=inconsistent-return-statements ++ """Walk the syntax tree""" ++ method_name = "_" + node.__class__.__name__ ++ method = getattr(walker, method_name, None) ++ if method is not None: ++ if isinstance(node, ast.ImportFrom) and node.module is None: ++ # In python < 2.7 ``node.module == ''`` for relative imports ++ # but for python 2.7 it is None. Generalizing it to ''. ++ node.module = "" ++ return method(node) ++ for child in get_child_nodes(node): ++ walk(child, walker) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,23 +1,9 @@ + @path C:/Repos/ekr-rope/rope/base/ +-from rope.base import ast +- +- +-def get_name_levels(node): +- """Return a list of ``(name, level)`` tuples for assigned names +- +- The `level` is `None` for simple assignments and is a list of +- numbers for tuple assignments for example in:: +- +- a, (b, c) = x +- +- The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for +- `c` is ``[1, 1]``. +- +- """ +- visitor = _NodeNameCollector() +- ast.walk(node, visitor) +- return visitor.names +- ++""" ++ast utilities, renamed from base.ast.py. ++""" ++import ast ++from rope.base.fscommands import unicode_to_file_data + + @others + @language python +@language python + +@path C:/Repos/ekr-rope/rope/base/ +from rope.base import ast + + +def get_name_levels(node): + """Return a list of ``(name, level)`` tuples for assigned names + + The `level` is `None` for simple assignments and is a list of + numbers for tuple assignments for example in:: + + a, (b, c) = x + + The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for + `c` is ``[1, 1]``. + + """ + visitor = _NodeNameCollector() + ast.walk(node, visitor) + return visitor.names + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,7 +5,7 @@ + new_levels.append(self.index) + self.index += 1 + visitor = _NodeNameCollector(new_levels) +- for child in ast.get_child_nodes(node): +- ast.walk(child, visitor) ++ for child in get_child_nodes(node): ++ walk(child, visitor) + self.names.extend(visitor.names) + +@language python + +def _Tuple(self, node): + new_levels = [] + if self.levels is not None: + new_levels = list(self.levels) + new_levels.append(self.index) + self.index += 1 + visitor = _NodeNameCollector(new_levels) + for child in ast.get_child_nodes(node): + ast.walk(child, visitor) + self.names.extend(visitor.names) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,2 +1,77 @@ + def _Slice(self, node): + self._add_node(node) ++ ++ ++def call_for_nodes(node, callback, recursive=False): ++"""If callback returns `True` the child nodes are skipped""" ++result = callback(node) ++if recursive and not result: ++ for child in get_child_nodes(node): ++ call_for_nodes(child, callback, recursive) ++def get_child_nodes(node): ++if isinstance(node, ast.Module): ++ return node.body ++result = [] ++if node._fields is not None: ++ for name in node._fields: ++ child = getattr(node, name) ++ if isinstance(child, list): ++ for entry in child: ++ if isinstance(entry, ast.AST): ++ result.append(entry) ++ if isinstance(child, ast.AST): ++ result.append(child) ++return result ++def get_children(node): ++result = [] ++if node._fields is not None: ++ for name in node._fields: ++ if name in ["lineno", "col_offset"]: ++ continue ++ child = getattr(node, name) ++ result.append(child) ++return result ++def get_name_levels(node): ++"""Return a list of ``(name, level)`` tuples for assigned names ++ ++The `level` is `None` for simple assignments and is a list of ++numbers for tuple assignments for example in:: ++ ++ a, (b, c) = x ++ ++The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for ++`c` is ``[1, 1]``. ++ ++""" ++visitor = _NodeNameCollector() ++walk(node, visitor) ++return visitor.names ++def parse(source, filename="<string>"): ++# NOTE: the raw string should be given to `compile` function ++if isinstance(source, str): ++ source = unicode_to_file_data(source) ++if b"\r" in source: ++ source = source.replace(b"\r\n", b"\n").replace(b"\r", b"\n") ++if not source.endswith(b"\n"): ++ source += b"\n" ++try: ++ return ast.parse(source, filename="<unknown>") ++except (TypeError, ValueError) as e: ++ error = SyntaxError() ++ error.lineno = 1 ++ error.filename = filename ++ error.msg = str(e) ++ raise error # pylint: disable=raise-missing-from ++ ++def walk(node, walker): # pylint: disable=inconsistent-return-statements ++"""Walk the syntax tree""" ++method_name = "_" + node.__class__.__name__ ++method = getattr(walker, method_name, None) ++if method is not None: ++ if isinstance(node, ast.ImportFrom) and node.module is None: ++ # In python < 2.7 ``node.module == ''`` for relative imports ++ # but for python 2.7 it is None. Generalizing it to ''. ++ node.module = "" ++ return method(node) ++for child in get_child_nodes(node): ++ walk(child, walker) +@language python + +def _Slice(self, node): + self._add_node(node) + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,19 +1,18 @@ ++import ast + from operator import itemgetter + from typing import Optional, Tuple + ++import rope.base.astutils as au + import rope.base.builtins +-import rope.base.pynames + import rope.base.pyobjects + from rope.base import ( +- ast, +- astutils, ++ arguments, + exceptions, ++ pynames, + pyobjects, + pyobjectsdef, +- arguments, + worder, + ) +- + + BadIdentifierError = exceptions.BadIdentifierError + +@@ -39,7 +38,7 @@ + + def eval_node2(scope, node): + evaluator = StatementEvaluator(scope) +- ast.walk(node, evaluator) ++ au.walk(node, evaluator) + return evaluator.old_result, evaluator.result + + +@@ -50,7 +49,7 @@ + def eval_str2(holding_scope, name): + try: + # parenthesizing for handling cases like 'a_var.\nattr' +- node = ast.parse("(%s)" % name) ++ node = au.parse("(%s)" % name) + except SyntaxError: + raise BadIdentifierError("Not a resolvable python identifier selected.") + return eval_node2(holding_scope, node) +@@ -91,7 +90,7 @@ + def get_primary_and_pyname_at( + self, + offset: int, +- ) -> Tuple[Optional[rope.base.pynames.PyName], Optional[rope.base.pynames.PyName]]: ++ ) -> Tuple[Optional[pynames.PyName], Optional[pynames.PyName]]: + lineno = self.lines.get_line_number(offset) + holding_scope = self.module_scope.get_inner_scope_for_offset(offset) + # function keyword parameter +@@ -102,7 +101,7 @@ + parameter_name = pyobject.get_parameters().get(keyword_name, None) + return (None, parameter_name) + elif isinstance(pyobject, pyobjects.AbstractFunction): +- parameter_name = rope.base.pynames.ParameterName() ++ parameter_name = pynames.ParameterName() + return (None, parameter_name) + # class body + if self._is_defined_in_class_body(holding_scope, offset, lineno): +@@ -153,7 +152,7 @@ + dots = 0 + while module_name[dots] == ".": + dots += 1 +- return rope.base.pynames.ImportedModule( ++ return pynames.ImportedModule( + self.module_scope.pyobject, module_name[dots:], dots + ) + +@@ -170,7 +169,7 @@ + def _Attribute(self, node): + pyname = eval_node(self.scope, node.value) + if pyname is None: +- pyname = rope.base.pynames.UnboundName() ++ pyname = pynames.UnboundName() + self.old_result = pyname + if pyname.get_object() != rope.base.pyobjects.get_unknown(): + try: +@@ -194,7 +193,7 @@ + result = _get_returned(new_function) + if result is None or result == rope.base.pyobjects.get_unknown(): + result = rope.base.pyobjects.PyObject(pyobject) +- self.result = rope.base.pynames.UnboundName(pyobject=result) ++ self.result = pynames.UnboundName(pyobject=result) + return + + pyfunction = None +@@ -203,12 +202,12 @@ + elif "__call__" in pyobject: + pyfunction = pyobject["__call__"].get_object() + if pyfunction is not None: +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=_get_returned(pyfunction) + ) + + def _Str(self, node): +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_str() + ) + +@@ -226,10 +225,10 @@ + + def _get_builtin_name(self, type_name): + pytype = rope.base.builtins.builtins[type_name].get_object() +- return rope.base.pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) ++ return pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) + + def _BinOp(self, node): +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + self._get_object_for_node(node.left) + ) + +@@ -237,13 +236,13 @@ + pyobject = self._get_object_for_node(node.values[0]) + if pyobject is None: + pyobject = self._get_object_for_node(node.values[1]) +- self.result = rope.base.pynames.UnboundName(pyobject) ++ self.result = pynames.UnboundName(pyobject) + + def _Repr(self, node): + self.result = self._get_builtin_name("str") + + def _UnaryOp(self, node): +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + self._get_object_for_node(node.operand) + ) + +@@ -261,7 +260,7 @@ + keys = self._get_object_for_node(keys) + if values: + values = self._get_object_for_node(values) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_dict(keys, values) + ) + +@@ -269,19 +268,19 @@ + holding = None + if node.elts: + holding = self._get_object_for_node(node.elts[0]) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_list(holding) + ) + + def _ListComp(self, node): + pyobject = self._what_does_comprehension_hold(node) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_list(pyobject) + ) + + def _GeneratorExp(self, node): + pyobject = self._what_does_comprehension_hold(node) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_iterator(pyobject) + ) + +@@ -309,7 +308,7 @@ + objects.append(pyobject) + else: + objects.append(self._get_object_for_node(node.elts[0])) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.get_tuple(*objects) + ) + +@@ -352,22 +351,21 @@ + if other_args: + args += other_args + arguments_ = arguments.Arguments(args, self.scope) +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=called.get_returned_object(arguments_) + ) + + def _Lambda(self, node): +- self.result = rope.base.pynames.UnboundName( ++ self.result = pynames.UnboundName( + pyobject=rope.base.builtins.Lambda(node, self.scope) + ) + + + def _get_evaluated_names(targets, assigned, module, evaluation, lineno): + result = {} +- for name, levels in astutils.get_name_levels(targets): +- assignment = rope.base.pynames.AssignmentValue(assigned, levels, evaluation) +- # XXX: this module should not access `rope.base.pynamesdef`! +- pyname = rope.base.pynamesdef.AssignedName(lineno, module) ++ for name, levels in au.get_name_levels(targets): ++ assignment = pynames.AssignmentValue(assigned, levels, evaluation) ++ pyname = rope.base.pynames.AssignedName(lineno, module) + pyname.assignments.append(assignment) + result[name] = pyname + return result +@language python + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -47,7 +47,7 @@ + + def __call__(self, pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + for delegate in self._delegates: +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -8,7 +8,7 @@ + + def __call__(self, pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + raise NotImplementedError +@language python + + +class IAssignmentProvider: +""" +:type resolve: rope.base.oi.type_hinting.resolvers.interfaces.IResolver +""" + +resolve = None + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + raise NotImplementedError + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -14,7 +14,7 @@ + + def __call__(self, pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + from rope.base.oi.soi import _get_lineno_for_node +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def __call__(self, pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + from rope.base.oi.soi import _get_lineno_for_node +@language python + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + from rope.base.oi.soi import _get_lineno_for_node + + lineno = _get_lineno_for_node(pyname.assignments[0].ast_node) + holding_scope = pyname.module.get_scope().get_inner_scope_for_line(lineno) + line = holding_scope._get_global_scope()._scope_finder.lines.get_line(lineno) + if "#" in line: + type_strs = self._search_type_in_type_comment(line.split("#", 1)[1]) + if type_strs: + return self._resolve(type_strs[0], holding_scope.pyobject) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -28,8 +28,8 @@ + + def get_super_assignment(pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName +- :type: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName ++ :type: rope.base.pynames.AssignedName + """ + try: + pyclass, attr_name = get_class_with_attr_name(pyname) +@@ -43,7 +43,7 @@ + + def get_class_with_attr_name(pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :return: rope.base.pyobjectsdef.PyClass, str + :rtype: tuple + """ +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + def get_super_assignment(pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName +- :type: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName ++ :type: rope.base.pynames.AssignedName + """ + try: + pyclass, attr_name = get_class_with_attr_name(pyname) +@language python + +def get_super_assignment(pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :type: rope.base.pynamesdef.AssignedName + """ + try: + pyclass, attr_name = get_class_with_attr_name(pyname) + except TypeError: + return + else: + for super_pyclass in get_mro(pyclass)[1:]: + if attr_name in super_pyclass: + return super_pyclass[attr_name] + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def get_class_with_attr_name(pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :return: rope.base.pyobjectsdef.PyClass, str + :rtype: tuple + """ +@language python + +def get_class_with_attr_name(pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :return: rope.base.pyobjectsdef.PyClass, str + :rtype: tuple + """ + lineno = get_lineno_for_node(pyname.assignments[0].ast_node) + holding_scope = pyname.module.get_scope().get_inner_scope_for_line(lineno) + pyobject = holding_scope.pyobject + if isinstance(pyobject, PyClass): + pyclass = pyobject + elif isinstance(pyobject, PyFunction) and isinstance(pyobject.parent, PyClass): + pyclass = pyobject.parent + else: + return + for name, attr in pyclass.get_attributes().items(): + if attr is pyname: + return (pyclass, name) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,5 @@ + import bisect + import difflib +-import sys + import warnings + + import rope.base.libutils +@@ -15,7 +14,6 @@ + from rope.base import stdmods + from rope.base import taskhandle + from rope.base import utils +-from rope.base.exceptions import ModuleNotFoundError + + + class PyCore: +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def __call__(self, pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + for delegate in self._delegates: +@language python + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + for delegate in self._delegates: + result = delegate(pyname) + if result: + return result + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,6 @@ + @path C:/Repos/ekr-rope/rope/base/ + import bisect + import difflib +-import sys + import warnings + + import rope.base.libutils +@@ -16,7 +15,6 @@ + from rope.base import stdmods + from rope.base import taskhandle + from rope.base import utils +-from rope.base.exceptions import ModuleNotFoundError + + + @others +@language python + +@path C:/Repos/ekr-rope/rope/base/ +import bisect +import difflib +import sys +import warnings + +import rope.base.libutils +import rope.base.resourceobserver +import rope.base.resources +import rope.base.oi.doa +import rope.base.oi.objectinfo +import rope.base.oi.soa +from rope.base import builtins +from rope.base import exceptions +from rope.base import pyobjectsdef +from rope.base import stdmods +from rope.base import taskhandle +from rope.base import utils +from rope.base.exceptions import ModuleNotFoundError + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,5 @@ + import rope.base.pyobjects + from rope.base import exceptions, utils +- + + class PyName: + """References to `PyObject` inside python programs""" +@@ -27,7 +26,36 @@ + + + class AssignedName(PyName): +- """Only a placeholder""" ++ def __init__(self, lineno=None, module=None, pyobject=None): ++ self.lineno = lineno ++ self.module = module ++ self.assignments = [] ++ self.pyobject = _Inferred( ++ self._get_inferred, _get_concluded_data(module) ++ ) ++ self.pyobject.set(pyobject) ++ ++ @utils.prevent_recursion(lambda: None) ++ def _get_inferred(self): ++ if self.module is not None: ++ return rope.base.oi.soi.infer_assigned_object(self) ++ return None ++ ++ def get_object(self): ++ return self.pyobject.get() ++ ++ def get_definition_location(self): ++ """Returns a (module, lineno) tuple""" ++ if self.lineno is None and self.assignments: ++ try: ++ self.lineno = self.assignments[0].get_lineno() ++ except AttributeError: ++ pass ++ return (self.module, self.lineno) ++ ++ def invalidate(self): ++ """Forget the `PyObject` this `PyName` holds""" ++ self.pyobject.set(None) + + + class UnboundName(PyName): +@@ -92,7 +120,22 @@ + + + class ParameterName(PyName): +- """Only a placeholder""" ++ def __init__(self, pyfunction=None, index=0): ++ self.pyfunction = pyfunction ++ self.index = index ++ ++ def get_object(self): ++ result = self.pyfunction.get_parameter(self.index) ++ if result is None: ++ result = rope.base.pyobjects.get_unknown() ++ return result ++ ++ def get_objects(self): ++ """Returns the list of objects passed as this parameter""" ++ return rope.base.oi.soi.get_passed_objects(self.pyfunction, self.index) ++ ++ def get_definition_location(self): ++ return (self.pyfunction.get_module(), self.pyfunction.get_ast().lineno) + + + class ImportedModule(PyName): +@language python + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -77,7 +77,7 @@ + + def __call__(self, pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + try: +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,6 @@ + import rope.base.pyobjects + from rope.base import exceptions, utils + +- + @others + @language python + @tabwidth -4 +@language python + +@path C:/Repos/ekr-rope/rope/base/ +import rope.base.pyobjects +from rope.base import exceptions, utils + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1 +1,30 @@ +-"""Only a placeholder""" ++def __init__(self, lineno=None, module=None, pyobject=None): ++ self.lineno = lineno ++ self.module = module ++ self.assignments = [] ++ self.pyobject = _Inferred( ++ self._get_inferred, _get_concluded_data(module) ++ ) ++ self.pyobject.set(pyobject) ++ ++@utils.prevent_recursion(lambda: None) ++def _get_inferred(self): ++ if self.module is not None: ++ return rope.base.oi.soi.infer_assigned_object(self) ++ return None ++ ++def get_object(self): ++ return self.pyobject.get() ++ ++def get_definition_location(self): ++ """Returns a (module, lineno) tuple""" ++ if self.lineno is None and self.assignments: ++ try: ++ self.lineno = self.assignments[0].get_lineno() ++ except AttributeError: ++ pass ++ return (self.module, self.lineno) ++ ++def invalidate(self): ++ """Forget the `PyObject` this `PyName` holds""" ++ self.pyobject.set(None) +@language python + +"""Only a placeholder""" + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1 +1,16 @@ +-"""Only a placeholder""" ++def __init__(self, pyfunction=None, index=0): ++ self.pyfunction = pyfunction ++ self.index = index ++ ++def get_object(self): ++ result = self.pyfunction.get_parameter(self.index) ++ if result is None: ++ result = rope.base.pyobjects.get_unknown() ++ return result ++ ++def get_objects(self): ++ """Returns the list of objects passed as this parameter""" ++ return rope.base.oi.soi.get_passed_objects(self.pyfunction, self.index) ++ ++def get_definition_location(self): ++ return (self.pyfunction.get_module(), self.pyfunction.get_ast().lineno) +@language python + +"""Only a placeholder""" + +@ignore +@nosearch +@language patch + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,7 @@ +-from typing import Optional +- +-from rope.base import ast, exceptions, utils ++import ast ++from rope.base import exceptions, utils ++import rope.base.astutils as au ++from rope.base.fscommands import _decode_data + + + class PyObject: +@@ -225,14 +226,13 @@ + current_object = current_object.parent + return current_object + +- def get_doc(self) -> Optional[str]: ++ def get_doc(self): + if len(self.get_ast().body) > 0: + expr = self.get_ast().body[0] + if isinstance(expr, ast.Expr) and isinstance(expr.value, ast.Str): + docstring = expr.value.s +- assert isinstance(docstring, str) +- return docstring +- return None ++ coding = self.get_module().coding ++ return _decode_data(docstring, coding) + + def _get_defined_objects(self): + if self.defineds is None: +@@ -243,8 +243,8 @@ + if self.visitor_class is None: + return {} + new_visitor = self.visitor_class(self.pycore, self) +- for child in ast.get_child_nodes(self.ast_node): +- ast.walk(child, new_visitor) ++ for child in au.get_child_nodes(self.ast_node): ++ au.walk(child, new_visitor) + self.defineds = new_visitor.defineds + return new_visitor.names +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,8 @@ + @path C:/Repos/ekr-rope/rope/base/ +-from typing import Optional +- +-from rope.base import ast, exceptions, utils ++import ast ++from rope.base import exceptions, utils ++import rope.base.astutils as au ++from rope.base.fscommands import _decode_data + + + @others +@language python + +@path C:/Repos/ekr-rope/rope/base/ +from typing import Optional + +from rope.base import ast, exceptions, utils + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,8 @@ +-def get_doc(self) -> Optional[str]: ++def get_doc(self): + if len(self.get_ast().body) > 0: + expr = self.get_ast().body[0] + if isinstance(expr, ast.Expr) and isinstance(expr.value, ast.Str): + docstring = expr.value.s +- assert isinstance(docstring, str) +- return docstring +- return None ++ coding = self.get_module().coding ++ return _decode_data(docstring, coding) + +@language python + +def get_doc(self) -> Optional[str]: + if len(self.get_ast().body) > 0: + expr = self.get_ast().body[0] + if isinstance(expr, ast.Expr) and isinstance(expr.value, ast.Str): + docstring = expr.value.s + assert isinstance(docstring, str) + return docstring + return None + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,8 +2,8 @@ + if self.visitor_class is None: + return {} + new_visitor = self.visitor_class(self.pycore, self) +- for child in ast.get_child_nodes(self.ast_node): +- ast.walk(child, new_visitor) ++ for child in au.get_child_nodes(self.ast_node): ++ au.walk(child, new_visitor) + self.defineds = new_visitor.defineds + return new_visitor.names + +@language python + +def _create_structural_attributes(self): + if self.visitor_class is None: + return {} + new_visitor = self.visitor_class(self.pycore, self) + for child in ast.get_child_nodes(self.ast_node): + ast.walk(child, new_visitor) + self.defineds = new_visitor.defineds + return new_visitor.names + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def __call__(self, pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + try: +@language python + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + try: + pyclass, attr_name = utils.get_class_with_attr_name(pyname) + except TypeError: + return + else: + type_strs = self._parse_docstring(pyclass.get_doc(), attr_name) + if type_strs: + return self._resolve(type_strs[0], pyclass) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -52,7 +52,7 @@ + + def __call__(self, pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + super_pyname = pyname +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def __call__(self, pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + super_pyname = pyname +@language python + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + super_pyname = pyname + while super_pyname: + result = self._delegate(super_pyname) + if result: + return result + super_pyname = utils.get_super_assignment(super_pyname) + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -32,7 +32,7 @@ + + def __call__(self, pyname): + """ +- :type pyname: rope.base.pynamesdef.AssignedName ++ :type pyname: rope.base.pynames.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + raise NotImplementedError +@language python + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,6 @@ +-from rope.base.pynames import DefinedName ++import ast ++ ++import rope.base.astutils as au + import rope.base.builtins + import rope.base.codeanalyze + import rope.base.evaluate +@@ -6,18 +8,14 @@ + import rope.base.oi.soi + import rope.base.pyscopes + from rope.base import ( +- pynamesdef as pynames, ++ arguments, + exceptions, +- ast, +- astutils, ++ fscommands, ++ pynames, + pyobjects, +- fscommands, +- arguments, + utils, + ) + from rope.base.utils import pycompat +- +- + class PyFunction(pyobjects.PyFunction): + def __init__(self, pycore, ast_node, parent): + rope.base.pyobjects.AbstractFunction.__init__(self) +@@ -183,7 +181,7 @@ + raise + else: + source = "\n" +- node = ast.parse("\n") ++ node = au.parse("\n") + self.source_code = source + self.star_imports = [] + self.visitor_class = _GlobalVisitor +@@ -203,7 +201,7 @@ + source_bytes = fscommands.unicode_to_file_data(source_code) + else: + source_bytes = source_code +- ast_node = ast.parse(source_bytes, filename=filename) ++ ast_node = au.parse(source_bytes, filename=filename) + except SyntaxError as e: + raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg) + except UnicodeDecodeError as e: +@@ -245,7 +243,7 @@ + init_dot_py, force_errors=force_errors + ).get_ast() + else: +- ast_node = ast.parse("\n") ++ ast_node = au.parse("\n") + super().__init__(pycore, ast_node, resource) + + def _create_structural_attributes(self): +@@ -307,7 +305,7 @@ + self.assigned_ast = node.value + self.type_hint = node.annotation + +- ast.walk(node.target, self) ++ au.walk(node.target, self) + + def _assigned(self, name, assignment=None): + self.scope_visitor._assigned(name, assignment) +@@ -319,7 +317,7 @@ + self._assigned(node.id, assignment) + + def _Tuple(self, node): +- names = astutils.get_name_levels(node) ++ names = au.get_name_levels(node) + for name, levels in names: + assignment = None + if self.assigned_ast is not None: +@@ -362,8 +360,8 @@ + self._GeneratorExp(node) + + def _NamedExpr(self, node): +- ast.walk(node.target, _AssignVisitor(self)) +- ast.walk(node.value, self) ++ au.walk(node.target, _AssignVisitor(self)) ++ au.walk(node.value, self) + + + class _AssignVisitor: +@@ -374,8 +372,8 @@ + def _Assign(self, node): + self.assigned_ast = node.value + for child_node in node.targets: +- ast.walk(child_node, self) +- ast.walk(node.value, _ExpressionVisitor(self.scope_visitor)) ++ au.walk(child_node, self) ++ au.walk(node.value, _ExpressionVisitor(self.scope_visitor)) + + def _assigned(self, name, assignment=None): + self.scope_visitor._assigned(name, assignment) +@@ -387,7 +385,7 @@ + self._assigned(node.id, assignment) + + def _Tuple(self, node): +- names = astutils.get_name_levels(node) ++ names = au.get_name_levels(node) + for name, levels in names: + assignment = None + if self.assigned_ast is not None: +@@ -452,20 +450,18 @@ + return self._FunctionDef(node) + + def _Assign(self, node): +- ast.walk(node, _AssignVisitor(self)) ++ au.walk(node, _AssignVisitor(self)) + + def _AnnAssign(self, node): +- ast.walk(node, _AnnAssignVisitor(self)) ++ au.walk(node, _AnnAssignVisitor(self)) + + def _AugAssign(self, node): + pass + + def _For(self, node): +- names = self._update_evaluated( +- node.target, node.iter, ".__iter__().next()" # noqa +- ) ++ self._update_evaluated(node.target, node.iter, ".__iter__().next()") # noqa + for child in node.body + node.orelse: +- ast.walk(child, self) ++ au.walk(child, self) + + def _AsyncFor(self, node): + return self._For(node) +@@ -487,7 +483,7 @@ + assignment = pynames.AssignmentValue(assigned, [], evaluation, eval_type) + self._assigned(targets, assignment) + else: +- names = astutils.get_name_levels(targets) ++ names = au.get_name_levels(targets) + for name, levels in names: + assignment = pynames.AssignmentValue( + assigned, levels, evaluation, eval_type +@@ -502,7 +498,7 @@ + item.optional_vars, item.context_expr, ".__enter__()" + ) + for child in node.body: +- ast.walk(child, self) ++ au.walk(child, self) + + def _AsyncWith(self, node): + return self._With(node) +@@ -516,7 +512,7 @@ + self._update_evaluated(node.name, type_node, eval_type=True) + + for child in node.body: +- ast.walk(child, self) ++ au.walk(child, self) + + def _ExceptHandler(self, node): + self._excepthandler(node) +@@ -575,8 +571,8 @@ + + class _ComprehensionVisitor(_ScopeVisitor): + def _comprehension(self, node): +- ast.walk(node.target, self) +- ast.walk(node.iter, self) ++ au.walk(node.target, self) ++ au.walk(node.iter, self) + + def _Name(self, node): + if isinstance(node.ctx, ast.Store): +@@ -603,8 +599,8 @@ + if isinstance(first, pycompat.ast_arg_type): + new_visitor = _ClassInitVisitor(self, pycompat.get_ast_arg_arg(first)) + if new_visitor is not None: +- for child in ast.get_child_nodes(node): +- ast.walk(child, new_visitor) ++ for child in au.get_child_nodes(node): ++ au.walk(child, new_visitor) + + + class _FunctionVisitor(_ScopeVisitor): +@@ -646,8 +642,8 @@ + def _Tuple(self, node): + if not isinstance(node.ctx, ast.Store): + return +- for child in ast.get_child_nodes(node): +- ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + + def _Name(self, node): + pass +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,16 +1,18 @@ + @path C:/Repos/ekr-rope/rope/refactor/ ++ ++import ast + import re + from contextlib import contextmanager + from itertools import chain + +-from rope.base import ast, codeanalyze ++from rope.base import codeanalyze ++import rope.base.astutils as au + from rope.base.change import ChangeSet, ChangeContents + from rope.base.exceptions import RefactoringError + from rope.base.utils import pycompat + from rope.base.utils.datastructures import OrderedSet + from rope.refactor import sourceutils, similarfinder, patchedast, suites, usefunction + +- + @others + @language python + @tabwidth -4 +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +import re +from contextlib import contextmanager +from itertools import chain + +from rope.base import ast, codeanalyze +from rope.base.change import ChangeSet, ChangeContents +from rope.base.exceptions import RefactoringError +from rope.base.utils import pycompat +from rope.base.utils.datastructures import OrderedSet +from rope.refactor import sourceutils, similarfinder, patchedast, suites, usefunction + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -7,6 +7,6 @@ + ) + body = self.info.source[self.info.scope_region[0] : self.info.scope_region[1]] + node = _parse_text(body) +- ast.walk(node, info_collector) ++ au.walk(node, info_collector) + return info_collector + +@language python + +def _create_info_collector(self): + zero = self.info.scope.get_start() - 1 + start_line = self.info.region_lines[0] - zero + end_line = self.info.region_lines[1] - zero + info_collector = _FunctionInformationCollector( + start_line, end_line, self.info.global_ + ) + body = self.info.source[self.info.scope_region[0] : self.info.scope_region[1]] + node = _parse_text(body) + ast.walk(node, info_collector) + return info_collector + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,7 @@ + def _get_globals_in_body(unindented_body): + node = _parse_text(unindented_body) + visitor = _GlobalFinder() +- ast.walk(node, visitor) ++ au.walk(node, visitor) + return visitor.globals_ + + +@language python + +@staticmethod +def _get_globals_in_body(unindented_body): + node = _parse_text(unindented_body) + visitor = _GlobalFinder() + ast.walk(node, visitor) + return visitor.globals_ + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,12 +4,12 @@ + for name in _get_argnames(node.args): + self._written_variable(name, node.lineno) + for child in node.body: +- ast.walk(child, self) ++ au.walk(child, self) + else: + self._written_variable(node.name, node.lineno) + visitor = _VariableReadsAndWritesFinder() + for child in node.body: +- ast.walk(child, visitor) ++ au.walk(child, visitor) + for name in visitor.read - visitor.written: + self._read_variable(name, node.lineno) + +@language python + +def _FunctionDef(self, node): + if not self.is_global and self.host_function: + self.host_function = False + for name in _get_argnames(node.args): + self._written_variable(name, node.lineno) + for child in node.body: + ast.walk(child, self) + else: + self._written_variable(node.name, node.lineno) + visitor = _VariableReadsAndWritesFinder() + for child in node.body: + ast.walk(child, visitor) + for name in visitor.read - visitor.written: + self._read_variable(name, node.lineno) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _MatchAs(self, node): + self._written_variable(node.name, node.lineno) + if node.pattern: +- ast.walk(node.pattern, self) ++ au.walk(node.pattern, self) + +@language python + +def _MatchAs(self, node): + self._written_variable(node.name, node.lineno) + if node.pattern: + ast.walk(node.pattern, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _Assign(self, node): +- ast.walk(node.value, self) ++ au.walk(node.value, self) + for child in node.targets: +- ast.walk(child, self) ++ au.walk(child, self) + +@language python + +def _Assign(self, node): + ast.walk(node.value, self) + for child in node.targets: + ast.walk(child, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,9 @@ + def _AugAssign(self, node): +- ast.walk(node.value, self) ++ au.walk(node.value, self) + if isinstance(node.target, ast.Name): + target_id = node.target.id + self._read_variable(target_id, node.target.lineno) + self._written_variable(target_id, node.target.lineno) + else: +- ast.walk(node.target, self) ++ au.walk(node.target, self) + +@language python + +def _AugAssign(self, node): + ast.walk(node.value, self) + if isinstance(node.target, ast.Name): + target_id = node.target.id + self._read_variable(target_id, node.target.lineno) + self._written_variable(target_id, node.target.lineno) + else: + ast.walk(node.target, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -3,8 +3,8 @@ + written = OrderedSet(self.written) + maybe_written = OrderedSet(self.maybe_written) + +- for child in ast.get_child_nodes(node): +- ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + + comp_names = list( + chain.from_iterable( +@language python + +def _comp_exp(self, node): + read = OrderedSet(self.read) + written = OrderedSet(self.written) + maybe_written = OrderedSet(self.maybe_written) + + for child in ast.get_child_nodes(node): + ast.walk(child, self) + + comp_names = list( + chain.from_iterable( + self._flatten_nested_tuple_of_names(generator.target) + for generator in node.generators + ) + ) + self.read = self.read - comp_names | read + self.written = self.written - comp_names | written + self.maybe_written = self.maybe_written - comp_names | maybe_written + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,11 +1,11 @@ + def _For(self, node): + with self._handle_loop_context(node), self._handle_conditional_context(node): + # iter has to be checked before the target variables +- ast.walk(node.iter, self) +- ast.walk(node.target, self) ++ au.walk(node.iter, self) ++ au.walk(node.target, self) + + for child in node.body: +- ast.walk(child, self) ++ au.walk(child, self) + for child in node.orelse: +- ast.walk(child, self) ++ au.walk(child, self) + +@language python + +def _For(self, node): + with self._handle_loop_context(node), self._handle_conditional_context(node): + # iter has to be checked before the target variables + ast.walk(node.iter, self) + ast.walk(node.target, self) + + for child in node.body: + ast.walk(child, self) + for child in node.orelse: + ast.walk(child, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _handle_conditional_node(self, node): + with self._handle_conditional_context(node): +- for child in ast.get_child_nodes(node): +- ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + +@language python + +def _handle_conditional_node(self, node): + with self._handle_conditional_context(node): + for child in ast.get_child_nodes(node): + ast.walk(child, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + def _FunctionDef(self, node): + self.written.add(node.name) + visitor = _VariableReadsAndWritesFinder() +- for child in ast.get_child_nodes(node): +- ast.walk(child, visitor) ++ for child in au.get_child_nodes(node): ++ au.walk(child, visitor) + self.read.update(visitor.read - visitor.written) + +@language python + +def _FunctionDef(self, node): + self.written.add(node.name) + visitor = _VariableReadsAndWritesFinder() + for child in ast.get_child_nodes(node): + ast.walk(child, visitor) + self.read.update(visitor.read - visitor.written) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,6 +4,6 @@ + return set(), set() + node = _parse_text(code) + visitor = _VariableReadsAndWritesFinder() +- ast.walk(node, visitor) ++ au.walk(node, visitor) + return visitor.read, visitor.written + +@language python + +@staticmethod +def find_reads_and_writes(code): + if code.strip() == "": + return set(), set() + node = _parse_text(code) + visitor = _VariableReadsAndWritesFinder() + ast.walk(node, visitor) + return visitor.read, visitor.written + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,7 +4,7 @@ + return set(), set() + node = _parse_text(code) + visitor = _VariableReadsAndWritesFinder() +- ast.walk(node, visitor) ++ au.walk(node, visitor) + return visitor.read + + +@language python + +@staticmethod +def find_reads_for_one_liners(code): + if code.strip() == "": + return set(), set() + node = _parse_text(code) + visitor = _VariableReadsAndWritesFinder() + ast.walk(node, visitor) + return visitor.read + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,7 +4,7 @@ + return False + node = _parse_text(code) + visitor = cls() +- ast.walk(node, visitor) ++ au.walk(node, visitor) + return visitor.error + + +@language python + +@classmethod +def has_errors(cls, code): + if code.strip() == "": + return False + node = _parse_text(code) + visitor = cls() + ast.walk(node, visitor) + return visitor.error + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,12 +1,12 @@ + def loop_encountered(self, node): + self.loop_count += 1 + for child in node.body: +- ast.walk(child, self) ++ au.walk(child, self) + self.loop_count -= 1 + if node.orelse: + if isinstance(node.orelse, (list, tuple)): + for node_ in node.orelse: +- ast.walk(node_, self) ++ au.walk(node_, self) + else: +- ast.walk(node.orelse, self) ++ au.walk(node.orelse, self) + +@language python + +def loop_encountered(self, node): + self.loop_count += 1 + for child in node.body: + ast.walk(child, self) + self.loop_count -= 1 + if node.orelse: + if isinstance(node.orelse, (list, tuple)): + for node_ in node.orelse: + ast.walk(node_, self) + else: + ast.walk(node.orelse, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,9 @@ ++import ast + from typing import Union, List + +-from rope.base import ast, exceptions, pynames, pynamesdef, utils ++from rope.base import exceptions, pynames, utils ++import rope.base.astutils as au + from rope.refactor.importutils import actions, importinfo +- + + class ModuleImports: + def __init__(self, project, pymodule, import_filter=None): +@@ -26,12 +27,12 @@ + + def _get_unbound_names(self, defined_pyobject): + visitor = _GlobalUnboundNameFinder(self.pymodule, defined_pyobject) +- ast.walk(self.pymodule.get_ast(), visitor) ++ au.walk(self.pymodule.get_ast(), visitor) + return visitor.unbound + + def _get_all_star_list(self, pymodule): + def _resolve_name( +- name: Union[pynamesdef.AssignedName, pynames.ImportedName] ++ name: Union[pynames.AssignedName, pynames.ImportedName] + ) -> List: + while isinstance(name, pynames.ImportedName): + try: +@@ -40,7 +41,7 @@ + ) + except exceptions.AttributeNotFoundError: + return [] +- assert isinstance(name, pynamesdef.AssignedName) ++ assert isinstance(name, pynames.AssignedName) + return name.assignments + + result = set() +@@ -427,8 +428,8 @@ + .pyobject + ) + visitor = _LocalUnboundNameFinder(pyobject, self) +- for child in ast.get_child_nodes(node): +- ast.walk(child, visitor) ++ for child in au.get_child_nodes(node): ++ au.walk(child, visitor) + + def _FunctionDef(self, node): + self._visit_child_scope(node) +@@ -453,7 +454,7 @@ + ): + self.add_unbound(primary) + else: +- ast.walk(node, self) ++ au.walk(node, self) + + def _get_root(self): + pass +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,6 @@ +-from rope.base.pynames import DefinedName ++import ast ++ ++import rope.base.astutils as au + import rope.base.builtins + import rope.base.codeanalyze + import rope.base.evaluate +@@ -6,15 +8,11 @@ + import rope.base.oi.soi + import rope.base.pyscopes + from rope.base import ( +- pynamesdef as pynames, ++ arguments, + exceptions, +- ast, +- astutils, ++ fscommands, ++ pynames, + pyobjects, +- fscommands, +- arguments, + utils, + ) + from rope.base.utils import pycompat +- +- +@language python + +from rope.base.pynames import DefinedName +import rope.base.builtins +import rope.base.codeanalyze +import rope.base.evaluate +import rope.base.libutils +import rope.base.oi.soi +import rope.base.pyscopes +from rope.base import ( + pynamesdef as pynames, + exceptions, + ast, + astutils, + pyobjects, + fscommands, + arguments, + utils, +) +from rope.base.utils import pycompat + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -10,7 +10,7 @@ + raise + else: + source = "\n" +- node = ast.parse("\n") ++ node = au.parse("\n") + self.source_code = source + self.star_imports = [] + self.visitor_class = _GlobalVisitor +@language python + +def __init__(self, pycore, source=None, resource=None, force_errors=False): + ignore = pycore.project.prefs.get("ignore_syntax_errors", False) + syntax_errors = force_errors or not ignore + self.has_errors = False + try: + source, node = self._init_source(pycore, source, resource) + except exceptions.ModuleSyntaxError: + self.has_errors = True + if syntax_errors: + raise + else: + source = "\n" + node = ast.parse("\n") + self.source_code = source + self.star_imports = [] + self.visitor_class = _GlobalVisitor + self.coding = fscommands.read_str_coding(self.source_code) + super().__init__(pycore, node, resource) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -11,7 +11,7 @@ + source_bytes = fscommands.unicode_to_file_data(source_code) + else: + source_bytes = source_code +- ast_node = ast.parse(source_bytes, filename=filename) ++ ast_node = au.parse(source_bytes, filename=filename) + except SyntaxError as e: + raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg) + except UnicodeDecodeError as e: +@language python + +def _init_source(self, pycore, source_code, resource): + filename = "string" + if resource: + filename = resource.path + try: + if source_code is None: + source_bytes = resource.read_bytes() + source_code, _ = fscommands.file_data_to_unicode(source_bytes) + else: + if isinstance(source_code, str): + source_bytes = fscommands.unicode_to_file_data(source_code) + else: + source_bytes = source_code + ast_node = ast.parse(source_bytes, filename=filename) + except SyntaxError as e: + raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg) + except UnicodeDecodeError as e: + raise exceptions.ModuleSyntaxError(filename, 1, "%s" % (e.reason)) + return source_code, ast_node + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,6 +6,6 @@ + init_dot_py, force_errors=force_errors + ).get_ast() + else: +- ast_node = ast.parse("\n") ++ ast_node = au.parse("\n") + super().__init__(pycore, ast_node, resource) + +@language python + +def __init__(self, pycore, resource=None, force_errors=False): + self.resource = resource + init_dot_py = self._get_init_dot_py() + if init_dot_py is not None: + ast_node = pycore.project.get_pymodule( + init_dot_py, force_errors=force_errors + ).get_ast() + else: + ast_node = ast.parse("\n") + super().__init__(pycore, ast_node, resource) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,5 +2,5 @@ + self.assigned_ast = node.value + self.type_hint = node.annotation + +- ast.walk(node.target, self) ++ au.walk(node.target, self) + +@language python + +def _AnnAssign(self, node): + self.assigned_ast = node.value + self.type_hint = node.annotation + + ast.walk(node.target, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _Tuple(self, node): +- names = astutils.get_name_levels(node) ++ names = au.get_name_levels(node) + for name, levels in names: + assignment = None + if self.assigned_ast is not None: +@language python + +def _Tuple(self, node): + names = astutils.get_name_levels(node) + for name, levels in names: + assignment = None + if self.assigned_ast is not None: + assignment = pynames.AssignmentValue(self.assigned_ast, levels) + self._assigned(name, assignment) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _NamedExpr(self, node): +- ast.walk(node.target, _AssignVisitor(self)) +- ast.walk(node.value, self) ++ au.walk(node.target, _AssignVisitor(self)) ++ au.walk(node.value, self) + + +@language python + +def _NamedExpr(self, node): + ast.walk(node.target, _AssignVisitor(self)) + ast.walk(node.value, self) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def _Assign(self, node): + self.assigned_ast = node.value + for child_node in node.targets: +- ast.walk(child_node, self) +- ast.walk(node.value, _ExpressionVisitor(self.scope_visitor)) ++ au.walk(child_node, self) ++ au.walk(node.value, _ExpressionVisitor(self.scope_visitor)) + +@language python + +def _Assign(self, node): + self.assigned_ast = node.value + for child_node in node.targets: + ast.walk(child_node, self) + ast.walk(node.value, _ExpressionVisitor(self.scope_visitor)) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _Tuple(self, node): +- names = astutils.get_name_levels(node) ++ names = au.get_name_levels(node) + for name, levels in names: + assignment = None + if self.assigned_ast is not None: +@language python + +def _Tuple(self, node): + names = astutils.get_name_levels(node) + for name, levels in names: + assignment = None + if self.assigned_ast is not None: + assignment = pynames.AssignmentValue(self.assigned_ast, levels) + self._assigned(name, assignment) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,3 +1,3 @@ + def _Assign(self, node): +- ast.walk(node, _AssignVisitor(self)) ++ au.walk(node, _AssignVisitor(self)) + +@language python + +def _Assign(self, node): + ast.walk(node, _AssignVisitor(self)) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,3 +1,3 @@ + def _AnnAssign(self, node): +- ast.walk(node, _AnnAssignVisitor(self)) ++ au.walk(node, _AnnAssignVisitor(self)) + +@language python + +def _AnnAssign(self, node): + ast.walk(node, _AnnAssignVisitor(self)) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,5 @@ + def _For(self, node): +- names = self._update_evaluated( +- node.target, node.iter, ".__iter__().next()" # noqa +- ) ++ self._update_evaluated(node.target, node.iter, ".__iter__().next()") # noqa + for child in node.body + node.orelse: +- ast.walk(child, self) ++ au.walk(child, self) + +@language python + +def _For(self, node): + names = self._update_evaluated( + node.target, node.iter, ".__iter__().next()" # noqa + ) + for child in node.body + node.orelse: + ast.walk(child, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,7 +6,7 @@ + assignment = pynames.AssignmentValue(assigned, [], evaluation, eval_type) + self._assigned(targets, assignment) + else: +- names = astutils.get_name_levels(targets) ++ names = au.get_name_levels(targets) + for name, levels in names: + assignment = pynames.AssignmentValue( + assigned, levels, evaluation, eval_type +@language python + +def _update_evaluated( + self, targets, assigned, evaluation="", eval_type=False, type_hint=None +): + result = {} + if isinstance(targets, str): + assignment = pynames.AssignmentValue(assigned, [], evaluation, eval_type) + self._assigned(targets, assignment) + else: + names = astutils.get_name_levels(targets) + for name, levels in names: + assignment = pynames.AssignmentValue( + assigned, levels, evaluation, eval_type + ) + self._assigned(name, assignment) + return result + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,5 +5,5 @@ + item.optional_vars, item.context_expr, ".__enter__()" + ) + for child in node.body: +- ast.walk(child, self) ++ au.walk(child, self) + +@language python + +def _With(self, node): + for item in pycompat.get_ast_with_items(node): + if item.optional_vars: + self._update_evaluated( + item.optional_vars, item.context_expr, ".__enter__()" + ) + for child in node.body: + ast.walk(child, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -7,5 +7,5 @@ + self._update_evaluated(node.name, type_node, eval_type=True) + + for child in node.body: +- ast.walk(child, self) ++ au.walk(child, self) + +@language python + +def _excepthandler(self, node): + node_name_type = str + if node.name is not None and isinstance(node.name, node_name_type): + type_node = node.type + if isinstance(node.type, ast.Tuple) and type_node.elts: + type_node = type_node.elts[0] + self._update_evaluated(node.name, type_node, eval_type=True) + + for child in node.body: + ast.walk(child, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,4 @@ + def _comprehension(self, node): +- ast.walk(node.target, self) +- ast.walk(node.iter, self) ++ au.walk(node.target, self) ++ au.walk(node.iter, self) + +@language python + +def _comprehension(self, node): + ast.walk(node.target, self) + ast.walk(node.iter, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,7 +6,7 @@ + if isinstance(first, pycompat.ast_arg_type): + new_visitor = _ClassInitVisitor(self, pycompat.get_ast_arg_arg(first)) + if new_visitor is not None: +- for child in ast.get_child_nodes(node): +- ast.walk(child, new_visitor) ++ for child in au.get_child_nodes(node): ++ au.walk(child, new_visitor) + + +@language python + +def _FunctionDef(self, node): + _ScopeVisitor._FunctionDef(self, node) + if len(node.args.args) > 0: + first = node.args.args[0] + new_visitor = None + if isinstance(first, pycompat.ast_arg_type): + new_visitor = _ClassInitVisitor(self, pycompat.get_ast_arg_arg(first)) + if new_visitor is not None: + for child in ast.get_child_nodes(node): + ast.walk(child, new_visitor) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def _Tuple(self, node): + if not isinstance(node.ctx, ast.Store): + return +- for child in ast.get_child_nodes(node): +- ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + +@language python + +def _Tuple(self, node): + if not isinstance(node.ctx, ast.Store): + return + for child in ast.get_child_nodes(node): + ast.walk(child, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,8 @@ ++import rope.base.astutils as au + import rope.base.builtins + import rope.base.codeanalyze + import rope.base.pynames +-from rope.base import ast, exceptions, utils ++from rope.base import exceptions, utils + from rope.refactor import patchedast + + +@@ -186,8 +187,8 @@ + def _visit_comprehension(self): + if self.names is None: + new_visitor = self.visitor(self.pycore, self.pyobject) +- for node in ast.get_child_nodes(self.pyobject.get_ast()): +- ast.walk(node, new_visitor) ++ for node in au.get_child_nodes(self.pyobject.get_ast()): ++ au.walk(node, new_visitor) + self.names = dict(self.parent.get_names()) + self.names.update(new_visitor.names) + self.defineds = new_visitor.defineds +@@ -218,8 +219,8 @@ + def _visit_function(self): + if self.names is None: + new_visitor = self.visitor(self.pycore, self.pyobject) +- for n in ast.get_child_nodes(self.pyobject.get_ast()): +- ast.walk(n, new_visitor) ++ for n in au.get_child_nodes(self.pyobject.get_ast()): ++ au.walk(n, new_visitor) + self.names = new_visitor.names + self.names.update(self.pyobject.get_parameters()) + self.returned_asts = new_visitor.returned_asts +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,9 @@ + @path C:/Repos/ekr-rope/rope/base/ ++import rope.base.astutils as au + import rope.base.builtins + import rope.base.codeanalyze + import rope.base.pynames +-from rope.base import ast, exceptions, utils ++from rope.base import exceptions, utils + from rope.refactor import patchedast + + +@language python + +@path C:/Repos/ekr-rope/rope/base/ +import rope.base.builtins +import rope.base.codeanalyze +import rope.base.pynames +from rope.base import ast, exceptions, utils +from rope.refactor import patchedast + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,8 @@ + def _visit_comprehension(self): + if self.names is None: + new_visitor = self.visitor(self.pycore, self.pyobject) +- for node in ast.get_child_nodes(self.pyobject.get_ast()): +- ast.walk(node, new_visitor) ++ for node in au.get_child_nodes(self.pyobject.get_ast()): ++ au.walk(node, new_visitor) + self.names = dict(self.parent.get_names()) + self.names.update(new_visitor.names) + self.defineds = new_visitor.defineds +@language python + +def _visit_comprehension(self): + if self.names is None: + new_visitor = self.visitor(self.pycore, self.pyobject) + for node in ast.get_child_nodes(self.pyobject.get_ast()): + ast.walk(node, new_visitor) + self.names = dict(self.parent.get_names()) + self.names.update(new_visitor.names) + self.defineds = new_visitor.defineds + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,8 @@ + def _visit_function(self): + if self.names is None: + new_visitor = self.visitor(self.pycore, self.pyobject) +- for n in ast.get_child_nodes(self.pyobject.get_ast()): +- ast.walk(n, new_visitor) ++ for n in au.get_child_nodes(self.pyobject.get_ast()): ++ au.walk(n, new_visitor) + self.names = new_visitor.names + self.names.update(self.pyobject.get_parameters()) + self.returned_asts = new_visitor.returned_asts +@language python + +def _visit_function(self): + if self.names is None: + new_visitor = self.visitor(self.pycore, self.pyobject) + for n in ast.get_child_nodes(self.pyobject.get_ast()): + ast.walk(n, new_visitor) + self.names = new_visitor.names + self.names.update(self.pyobject.get_parameters()) + self.returned_asts = new_visitor.returned_asts + self.is_generator = new_visitor.generator + self.defineds = new_visitor.defineds + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -8,7 +8,6 @@ + from rope.base import exceptions + from rope.base import libutils + from rope.base import pynames +-from rope.base import pynamesdef + from rope.base import pyobjects + from rope.base import pyobjectsdef + from rope.base import pyscopes +@@ -186,9 +185,9 @@ + + # Start with the name of the object we're interested in. + names = [] +- if isinstance(pyname, pynamesdef.ParameterName): ++ if isinstance(pyname, pynames.ParameterName): + names = [(worder.get_name_at(pymod.get_resource(), offset), "PARAMETER")] +- elif isinstance(pyname, pynamesdef.AssignedName): ++ elif isinstance(pyname, pynames.AssignedName): + names = [(worder.get_name_at(pymod.get_resource(), offset), "VARIABLE")] + + # Collect scope names. +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -9,7 +9,6 @@ + from rope.base import exceptions + from rope.base import libutils + from rope.base import pynames +-from rope.base import pynamesdef + from rope.base import pyobjects + from rope.base import pyobjectsdef + from rope.base import pyscopes +@language python + +@path C:/Repos/ekr-rope/rope/contrib/ +import keyword +import sys +import warnings + +import rope.base.codeanalyze +import rope.base.evaluate +from rope.base import builtins +from rope.base import exceptions +from rope.base import libutils +from rope.base import pynames +from rope.base import pynamesdef +from rope.base import pyobjects +from rope.base import pyobjectsdef +from rope.base import pyscopes +from rope.base import worder +from rope.contrib import fixsyntax +from rope.refactor import functionutils + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -33,9 +33,9 @@ + + # Start with the name of the object we're interested in. + names = [] +- if isinstance(pyname, pynamesdef.ParameterName): ++ if isinstance(pyname, pynames.ParameterName): + names = [(worder.get_name_at(pymod.get_resource(), offset), "PARAMETER")] +- elif isinstance(pyname, pynamesdef.AssignedName): ++ elif isinstance(pyname, pynames.AssignedName): + names = [(worder.get_name_at(pymod.get_resource(), offset), "VARIABLE")] + + # Collect scope names. +@language python + +def get_canonical_path(project, resource, offset): + """Get the canonical path to an object. + + Given the offset of the object, this returns a list of + (name, name_type) tuples representing the canonical path to the + object. For example, the 'x' in the following code: + + class Foo(object): + def bar(self): + class Qux(object): + def mux(self, x): + pass + + we will return: + + [('Foo', 'CLASS'), ('bar', 'FUNCTION'), ('Qux', 'CLASS'), + ('mux', 'FUNCTION'), ('x', 'PARAMETER')] + + `resource` is a `rope.base.resources.Resource` object. + + `offset` is the offset of the pyname you want the path to. + + """ + # Retrieve the PyName. + pymod = project.get_pymodule(resource) + pyname = rope.base.evaluate.eval_location(pymod, offset) + + # Now get the location of the definition and its containing scope. + defmod, lineno = pyname.get_definition_location() + if not defmod: + return None + scope = defmod.get_scope().get_inner_scope_for_line(lineno) + + # Start with the name of the object we're interested in. + names = [] + if isinstance(pyname, pynamesdef.ParameterName): + names = [(worder.get_name_at(pymod.get_resource(), offset), "PARAMETER")] + elif isinstance(pyname, pynamesdef.AssignedName): + names = [(worder.get_name_at(pymod.get_resource(), offset), "VARIABLE")] + + # Collect scope names. + while scope.parent: + if isinstance(scope, pyscopes.FunctionScope): + scope_type = "FUNCTION" + elif isinstance(scope, pyscopes.ClassScope): + scope_type = "CLASS" + else: + scope_type = None + names.append((scope.pyobject.get_name(), scope_type)) + scope = scope.parent + + names.append((defmod.get_resource().real_path, "MODULE")) + names.reverse() + return names + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -23,8 +23,9 @@ + * ... ;-) + + """ +-from rope.base import ast, evaluate, pyobjects +- ++import ast ++from rope.base import evaluate, pyobjects ++import rope.base.astutils as au + + def find_errors(project, resource): + """Find possible bad name and attribute accesses +@@ -33,7 +34,7 @@ + """ + pymodule = project.get_pymodule(resource) + finder = _BadAccessFinder(pymodule) +- ast.walk(pymodule.get_ast(), finder) ++ au.walk(pymodule.get_ast(), finder) + return finder.errors + + +@@ -60,7 +61,7 @@ + if pyname is not None and pyname.get_object() != pyobjects.get_unknown(): + if node.attr not in pyname.get_object(): + self._add_error(node, "Unresolved attribute") +- ast.walk(node.value, self) ++ au.walk(node.value, self) + + def _add_error(self, node, msg): + if isinstance(node, ast.Attribute): +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -24,8 +24,9 @@ + * ... ;-) + + """ +-from rope.base import ast, evaluate, pyobjects +- ++import ast ++from rope.base import evaluate, pyobjects ++import rope.base.astutils as au + + @others + @language python +@language python + +@path C:/Repos/ekr-rope/rope/contrib/ +"""Finding bad name and attribute accesses + +`find_errors` function can be used to find possible bad name and +attribute accesses. As an example:: + + errors = find_errors(project, project.get_resource('mod.py')) + for error in errors: + print('%s: %s' % (error.lineno, error.error)) + +prints possible errors for ``mod.py`` file. + +TODO: + +* use task handles +* reporting names at most once +* attributes of extension modules that don't appear in + extension_modules project config can be ignored +* not calling `PyScope.get_inner_scope_for_line()` if it is a + bottleneck; needs profiling +* not reporting occurrences where rope cannot infer the object +* rope saves multiple objects for some of the names in its objectdb + use all of them not to give false positives +* ... ;-) + +""" +from rope.base import ast, evaluate, pyobjects + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,7 +5,7 @@ + """ + pymodule = project.get_pymodule(resource) + finder = _BadAccessFinder(pymodule) +- ast.walk(pymodule.get_ast(), finder) ++ au.walk(pymodule.get_ast(), finder) + return finder.errors + + +@language python + +def find_errors(project, resource): + """Find possible bad name and attribute accesses + + It returns a list of `Error`. + """ + pymodule = project.get_pymodule(resource) + finder = _BadAccessFinder(pymodule) + ast.walk(pymodule.get_ast(), finder) + return finder.errors + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,5 +5,5 @@ + if pyname is not None and pyname.get_object() != pyobjects.get_unknown(): + if node.attr not in pyname.get_object(): + self._add_error(node, "Unresolved attribute") +- ast.walk(node.value, self) ++ au.walk(node.value, self) + +@language python + +def _Attribute(self, node): + if not isinstance(node.ctx, ast.Store): + scope = self.scope.get_inner_scope_for_line(node.lineno) + pyname = evaluate.eval_node(scope, node.value) + if pyname is not None and pyname.get_object() != pyobjects.get_unknown(): + if node.attr not in pyname.get_object(): + self._add_error(node, "Unresolved attribute") + ast.walk(node.value, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,6 @@ + import rope.base.evaluate +-from rope.base import libutils +-from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze +-from rope.refactor import sourceutils, importutils, functionutils, suites +- ++from rope.base import change, codeanalyze, exceptions, libutils, pyobjects, pynames, worder ++from rope.refactor import functionutils, importutils, sourceutils, suites + + def create_generate(kind, project, resource, offset, goal_resource=None): + """A factory for creating `Generate` objects +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,7 @@ + @path C:/Repos/ekr-rope/rope/contrib/ + import rope.base.evaluate +-from rope.base import libutils +-from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze +-from rope.refactor import sourceutils, importutils, functionutils, suites +- ++from rope.base import change, codeanalyze, exceptions, libutils, pyobjects, pynames, worder ++from rope.refactor import functionutils, importutils, sourceutils, suites + + @others + @language python +@language python + +@path C:/Repos/ekr-rope/rope/contrib/ +import rope.base.evaluate +from rope.base import libutils +from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze +from rope.refactor import sourceutils, importutils, functionutils, suites + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,14 +1,16 @@ ++ ++import ast + import re + from contextlib import contextmanager + from itertools import chain + +-from rope.base import ast, codeanalyze ++from rope.base import codeanalyze ++import rope.base.astutils as au + from rope.base.change import ChangeSet, ChangeContents + from rope.base.exceptions import RefactoringError + from rope.base.utils import pycompat + from rope.base.utils.datastructures import OrderedSet + from rope.refactor import sourceutils, similarfinder, patchedast, suites, usefunction +- + + # Extract refactoring has lots of special cases. I tried to split it + # to smaller parts to make it more manageable: +@@ -590,7 +592,7 @@ + ) + body = self.info.source[self.info.scope_region[0] : self.info.scope_region[1]] + node = _parse_text(body) +- ast.walk(node, info_collector) ++ au.walk(node, info_collector) + return info_collector + + def _get_function_definition(self): +@@ -756,7 +758,7 @@ + def _get_globals_in_body(unindented_body): + node = _parse_text(unindented_body) + visitor = _GlobalFinder() +- ast.walk(node, visitor) ++ au.walk(node, visitor) + return visitor.globals_ + + +@@ -823,12 +825,12 @@ + for name in _get_argnames(node.args): + self._written_variable(name, node.lineno) + for child in node.body: +- ast.walk(child, self) ++ au.walk(child, self) + else: + self._written_variable(node.name, node.lineno) + visitor = _VariableReadsAndWritesFinder() + for child in node.body: +- ast.walk(child, visitor) ++ au.walk(child, visitor) + for name in visitor.read - visitor.written: + self._read_variable(name, node.lineno) + +@@ -847,21 +849,21 @@ + def _MatchAs(self, node): + self._written_variable(node.name, node.lineno) + if node.pattern: +- ast.walk(node.pattern, self) ++ au.walk(node.pattern, self) + + def _Assign(self, node): +- ast.walk(node.value, self) ++ au.walk(node.value, self) + for child in node.targets: +- ast.walk(child, self) ++ au.walk(child, self) + + def _AugAssign(self, node): +- ast.walk(node.value, self) ++ au.walk(node.value, self) + if isinstance(node.target, ast.Name): + target_id = node.target.id + self._read_variable(target_id, node.target.lineno) + self._written_variable(target_id, node.target.lineno) + else: +- ast.walk(node.target, self) ++ au.walk(node.target, self) + + def _ClassDef(self, node): + self._written_variable(node.name, node.lineno) +@@ -883,8 +885,8 @@ + written = OrderedSet(self.written) + maybe_written = OrderedSet(self.maybe_written) + +- for child in ast.get_child_nodes(node): +- ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + + comp_names = list( + chain.from_iterable( +@@ -915,18 +917,18 @@ + def _For(self, node): + with self._handle_loop_context(node), self._handle_conditional_context(node): + # iter has to be checked before the target variables +- ast.walk(node.iter, self) +- ast.walk(node.target, self) ++ au.walk(node.iter, self) ++ au.walk(node.target, self) + + for child in node.body: +- ast.walk(child, self) ++ au.walk(child, self) + for child in node.orelse: +- ast.walk(child, self) ++ au.walk(child, self) + + def _handle_conditional_node(self, node): + with self._handle_conditional_context(node): +- for child in ast.get_child_nodes(node): +- ast.walk(child, self) ++ for child in au.get_child_nodes(node): ++ au.walk(child, self) + + @contextmanager + def _handle_conditional_context(self, node): +@@ -974,8 +976,8 @@ + def _FunctionDef(self, node): + self.written.add(node.name) + visitor = _VariableReadsAndWritesFinder() +- for child in ast.get_child_nodes(node): +- ast.walk(child, visitor) ++ for child in au.get_child_nodes(node): ++ au.walk(child, visitor) + self.read.update(visitor.read - visitor.written) + + def _Class(self, node): +@@ -987,7 +989,7 @@ + return set(), set() + node = _parse_text(code) + visitor = _VariableReadsAndWritesFinder() +- ast.walk(node, visitor) ++ au.walk(node, visitor) + return visitor.read, visitor.written + + @staticmethod +@@ -996,7 +998,7 @@ + return set(), set() + node = _parse_text(code) + visitor = _VariableReadsAndWritesFinder() +- ast.walk(node, visitor) ++ au.walk(node, visitor) + return visitor.read + + +@@ -1007,7 +1009,7 @@ + return False + node = _parse_text(code) + visitor = cls() +- ast.walk(node, visitor) ++ au.walk(node, visitor) + return visitor.error + + +@@ -1025,14 +1027,14 @@ + def loop_encountered(self, node): + self.loop_count += 1 + for child in node.body: +- ast.walk(child, self) ++ au.walk(child, self) + self.loop_count -= 1 + if node.orelse: + if isinstance(node.orelse, (list, tuple)): + for node_ in node.orelse: +- ast.walk(node_, self) ++ au.walk(node_, self) + else: +- ast.walk(node.orelse, self) ++ au.walk(node.orelse, self) + + def _Break(self, node): + self.check_loop() +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,11 +1,13 @@ + @path C:/Repos/ekr-rope/rope/refactor/ ++import ast + import collections + import numbers + import re + import warnings + from itertools import chain + +-from rope.base import ast, codeanalyze, exceptions ++import rope.base.astutils as au ++from rope.base import codeanalyze, exceptions + from rope.base.utils import pycompat + + +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +import collections +import numbers +import re +import warnings +from itertools import chain + +from rope.base import ast, codeanalyze, exceptions +from rope.base.utils import pycompat + + +try: + basestring +except NameError: + basestring = (str, bytes) + +COMMA_IN_WITH_PATTERN = re.compile(r"\(.*?\)|(,)") + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,6 +4,6 @@ + Adds ``sorted_children`` field only if `sorted_children` is True. + + """ +- return patch_ast(ast.parse(source), source, sorted_children) ++ return patch_ast(au.parse(source), source, sorted_children) + + +@language python + +def get_patched_ast(source, sorted_children=False): + """Adds ``region`` and ``sorted_children`` fields to nodes + + Adds ``sorted_children`` field only if `sorted_children` is True. + + """ + return patch_ast(ast.parse(source), source, sorted_children) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -14,7 +14,7 @@ + if hasattr(node, "region"): + return node + walker = _PatchingASTWalker(source, children=sorted_children) +- ast.call_for_nodes(node, walker) ++ au.call_for_nodes(node, walker) + return node + + +@language python + +def patch_ast(node, source, sorted_children=False): + """Patches the given node + + After calling, each node in `node` will have a new field named + `region` that is a tuple containing the start and end offsets + of the code that generated it. + + If `sorted_children` is true, a `sorted_children` field will + be created for each node, too. It is a list containing child + nodes as well as whitespaces and comments that occur between + them. + + """ + if hasattr(node, "region"): + return node + walker = _PatchingASTWalker(source, children=sorted_children) + ast.call_for_nodes(node, walker) + return node + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -9,5 +9,5 @@ + ) + node.region = (self.source.offset, self.source.offset) + if self.children: +- node.sorted_children = ast.get_children(node) ++ node.sorted_children = au.get_children(node) + +@language python + +def __call__(self, node): + method = getattr(self, "_" + node.__class__.__name__, None) + if method is not None: + return method(node) + # ???: Unknown node; what should we do here? + warnings.warn( + "Unknown node type <%s>; please report!" % node.__class__.__name__, + RuntimeWarning, + ) + node.region = (self.source.offset, self.source.offset) + if self.children: + node.sorted_children = ast.get_children(node) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -21,7 +21,7 @@ + continue + offset = self.source.offset + if isinstance(child, ast.AST): +- ast.call_for_nodes(child, self) ++ au.call_for_nodes(child, self) + token_start = child.region[0] + else: + if child is self.String: +@language python + +def _handle(self, node, base_children, eat_parens=False, eat_spaces=False): + if hasattr(node, "region"): + # ???: The same node was seen twice; what should we do? + warnings.warn( + "Node <%s> has been already patched; please report!" + % node.__class__.__name__, + RuntimeWarning, + ) + return + + base_children = collections.deque(base_children) + self.children_stack.append(base_children) + children = collections.deque() + formats = [] + suspected_start = self.source.offset + start = suspected_start + first_token = True + while base_children: + child = base_children.popleft() + if child is None: + continue + offset = self.source.offset + if isinstance(child, ast.AST): + ast.call_for_nodes(child, self) + token_start = child.region[0] + else: + if child is self.String: + region = self.source.consume_string( + end=self._find_next_statement_start() + ) + elif child is self.Number: + region = self.source.consume_number() + elif child == self.empty_tuple: + region = self.source.consume_empty_tuple() + elif child == "!=": + # INFO: This has been added to handle deprecated ``<>`` + region = self.source.consume_not_equal() + elif child == self.semicolon_or_as_in_except: + # INFO: This has been added to handle deprecated + # semicolon in except + region = self.source.consume_except_as_or_semicolon() + elif child == self.exec_open_paren_or_space: + # These three cases handle the differences between + # the deprecated exec statement and the exec + # function. + region = self.source.consume_exec_open_paren_or_space() + elif child == self.exec_in_or_comma: + region = self.source.consume_exec_in_or_comma() + elif child == self.exec_close_paren_or_space: + region = self.source.consume_exec_close_paren_or_space() + elif child == self.with_or_comma_context_manager: + region = self.source.consume_with_or_comma_context_manager() + else: + if hasattr(ast, "JoinedStr") and isinstance( + node, (ast.JoinedStr, ast.FormattedValue) + ): + region = self.source.consume_joined_string(child) + else: + region = self.source.consume(child) + child = self.source[region[0] : region[1]] + token_start = region[0] + if not first_token: + formats.append(self.source[offset:token_start]) + if self.children: + children.append(self.source[offset:token_start]) + else: + first_token = False + start = token_start + if self.children: + children.append(child) + start = self._handle_parens(children, start, formats) + if eat_parens: + start = self._eat_surrounding_parens(children, suspected_start, start) + if eat_spaces: + if self.children: + children.appendleft(self.source[0:start]) + end_spaces = self.source[self.source.offset :] + self.source.consume(end_spaces) + if self.children: + children.append(end_spaces) + start = 0 + if self.children: + node.sorted_children = children + node.region = (start, self.source.offset) + self.children_stack.pop() + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,7 +6,7 @@ + break + else: + self._skip_comment() +- except (ValueError, TypeError) as e: ++ except (ValueError, TypeError): + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) +@language python + +def consume(self, token, skip_comment=True): + try: + while True: + new_offset = self.source.index(token, self.offset) + if self._good_token(token, new_offset) or not skip_comment: + break + else: + self._skip_comment() + except (ValueError, TypeError) as e: + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) + self.offset = new_offset + len(token) + return (new_offset, self.offset) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,7 @@ + import warnings + +-from rope.base import change, taskhandle, builtins, ast, codeanalyze ++import rope.base.astutils as au ++from rope.base import change, taskhandle, builtins, codeanalyze + from rope.base import libutils + from rope.refactor import patchedast, similarfinder, sourceutils + from rope.refactor.importutils import module_imports +@@ -312,7 +313,7 @@ + def _get_nearest_roots(self, node): + if node not in self._nearest_roots: + result = [] +- for child in ast.get_child_nodes(node): ++ for child in au.get_child_nodes(node): + if child in self.matched_asts: + result.append(child) + else: +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,8 @@ + @path C:/Repos/ekr-rope/rope/refactor/ + import warnings + +-from rope.base import change, taskhandle, builtins, ast, codeanalyze ++import rope.base.astutils as au ++from rope.base import change, taskhandle, builtins, codeanalyze + from rope.base import libutils + from rope.refactor import patchedast, similarfinder, sourceutils + from rope.refactor.importutils import module_imports +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +import warnings + +from rope.base import change, taskhandle, builtins, ast, codeanalyze +from rope.base import libutils +from rope.refactor import patchedast, similarfinder, sourceutils +from rope.refactor.importutils import module_imports + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + def _get_nearest_roots(self, node): + if node not in self._nearest_roots: + result = [] +- for child in ast.get_child_nodes(node): ++ for child in au.get_child_nodes(node): + if child in self.matched_asts: + result.append(child) + else: +@language python + +def _get_nearest_roots(self, node): + if node not in self._nearest_roots: + result = [] + for child in ast.get_child_nodes(node): + if child in self.matched_asts: + result.append(child) + else: + result.extend(self._get_nearest_roots(child)) + self._nearest_roots[node] = result + return self._nearest_roots[node] + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,11 +1,11 @@ + """This module can be used for finding similar code""" ++import ast + import re + ++import rope.base.astutils as au + import rope.refactor.wildcards +-from rope.base import libutils +-from rope.base import codeanalyze, exceptions, ast, builtins ++from rope.base import builtins, codeanalyze, exceptions, libutils + from rope.refactor import patchedast, wildcards +- + from rope.refactor.patchedast import MismatchedTokenError + + +@@ -72,10 +72,10 @@ + def __init__(self, source, node=None, does_match=None): + if node is None: + try: +- node = ast.parse(source) ++ node = au.parse(source) + except SyntaxError: + # needed to parse expression containing := operator +- node = ast.parse("(" + source + ")") ++ node = au.parse("(" + source + ")") + if does_match is None: + self.does_match = self._simple_does_match + else: +@@ -119,7 +119,7 @@ + + def _create_pattern(self, expression): + expression = self._replace_wildcards(expression) +- node = ast.parse(expression) ++ node = au.parse(expression) + # Getting Module.Stmt.nodes + nodes = node.body + if len(nodes) == 1 and isinstance(nodes[0], ast.Expr): +@@ -154,7 +154,7 @@ + def find_matches(self): + if self.matches is None: + self.matches = [] +- ast.call_for_nodes(self.body, self._check_node, recursive=True) ++ au.call_for_nodes(self.body, self._check_node, recursive=True) + return self.matches + + def _check_node(self, node): +@@ -169,7 +169,7 @@ + self.matches.append(ExpressionMatch(node, mapping)) + + def _check_statements(self, node): +- for child in ast.get_children(node): ++ for child in au.get_children(node): + if isinstance(child, (list, tuple)): + self.__check_stmt_list(child) + +@@ -211,7 +211,7 @@ + + def _get_children(self, node): + """Return not `ast.expr_context` children of `node`""" +- children = ast.get_children(node) ++ children = au.get_children(node) + return [child for child in children if not isinstance(child, ast.expr_context)] + + def _match_stmts(self, current_stmts, mapping): +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,12 +1,12 @@ + @path C:/Repos/ekr-rope/rope/refactor/ + """This module can be used for finding similar code""" ++import ast + import re + ++import rope.base.astutils as au + import rope.refactor.wildcards +-from rope.base import libutils +-from rope.base import codeanalyze, exceptions, ast, builtins ++from rope.base import builtins, codeanalyze, exceptions, libutils + from rope.refactor import patchedast, wildcards +- + from rope.refactor.patchedast import MismatchedTokenError + + +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +"""This module can be used for finding similar code""" +import re + +import rope.refactor.wildcards +from rope.base import libutils +from rope.base import codeanalyze, exceptions, ast, builtins +from rope.refactor import patchedast, wildcards + +from rope.refactor.patchedast import MismatchedTokenError + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,10 +1,10 @@ + def __init__(self, source, node=None, does_match=None): + if node is None: + try: +- node = ast.parse(source) ++ node = au.parse(source) + except SyntaxError: + # needed to parse expression containing := operator +- node = ast.parse("(" + source + ")") ++ node = au.parse("(" + source + ")") + if does_match is None: + self.does_match = self._simple_does_match + else: +@language python + +def __init__(self, source, node=None, does_match=None): + if node is None: + try: + node = ast.parse(source) + except SyntaxError: + # needed to parse expression containing := operator + node = ast.parse("(" + source + ")") + if does_match is None: + self.does_match = self._simple_does_match + else: + self.does_match = does_match + self._init_using_ast(node, source) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def _create_pattern(self, expression): + expression = self._replace_wildcards(expression) +- node = ast.parse(expression) ++ node = au.parse(expression) + # Getting Module.Stmt.nodes + nodes = node.body + if len(nodes) == 1 and isinstance(nodes[0], ast.Expr): +@language python + +def _create_pattern(self, expression): + expression = self._replace_wildcards(expression) + node = ast.parse(expression) + # Getting Module.Stmt.nodes + nodes = node.body + if len(nodes) == 1 and isinstance(nodes[0], ast.Expr): + # Getting Discard.expr + wanted = nodes[0].value + else: + wanted = nodes + return wanted + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def find_matches(self): + if self.matches is None: + self.matches = [] +- ast.call_for_nodes(self.body, self._check_node, recursive=True) ++ au.call_for_nodes(self.body, self._check_node, recursive=True) + return self.matches + +@language python + +def find_matches(self): + if self.matches is None: + self.matches = [] + ast.call_for_nodes(self.body, self._check_node, recursive=True) + return self.matches + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _check_statements(self, node): +- for child in ast.get_children(node): ++ for child in au.get_children(node): + if isinstance(child, (list, tuple)): + self.__check_stmt_list(child) + +@language python + +def _check_statements(self, node): + for child in ast.get_children(node): + if isinstance(child, (list, tuple)): + self.__check_stmt_list(child) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _get_children(self, node): + """Return not `ast.expr_context` children of `node`""" +- children = ast.get_children(node) ++ children = au.get_children(node) + return [child for child in children if not isinstance(child, ast.expr_context)] + +@language python + +def _get_children(self, node): + """Return not `ast.expr_context` children of `node`""" + children = ast.get_children(node) + return [child for child in children if not isinstance(child, ast.expr_context)] + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ ++import ast + from itertools import chain + +-from rope.base import ast +-from rope.base.utils import pycompat ++import rope.base.astutils as au + + + def find_visible(node, lines): +@@ -72,7 +72,7 @@ + if self._children is None: + walker = _SuiteWalker(self) + for child in self.child_nodes: +- ast.walk(child, walker) ++ au.walk(child, walker) + self._children = walker.suites + return self._children +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,8 @@ + @path C:/Repos/ekr-rope/rope/refactor/ ++import ast + from itertools import chain + +-from rope.base import ast +-from rope.base.utils import pycompat ++import rope.base.astutils as au + + + @others +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +from itertools import chain + +from rope.base import ast +from rope.base.utils import pycompat + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,7 @@ + if self._children is None: + walker = _SuiteWalker(self) + for child in self.child_nodes: +- ast.walk(child, walker) ++ au.walk(child, walker) + self._children = walker.suites + return self._children + +@language python + +def get_children(self): + if self._children is None: + walker = _SuiteWalker(self) + for child in self.child_nodes: + ast.walk(child, walker) + self._children = walker.suites + return self._children + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,8 @@ +-from rope.base import change, taskhandle, evaluate, exceptions, pyobjects, pynames, ast +-from rope.base import libutils ++ ++import ast ++ ++import rope.base.astutils as au ++from rope.base import change, taskhandle, evaluate, exceptions, libutils, pyobjects, pynames + from rope.refactor import restructure, sourceutils, similarfinder + + +@@ -191,6 +194,6 @@ + def start_walking(self, node): + nodes = [node] + if isinstance(node, ast.FunctionDef): +- nodes = ast.get_child_nodes(node) ++ nodes = au.get_child_nodes(node) + for child in nodes: +- ast.walk(child, self) ++ au.walk(child, self) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,9 @@ + @path C:/Repos/ekr-rope/rope/refactor/ +-from rope.base import change, taskhandle, evaluate, exceptions, pyobjects, pynames, ast +-from rope.base import libutils ++ ++import ast ++ ++import rope.base.astutils as au ++from rope.base import change, taskhandle, evaluate, exceptions, libutils, pyobjects, pynames + from rope.refactor import restructure, sourceutils, similarfinder + + +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +from rope.base import change, taskhandle, evaluate, exceptions, pyobjects, pynames, ast +from rope.base import libutils +from rope.refactor import restructure, sourceutils, similarfinder + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def start_walking(self, node): + nodes = [node] + if isinstance(node, ast.FunctionDef): +- nodes = ast.get_child_nodes(node) ++ nodes = au.get_child_nodes(node) + for child in nodes: +- ast.walk(child, self) ++ au.walk(child, self) +@language python + +def start_walking(self, node): + nodes = [node] + if isinstance(node, ast.FunctionDef): + nodes = ast.get_child_nodes(node) + for child in nodes: + ast.walk(child, self) + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,5 @@ +-from rope.base import ast, evaluate, builtins, pyobjects ++import ast ++from rope.base import evaluate, builtins, pyobjects + from rope.refactor import patchedast, occurrences +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,6 @@ + @path C:/Repos/ekr-rope/rope/refactor/ +-from rope.base import ast, evaluate, builtins, pyobjects ++import ast ++from rope.base import evaluate, builtins, pyobjects + from rope.refactor import patchedast, occurrences + + +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +from rope.base import ast, evaluate, builtins, pyobjects +from rope.refactor import patchedast, occurrences + + +@others +@language python +@tabwidth -4 + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,10 @@ + @path C:/Repos/ekr-rope/rope/refactor/importutils/ ++import ast + from typing import Union, List + +-from rope.base import ast, exceptions, pynames, pynamesdef, utils ++from rope.base import exceptions, pynames, utils ++import rope.base.astutils as au + from rope.refactor.importutils import actions, importinfo +- + + @others + @language python +@language python + +@path C:/Repos/ekr-rope/rope/refactor/importutils/ +from typing import Union, List + +from rope.base import ast, exceptions, pynames, pynamesdef, utils +from rope.refactor.importutils import actions, importinfo + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def _get_unbound_names(self, defined_pyobject): + visitor = _GlobalUnboundNameFinder(self.pymodule, defined_pyobject) +- ast.walk(self.pymodule.get_ast(), visitor) ++ au.walk(self.pymodule.get_ast(), visitor) + return visitor.unbound + +@language python + +def _get_unbound_names(self, defined_pyobject): + visitor = _GlobalUnboundNameFinder(self.pymodule, defined_pyobject) + ast.walk(self.pymodule.get_ast(), visitor) + return visitor.unbound + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + def _get_all_star_list(self, pymodule): + def _resolve_name( +- name: Union[pynamesdef.AssignedName, pynames.ImportedName] ++ name: Union[pynames.AssignedName, pynames.ImportedName] + ) -> List: + while isinstance(name, pynames.ImportedName): + try: +@@ -9,7 +9,7 @@ + ) + except exceptions.AttributeNotFoundError: + return [] +- assert isinstance(name, pynamesdef.AssignedName) ++ assert isinstance(name, pynames.AssignedName) + return name.assignments + + result = set() +@language python + +def _get_all_star_list(self, pymodule): + def _resolve_name( + name: Union[pynamesdef.AssignedName, pynames.ImportedName] + ) -> List: + while isinstance(name, pynames.ImportedName): + try: + name = name.imported_module.get_object().get_attribute( + name.imported_name, + ) + except exceptions.AttributeNotFoundError: + return [] + assert isinstance(name, pynamesdef.AssignedName) + return name.assignments + + result = set() + try: + all_star_list = pymodule.get_attribute("__all__") + except exceptions.AttributeNotFoundError: + return result + + assignments = [ + assignment.ast_node for assignment in _resolve_name(all_star_list) + ] + + # FIXME: Need a better way to recursively infer possible values. + # Currently pyobjects can recursively infer type, but not values. + # Do a very basic 1-level value inference + + while assignments: + assignment = assignments.pop() + if isinstance(assignment, ast.List): + stack = list(assignment.elts) + while stack: + el = stack.pop() + if isinstance(el, ast.IfExp): + stack.append(el.body) + stack.append(el.orelse) + elif isinstance(el, ast.Starred): + assignments.append(el.value) + else: + if isinstance(el, ast.Str): + result.add(el.s) + elif isinstance(el, ast.Name): + try: + name = pymodule.get_attribute(el.id) + except exceptions.AttributeNotFoundError: + continue + else: + for av in _resolve_name(name): + if isinstance(av.ast_node, ast.Str): + result.add(av.ast_node.s) + elif isinstance(assignment, ast.Name): + try: + name = pymodule.get_attribute(assignment.id) + except exceptions.AttributeNotFoundError: + continue + else: + assignments.extend( + assignment.ast_node for assignment in _resolve_name(name) + ) + elif isinstance(assignment, ast.BinOp): + assignments.append(assignment.left) + assignments.append(assignment.right) + return result + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,6 +6,6 @@ + .pyobject + ) + visitor = _LocalUnboundNameFinder(pyobject, self) +- for child in ast.get_child_nodes(node): +- ast.walk(child, visitor) ++ for child in au.get_child_nodes(node): ++ au.walk(child, visitor) + +@language python + +def _visit_child_scope(self, node): + pyobject = ( + self.pyobject.get_module() + .get_scope() + .get_inner_scope_for_line(node.lineno) + .pyobject + ) + visitor = _LocalUnboundNameFinder(pyobject, self) + for child in ast.get_child_nodes(node): + ast.walk(child, visitor) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -11,5 +11,5 @@ + ): + self.add_unbound(primary) + else: +- ast.walk(node, self) ++ au.walk(node, self) + +@language python + +def _Attribute(self, node): + result = [] + while isinstance(node, ast.Attribute): + result.append(node.attr) + node = node.value + if isinstance(node, ast.Name): + result.append(node.id) + primary = ".".join(reversed(result)) + if self._get_root()._is_node_interesting(node) and not self.is_bound( + primary + ): + self.add_unbound(primary) + else: + ast.walk(node, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,10 +1,12 @@ ++import ast + import collections + import numbers + import re + import warnings + from itertools import chain + +-from rope.base import ast, codeanalyze, exceptions ++import rope.base.astutils as au ++from rope.base import codeanalyze, exceptions + from rope.base.utils import pycompat + + +@@ -22,7 +24,7 @@ + Adds ``sorted_children`` field only if `sorted_children` is True. + + """ +- return patch_ast(ast.parse(source), source, sorted_children) ++ return patch_ast(au.parse(source), source, sorted_children) + + + def patch_ast(node, source, sorted_children=False): +@@ -41,7 +43,7 @@ + if hasattr(node, "region"): + return node + walker = _PatchingASTWalker(source, children=sorted_children) +- ast.call_for_nodes(node, walker) ++ au.call_for_nodes(node, walker) + return node + + +@@ -96,7 +98,7 @@ + ) + node.region = (self.source.offset, self.source.offset) + if self.children: +- node.sorted_children = ast.get_children(node) ++ node.sorted_children = au.get_children(node) + + def _handle(self, node, base_children, eat_parens=False, eat_spaces=False): + if hasattr(node, "region"): +@@ -121,7 +123,7 @@ + continue + offset = self.source.offset + if isinstance(child, ast.AST): +- ast.call_for_nodes(child, self) ++ au.call_for_nodes(child, self) + token_start = child.region[0] + else: + if child is self.String: +@@ -927,7 +929,7 @@ + break + else: + self._skip_comment() +- except (ValueError, TypeError) as e: ++ except (ValueError, TypeError): + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) +@language python + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,4 @@ + """Tests for autoimport utility functions, written in pytest""" +- +-from sys import platform +- +-import pytest + + from rope.contrib.autoimport import utils + from rope.contrib.autoimport.defs import Package, PackageType, Source +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,5 @@ + @path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ + """Tests for autoimport utility functions, written in pytest""" +- +-from sys import platform +- +-import pytest + + from rope.contrib.autoimport import utils + from rope.contrib.autoimport.defs import Package, PackageType, Source +@language python + +@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ +"""Tests for autoimport utility functions, written in pytest""" + +from sys import platform + +import pytest + +from rope.contrib.autoimport import utils +from rope.contrib.autoimport.defs import Package, PackageType, Source + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -9,7 +9,7 @@ + from rope.base import libutils + from rope.base.pycore import _TextChangeDetector + from rope.base.pyobjects import get_base_type, AbstractFunction +-from rope.base.pynamesdef import AssignedName ++from rope.base.pynames import AssignedName + from ropetest import testutils +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -10,7 +10,7 @@ + from rope.base import libutils + from rope.base.pycore import _TextChangeDetector + from rope.base.pyobjects import get_base_type, AbstractFunction +-from rope.base.pynamesdef import AssignedName ++from rope.base.pynames import AssignedName + from ropetest import testutils + + +@language python + +@path C:/Repos/ekr-rope/ropetest/ +import sys +from textwrap import dedent + +from rope.base.builtins import File, BuiltinClass + +import unittest + +from rope.base import exceptions +from rope.base import libutils +from rope.base.pycore import _TextChangeDetector +from rope.base.pyobjects import get_base_type, AbstractFunction +from rope.base.pynamesdef import AssignedName +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + + + + + + + + +@language rest +@wrap + +PR: move special case from walk to _ScopeVisitor._ImportFrom +https://github.com/python-rope/rope/pull/538 + +To do: +- comment out parts of unit test to increase focus. + +@language python + + +@language rest +@wrap + +- Add # pragma: no cover + +@language python + + +@ignore +@nosearch + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -11,8 +11,6 @@ + import os + import shutil + import subprocess +- +-import rope.base.utils.pycompat as pycompat + import typing + + +@language python + +@path C:/Repos/ekr-rope/rope/base/ +"""Project file system commands. + +This modules implements file system operations used by rope. Different +version control systems can be supported by implementing the interface +provided by `FileSystemCommands` class. See `SubversionCommands` and +`MercurialCommands` for example. + +""" +import re +import os +import shutil +import subprocess + +import rope.base.utils.pycompat as pycompat +import typing + + +FileContent = typing.NewType("FileContent", bytes) + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -30,9 +30,7 @@ + pycore, pyfunction, return_true, return_false, new_followed_calls + ) + +- if not followed_calls: +- _follow = None +- visitor = SOAVisitor(pycore, pydefined, _follow) ++ visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None) + for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): + rope.base.ast.walk(child, visitor) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -14,9 +14,7 @@ + pycore, pyfunction, return_true, return_false, new_followed_calls + ) + +- if not followed_calls: +- _follow = None +- visitor = SOAVisitor(pycore, pydefined, _follow) ++ visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None) + for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): + rope.base.ast.walk(child, visitor) + +@language python + +def _analyze_node(pycore, pydefined, should_analyze, search_subscopes, followed_calls): + if search_subscopes(pydefined): + for scope in pydefined.get_scope().get_scopes(): + _analyze_node( + pycore, scope.pyobject, should_analyze, search_subscopes, followed_calls + ) + if should_analyze(pydefined): + new_followed_calls = max(0, followed_calls - 1) + return_true = lambda pydefined: True + return_false = lambda pydefined: False + + def _follow(pyfunction): + _analyze_node( + pycore, pyfunction, return_true, return_false, new_followed_calls + ) + + if not followed_calls: + _follow = None + visitor = SOAVisitor(pycore, pydefined, _follow) + for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): + rope.base.ast.walk(child, visitor) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,6 @@ + # Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm + # and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py + import re +-from rope.base.utils import pycompat + from rope.base.oi.type_hinting import utils + from rope.base import utils as base_utils + +@@ -268,7 +267,7 @@ + + + @method(symbol("[")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa + return utils.parametrize_type( + self.first.evaluate(pyobject), *[i.evaluate(pyobject) for i in self.second] + ) +@@ -276,7 +275,7 @@ + + # Anonymous Function Calls + @method(symbol("(")) +-def nud(self, parser): ++def nud(self, parser): # noqa + self.second = [] + if parser.token.name != ")": + while 1: +@@ -292,7 +291,7 @@ + + # Function Calls + @method(symbol("(")) +-def led(self, left, parser): ++def led(self, left, parser): # noqa + self.first = left + self.second = [] + if parser.token.name != ")": +@@ -308,14 +307,14 @@ + + + @method(symbol("(")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa + # TODO: Implement me + raise NotImplementedError + + + @method(symbol("or")) + @method(symbol("|")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa + # TODO: Implement me + raise NotImplementedError + +@@ -355,4 +354,4 @@ + return ast.evaluate(pyobject) + + +-evaluate = Evaluator() ++evaluate = Evaluator() # noqa +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + @path C:/Repos/ekr-rope/rope/base/ + @nopyflakes +-import ast +-from ast import * ++import ast # noqu ++from ast import * # noqa + + from rope.base import fscommands + +@language python + +@path C:/Repos/ekr-rope/rope/base/ +@nopyflakes +import ast +from ast import * + +from rope.base import fscommands + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ +-import ast +-from ast import * ++import ast # noqu ++from ast import * # noqa + + from rope.base import fscommands +@language python + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -10,8 +10,6 @@ + import os + import shutil + import subprocess +- +-import rope.base.utils.pycompat as pycompat + import typing +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,6 @@ + # Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm + # and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py + import re +-from rope.base.utils import pycompat + from rope.base.oi.type_hinting import utils + from rope.base import utils as base_utils + +@language python + +@path C:/Repos/ekr-rope/rope/base/ +# Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm +# and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py +import re +from rope.base.utils import pycompat +from rope.base.oi.type_hinting import utils +from rope.base import utils as base_utils + + +class SymbolBase: + + name = None # node/token type name + + def __init__(self): + self.value = None # used by name and literals + self.first = None + self.second = None + self.third = None # used by tree nodes + + def nud(self, parser): + raise SyntaxError("Syntax error (%r)." % self.name) + + def led(self, left, parser): + raise SyntaxError("Unknown operator (%r)." % self.name) + + def evaluate(self, pyobject): + raise NotImplementedError(self.name, self) + + def __repr__(self): + if self.name == "(name)": + return "({} {})".format(self.name[1:-1], self.value) + out = [repr(self.name), self.first, self.second, self.third] + out = [str(i) for i in out if i] + return "(" + " ".join(out) + ")" + + +class SymbolTable: + def multi(func): + def _inner(self, names, *a, **kw): + for name in names.split(): + func(self, name, *a, **kw) + + return _inner + + def __init__(self): + self.symbol_table = {} + + def get(self, name, default=None): + return self.symbol_table.get(name, default) + + def __getitem__(self, name): + return self.symbol_table[name] + + def __iter__(self): + return iter(self.symbol_table) + + def symbol(self, name, bp=0): + try: + s = self.symbol_table[name] + except KeyError: + + class S(SymbolBase): + pass + + s = S + s.__name__ = "symbol-" + name # for debugging + s.name = name + s.lbp = bp + self.symbol_table[name] = s + else: + s.lbp = max(bp, s.lbp) + return s + + @multi + def infix(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def led(self, left, parser): + self.first = left + self.second = parser.expression(bp) + return self + + @multi + def infix_r(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def led(self, left, parser): + self.first = left + self.second = parser.expression(bp - 0.1) + return self + + def ternary(self, name, name2, bp): + symbol = self.symbol(name, bp) + symbol2 = self.symbol(name2) + + @method(symbol) + def led(self, left, parser): + self.first = left + self.second = parser.expression(symbol2.lbp) + parser.advance(symbol2.name) + self.third = parser.expression(symbol2.lbp + 0.1) + return self + + @multi + def prefix(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def nud(self, parser): + self.first = parser.expression(bp) + return self + + @multi + def postfix(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def led(self, left, parser): + self.first = left + return self + + multi = staticmethod(multi) # Just for code checker + + +symbol_table = SymbolTable() + + +class Lexer: + + _token_pattern = re.compile( + r""" + \s* + (?: + ( + [,()\[\]|] + | -> + | (?<=\s)(?:or)\b + ) # operator + | ([a-zA-Z](?:\w|\.)*) # name + ) + """, + re.U | re.S | re.X, + ) + + def __init__(self, symbol_table): + self.symbol_table = symbol_table + + def tokenize(self, program): + for name, value in self._tokenize_expr(program): + symbol = symbol_table.get(value) + if symbol: + s = symbol() + elif name == "(name)": + symbol = symbol_table[name] + s = symbol() + s.value = value + else: + raise SyntaxError( + "Unknown operator ({}). Possible operators are {!r}".format( + value, list(self.symbol_table) + ) + ) + + yield s + + def _tokenize_expr(self, program): + if isinstance(program, bytes): + program = program.decode("utf-8") + # import pprint; pprint.pprint(self._token_pattern.findall(program)) + for operator, name in self._token_pattern.findall(program): + if operator: + yield "(operator)", operator + elif name: + yield "(name)", name + else: + raise SyntaxError + yield "(end)", "(end)" + + +class Parser: + + token = None + next = None + + def __init__(self, lexer): + self.lexer = lexer + + def parse(self, program): + generator = self.lexer.tokenize(program) + self.next = generator.__next__ + self.token = self.next() + return self.expression() + + def expression(self, rbp=0): + t = self.token + self.token = self.next() + left = t.nud(self) + while rbp < self.token.lbp: + t = self.token + self.token = self.next() + left = t.led(left, self) + return left + + def advance(self, name=None): + if name and self.token.name != name: + raise SyntaxError(f"Expected {name!r} but found {self.token.name!r}") + self.token = self.next() + + +def method(s): + assert issubclass(s, SymbolBase) + + def bind(fn): + setattr(s, fn.__name__, fn) + return fn + + return bind + + +symbol, infix, infix_r, prefix, postfix, ternary = ( + symbol_table.symbol, + symbol_table.infix, + symbol_table.infix_r, + symbol_table.prefix, + symbol_table.postfix, + symbol_table.ternary, +) + +symbol("(", 270) +symbol(")") +symbol("[", 250) # Parameters +symbol("]") +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,4 +6,4 @@ + + + @method(symbol("[")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa +@language python + + if parser.token.name != ",": + break + parser.advance(",") + parser.advance("]") + return self + + +@method(symbol("[")) +def evaluate(self, pyobject): + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + @method(symbol("(")) +-def nud(self, parser): ++def nud(self, parser): # noqa + self.second = [] + if parser.token.name != ")": + while 1: +@language python + +@method(symbol("(")) +def nud(self, parser): +self.second = [] +if parser.token.name != ")": + while 1: + self.second.append(parser.expression()) + if parser.token.name != ",": + break + parser.advance(",") +parser.advance(")") +parser.advance("->") +self.third = parser.expression(symbol("->").lbp + 0.1) +return self + + +# Function Calls + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + @method(symbol("(")) +-def led(self, left, parser): ++def led(self, left, parser): # noqa + self.first = left + self.second = [] + if parser.token.name != ")": +@language python + +@method(symbol("(")) +def led(self, left, parser): +self.first = left +self.second = [] +if parser.token.name != ")": + while 1: + self.second.append(parser.expression()) + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,14 +5,14 @@ + + + @method(symbol("(")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa + # TODO: Implement me + raise NotImplementedError + + + @method(symbol("or")) + @method(symbol("|")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa + # TODO: Implement me + raise NotImplementedError + +@language python + +parser.advance(")") +parser.advance("->") +self.third = parser.expression(symbol("->").lbp + 0.1) +return self + + +@method(symbol("(")) +def evaluate(self, pyobject): +# TODO: Implement me +raise NotImplementedError + + +@method(symbol("or")) +@method(symbol("|")) +def evaluate(self, pyobject): +# TODO: Implement me +raise NotImplementedError + + +class Compiler: + +parser_factory = Parser +lexer_factory = Lexer +symbol_table = symbol_table + +def _make_parser(self): + return self.parser_factory(self.lexer_factory(self.symbol_table)) + +@base_utils.cached(500) +def __call__(self, program): + """ + :type program: str + :rtype: rope.base.oi.type_hinting.evaluate.SymbolBase + """ + return self._make_parser().parse(program) + + +compile = Compiler() + + +class Evaluator: + +compile = compile + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -9,4 +9,4 @@ + return ast.evaluate(pyobject) + + +-evaluate = Evaluator() ++evaluate = Evaluator() # noqa +@language python + + +def __call__(self, program, pyobject): + """Evaluates the program string or AST + + :type program: str or rope.base.oi.type_hinting.evaluate.SymbolBase + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + ast = self.compile(program) if isinstance(program, str) else program + return ast.evaluate(pyobject) + + +evaluate = Evaluator() + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + import re +-from rope.base.oi.type_hinting import utils ++ + from rope.base.oi.type_hinting.providers import interfaces +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + @path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ + import re +-from rope.base.oi.type_hinting import utils ++ + from rope.base.oi.type_hinting.providers import interfaces + + +@language python + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ +import re +from rope.base.oi.type_hinting import utils +from rope.base.oi.type_hinting.providers import interfaces + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,14 +1,10 @@ + import logging ++from typing import Optional, Union + +-try: +- from typing import Union, Optional +-except ImportError: +- pass + import rope.base.utils as base_utils + from rope.base import evaluate + from rope.base.exceptions import AttributeNotFoundError + from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject +-from rope.base.utils import pycompat + + + def get_super_func(pyfunc): +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,15 +1,11 @@ + @path C:/Repos/ekr-rope/rope/base/ + import logging ++from typing import Optional, Union + +-try: +- from typing import Union, Optional +-except ImportError: +- pass + import rope.base.utils as base_utils + from rope.base import evaluate + from rope.base.exceptions import AttributeNotFoundError + from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject +-from rope.base.utils import pycompat + + + @others +@language python + +@path C:/Repos/ekr-rope/rope/base/ +import logging + +try: + from typing import Union, Optional +except ImportError: + pass +import rope.base.utils as base_utils +from rope.base import evaluate +from rope.base.exceptions import AttributeNotFoundError +from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject +from rope.base.utils import pycompat + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,5 @@ + import bisect + import difflib +-import sys + import warnings + + import rope.base.libutils +@@ -15,7 +14,6 @@ + from rope.base import stdmods + from rope.base import taskhandle + from rope.base import utils +-from rope.base.exceptions import ModuleNotFoundError + + + class PyCore: +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,3 @@ +-from rope.base.pynames import DefinedName + import rope.base.builtins + import rope.base.codeanalyze + import rope.base.evaluate +@language python + +from rope.base.pynames import DefinedName +import rope.base.builtins +import rope.base.codeanalyze +import rope.base.evaluate +import rope.base.libutils +import rope.base.oi.soi +import rope.base.pyscopes +from rope.base import ( + pynamesdef as pynames, + exceptions, + ast, + astutils, + pyobjects, + fscommands, + arguments, + utils, +) +from rope.base.utils import pycompat + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,5 @@ + def _For(self, node): +- names = self._update_evaluated( +- node.target, node.iter, ".__iter__().next()" # noqa +- ) ++ self._update_evaluated(node.target, node.iter, ".__iter__().next()") + for child in node.body + node.orelse: + ast.walk(child, self) + +@language python + +def _For(self, node): + names = self._update_evaluated( + node.target, node.iter, ".__iter__().next()" # noqa + ) + for child in node.body + node.orelse: + ast.walk(child, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,6 +2,7 @@ + from .pickle import AutoImport as _PickleAutoImport + from .sqlite import AutoImport as _SqliteAutoImport + ++assert _SqliteAutoImport # Workaround for an apparent pyflakes bug. + + AutoImport = _PickleAutoImport +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -3,6 +3,7 @@ + from .pickle import AutoImport as _PickleAutoImport + from .sqlite import AutoImport as _SqliteAutoImport + ++assert _SqliteAutoImport # Workaround for an apparent pyflakes bug. + + AutoImport = _PickleAutoImport + +@language python + +@path C:/Repos/ekr-rope/rope/ +"""AutoImport module for rope.""" +from .pickle import AutoImport as _PickleAutoImport +from .sqlite import AutoImport as _SqliteAutoImport + + +AutoImport = _PickleAutoImport + +__all__ = ["AutoImport"] +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -45,8 +45,11 @@ + monitoring the progress of refactorings. + + """ +-from rope.refactor.importutils import ImportOrganizer # noqa +-from rope.refactor.topackage import ModuleToPackage # noqa ++from rope.refactor.importutils import ImportOrganizer # essential. ++from rope.refactor.topackage import ModuleToPackage # essential. ++ ++assert ImportOrganizer ++assert ModuleToPackage + + + __all__ = [ +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -46,8 +46,11 @@ + monitoring the progress of refactorings. + + """ +-from rope.refactor.importutils import ImportOrganizer # noqa +-from rope.refactor.topackage import ModuleToPackage # noqa ++from rope.refactor.importutils import ImportOrganizer # essential. ++from rope.refactor.topackage import ModuleToPackage # essential. ++ ++assert ImportOrganizer ++assert ModuleToPackage + + + __all__ = [ +@language python + +@path C:/Repos/ekr-rope/rope/ +"""rope refactor package + +This package contains modules that perform python refactorings. +Refactoring classes perform refactorings in 4 steps: + +1. Collect some data for performing the refactoring and use them + to construct a refactoring class. Like:: + + renamer = Rename(project, resource, offset) + +2. Some refactorings give you useful information about the + refactoring after their construction. Like:: + + print(renamer.get_old_name()) + +3. Give the refactoring class more information about how to + perform the refactoring and get the changes this refactoring is + going to make. This is done by calling `get_changes` method of the + refactoring class. Like:: + + changes = renamer.get_changes(new_name) + +4. You can commit the changes. Like:: + + project.do(changes) + +These steps are like the steps IDEs usually do for performing a +refactoring. These are the things an IDE does in each step: + +1. Construct a refactoring object by giving it information like + resource, offset and ... . Some of the refactoring problems (like + performing rename refactoring on language keywords) can be reported + here. +2. Print some information about the refactoring and ask the user + about the information that are necessary for completing the + refactoring (like new name). +3. Call the `get_changes` by passing it information asked from + the user (if necessary) and get and preview the changes returned by + it. +4. perform the refactoring. + +From ``0.5m5`` release the `get_changes()` method of some time- +consuming refactorings take an optional `rope.base.taskhandle. +TaskHandle` parameter. You can use this object for stopping or +monitoring the progress of refactorings. + +""" +from rope.refactor.importutils import ImportOrganizer # noqa +from rope.refactor.topackage import ModuleToPackage # noqa + + +__all__ = [ + "rename", + "move", + "inline", + "extract", + "restructure", + "topackage", + "importutils", + "usefunction", + "change_signature", + "encapsulate_field", + "introduce_factory", + "introduce_parameter", + "localtofield", + "method_object", + "multiproject", +] +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -22,7 +22,6 @@ + import rope.base.exceptions + import rope.refactor.functionutils + from rope.base import ( +- ast, + pynames, + pyobjects, + codeanalyze, +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -23,7 +23,6 @@ + import rope.base.exceptions + import rope.refactor.functionutils + from rope.base import ( +- ast, + pynames, + pyobjects, + codeanalyze, +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +# Known Bugs when inlining a function/method +# The values passed to function are inlined using _inlined_variable. +# This may cause two problems, illustrated in the examples below +# +# def foo(var1): +# var1 = var1*10 +# return var1 +# +# If a call to foo(20) is inlined, the result of inlined function is 20, +# but it should be 200. +# +# def foo(var1): +# var2 = var1*10 +# return var2 +# +# 2- If a call to foo(10+10) is inlined the result of inlined function is 110 +# but it should be 200. + +import re +from typing import List + +import rope.base.exceptions +import rope.refactor.functionutils +from rope.base import ( + ast, + pynames, + pyobjects, + codeanalyze, + taskhandle, + evaluate, + worder, + utils, + libutils, +) +from rope.base.change import ChangeSet, ChangeContents +from rope.refactor import ( + occurrences, + rename, + sourceutils, + importutils, + move, + change_signature, +) + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -927,7 +927,7 @@ + break + else: + self._skip_comment() +- except (ValueError, TypeError) as e: ++ except (ValueError, TypeError): + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,7 +6,7 @@ + break + else: + self._skip_comment() +- except (ValueError, TypeError) as e: ++ except (ValueError, TypeError): + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) +@language python + +def consume(self, token, skip_comment=True): + try: + while True: + new_offset = self.source.index(token, self.offset) + if self._good_token(token, new_offset) or not skip_comment: + break + else: + self._skip_comment() + except (ValueError, TypeError) as e: + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) + self.offset = new_offset + len(token) + return (new_offset, self.offset) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,6 @@ + from itertools import chain + + from rope.base import ast +-from rope.base.utils import pycompat + + + def find_visible(node, lines): +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,6 @@ + from itertools import chain + + from rope.base import ast +-from rope.base.utils import pycompat + + + @others +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +from itertools import chain + +from rope.base import ast +from rope.base.utils import pycompat + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,12 +1,9 @@ + from textwrap import dedent ++import unittest + + from rope.base.builtins import Str +- +-import unittest +- + import rope.base.libutils + import rope.base.oi +-from rope.base.utils import pycompat + from ropetest import testutils + + +@@ -1052,9 +1049,10 @@ + l = {} + v = l["key"] + """)) +- pymod1 = self.project.get_pymodule(mod1) # noqa +- var = pymod1["v"].get_object() # noqa +- ++ pymod1 = self.project.get_pymodule(mod1) ++ var = pymod1["v"].get_object() ++ self.assertTrue(pymod1 is not None) ++ self.assertTrue(var is not None) + def test_always_returning_containing_class_for_selfs(self): + code = dedent("""\ + class A(object): +@@ -1100,3 +1098,4 @@ + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + x_var = pymod["x"].pyobject.get() ++ self.assertTrue(x_var is not None) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,13 +1,10 @@ + @path C:/Repos/ekr-rope/ropetest/ + from textwrap import dedent ++import unittest + + from rope.base.builtins import Str +- +-import unittest +- + import rope.base.libutils + import rope.base.oi +-from rope.base.utils import pycompat + from ropetest import testutils + + +@language python + +@path C:/Repos/ekr-rope/ropetest/ +from textwrap import dedent + +from rope.base.builtins import Str + +import unittest + +import rope.base.libutils +import rope.base.oi +from rope.base.utils import pycompat +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -10,6 +10,7 @@ + l = {} + v = l["key"] + """)) +- pymod1 = self.project.get_pymodule(mod1) # noqa +- var = pymod1["v"].get_object() # noqa +- ++ pymod1 = self.project.get_pymodule(mod1) ++ var = pymod1["v"].get_object() ++ self.assertTrue(pymod1 is not None) ++ self.assertTrue(var is not None) +@language python + +def test_validation_problems_for_changing_builtin_types(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + l = [] + l.append("") + """)) + self.pycore.analyze_module(mod1) + + mod1.write(dedent("""\ + l = {} + v = l["key"] + """)) + pymod1 = self.project.get_pymodule(mod1) # noqa + var = pymod1["v"].get_object() # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,3 +6,4 @@ + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + x_var = pymod["x"].pyobject.get() ++ self.assertTrue(x_var is not None) +@language python + +def test_set_comprehension(self): + code = dedent("""\ + x = {s.strip() for s in X()} + x.add('x') + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + x_var = pymod["x"].pyobject.get() + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -485,8 +485,9 @@ + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a"].get_object() +- b_var = pymod["b"].get_object() # noqa ++ b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) ++ self.assertTrue(b_var is not None) + + def test_enumerate_builtin_function(self): + self.mod.write(dedent("""\ +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,6 @@ + @path C:/Repos/ekr-rope/rope/base/ + import bisect + import difflib +-import sys + import warnings + + import rope.base.libutils +@@ -16,7 +15,6 @@ + from rope.base import stdmods + from rope.base import taskhandle + from rope.base import utils +-from rope.base.exceptions import ModuleNotFoundError + + + @others +@language python + +@path C:/Repos/ekr-rope/rope/base/ +import bisect +import difflib +import sys +import warnings + +import rope.base.libutils +import rope.base.resourceobserver +import rope.base.resources +import rope.base.oi.doa +import rope.base.oi.objectinfo +import rope.base.oi.soa +from rope.base import builtins +from rope.base import exceptions +from rope.base import pyobjectsdef +from rope.base import stdmods +from rope.base import taskhandle +from rope.base import utils +from rope.base.exceptions import ModuleNotFoundError + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,3 @@ +-from rope.base.pynames import DefinedName + import rope.base.builtins + import rope.base.codeanalyze + import rope.base.evaluate +@@ -461,9 +460,7 @@ + pass + + def _For(self, node): +- names = self._update_evaluated( +- node.target, node.iter, ".__iter__().next()" # noqa +- ) ++ self._update_evaluated(node.target, node.iter, ".__iter__().next()") + for child in node.body + node.orelse: + ast.walk(child, self) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,5 +5,6 @@ + """) + mod = libutils.get_string_module(self.project, code) + +- a = mod["a"].get_object() # noqa ++ a = mod["a"].get_object() ++ self.assertTrue(a is not None) + +@language python + +def test_empty_tuples(self): + code = dedent("""\ + t = () + a, b = t + """) + mod = libutils.get_string_module(self.project, code) + + a = mod["a"].get_object() # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,7 @@ + import os.path + import shutil + from textwrap import dedent +- +-import pytest ++import unittest + + from rope.base.exceptions import RopeError, ResourceNotFoundError + from rope.base.fscommands import FileSystemCommands +@@ -10,9 +9,6 @@ + from rope.base.project import Project, NoProject, _realpath + from rope.base.resourceobserver import FilteredResourceObserver + from ropetest import testutils +- +- +-import unittest + + + class ProjectTest(unittest.TestCase): +@@ -705,7 +701,7 @@ + def test_revalidating_folders(self): + root = self.project.root + my_folder = root.create_folder("myfolder") +- my_file = my_folder.create_file("myfile.txt") # noqa ++ my_file = my_folder.create_file("myfile.txt") + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [my_folder]) +@@ -714,6 +710,7 @@ + self.project.validate(root) + self.assertEqual(my_folder, sample_observer.last_removed) + self.assertEqual(1, sample_observer.change_count) ++ self.assertTrue(my_file is not None) + + def test_removing_and_adding_resources_to_filtered_observer(self): + my_file = self.project.root.create_file("my_file.txt") +@@ -812,7 +809,7 @@ + self.assertEqual(1, sample_observer.change_count) + + def test_changes_and_adding_resources(self): +- root = self.project.root # noqa ++ # root = self.project.root + file1 = self.project.get_file("file1.txt") + file2 = self.project.get_file("file2.txt") + file1.create() +@@ -826,7 +823,7 @@ + self.assertEqual((file1, file2), sample_observer.last_moved) + + def test_validating_get_files_list(self): +- root = self.project.root # noqa ++ # root = self.project.root + self.assertEqual(0, len(self.project.get_files())) + file = open(os.path.join(self.project.address, "myfile.txt"), "w") + file.close() +@@ -1040,8 +1037,9 @@ + self.project = testutils.sample_project( + ignored_resources=["myfile.txt"], ropefolder=None + ) +- myfile = self.project.root.create_file("myfile.txt") # noqa ++ myfile = self.project.root.create_file("myfile.txt") + self.assertEqual(0, len(self.project.get_files())) ++ self.assertTrue(myfile is not None) + + def test_setting_ignored_resources_patterns(self): + self.project = testutils.sample_project(ignored_resources=["m?file.*"]) +@@ -1162,7 +1160,8 @@ + ) + mod = testutils.create_module(self.project, "mod") + mod.write("xyz print") +- pymod = self.project.get_pymodule(mod) # noqa ++ pymod = self.project.get_pymodule(mod) ++ self.assertTrue(pymod is not None) + + def test_compressed_history(self): + self.project = testutils.sample_project(compress_history=True) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -8,6 +8,7 @@ + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a"].get_object() +- b_var = pymod["b"].get_object() # noqa ++ b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) ++ self.assertTrue(b_var is not None) + +@language python + +def test_wrong_arguments_to_zip_function(self): + self.mod.write(dedent("""\ + class C1(object): + pass + c1_list = [C1()] + a, b = zip(c1_list, 1)[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() # noqa + self.assertEqual(c1_class, a_var.get_type()) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -335,7 +335,8 @@ + + def test_getting_primary_and_strings_at_the_end_of_line(self): + code = "f('\\'')\n" +- result = self._find_primary(code, len(code) - 1) # noqa ++ result = self._find_primary(code, len(code) - 1) ++ self.assertTrue(result is not None) + + def test_getting_primary_and_not_crossing_newlines(self): + code = "\na = (b + c)\n(4 + 1).x\n" +@@ -753,7 +754,7 @@ + mod1 = testutils.create_module(self.project, "mod1") + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) +- mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa ++ mod2 = testutils.create_module(self.project, "mod2", pkg2) + mod1.write("import pkg1.pkg2.mod2") + + mod1_scope = self.project.get_pymodule(mod1).get_scope() +@@ -761,6 +762,7 @@ + pkg2_pyobject = self.project.get_pymodule(pkg2) + found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) + self.assertEqual(pkg2_pyobject, found_pyname.get_object()) ++ self.assertTrue(mod2 is not None) + + def test_get_pyname_at_on_language_keywords(self): + code = dedent("""\ +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,5 @@ + def test_getting_primary_and_strings_at_the_end_of_line(self): + code = "f('\\'')\n" +- result = self._find_primary(code, len(code) - 1) # noqa ++ result = self._find_primary(code, len(code) - 1) ++ self.assertTrue(result is not None) + +@language python + +def test_getting_primary_and_strings_at_the_end_of_line(self): + code = "f('\\'')\n" + result = self._find_primary(code, len(code) - 1) # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,7 @@ + mod1 = testutils.create_module(self.project, "mod1") + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) +- mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa ++ mod2 = testutils.create_module(self.project, "mod2", pkg2) + mod1.write("import pkg1.pkg2.mod2") + + mod1_scope = self.project.get_pymodule(mod1).get_scope() +@@ -10,4 +10,5 @@ + pkg2_pyobject = self.project.get_pymodule(pkg2) + found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) + self.assertEqual(pkg2_pyobject, found_pyname.get_object()) ++ self.assertTrue(mod2 is not None) + +@language python + +def test_relative_modules_after_from_statements2(self): + mod1 = testutils.create_module(self.project, "mod1") + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) + mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa + mod1.write("import pkg1.pkg2.mod2") + + mod1_scope = self.project.get_pymodule(mod1).get_scope() + name_finder = rope.base.evaluate.ScopeNameFinder(mod1_scope.pyobject) + pkg2_pyobject = self.project.get_pymodule(pkg2) + found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) + self.assertEqual(pkg2_pyobject, found_pyname.get_object()) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,4 @@ + """Tests for autoimport utility functions, written in pytest""" +- +-from sys import platform +- +-import pytest + + from rope.contrib.autoimport import utils + from rope.contrib.autoimport.defs import Package, PackageType, Source +@@ -59,5 +55,5 @@ + def test_get_package_tuple_compiled(compiled_lib): + lib_name, lib_path = compiled_lib + assert Package( +- lib_name, Source.STANDARD, lib_path, PackageType.COMPILED ++ lib_name, Source.STANDARD, lib_path, PackageType.COMPILED + ) == utils.get_package_tuple(lib_path) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,5 @@ + @path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ + """Tests for autoimport utility functions, written in pytest""" +- +-from sys import platform +- +-import pytest + + from rope.contrib.autoimport import utils + from rope.contrib.autoimport.defs import Package, PackageType, Source +@language python + +@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ +"""Tests for autoimport utility functions, written in pytest""" + +from sys import platform + +import pytest + +from rope.contrib.autoimport import utils +from rope.contrib.autoimport.defs import Package, PackageType, Source + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def test_get_package_tuple_compiled(compiled_lib): + lib_name, lib_path = compiled_lib + assert Package( +- lib_name, Source.STANDARD, lib_path, PackageType.COMPILED ++ lib_name, Source.STANDARD, lib_path, PackageType.COMPILED + ) == utils.get_package_tuple(lib_path) +@language python + +def test_get_package_tuple_compiled(compiled_lib): + lib_name, lib_path = compiled_lib + assert Package( + lib_name, Source.STANDARD, lib_path, PackageType.COMPILED + ) == utils.get_package_tuple(lib_path) + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -718,7 +718,8 @@ + pass + my_""") + result = self._assist(code) +- proposals = sorted_proposals(result, typepref=["function"]) # noqa ++ proposals = sorted_proposals(result, typepref=["function"]) ++ self.assertTrue(proposals is not None) + + def test_get_pydoc_unicode(self): + src = dedent('''\ +@@ -824,7 +825,8 @@ + s = "hey" + s.replace() + """) +- doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa ++ doc = get_doc(self.project, src, src.rindex("replace") + 1) ++ self.assertTrue(doc is not None) + + def test_proposing_variables_defined_till_the_end_of_scope(self): + code = dedent("""\ +@@ -928,7 +930,8 @@ + except: + pass + """) +- result = self._assist(code, code.index("."), maxfixes=1) # noqa ++ result = self._assist(code, code.index("."), maxfixes=1) ++ self.assertTrue(result is not None) + + def test_nested_blocks(self): + code = dedent("""\ +@@ -951,7 +954,8 @@ + code = dedent("""\ + f = 1 + f(p""") +- result = self._assist(code) # noqa ++ result = self._assist(code) ++ self.assertTrue(result is not None) + + def test_proposing_function_keywords_when_calling_extra_spaces(self): + code = dedent("""\ +@@ -1337,7 +1341,8 @@ + """) + samplemod.write(code) + package = testutils.create_package(self.project, "package") +- nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa ++ nestedmod = testutils.create_module(self.project, "nestedmod", package) ++ self.assertTrue(nestedmod is not None) + + def tearDown(self): + testutils.remove_project(self.project) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,5 +5,6 @@ + pass + my_""") + result = self._assist(code) +- proposals = sorted_proposals(result, typepref=["function"]) # noqa ++ proposals = sorted_proposals(result, typepref=["function"]) ++ self.assertTrue(proposals is not None) + +@language python + +def test_proposals_sorter_and_missing_type_in_typepref(self): + code = dedent("""\ + my_global_var = 1 + def my_global_func(): + pass + my_""") + result = self._assist(code) + proposals = sorted_proposals(result, typepref=["function"]) # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,5 +4,6 @@ + s = "hey" + s.replace() + """) +- doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa ++ doc = get_doc(self.project, src, src.rindex("replace") + 1) ++ self.assertTrue(doc is not None) + +@language python + +def test_commenting_errors_before_offset(self): + src = dedent("""\ + lsjd lsjdf + s = "hey" + s.replace() + """) + doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,5 +5,6 @@ + except: + pass + """) +- result = self._assist(code, code.index("."), maxfixes=1) # noqa ++ result = self._assist(code, code.index("."), maxfixes=1) ++ self.assertTrue(result is not None) + +@language python + +def test_and_normal_complete_blocks_and_single_fixing(self): + code = dedent("""\ + try: + range. + except: + pass + """) + result = self._assist(code, code.index("."), maxfixes=1) # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,5 +2,6 @@ + code = dedent("""\ + f = 1 + f(p""") +- result = self._assist(code) # noqa ++ result = self._assist(code) ++ self.assertTrue(result is not None) + +@language python + +def test_proposing_function_keywords_when_calling_for_non_functions(self): + code = dedent("""\ + f = 1 + f(p""") + result = self._assist(code) # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -18,5 +18,6 @@ + """) + samplemod.write(code) + package = testutils.create_package(self.project, "package") +- nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa ++ nestedmod = testutils.create_module(self.project, "nestedmod", package) ++ self.assertTrue(nestedmod is not None) + +@language python + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + samplemod = testutils.create_module(self.project, "samplemod") + code = dedent("""\ + class SampleClass(object): + def sample_method(): + pass + + def sample_func(): + pass + sample_var = 10 + + def _underlined_func(): + pass + + """) + samplemod.write(code) + package = testutils.create_package(self.project, "package") + nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -42,11 +42,12 @@ + + def test_handling_nested_modules(self): + pkg = create_package(self.project, "xkg") +- mod = create_module(self.project, "xkg.xod") # noqa ++ mod = create_module(self.project, "xkg.xod") + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + self.assertFalse(pkg.exists()) + self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) + self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) ++ self.assertTrue(mod is not None) + + + def _fixer(name): +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,10 @@ + def test_handling_nested_modules(self): + pkg = create_package(self.project, "xkg") +- mod = create_module(self.project, "xkg.xod") # noqa ++ mod = create_module(self.project, "xkg.xod") + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + self.assertFalse(pkg.exists()) + self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) + self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) ++ self.assertTrue(mod is not None) + + +@language python + +def test_handling_nested_modules(self): + pkg = create_package(self.project, "xkg") + mod = create_module(self.project, "xkg.xod") # noqa + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + self.assertFalse(pkg.exists()) + self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) + self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -373,7 +373,7 @@ + self.assertFalse(myfile.exists()) + + def test_writing_and_reading_history(self): +- history_file = self.project.get_file("history.pickle") # noqa ++ history_file = self.project.get_file("history.pickle") + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") +@@ -383,9 +383,10 @@ + history = rope.base.history.History(self.project) + history.undo() + self.assertFalse(myfile.exists()) ++ self.assertTrue(history_file is not None) + + def test_writing_and_reading_history2(self): +- history_file = self.project.get_file("history.pickle") # noqa ++ history_file = self.project.get_file("history.pickle") + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") +@@ -396,3 +397,4 @@ + history = rope.base.history.History(self.project) + history.redo() + self.assertTrue(myfile.exists()) ++ self.assertTrue(history_file is not None) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def test_writing_and_reading_history(self): +- history_file = self.project.get_file("history.pickle") # noqa ++ history_file = self.project.get_file("history.pickle") + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") +@@ -9,4 +9,5 @@ + history = rope.base.history.History(self.project) + history.undo() + self.assertFalse(myfile.exists()) ++ self.assertTrue(history_file is not None) + +@language python + +def test_writing_and_reading_history(self): + history_file = self.project.get_file("history.pickle") # noqa + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") + history.do(rope.base.change.CreateResource(myfile)) + history.write() + + history = rope.base.history.History(self.project) + history.undo() + self.assertFalse(myfile.exists()) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def test_writing_and_reading_history2(self): +- history_file = self.project.get_file("history.pickle") # noqa ++ history_file = self.project.get_file("history.pickle") + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") +@@ -10,3 +10,4 @@ + history = rope.base.history.History(self.project) + history.redo() + self.assertTrue(myfile.exists()) ++ self.assertTrue(history_file is not None) +@language python + +def test_writing_and_reading_history2(self): + history_file = self.project.get_file("history.pickle") # noqa + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") + history.do(rope.base.change.CreateResource(myfile)) + history.undo() + history.write() + + history = rope.base.history.History(self.project) + history.redo() + self.assertTrue(myfile.exists()) + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -285,7 +285,8 @@ + """) + mod = libutils.get_string_module(self.project, code) + +- a = mod["a"].get_object() # noqa ++ a = mod["a"].get_object() ++ self.assertTrue(a is not None) + + def test_handling_generator_functions(self): + code = dedent("""\ +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -12,6 +12,8 @@ + p1 = testutils.create_package(self.project, "p1") + p2 = testutils.create_package(self.project, "p2", p1) + p3 = testutils.create_package(self.project, "p3", p2) +- m1 = testutils.create_module(self.project, "m1", p3) # noqa +- l = testutils.create_module(self.project, "l", p3) # noqa ++ m1 = testutils.create_module(self.project, "m1", p3) ++ mod_l = testutils.create_module(self.project, "l", p3) ++ self.assertTrue(m1 is not None) ++ self.assertTrue(mod_l is not None) + +@language python + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.import_tools = ImportTools(self.project) + + self.mod = testutils.create_module(self.project, "mod") + self.pkg1 = testutils.create_package(self.project, "pkg1") + self.mod1 = testutils.create_module(self.project, "mod1", self.pkg1) + self.pkg2 = testutils.create_package(self.project, "pkg2") + self.mod2 = testutils.create_module(self.project, "mod2", self.pkg2) + self.mod3 = testutils.create_module(self.project, "mod3", self.pkg2) + p1 = testutils.create_package(self.project, "p1") + p2 = testutils.create_package(self.project, "p2", p1) + p3 = testutils.create_package(self.project, "p3", p2) + m1 = testutils.create_module(self.project, "m1", p3) # noqa + l = testutils.create_module(self.project, "l", p3) # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -314,6 +314,7 @@ + mover = move.create_move( + self.project, self.mod1, code.index("CONSTANT") + 1 + ) ++ self.assertTrue(mover is not None) + + def test_raising_exception_for_mov_glob_elemnts_to_the_same_module(self): + self.mod1.write("def a_func():\n pass\n") +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -8,4 +8,5 @@ + mover = move.create_move( + self.project, self.mod1, code.index("CONSTANT") + 1 + ) ++ self.assertTrue(mover is not None) + +@language python + +def test_raising_an_exception_for_moving_non_global_variable(self): + code = dedent("""\ + class TestClass: + CONSTANT = 5 + """) + self.mod1.write(code) + with self.assertRaises(exceptions.RefactoringError): + mover = move.create_move( + self.project, self.mod1, code.index("CONSTANT") + 1 + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1558,7 +1558,6 @@ + ")", + ]) + +- + @testutils.only_for_versions_higher("3.10") + def test_match_node_with_match_mapping_match_as(self): + source = dedent("""\ +@@ -1587,8 +1586,6 @@ + "", + "}", + ]) +- +- + class _ResultChecker: + def __init__(self, test_case, ast): + self.test_case = test_case +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,8 +2,7 @@ + import os.path + import shutil + from textwrap import dedent +- +-import pytest ++import unittest + + from rope.base.exceptions import RopeError, ResourceNotFoundError + from rope.base.fscommands import FileSystemCommands +@@ -13,9 +12,6 @@ + from ropetest import testutils + + +-import unittest +- +- + @others + @language python + @tabwidth -4 +@language python + +@path C:/Repos/ekr-rope/ropetest/ +import os.path +import shutil +from textwrap import dedent + +import pytest + +from rope.base.exceptions import RopeError, ResourceNotFoundError +from rope.base.fscommands import FileSystemCommands +from rope.base.libutils import path_to_resource +from rope.base.project import Project, NoProject, _realpath +from rope.base.resourceobserver import FilteredResourceObserver +from ropetest import testutils + + +import unittest + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + def test_revalidating_folders(self): + root = self.project.root + my_folder = root.create_folder("myfolder") +- my_file = my_folder.create_file("myfile.txt") # noqa ++ my_file = my_folder.create_file("myfile.txt") + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [my_folder]) +@@ -10,4 +10,5 @@ + self.project.validate(root) + self.assertEqual(my_folder, sample_observer.last_removed) + self.assertEqual(1, sample_observer.change_count) ++ self.assertTrue(my_file is not None) + +@language python + +def test_revalidating_folders(self): + root = self.project.root + my_folder = root.create_folder("myfolder") + my_file = my_folder.create_file("myfile.txt") # noqa + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [my_folder]) + ) + testutils.remove_recursively(my_folder.real_path) + self.project.validate(root) + self.assertEqual(my_folder, sample_observer.last_removed) + self.assertEqual(1, sample_observer.change_count) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def test_changes_and_adding_resources(self): +- root = self.project.root # noqa ++ # root = self.project.root + file1 = self.project.get_file("file1.txt") + file2 = self.project.get_file("file2.txt") + file1.create() +@language python + +def test_changes_and_adding_resources(self): + root = self.project.root # noqa + file1 = self.project.get_file("file1.txt") + file2 = self.project.get_file("file2.txt") + file1.create() + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [file1, file2]) + ) + file1.move(file2.path) + self.assertEqual(2, sample_observer.change_count) + self.assertEqual(file2, sample_observer.last_created) + self.assertEqual((file1, file2), sample_observer.last_moved) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def test_validating_get_files_list(self): +- root = self.project.root # noqa ++ # root = self.project.root + self.assertEqual(0, len(self.project.get_files())) + file = open(os.path.join(self.project.address, "myfile.txt"), "w") + file.close() +@language python + +def test_validating_get_files_list(self): + root = self.project.root # noqa + self.assertEqual(0, len(self.project.get_files())) + file = open(os.path.join(self.project.address, "myfile.txt"), "w") + file.close() + self.project.validate() + self.assertEqual(1, len(self.project.get_files())) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,6 +2,7 @@ + self.project = testutils.sample_project( + ignored_resources=["myfile.txt"], ropefolder=None + ) +- myfile = self.project.root.create_file("myfile.txt") # noqa ++ myfile = self.project.root.create_file("myfile.txt") + self.assertEqual(0, len(self.project.get_files())) ++ self.assertTrue(myfile is not None) + +@language python + +def test_ignored_resources_and_get_files2(self): + self.project = testutils.sample_project( + ignored_resources=["myfile.txt"], ropefolder=None + ) + myfile = self.project.root.create_file("myfile.txt") # noqa + self.assertEqual(0, len(self.project.get_files())) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,5 +4,6 @@ + ) + mod = testutils.create_module(self.project, "mod") + mod.write("xyz print") +- pymod = self.project.get_pymodule(mod) # noqa ++ pymod = self.project.get_pymodule(mod) ++ self.assertTrue(pymod is not None) + +@language python + +def test_ignoring_syntax_errors(self): + self.project = testutils.sample_project( + ropefolder=None, ignore_syntax_errors=True + ) + mod = testutils.create_module(self.project, "mod") + mod.write("xyz print") + pymod = self.project.get_pymodule(mod) # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -31,18 +31,19 @@ + + def test_nested_modules(self): + pkg = testutils.create_package(self.project, "pkg") +- mod = testutils.create_module(self.project, "mod", pkg) # noqa ++ mod = testutils.create_module(self.project, "mod", pkg) + package = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), package.get_type()) + self.assertEqual(1, len(package.get_attributes())) + module = package["mod"].get_object() + self.assertEqual(get_base_type("Module"), module.get_type()) +- ++ self.assertTrue(mod is not None) + def test_package(self): + pkg = testutils.create_package(self.project, "pkg") +- mod = testutils.create_module(self.project, "mod", pkg) # noqa ++ mod = testutils.create_module(self.project, "mod", pkg) + result = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), result.type) ++ self.assertTrue(mod is not None) + + def test_simple_class(self): + mod = testutils.create_module(self.project, "mod") +@@ -101,7 +102,8 @@ + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["SampleClass"].get_object() +- var = sample_class["var"] # noqa ++ var = sample_class["var"] ++ self.assertTrue(var is not None) + + def test_class_attributes_set_in_init(self): + mod = testutils.create_module(self.project, "mod") +@@ -112,7 +114,8 @@ + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["C"].get_object() +- var = sample_class["var"] # noqa ++ var = sample_class["var"] ++ self.assertTrue(var is not None) + + def test_class_attributes_set_in_init_overwriting_a_defined(self): + mod = testutils.create_module(self.project, "mod") +@@ -174,7 +177,8 @@ + + def test_get_string_module_with_extra_spaces(self): + code = "a = 10\n " +- mod = libutils.get_string_module(self.project, code) # noqa ++ mod = libutils.get_string_module(self.project, code) ++ self.assertTrue(mod is not None) + + def test_parameter_info_for_functions(self): + code = dedent("""\ +@@ -264,9 +268,10 @@ + self.assertEqual(self.project.get_resource("module.py"), new_module) + + def test_packaged_module_creation(self): +- package = self.project.root.create_folder("package") # noqa ++ package = self.project.root.create_folder("package") + new_module = testutils.create_module(self.project, "package.module") + self.assertEqual(self.project.get_resource("package/module.py"), new_module) ++ self.assertTrue(package is not None) + + def test_packaged_module_creation_with_nested_src(self): + src = self.project.root.create_folder("src") +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,9 @@ + def test_nested_modules(self): + pkg = testutils.create_package(self.project, "pkg") +- mod = testutils.create_module(self.project, "mod", pkg) # noqa ++ mod = testutils.create_module(self.project, "mod", pkg) + package = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), package.get_type()) + self.assertEqual(1, len(package.get_attributes())) + module = package["mod"].get_object() + self.assertEqual(get_base_type("Module"), module.get_type()) +- ++ self.assertTrue(mod is not None) +@language python + +def test_nested_modules(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) # noqa + package = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), package.get_type()) + self.assertEqual(1, len(package.get_attributes())) + module = package["mod"].get_object() + self.assertEqual(get_base_type("Module"), module.get_type()) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,7 @@ + def test_package(self): + pkg = testutils.create_package(self.project, "pkg") +- mod = testutils.create_module(self.project, "mod", pkg) # noqa ++ mod = testutils.create_module(self.project, "mod", pkg) + result = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), result.type) ++ self.assertTrue(mod is not None) + +@language python + +def test_package(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) # noqa + result = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), result.type) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,5 +6,6 @@ + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["SampleClass"].get_object() +- var = sample_class["var"] # noqa ++ var = sample_class["var"] ++ self.assertTrue(var is not None) + +@language python + +def test_class_variables(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + class SampleClass(object): + var = 10 + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["SampleClass"].get_object() + var = sample_class["var"] # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -7,5 +7,6 @@ + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["C"].get_object() +- var = sample_class["var"] # noqa ++ var = sample_class["var"] ++ self.assertTrue(var is not None) + +@language python + +def test_class_attributes_set_in_init(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + class C(object): + def __init__(self): + self.var = 20 + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["C"].get_object() + var = sample_class["var"] # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,5 @@ + def test_get_string_module_with_extra_spaces(self): + code = "a = 10\n " +- mod = libutils.get_string_module(self.project, code) # noqa ++ mod = libutils.get_string_module(self.project, code) ++ self.assertTrue(mod is not None) + +@language python + +def test_get_string_module_with_extra_spaces(self): + code = "a = 10\n " + mod = libutils.get_string_module(self.project, code) # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,6 @@ + def test_packaged_module_creation(self): +- package = self.project.root.create_folder("package") # noqa ++ package = self.project.root.create_folder("package") + new_module = testutils.create_module(self.project, "package.module") + self.assertEqual(self.project.get_resource("package/module.py"), new_module) ++ self.assertTrue(package is not None) + +@language python + +def test_packaged_module_creation(self): + package = self.project.root.create_folder("package") # noqa + new_module = testutils.create_module(self.project, "package.module") + self.assertEqual(self.project.get_resource("package/module.py"), new_module) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -53,6 +53,7 @@ + get_base_type("Type"), + sample_func_scope["SampleClass"].get_object().get_type(), + ) ++ self.assertTrue(sample_func_scope is not None) + + def test_list_comprehension_scope_inside_assignment(self): + code = "a_var = [b_var + d_var for b_var, c_var in e_var]\n" +@@ -468,12 +469,13 @@ + """) + scope = libutils.get_string_scope(self.project, code) + +- a_scope = scope["A"].get_object().get_scope() # noqa ++ a_scope = scope["A"].get_object().get_scope() + b_scope = scope["B"].get_object().get_scope() + self.assertTrue("a" in b_scope.get_names()) + self.assertTrue("b" in b_scope.get_names()) + self.assertTrue("a" not in b_scope.get_defined_names()) + self.assertTrue("b" in b_scope.get_defined_names()) ++ self.assertTrue(a_scope is not None) + + def test_getting_defined_names_for_modules(self): + code = dedent("""\ +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -12,4 +12,5 @@ + get_base_type("Type"), + sample_func_scope["SampleClass"].get_object().get_type(), + ) ++ self.assertTrue(sample_func_scope is not None) + +@language python + +def test_classes_inside_function_scopes(self): + code = dedent("""\ + def sample_func(): + class SampleClass(object): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(1, len(scope.get_scopes())) + sample_func_scope = scope.get_scopes()[0] + self.assertEqual( + get_base_type("Type"), + sample_func_scope["SampleClass"].get_object().get_type(), + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -9,10 +9,11 @@ + """) + scope = libutils.get_string_scope(self.project, code) + +- a_scope = scope["A"].get_object().get_scope() # noqa ++ a_scope = scope["A"].get_object().get_scope() + b_scope = scope["B"].get_object().get_scope() + self.assertTrue("a" in b_scope.get_names()) + self.assertTrue("b" in b_scope.get_names()) + self.assertTrue("a" not in b_scope.get_defined_names()) + self.assertTrue("b" in b_scope.get_defined_names()) ++ self.assertTrue(a_scope is not None) + +@language python + +def test_getting_defined_names_for_classes(self): + code = dedent("""\ + class A(object): + def a(self): + pass + class B(A): + def b(self): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + a_scope = scope["A"].get_object().get_scope() # noqa + b_scope = scope["B"].get_object().get_scope() + self.assertTrue("a" in b_scope.get_names()) + self.assertTrue("b" in b_scope.get_names()) + self.assertTrue("a" not in b_scope.get_defined_names()) + self.assertTrue("b" in b_scope.get_defined_names()) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,23 +4,12 @@ + + import rope.base.taskhandle + import rope.refactor.introduce_parameter +-import ropetest.refactor.extracttest +-import ropetest.refactor.importutilstest +-import ropetest.refactor.inlinetest +-import ropetest.refactor.movetest +-import ropetest.refactor.multiprojecttest +-import ropetest.refactor.patchedasttest +-import ropetest.refactor.renametest +-import ropetest.refactor.restructuretest +-import ropetest.refactor.suitestest +-import ropetest.refactor.usefunctiontest + from rope.base.exceptions import RefactoringError, InterruptedTaskError + from rope.refactor.encapsulate_field import EncapsulateField + from rope.refactor.introduce_factory import IntroduceFactory + from rope.refactor.localtofield import LocalToField + from rope.refactor.method_object import MethodObject + from ropetest import testutils +-from ropetest.refactor import change_signature_test, similarfindertest + + + class MethodObjectTest(unittest.TestCase): +@@ -1093,8 +1082,9 @@ + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) +- jobs = handle.create_jobset() # noqa ++ jobs = handle.create_jobset() + self.assertEqual(1, observer.called) ++ self.assertTrue(jobs is not None) + + def test_calling_the_observer_when_starting_and_finishing_jobs(self): + handle = rope.base.taskhandle.TaskHandle() +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,23 +5,12 @@ + + import rope.base.taskhandle + import rope.refactor.introduce_parameter +-import ropetest.refactor.extracttest +-import ropetest.refactor.importutilstest +-import ropetest.refactor.inlinetest +-import ropetest.refactor.movetest +-import ropetest.refactor.multiprojecttest +-import ropetest.refactor.patchedasttest +-import ropetest.refactor.renametest +-import ropetest.refactor.restructuretest +-import ropetest.refactor.suitestest +-import ropetest.refactor.usefunctiontest + from rope.base.exceptions import RefactoringError, InterruptedTaskError + from rope.refactor.encapsulate_field import EncapsulateField + from rope.refactor.introduce_factory import IntroduceFactory + from rope.refactor.localtofield import LocalToField + from rope.refactor.method_object import MethodObject + from ropetest import testutils +-from ropetest.refactor import change_signature_test, similarfindertest + + + class MethodObjectTest(unittest.TestCase): +@@ -1094,8 +1083,9 @@ + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) +- jobs = handle.create_jobset() # noqa ++ jobs = handle.create_jobset() + self.assertEqual(1, observer.called) ++ self.assertTrue(jobs is not None) + + def test_calling_the_observer_when_starting_and_finishing_jobs(self): + handle = rope.base.taskhandle.TaskHandle() +@language python + +@path C:/Repos/ekr-rope/rope/ +from textwrap import dedent + +import unittest + +import rope.base.taskhandle +import rope.refactor.introduce_parameter +import ropetest.refactor.extracttest +import ropetest.refactor.importutilstest +import ropetest.refactor.inlinetest +import ropetest.refactor.movetest +import ropetest.refactor.multiprojecttest +import ropetest.refactor.patchedasttest +import ropetest.refactor.renametest +import ropetest.refactor.restructuretest +import ropetest.refactor.suitestest +import ropetest.refactor.usefunctiontest +from rope.base.exceptions import RefactoringError, InterruptedTaskError +from rope.refactor.encapsulate_field import EncapsulateField +from rope.refactor.introduce_factory import IntroduceFactory +from rope.refactor.localtofield import LocalToField +from rope.refactor.method_object import MethodObject +from ropetest import testutils +from ropetest.refactor import change_signature_test, similarfindertest + + +class MethodObjectTest(unittest.TestCase): + def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + def test_empty_method(self): + code = dedent("""\ + def func(): + pass + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __call__(self): + pass + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_trivial_return(self): + code = dedent("""\ + def func(): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_multi_line_header(self): + code = dedent("""\ + def func( + ): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_a_single_parameter(self): + code = dedent("""\ + def func(param): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, param): + self.param = param + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_self_parameter(self): + code = dedent("""\ + def func(self): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, host): + self.self = host + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_simple_using_passed_parameters(self): + code = dedent("""\ + def func(param): + return param + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, param): + self.param = param + + def __call__(self): + return self.param + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_self_keywords_and_args_parameters(self): + code = dedent("""\ + def func(arg, *args, **kwds): + result = arg + args[0] + kwds[arg] + return result + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, arg, args, kwds): + self.arg = arg + self.args = args + self.kwds = kwds + + def __call__(self): + result = self.arg + self.args[0] + self.kwds[self.arg] + return result + """) + self.assertEqual(expected, replacer.get_new_class("_New")) + + def test_performing_on_not_a_function(self): + code = dedent("""\ + my_var = 10 + """) + self.mod.write(code) + with self.assertRaises(RefactoringError): + MethodObject(self.project, self.mod, code.index("my_var")) + + def test_changing_the_module(self): + code = dedent("""\ + def func(): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + self.project.do(replacer.get_changes("_New")) + expected = dedent("""\ + def func(): + return _New()() + + + class _New(object): + + def __call__(self): + return 1 + """) + self.assertEqual(expected, self.mod.read()) + + def test_changing_the_module_and_class_methods(self): + code = dedent("""\ + class C(object): + + def a_func(self): + return 1 + + def another_func(self): + pass + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + self.project.do(replacer.get_changes("_New")) + expected = dedent("""\ + class C(object): + + def a_func(self): + return _New(self)() + + def another_func(self): + pass + + + class _New(object): + + def __init__(self, host): + self.self = host + + def __call__(self): + return 1 + """) + self.assertEqual(expected, self.mod.read()) + + +class IntroduceFactoryTest(unittest.TestCase): + def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + + def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + def _introduce_factory(self, resource, offset, *args, **kwds): + factory_introducer = IntroduceFactory(self.project, resource, offset) + changes = factory_introducer.get_changes(*args, **kwds) + self.project.do(changes) + + def test_adding_the_method(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + def test_changing_occurrences_in_the_main_module(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + a_var = AClass()""") + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + a_var = AClass.create()""") + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + def test_changing_occurrences_with_arguments(self): + code = dedent("""\ + class AClass(object): + def __init__(self, arg): + pass + a_var = AClass(10) + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + def __init__(self, arg): + pass + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + a_var = AClass.create(10) + """) + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + def test_changing_occurrences_in_other_modules(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("import mod1\na_var = mod1.AClass()\n") + self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = dedent("""\ + import mod1 + a_var = mod1.AClass.create() + """) + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + def test_raising_exception_for_non_classes(self): + mod = testutils.create_module(self.project, "mod") + mod.write("def a_func():\n pass\n") + with self.assertRaises(RefactoringError): + self._introduce_factory(mod, mod.read().index("a_func") + 1, "create") + + def test_undoing_introduce_factory(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + code1 = dedent("""\ + class AClass(object): + an_attr = 10 + """) + mod1.write(code1) + code2 = dedent("""\ + from mod1 import AClass + a_var = AClass() + """) + mod2.write(code2) + self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") + self.project.history.undo() + self.assertEqual(code1, mod1.read()) + self.assertEqual(code2, mod2.read()) + + def test_using_on_an_occurrence_outside_the_main_module(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("import mod1\na_var = mod1.AClass()\n") + self._introduce_factory(mod2, mod2.read().index("AClass") + 1, "create") + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = "import mod1\n" "a_var = mod1.AClass.create()\n" + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + def test_introduce_factory_in_nested_scopes(self): + code = dedent("""\ + def create_var(): + class AClass(object): + an_attr = 10 + return AClass() + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + def create_var(): + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + return AClass.create() + """) + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + def test_adding_factory_for_global_factories(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + self._introduce_factory( + mod, mod.read().index("AClass") + 1, "create", global_factory=True + ) + self.assertEqual(expected, mod.read()) + + def test_get_name_for_factories(self): + code = dedent("""\ + class C(object): + pass + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + factory = IntroduceFactory(self.project, mod, mod.read().index("C") + 1) + self.assertEqual("C", factory.get_name()) + + def test_raising_exception_for_global_factory_for_nested_classes(self): + code = dedent("""\ + def create_var(): + class AClass(object): + an_attr = 10 + return AClass() + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + with self.assertRaises(RefactoringError): + self._introduce_factory( + mod, mod.read().index("AClass") + 1, "create", global_factory=True + ) + + def test_changing_occurrences_in_the_main_module_for_global_factories(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + a_var = AClass()""") + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + a_var = create()""") + self._introduce_factory( + mod, mod.read().index("AClass") + 1, "create", global_factory=True + ) + self.assertEqual(expected, mod.read()) + + def test_changing_occurrences_in_other_modules_for_global_factories(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("import mod1\na_var = mod1.AClass()\n") + self._introduce_factory( + mod1, mod1.read().index("AClass") + 1, "create", global_factory=True + ) + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = "import mod1\n" "a_var = mod1.create()\n" + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + def test_import_if_necessary_in_other_mods_for_global_factories(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("from mod1 import AClass\npair = AClass(), AClass\n") + self._introduce_factory( + mod1, mod1.read().index("AClass") + 1, "create", global_factory=True + ) + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = dedent("""\ + from mod1 import AClass, create + pair = create(), AClass + """) + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + def test_changing_occurrences_for_renamed_classes(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + a_class = AClass + a_var = a_class()""") + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + a_class = AClass + a_var = a_class()""") + self._introduce_factory(mod, mod.read().index("a_class") + 1, "create") + self.assertEqual(expected, mod.read()) + + def test_changing_occurrs_in_the_same_module_with_conflict_ranges(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + def create(self): + return C() + """) + mod.write(code) + self._introduce_factory(mod, mod.read().index("C"), "create_c", True) + expected = dedent("""\ + class C(object): + def create(self): + return create_c() + """) + self.assertTrue(mod.read().startswith(expected)) + + def _transform_module_to_package(self, resource): + self.project.do( + rope.refactor.ModuleToPackage(self.project, resource).get_changes() + ) + + def test_transform_module_to_package(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write("import mod2\nfrom mod2 import AClass\n") + mod2 = testutils.create_module(self.project, "mod2") + mod2.write("class AClass(object):\n pass\n") + self._transform_module_to_package(mod2) + mod2 = self.project.get_resource("mod2") + root_folder = self.project.root + self.assertFalse(root_folder.has_child("mod2.py")) + self.assertEqual( + "class AClass(object):\n pass\n", + root_folder.get_child("mod2").get_child("__init__.py").read(), + ) + + def test_transform_module_to_package_undoing(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) + self._transform_module_to_package(mod) + self.assertFalse(pkg.has_child("mod.py")) + self.assertTrue(pkg.get_child("mod").has_child("__init__.py")) + self.project.history.undo() + self.assertTrue(pkg.has_child("mod.py")) + self.assertFalse(pkg.has_child("mod")) + + def test_transform_module_to_package_with_relative_imports(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod1.write("import mod2\nfrom mod2 import AClass\n") + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod2.write("class AClass(object):\n pass\n") + self._transform_module_to_package(mod1) + new_init = self.project.get_resource("pkg/mod1/__init__.py") + self.assertEqual( + "import pkg.mod2\nfrom pkg.mod2 import AClass\n", new_init.read() + ) + + def test_resources_parameter(self): + code = dedent("""\ + class A(object): + an_attr = 10 + """) + code1 = dedent("""\ + import mod + a = mod.A() + """) + mod = testutils.create_module(self.project, "mod") + mod1 = testutils.create_module(self.project, "mod1") + mod.write(code) + mod1.write(code1) + expected = dedent("""\ + class A(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return A(*args, **kwds) + """) + self._introduce_factory( + mod, mod.read().index("A") + 1, "create", resources=[mod] + ) + self.assertEqual(expected, mod.read()) + self.assertEqual(code1, mod1.read()) + + +class EncapsulateFieldTest(unittest.TestCase): + def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + self.mod1 = testutils.create_module(self.project, "mod1") + self.a_class = dedent("""\ + class A(object): + def __init__(self): + self.attr = 1 + """) + self.added_methods = ( + "\n" + " def get_attr(self):\n" + " return self.attr\n\n" + " def set_attr(self, value):\n" + " self.attr = value\n" + ) + self.encapsulated = self.a_class + self.added_methods + + def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + def _encapsulate(self, resource, offset, **args): + changes = EncapsulateField(self.project, resource, offset).get_changes(**args) + self.project.do(changes) + + def test_adding_getters_and_setters(self): + code = self.a_class + self.mod.write(code) + self._encapsulate(self.mod, code.index("attr") + 1) + self.assertEqual(self.encapsulated, self.mod.read()) + + def test_changing_getters_in_other_modules(self): + code = dedent("""\ + import mod + a_var = mod.A() + range(a_var.attr) + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + range(a_var.get_attr()) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_setters_in_other_modules(self): + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(1) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_getters_in_setters(self): + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + a_var.attr + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(1 + a_var.get_attr()) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_appending_to_class_end(self): + self.mod1.write(self.a_class + "a_var = A()\n") + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + self.assertEqual(self.encapsulated + "a_var = A()\n", self.mod1.read()) + + def test_performing_in_other_modules(self): + code = dedent("""\ + import mod + a_var = mod.A() + range(a_var.attr) + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + self.assertEqual(self.encapsulated, self.mod.read()) + expected = dedent("""\ + import mod + a_var = mod.A() + range(a_var.get_attr()) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_main_module_occurrences(self): + code = self.a_class + "a_var = A()\n" "a_var.attr = a_var.attr * 2\n" + self.mod1.write(code) + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + expected = ( + self.encapsulated + "a_var = A()\n" "a_var.set_attr(a_var.get_attr() * 2)\n" + ) + self.assertEqual(expected, self.mod1.read()) + + def test_raising_exception_when_performed_on_non_attributes(self): + self.mod1.write("attr = 10") + with self.assertRaises(RefactoringError): + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + + def test_raising_exception_on_tuple_assignments(self): + self.mod.write(self.a_class) + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + a_var.attr, b = 1, 2 + """) + self.mod1.write(code) + with self.assertRaises(RefactoringError): + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + + def test_raising_exception_on_tuple_assignments2(self): + self.mod.write(self.a_class) + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + b, a_var.attr = 1, 2 + """) + self.mod1.write(code) + with self.assertRaises(RefactoringError): + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + + def test_tuple_assignments_and_function_calls(self): + code = dedent("""\ + import mod + def func(a1=0, a2=0): + pass + a_var = mod.A() + func(a_var.attr, a2=2) + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + def func(a1=0, a2=0): + pass + a_var = mod.A() + func(a_var.get_attr(), a2=2) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_tuple_assignments(self): + code = dedent("""\ + import mod + a_var = mod.A() + a, b = a_var.attr, 1 + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a, b = a_var.get_attr(), 1 + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_augmented_assignments(self): + code = "import mod\n" "a_var = mod.A()\n" "a_var.attr += 1\n" + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(a_var.get_attr() + 1) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_augmented_assignments2(self): + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr <<= 1 + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(a_var.get_attr() << 1) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_occurrences_inside_the_class(self): + new_class = ( + self.a_class + "\n" " def a_func(self):\n" " self.attr = 1\n" + ) + self.mod.write(new_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = ( + self.a_class + "\n" + " def a_func(self):\n" + " self.set_attr(1)\n" + self.added_methods + ) + self.assertEqual(expected, self.mod.read()) + + def test_getter_and_setter_parameters(self): + self.mod.write(self.a_class) + self._encapsulate( + self.mod, + self.mod.read().index("attr") + 1, + getter="getAttr", + setter="setAttr", + ) + new_methods = self.added_methods.replace("get_attr", "getAttr").replace( + "set_attr", "setAttr" + ) + expected = self.a_class + new_methods + self.assertEqual(expected, self.mod.read()) + + def test_using_resources_parameter(self): + self.mod1.write("import mod\na = mod.A()\nvar = a.attr\n") + self.mod.write(self.a_class) + self._encapsulate( + self.mod, self.mod.read().index("attr") + 1, resources=[self.mod] + ) + self.assertEqual("import mod\na = mod.A()\nvar = a.attr\n", self.mod1.read()) + expected = self.a_class + self.added_methods + self.assertEqual(expected, self.mod.read()) + + +class LocalToFieldTest(unittest.TestCase): + def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + def _perform_convert_local_variable_to_field(self, resource, offset): + changes = LocalToField(self.project, resource, offset).get_changes() + self.project.do(changes) + + def test_simple_local_to_field(self): + code = dedent("""\ + class A(object): + def a_func(self): + var = 10 + """) + self.mod.write(code) + self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) + expected = dedent("""\ + class A(object): + def a_func(self): + self.var = 10 + """) + self.assertEqual(expected, self.mod.read()) + + def test_raising_exception_when_performed_on_a_global_var(self): + self.mod.write("var = 10\n") + with self.assertRaises(RefactoringError): + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().index("var") + 1 + ) + + def test_raising_exception_when_performed_on_field(self): + code = dedent("""\ + class A(object): + def a_func(self): + self.var = 10 + """) + self.mod.write(code) + with self.assertRaises(RefactoringError): + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().index("var") + 1 + ) + + def test_raising_exception_when_performed_on_a_parameter(self): + code = dedent("""\ + class A(object): + def a_func(self, var): + a = var + """) + self.mod.write(code) + with self.assertRaises(RefactoringError): + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().index("var") + 1 + ) + + # NOTE: This situation happens alot and is normally not an error + # @testutils.assert_raises(RefactoringError) + def test_not_rais_exception_when_there_is_a_field_with_the_same_name(self): + code = dedent("""\ + class A(object): + def __init__(self): + self.var = 1 + def a_func(self): + var = 10 + """) + self.mod.write(code) + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().rindex("var") + 1 + ) + + def test_local_to_field_with_self_renamed(self): + code = dedent("""\ + class A(object): + def a_func(myself): + var = 10 + """) + self.mod.write(code) + self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) + expected = dedent("""\ + class A(object): + def a_func(myself): + myself.var = 10 + """) + self.assertEqual(expected, self.mod.read()) + + +class IntroduceParameterTest(unittest.TestCase): + def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + def _introduce_parameter(self, offset, name): + rope.refactor.introduce_parameter.IntroduceParameter( + self.project, self.mod, offset + ).get_changes(name).do() + + def test_simple_case(self): + code = dedent("""\ + var = 1 + def f(): + b = var + """) + self.mod.write(code) + offset = self.mod.read().rindex("var") + self._introduce_parameter(offset, "var") + expected = dedent("""\ + var = 1 + def f(var=var): + b = var + """) + self.assertEqual(expected, self.mod.read()) + + def test_changing_function_body(self): + code = dedent("""\ + var = 1 + def f(): + b = var + """) + self.mod.write(code) + offset = self.mod.read().rindex("var") + self._introduce_parameter(offset, "p1") + expected = dedent("""\ + var = 1 + def f(p1=var): + b = p1 + """) + self.assertEqual(expected, self.mod.read()) + + def test_unknown_variables(self): + self.mod.write("def f():\n b = var + c\n") + offset = self.mod.read().rindex("var") + with self.assertRaises(RefactoringError): + self._introduce_parameter(offset, "p1") + self.assertEqual("def f(p1=var):\n b = p1 + c\n", self.mod.read()) + + def test_failing_when_not_inside(self): + self.mod.write("var = 10\nb = var\n") + offset = self.mod.read().rindex("var") + with self.assertRaises(RefactoringError): + self._introduce_parameter(offset, "p1") + + def test_attribute_accesses(self): + code = dedent("""\ + class C(object): + a = 10 + c = C() + def f(): + b = c.a + """) + self.mod.write(code) + offset = self.mod.read().rindex("a") + self._introduce_parameter(offset, "p1") + expected = dedent("""\ + class C(object): + a = 10 + c = C() + def f(p1=c.a): + b = p1 + """) + self.assertEqual(expected, self.mod.read()) + + def test_introducing_parameters_for_methods(self): + code = dedent("""\ + var = 1 + class C(object): + def f(self): + b = var + """) + self.mod.write(code) + offset = self.mod.read().rindex("var") + self._introduce_parameter(offset, "p1") + expected = dedent("""\ + var = 1 + class C(object): + def f(self, p1=var): + b = p1 + """) + self.assertEqual(expected, self.mod.read()) + + +class _MockTaskObserver: + def __init__(self): + self.called = 0 + + def __call__(self): + self.called += 1 + + +class TaskHandleTest(unittest.TestCase): + def test_trivial_case(self): + handle = rope.base.taskhandle.TaskHandle() + self.assertFalse(handle.is_stopped()) + + def test_stopping(self): + handle = rope.base.taskhandle.TaskHandle() + handle.stop() + self.assertTrue(handle.is_stopped()) + + def test_job_sets(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset() + self.assertEqual([jobs], handle.get_jobsets()) + + def test_starting_and_finishing_jobs(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset(name="test job set", count=1) + jobs.started_job("job1") + jobs.finished_job() + + def test_test_checking_status(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset() + handle.stop() + with self.assertRaises(InterruptedTaskError): + jobs.check_status() + + def test_test_checking_status_when_starting(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset() + handle.stop() + with self.assertRaises(InterruptedTaskError): + jobs.started_job("job1") + + def test_calling_the_observer_after_stopping(self): + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) + handle.stop() + self.assertEqual(1, observer.called) + + def test_calling_the_observer_after_creating_job_sets(self): + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) + jobs = handle.create_jobset() # noqa + self.assertEqual(1, observer.called) + + def test_calling_the_observer_when_starting_and_finishing_jobs(self): + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) + jobs = handle.create_jobset(name="test job set", count=1) + jobs.started_job("job1") + jobs.finished_job() + self.assertEqual(3, observer.called) + + def test_job_set_get_percent_done(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset(name="test job set", count=2) + self.assertEqual(0, jobs.get_percent_done()) + jobs.started_job("job1") + jobs.finished_job() + self.assertEqual(50, jobs.get_percent_done()) + jobs.started_job("job2") + jobs.finished_job() + self.assertEqual(100, jobs.get_percent_done()) + + def test_getting_job_name(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset(name="test job set", count=1) + # recommended name/job_name attribute + self.assertEqual("test job set", jobs.name) + self.assertEqual(None, jobs.job_name) + # deprecated getters + self.assertEqual("test job set", jobs.get_name()) + self.assertEqual(None, jobs.get_active_job_name()) + jobs.started_job("job1") + # recommended name/job_name attribute + self.assertEqual("test job set", jobs.get_name()) + # deprecated getters + self.assertEqual("job1", jobs.get_active_job_name()) +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -21,8 +21,10 @@ + p1 = testutils.create_package(self.project, "p1") + p2 = testutils.create_package(self.project, "p2", p1) + p3 = testutils.create_package(self.project, "p3", p2) +- m1 = testutils.create_module(self.project, "m1", p3) # noqa +- l = testutils.create_module(self.project, "l", p3) # noqa ++ m1 = testutils.create_module(self.project, "m1", p3) ++ mod_l = testutils.create_module(self.project, "l", p3) ++ self.assertTrue(m1 is not None) ++ self.assertTrue(mod_l is not None) + + def tearDown(self): + testutils.remove_project(self.project) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -24,7 +24,6 @@ + "", + ")", + ]) +- + + @testutils.only_for_versions_higher("3.10") + def test_match_node_with_match_mapping_match_as(self): +@@ -54,5 +53,3 @@ + "", + "}", + ]) +- +- +@language python + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name(self): + source = dedent("""\ + match x: + case Foo(x) as b: + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "MatchClass", + " ", + "as", + " ", + "b", + ]) + checker.check_children("MatchClass", [ + "Name", + "", + "(", + "", + "MatchAs", + "", + ")", + ]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_mapping_match_as(self): + source = dedent("""\ + match x: + case {"a": b} as c: + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "MatchMapping", + " ", + "as", + " ", + "c", + ]) + checker.check_children("MatchMapping", [ + "{", + "", + "Constant", + "", + ":", + " ", + "MatchAs", + "", + "}", + ]) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,12 +2,12 @@ + import shutil + import sys + import logging +- +-logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) + import unittest + + import rope.base.project + from rope.contrib import generate ++ ++logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) + + + def sample_project(root=None, foldername=None, **kwds): +@@ -51,7 +51,7 @@ + + # windows sometimes raises exceptions instead of removing files + if os.name == "nt" or sys.platform == "cygwin": +- for i in range(12): ++ for _i in range(12): + try: + _remove_recursively(path) + except OSError as e: +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -3,13 +3,13 @@ + import shutil + import sys + import logging +- +-logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) + import unittest + + import rope.base.project + from rope.contrib import generate + ++logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) ++ + + @others + @language python +@language python + +@path C:/Repos/ekr-rope/ropetest/ +import os.path +import shutil +import sys +import logging + +logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) +import unittest + +import rope.base.project +from rope.contrib import generate + + +@others +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -3,7 +3,7 @@ + + # windows sometimes raises exceptions instead of removing files + if os.name == "nt" or sys.platform == "cygwin": +- for i in range(12): ++ for _i in range(12): + try: + _remove_recursively(path) + except OSError as e: +@language python + +def remove_recursively(path): + import time + + # windows sometimes raises exceptions instead of removing files + if os.name == "nt" or sys.platform == "cygwin": + for i in range(12): + try: + _remove_recursively(path) + except OSError as e: + if e.errno not in (13, 16, 32): + raise + time.sleep(0.3) + else: + break + else: + _remove_recursively(path) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,3 +1,3 @@ + from setuptools import setup + +-setup()+setup() + + + + + + +@ignore +@nosearch + + +def _Name(self, node): + self.result = self.scope.lookup(node.id) + + +def _Attribute(self, node): + pyname = eval_node(self.scope, node.value) + if pyname is None: + pyname = rope.base.pynames.UnboundName() + self.old_result = pyname + if pyname.get_object() != rope.base.pyobjects.get_unknown(): + try: + self.result = pyname.get_object()[node.attr] + except exceptions.AttributeNotFoundError: + self.result = None + + +def _Call(self, node): + primary, pyobject = self._get_primary_and_object_for_node(node.func) + if pyobject is None: + return + + def _get_returned(pyobject): + args = arguments.create_arguments(primary, pyobject, node, self.scope) + return pyobject.get_returned_object(args) + + if isinstance(pyobject, rope.base.pyobjects.AbstractClass): + result = None + if "__new__" in pyobject: + new_function = pyobject["__new__"].get_object() + result = _get_returned(new_function) + if result is None or result == rope.base.pyobjects.get_unknown(): + result = rope.base.pyobjects.PyObject(pyobject) + self.result = rope.base.pynames.UnboundName(pyobject=result) + return + + pyfunction = None + if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): + pyfunction = pyobject + elif "__call__" in pyobject: + pyfunction = pyobject["__call__"].get_object() + if pyfunction is not None: + self.result = rope.base.pynames.UnboundName( + pyobject=_get_returned(pyfunction) + ) + + +def _Str(self, node): + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_str() + ) + + +def _Num(self, node): + type_name = type(node.n).__name__ + self.result = self._get_builtin_name(type_name) + + +def _Constant(self, node): + type_name = type(node.n).__name__ + try: + self.result = self._get_builtin_name(type_name) + except exceptions.AttributeNotFoundError: + # XXX: Right way to fix this is to add missing NoneType to builtins? + pass + + +def _get_builtin_name(self, type_name): + pytype = rope.base.builtins.builtins[type_name].get_object() + return rope.base.pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) + + +def _BinOp(self, node): + self.result = rope.base.pynames.UnboundName( + self._get_object_for_node(node.left) + ) + + +def _BoolOp(self, node): + pyobject = self._get_object_for_node(node.values[0]) + if pyobject is None: + pyobject = self._get_object_for_node(node.values[1]) + self.result = rope.base.pynames.UnboundName(pyobject) + + +def _Repr(self, node): + self.result = self._get_builtin_name("str") + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + @path C:/Repos/ekr-rope/rope/base/ + @nopyflakes +-import ast +-from ast import * ++import ast # noqu ++from ast import * # noqa + + from rope.base import fscommands + +@language python + +def _UnaryOp(self, node): + self.result = rope.base.pynames.UnboundName( + self._get_object_for_node(node.operand) + ) + + +def _Compare(self, node): + self.result = self._get_builtin_name("bool") + + +def _Dict(self, node): + keys = None + values = None + if node.keys and node.keys[0]: + keys, values = next( + iter(filter(itemgetter(0), zip(node.keys, node.values))), (None, None) + ) + if keys: + keys = self._get_object_for_node(keys) + if values: + values = self._get_object_for_node(values) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_dict(keys, values) + ) + + +def _List(self, node): + holding = None + if node.elts: + holding = self._get_object_for_node(node.elts[0]) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_list(holding) + ) + + +def _ListComp(self, node): + pyobject = self._what_does_comprehension_hold(node) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_list(pyobject) + ) + + +def _GeneratorExp(self, node): + pyobject = self._what_does_comprehension_hold(node) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_iterator(pyobject) + ) + + +def _what_does_comprehension_hold(self, node): + scope = self._make_comprehension_scope(node) + pyname = eval_node(scope, node.elt) + return pyname.get_object() if pyname is not None else None + + +def _make_comprehension_scope(self, node): + scope = self.scope + module = scope.pyobject.get_module() + names = {} + for comp in node.generators: + new_names = _get_evaluated_names( + comp.target, comp.iter, module, ".__iter__().next()", node.lineno + ) + names.update(new_names) + return rope.base.pyscopes.TemporaryScope(scope.pycore, scope, names) + + +def _Tuple(self, node): + objects = [] + if len(node.elts) < 4: + for stmt in node.elts: + pyobject = self._get_object_for_node(stmt) + objects.append(pyobject) + else: + objects.append(self._get_object_for_node(node.elts[0])) + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.get_tuple(*objects) + ) + + +def _get_object_for_node(self, stmt): + pyname = eval_node(self.scope, stmt) + pyobject = None + if pyname is not None: + pyobject = pyname.get_object() + return pyobject + + +@path C:/Repos/ekr-rope/rope/base/ +@nopyflakes +import ast +from ast import * + +from rope.base import fscommands + + +@others +@language python +@tabwidth -4 + +def _get_primary_and_object_for_node(self, stmt): + primary, pyname = eval_node2(self.scope, stmt) + pyobject = None + if pyname is not None: + pyobject = pyname.get_object() + return primary, pyobject + + +def _Subscript(self, node): + if isinstance(node.slice, ast.Index): + self._call_function(node.value, "__getitem__", [node.slice.value]) + elif isinstance(node.slice, ast.Slice): + self._call_function(node.value, "__getitem__", [node.slice]) + elif isinstance(node.slice, ast.expr): + self._call_function(node.value, "__getitem__", [node.value]) + + +def _Slice(self, node): + self.result = self._get_builtin_name("slice") + + +def _call_function(self, node, function_name, other_args=None): + pyname = eval_node(self.scope, node) + if pyname is not None: + pyobject = pyname.get_object() + else: + return + if function_name in pyobject: + called = pyobject[function_name].get_object() + if not called or not isinstance(called, pyobjects.AbstractFunction): + return + args = [node] + if other_args: + args += other_args + arguments_ = arguments.Arguments(args, self.scope) + self.result = rope.base.pynames.UnboundName( + pyobject=called.get_returned_object(arguments_) + ) + + +def _Lambda(self, node): + self.result = rope.base.pynames.UnboundName( + pyobject=rope.base.builtins.Lambda(node, self.scope) + ) + + + +def _get_evaluated_names(targets, assigned, module, evaluation, lineno): + result = {} + for name, levels in astutils.get_name_levels(targets): + assignment = rope.base.pynames.AssignmentValue(assigned, levels, evaluation) + # XXX: this module should not access `rope.base.pynamesdef`! + pyname = rope.base.pynamesdef.AssignedName(lineno, module) + pyname.assignments.append(assignment) + result[name] = pyname + return result + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,4 +6,4 @@ + + + @method(symbol("[")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa +@language python + + if parser.token.name != ",": + break + parser.advance(",") + parser.advance("]") + return self + + +@method(symbol("[")) +def evaluate(self, pyobject): + +def eval_str2(holding_scope, name): + try: + # parenthesizing for handling cases like 'a_var.\nattr' + node = ast.parse("(%s)" % name) + except SyntaxError: + raise BadIdentifierError("Not a resolvable python identifier selected.") + return eval_node2(holding_scope, node) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + @method(symbol("(")) +-def nud(self, parser): ++def nud(self, parser): # noqa + self.second = [] + if parser.token.name != ")": + while 1: +@language python + +@path C:/Repos/ekr-rope/rope/base/ +@nopyflakes +import ast +from ast import * + +from rope.base import fscommands + + +@others +@language python +@tabwidth -4 + +@method(symbol("(")) +def nud(self, parser): +self.second = [] +if parser.token.name != ")": + while 1: + self.second.append(parser.expression()) + if parser.token.name != ",": + break + parser.advance(",") +parser.advance(")") +parser.advance("->") +self.third = parser.expression(symbol("->").lbp + 0.1) +return self + + +# Function Calls + +def _is_defined_in_class_body(self, holding_scope, offset, lineno): + if ( + lineno == holding_scope.get_start() + and holding_scope.parent is not None + and holding_scope.parent.get_kind() == "Class" + and self.worder.is_a_class_or_function_name_in_header(offset) + ): + return True + if ( + lineno != holding_scope.get_start() + and holding_scope.get_kind() == "Class" + and self.worder.is_name_assigned_in_class_body(offset) + ): + return True + return False + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + @method(symbol("(")) +-def led(self, left, parser): ++def led(self, left, parser): # noqa + self.first = left + self.second = [] + if parser.token.name != ")": +@language python + +@method(symbol("(")) +def led(self, left, parser): +self.first = left +self.second = [] +if parser.token.name != ")": + while 1: + self.second.append(parser.expression()) + +def _is_function_name_in_function_header(self, scope, offset, lineno): + return ( + scope.get_start() <= lineno <= scope.get_body_start() + and scope.get_kind() == "Function" + and self.worder.is_a_class_or_function_name_in_header(offset) + ) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,14 +5,14 @@ + + + @method(symbol("(")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa + # TODO: Implement me + raise NotImplementedError + + + @method(symbol("or")) + @method(symbol("|")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa + # TODO: Implement me + raise NotImplementedError + +@language python + +parser.advance(")") +parser.advance("->") +self.third = parser.expression(symbol("->").lbp + 0.1) +return self + + +@method(symbol("(")) +def evaluate(self, pyobject): +# TODO: Implement me +raise NotImplementedError + + +@method(symbol("or")) +@method(symbol("|")) +def evaluate(self, pyobject): +# TODO: Implement me +raise NotImplementedError + + +class Compiler: + +parser_factory = Parser +lexer_factory = Lexer +symbol_table = symbol_table + +def _make_parser(self): + return self.parser_factory(self.lexer_factory(self.symbol_table)) + +@base_utils.cached(500) +def __call__(self, program): + """ + :type program: str + :rtype: rope.base.oi.type_hinting.evaluate.SymbolBase + """ + return self._make_parser().parse(program) + + +compile = Compiler() + + +class Evaluator: + +compile = compile + +def get_primary_and_pyname_at( + self, + offset: int, +) -> Tuple[Optional[rope.base.pynames.PyName], Optional[rope.base.pynames.PyName]]: + lineno = self.lines.get_line_number(offset) + holding_scope = self.module_scope.get_inner_scope_for_offset(offset) + # function keyword parameter + if self.worder.is_function_keyword_parameter(offset): + keyword_name = self.worder.get_word_at(offset) + pyobject = self.get_enclosing_function(offset) + if isinstance(pyobject, pyobjectsdef.PyFunction): + parameter_name = pyobject.get_parameters().get(keyword_name, None) + return (None, parameter_name) + elif isinstance(pyobject, pyobjects.AbstractFunction): + parameter_name = rope.base.pynames.ParameterName() + return (None, parameter_name) + # class body + if self._is_defined_in_class_body(holding_scope, offset, lineno): + class_scope = holding_scope + if lineno == holding_scope.get_start(): + class_scope = holding_scope.parent + name = self.worder.get_primary_at(offset).strip() + try: + return (None, class_scope.pyobject[name]) + except rope.base.exceptions.AttributeNotFoundError: + return (None, None) + # function header + if self._is_function_name_in_function_header(holding_scope, offset, lineno): + name = self.worder.get_primary_at(offset).strip() + return (None, holding_scope.parent[name]) + # module in a from statement or an imported name that is aliased + if self.worder.is_from_statement_module( + offset + ) or self.worder.is_import_statement_aliased_module(offset): + module = self.worder.get_primary_at(offset) + module_pyname = self._find_module(module) + return (None, module_pyname) + if self.worder.is_from_aliased(offset): + name = self.worder.get_from_aliased(offset) + else: + name = self.worder.get_primary_at(offset) + return eval_str2(holding_scope, name) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -9,4 +9,4 @@ + return ast.evaluate(pyobject) + + +-evaluate = Evaluator() ++evaluate = Evaluator() # noqa +@language python + + +def __call__(self, program, pyobject): + """Evaluates the program string or AST + + :type program: str or rope.base.oi.type_hinting.evaluate.SymbolBase + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + ast = self.compile(program) if isinstance(program, str) else program + return ast.evaluate(pyobject) + + +evaluate = Evaluator() + +def parse(source, filename="<string>"): + # NOTE: the raw string should be given to `compile` function + if isinstance(source, str): + source = fscommands.unicode_to_file_data(source) + if b"\r" in source: + source = source.replace(b"\r\n", b"\n").replace(b"\r", b"\n") + if not source.endswith(b"\n"): + source += b"\n" + try: + return ast.parse(source, filename="<unknown>") + except (TypeError, ValueError) as e: + error = SyntaxError() + error.lineno = 1 + error.filename = filename + error.msg = str(e) + raise error + + + +def get_enclosing_function(self, offset): + function_parens = self.worder.find_parens_start_from_inside(offset) + try: + function_pyname = self.get_pyname_at(function_parens - 1) + except BadIdentifierError: + function_pyname = None + if function_pyname is not None: + pyobject = function_pyname.get_object() + if isinstance(pyobject, pyobjects.AbstractFunction): + return pyobject + elif ( + isinstance(pyobject, pyobjects.AbstractClass) and "__init__" in pyobject + ): + return pyobject["__init__"].get_object() + elif "__call__" in pyobject: + return pyobject["__call__"].get_object() + return None + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + import re +-from rope.base.oi.type_hinting import utils ++ + from rope.base.oi.type_hinting.providers import interfaces +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,6 @@ + @path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ + import re +-from rope.base.oi.type_hinting import utils ++ + from rope.base.oi.type_hinting.providers import interfaces + + +@language python + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ +import re +from rope.base.oi.type_hinting import utils +from rope.base.oi.type_hinting.providers import interfaces + + +@others +@language python +@tabwidth -4 + +@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ +import re +from rope.base.oi.type_hinting import utils +from rope.base.oi.type_hinting.providers import interfaces + + +@others +@language python +@tabwidth -4 + +class AssignmentProvider(interfaces.IAssignmentProvider): + @others + +def __init__(self, resolver): + """ + :type resolver: rope.base.oi.type_hinting.resolvers.interfaces.IResolver + """ + self._resolve = resolver + + +PEP0484_TYPE_COMMENT_PATTERNS = (re.compile(r"type:\s*([^\n]+)"),) + + +def __call__(self, pyname): + """ + :type pyname: rope.base.pynamesdef.AssignedName + :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None + """ + from rope.base.oi.soi import _get_lineno_for_node + + lineno = _get_lineno_for_node(pyname.assignments[0].ast_node) + holding_scope = pyname.module.get_scope().get_inner_scope_for_line(lineno) + line = holding_scope._get_global_scope()._scope_finder.lines.get_line(lineno) + if "#" in line: + type_strs = self._search_type_in_type_comment(line.split("#", 1)[1]) + if type_strs: + return self._resolve(type_strs[0], holding_scope.pyobject) + + +def walk(node, walker) -> None: + """Walk the syntax tree""" + method_name = "_" + node.__class__.__name__ + method = getattr(walker, method_name, None) + if method is not None: + if isinstance(node, ast.ImportFrom) and node.module is None: + # In python < 2.7 ``node.module == ''`` for relative imports + # but for python 2.7 it is None. Generalizing it to ''. + node.module = "" + method(node) + return + for child in get_child_nodes(node): + walk(child, walker) + + + +def _search_type_in_type_comment(self, code): + """For more info see: + https://www.python.org/dev/peps/pep-0484/#type-comments + + >>> AssignmentProvider()._search_type_in_type_comment('type: int') + ['int'] + """ + for p in self.PEP0484_TYPE_COMMENT_PATTERNS: + match = p.search(code) + if match: + return [match.group(1)] + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,14 +1,10 @@ + import logging ++from typing import Optional, Union + +-try: +- from typing import Union, Optional +-except ImportError: +- pass + import rope.base.utils as base_utils + from rope.base import evaluate + from rope.base.exceptions import AttributeNotFoundError + from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject +-from rope.base.utils import pycompat + + + def get_super_func(pyfunc): +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,15 +1,11 @@ + @path C:/Repos/ekr-rope/rope/base/ + import logging ++from typing import Optional, Union + +-try: +- from typing import Union, Optional +-except ImportError: +- pass + import rope.base.utils as base_utils + from rope.base import evaluate + from rope.base.exceptions import AttributeNotFoundError + from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject +-from rope.base.utils import pycompat + + + @others +@language python + +@path C:/Repos/ekr-rope/rope/base/ +import logging + +try: + from typing import Union, Optional +except ImportError: + pass +import rope.base.utils as base_utils +from rope.base import evaluate +from rope.base.exceptions import AttributeNotFoundError +from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject +from rope.base.utils import pycompat + + +@others +@language python +@tabwidth -4 + +@path C:/Repos/ekr-rope/rope/base/ +"""A few useful functions for using rope as a library""" +import os.path + +import rope.base.project +import rope.base.pycore +from rope.base import pyobjectsdef +from rope.base import utils +from rope.base import taskhandle + + +@others +@language python +@tabwidth -4 + +def path_to_resource(project, path, type=None): + """Get the resource at path + + You only need to specify `type` if `path` does not exist. It can + be either 'file' or 'folder'. If the type is `None` it is assumed + that the resource already exists. + + Note that this function uses `Project.get_resource()`, + `Project.get_file()`, and `Project.get_folder()` methods. + + """ + project_path = path_relative_to_project_root(project, path) + if project_path is None: + project_path = rope.base.project._realpath(path) + project = rope.base.project.get_no_project() + if type is None: + return project.get_resource(project_path) + if type == "file": + return project.get_file(project_path) + if type == "folder": + return project.get_folder(project_path) + return None + + + +def path_relative_to_project_root(project, path): + return relative(project.address, path) + + + +@utils.deprecated() +def relative(root, path): + root = rope.base.project._realpath(root).replace(os.path.sep, "/") + path = rope.base.project._realpath(path).replace(os.path.sep, "/") + if path == root: + return "" + if path.startswith(root + "/"): + return path[len(root) + 1 :] + + + +def report_change(project, path, old_content): + """Report that the contents of file at `path` was changed + + The new contents of file is retrieved by reading the file. + + """ + resource = path_to_resource(project, path) + if resource is None: + return + for observer in list(project.observers): + observer.resource_changed(resource) + if project.pycore.automatic_soa: + rope.base.pycore.perform_soa_on_changed_scopes(project, resource, old_content) + + + +def get_child_nodes(node): + if isinstance(node, ast.Module): + return node.body + result = [] + if node._fields is not None: + for name in node._fields: + child = getattr(node, name) + if isinstance(child, list): + for entry in child: + if isinstance(entry, ast.AST): + result.append(entry) + if isinstance(child, ast.AST): + result.append(child) + return result + + + +def analyze_module(project, resource): + """Perform static object analysis on a python file in the project + + Note that this might be really time consuming. + """ + project.pycore.analyze_module(resource) + + + +def analyze_modules(project, task_handle=taskhandle.NullTaskHandle()): + """Perform static object analysis on all python files in the project + + Note that this might be really time consuming. + """ + resources = project.get_python_files() + job_set = task_handle.create_jobset("Analyzing Modules", len(resources)) + for resource in resources: + job_set.started_job(resource.path) + analyze_module(project, resource) + job_set.finished_job() + + + +def get_string_module(project, code, resource=None, force_errors=False): + """Returns a `PyObject` object for the given code + + If `force_errors` is `True`, `exceptions.ModuleSyntaxError` is + raised if module has syntax errors. This overrides + ``ignore_syntax_errors`` project config. + + """ + return pyobjectsdef.PyModule( + project.pycore, code, resource, force_errors=force_errors + ) + + + +def get_string_scope(project, code, resource=None): + """Returns a `Scope` object for the given code""" + return get_string_module(project, code, resource).get_scope() + + + +def is_python_file(project, resource): + return project.pycore.is_python_file(resource) + + + +def modname(resource): + if resource.is_folder(): + module_name = resource.name + source_folder = resource.parent + elif resource.name == "__init__.py": + module_name = resource.parent.name + source_folder = resource.parent.parent + else: + module_name = resource.name[:-3] + source_folder = resource.parent + + while source_folder != source_folder.parent and source_folder.has_child( + "__init__.py" + ): + module_name = source_folder.name + "." + module_name + source_folder = source_folder.parent + + return module_name + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,5 @@ + import bisect + import difflib +-import sys + import warnings + + import rope.base.libutils +@@ -15,7 +14,6 @@ + from rope.base import stdmods + from rope.base import taskhandle + from rope.base import utils +-from rope.base.exceptions import ModuleNotFoundError + + + class PyCore: +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,6 @@ + @path C:/Repos/ekr-rope/rope/base/ + import bisect + import difflib +-import sys + import warnings + + import rope.base.libutils +@@ -16,7 +15,6 @@ + from rope.base import stdmods + from rope.base import taskhandle + from rope.base import utils +-from rope.base.exceptions import ModuleNotFoundError + + + @others +@language python + +@path C:/Repos/ekr-rope/rope/base/ +import bisect +import difflib +import sys +import warnings + +import rope.base.libutils +import rope.base.resourceobserver +import rope.base.resources +import rope.base.oi.doa +import rope.base.oi.objectinfo +import rope.base.oi.soa +from rope.base import builtins +from rope.base import exceptions +from rope.base import pyobjectsdef +from rope.base import stdmods +from rope.base import taskhandle +from rope.base import utils +from rope.base.exceptions import ModuleNotFoundError + + +@others +@language python +@tabwidth -4 + +def call_for_nodes(node, callback, recursive=False): + """If callback returns `True` the child nodes are skipped""" + result = callback(node) + if recursive and not result: + for child in get_child_nodes(node): + call_for_nodes(child, callback, recursive) + + + +@path C:/Repos/ekr-rope/rope/base/ +import bisect +import difflib +import sys +import warnings + +import rope.base.libutils +import rope.base.resourceobserver +import rope.base.resources +import rope.base.oi.doa +import rope.base.oi.objectinfo +import rope.base.oi.soa +from rope.base import builtins +from rope.base import exceptions +from rope.base import pyobjectsdef +from rope.base import stdmods +from rope.base import taskhandle +from rope.base import utils +from rope.base.exceptions import ModuleNotFoundError + + +@others +@language python +@tabwidth -4 + +class PyCore: + @others + +def __init__(self, project): + self.project = project + self._init_resource_observer() + self.cache_observers = [] + self.module_cache = _ModuleCache(self) + self.extension_cache = _ExtensionCache(self) + self.object_info = rope.base.oi.objectinfo.ObjectInfoManager(project) + self._init_python_files() + self._init_automatic_soa() + + +def _init_python_files(self): + self.python_matcher = None + patterns = self.project.prefs.get("python_files", None) + if patterns is not None: + self.python_matcher = rope.base.resources._ResourceMatcher() + self.python_matcher.set_patterns(patterns) + + +def _init_resource_observer(self): + callback = self._invalidate_resource_cache + observer = rope.base.resourceobserver.ResourceObserver( + changed=callback, moved=callback, removed=callback + ) + self.observer = rope.base.resourceobserver.FilteredResourceObserver(observer) + self.project.add_observer(self.observer) + + +def _init_automatic_soa(self): + if not self.automatic_soa: + return + callback = self._file_changed_for_soa + observer = rope.base.resourceobserver.ResourceObserver( + changed=callback, moved=callback, removed=callback + ) + self.project.add_observer(observer) + + +@property +def automatic_soa(self): + auto_soa = self.project.prefs.get("automatic_soi", None) + return self.project.prefs.get("automatic_soa", auto_soa) + + +def _file_changed_for_soa(self, resource, new_resource=None): + old_contents = self.project.history.contents_before_current_change(resource) + if old_contents is not None: + perform_soa_on_changed_scopes(self.project, resource, old_contents) + + +def is_python_file(self, resource): + if resource.is_folder(): + return False + if self.python_matcher is None: + return resource.name.endswith(".py") + return self.python_matcher.does_match(resource) + + +@utils.deprecated("Use `project.get_module` instead") +def get_module(self, name, folder=None): + """Returns a `PyObject` if the module was found.""" + return self.project.get_module(name, folder) + + +def get_children(node): + result = [] + if node._fields is not None: + for name in node._fields: + if name in ["lineno", "col_offset"]: + continue + child = getattr(node, name) + result.append(child) + return result + +def _builtin_submodules(self, modname): + result = {} + for extension in self.extension_modules: + if extension.startswith(modname + "."): + name = extension[len(modname) + 1 :] + if "." not in name: + result[name] = self.builtin_module(extension) + return result + + +def builtin_module(self, name): + return self.extension_cache.get_pymodule(name) + + +@utils.deprecated("Use `project.get_relative_module` instead") +def get_relative_module(self, name, folder, level): + return self.project.get_relative_module(name, folder, level) + + +@utils.deprecated("Use `libutils.get_string_module` instead") +def get_string_module(self, code, resource=None, force_errors=False): + """Returns a `PyObject` object for the given code + + If `force_errors` is `True`, `exceptions.ModuleSyntaxError` is + raised if module has syntax errors. This overrides + ``ignore_syntax_errors`` project config. + + """ + return pyobjectsdef.PyModule(self, code, resource, force_errors=force_errors) + + +@utils.deprecated("Use `libutils.get_string_scope` instead") +def get_string_scope(self, code, resource=None): + """Returns a `Scope` object for the given code""" + return rope.base.libutils.get_string_scope(code, resource) + + +def _invalidate_resource_cache(self, resource, new_resource=None): + for observer in self.cache_observers: + observer(resource) + + +@utils.deprecated("Use `project.get_python_path_folders` instead") +def get_python_path_folders(self): + return self.project.get_python_path_folders() + + +@utils.deprecated("Use `project.find_module` instead") +def find_module(self, modname, folder=None): + """Returns a resource corresponding to the given module + + returns None if it can not be found + """ + return self.project.find_module(modname, folder) + + +@utils.deprecated("Use `project.find_relative_module` instead") +def find_relative_module(self, modname, folder, level): + return self.project.find_relative_module(modname, folder, level) + + +# INFO: It was decided not to cache source folders, since: +# - Does not take much time when the root folder contains +# packages, that is most of the time +# - We need a separate resource observer; `self.observer` +# does not get notified about module and folder creations +@utils.deprecated("Use `project.get_source_folders` instead") +def get_source_folders(self): + """Returns project source folders""" + return self.project.get_source_folders() + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -10,8 +10,6 @@ + import os + import shutil + import subprocess +- +-import rope.base.utils.pycompat as pycompat + import typing +@language python + +def resource_to_pyobject(self, resource, force_errors=False): + return self.module_cache.get_pymodule(resource, force_errors) + + +@utils.deprecated("Use `project.get_python_files` instead") +def get_python_files(self): + """Returns all python files available in the project""" + return self.project.get_python_files() + + +def _is_package(self, folder): + return ( + folder.has_child("__init__.py") + and not folder.get_child("__init__.py").is_folder() + ) + + +def _find_source_folders(self, folder): + for resource in folder.get_folders(): + if self._is_package(resource): + return [folder] + result = [] + for resource in folder.get_files(): + if resource.name.endswith(".py"): + result.append(folder) + break + for resource in folder.get_folders(): + result.extend(self._find_source_folders(resource)) + return result + + +def run_module(self, resource, args=None, stdin=None, stdout=None): + """Run `resource` module + + Returns a `rope.base.oi.doa.PythonFileRunner` object for + controlling the process. + + """ + perform_doa = self.project.prefs.get("perform_doi", True) + perform_doa = self.project.prefs.get("perform_doa", perform_doa) + receiver = self.object_info.doa_data_received + if not perform_doa: + receiver = None + runner = rope.base.oi.doa.PythonFileRunner( + self, resource, args, stdin, stdout, receiver + ) + runner.add_finishing_observer(self.module_cache.forget_all_data) + runner.run() + return runner + + +def analyze_module( + self, + resource, + should_analyze=lambda py: True, + search_subscopes=lambda py: True, + followed_calls=None, +): + """Analyze `resource` module for static object inference + + This function forces rope to analyze this module to collect + information about function calls. `should_analyze` is a + function that is called with a `PyDefinedObject` argument. If + it returns `True` the element is analyzed. If it is `None` or + returns `False` the element is not analyzed. + + `search_subscopes` is like `should_analyze`; The difference is + that if it returns `False` the sub-scopes are all ignored. + That is it is assumed that `should_analyze` returns `False` + for all of its subscopes. + + `followed_calls` override the value of ``soa_followed_calls`` + project config. + """ + if followed_calls is None: + followed_calls = self.project.prefs.get("soa_followed_calls", 0) + pymodule = self.resource_to_pyobject(resource) + self.module_cache.forget_all_data() + rope.base.oi.soa.analyze_module( + self, pymodule, should_analyze, search_subscopes, followed_calls + ) + + +def get_classes(self, task_handle=taskhandle.NullTaskHandle()): + warnings.warn( + "`PyCore.get_classes()` is deprecated", DeprecationWarning, stacklevel=2 + ) + return [] + + +def __str__(self): + return str(self.module_cache) + str(self.object_info) + + +@utils.deprecated("Use `libutils.modname` instead") +def modname(self, resource): + return rope.base.libutils.modname(resource) + + +@property +@utils.cacheit +def extension_modules(self): + result = set(self.project.prefs.get("extension_modules", [])) + if self.project.prefs.get("import_dynload_stdmods", False): + result.update(stdmods.dynload_modules()) + return result + + + + + +class _ModuleCache: + @others + +def __init__(self, pycore): + self.pycore = pycore + self.module_map = {} + self.pycore.cache_observers.append(self._invalidate_resource) + self.observer = self.pycore.observer + + +def _invalidate_resource(self, resource): + if resource in self.module_map: + self.forget_all_data() + self.observer.remove_resource(resource) + del self.module_map[resource] + + +def get_pymodule(self, resource, force_errors=False): + if resource in self.module_map: + return self.module_map[resource] + if resource.is_folder(): + result = pyobjectsdef.PyPackage( + self.pycore, + resource, + force_errors=force_errors, + ) + else: + result = pyobjectsdef.PyModule( + self.pycore, + resource=resource, + force_errors=force_errors, + ) + if result.has_errors: + return result + self.module_map[resource] = result + self.observer.add_resource(resource) + return result + + +def forget_all_data(self): + for pymodule in self.module_map.values(): + pymodule._forget_concluded_data() + + +def __str__(self): + return "PyCore caches %d PyModules\n" % len(self.module_map) + + + +class _ExtensionCache: + @others + +def __init__(self, pycore): + self.pycore = pycore + self.extensions = {} + + +def get_pymodule(self, name): + if name == "__builtin__": + return builtins.builtins + allowed = self.pycore.extension_modules + if name not in self.extensions and name in allowed: + self.extensions[name] = builtins.BuiltinModule(name, self.pycore) + return self.extensions.get(name) + + + +def perform_soa_on_changed_scopes(project, resource, old_contents): + pycore = project.pycore + if resource.exists() and pycore.is_python_file(resource): + try: + new_contents = resource.read() + # detecting changes in new_contents relative to old_contents + detector = _TextChangeDetector(new_contents, old_contents) + + def search_subscopes(pydefined): + scope = pydefined.get_scope() + return detector.is_changed(scope.get_start(), scope.get_end()) + + def should_analyze(pydefined): + scope = pydefined.get_scope() + start = scope.get_start() + end = scope.get_end() + return detector.consume_changes(start, end) + + pycore.analyze_module(resource, should_analyze, search_subscopes) + except exceptions.ModuleSyntaxError: + pass + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -11,8 +11,6 @@ + import os + import shutil + import subprocess +- +-import rope.base.utils.pycompat as pycompat + import typing + + +@language python + +class _TextChangeDetector: + @others + +def __init__(self, old, new): + self.old = old + self.new = new + self._set_diffs() + + +def _set_diffs(self): + differ = difflib.Differ() + self.lines = [] + lineno = 0 + for line in differ.compare( + self.old.splitlines(True), self.new.splitlines(True) + ): + if line.startswith(" "): + lineno += 1 + elif line.startswith("-"): + lineno += 1 + self.lines.append(lineno) + + +def is_changed(self, start, end): + """Tell whether any of start till end lines have changed + + The end points are inclusive and indices start from 1. + """ + left, right = self._get_changed(start, end) + return left < right + + +def consume_changes(self, start, end): + """Clear the changed status of lines from start till end""" + left, right = self._get_changed(start, end) + if left < right: + del self.lines[left:right] + return left < right + + +def _get_changed(self, start, end): + left = bisect.bisect_left(self.lines, start) + right = bisect.bisect_right(self.lines, end) + return left, right + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,3 @@ +-from rope.base.pynames import DefinedName + import rope.base.builtins + import rope.base.codeanalyze + import rope.base.evaluate +@@ -461,9 +460,7 @@ + pass + + def _For(self, node): +- names = self._update_evaluated( +- node.target, node.iter, ".__iter__().next()" # noqa +- ) ++ self._update_evaluated(node.target, node.iter, ".__iter__().next()") + for child in node.body + node.orelse: + ast.walk(child, self) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,3 @@ +-from rope.base.pynames import DefinedName + import rope.base.builtins + import rope.base.codeanalyze + import rope.base.evaluate +@language python + +from rope.base.pynames import DefinedName +import rope.base.builtins +import rope.base.codeanalyze +import rope.base.evaluate +import rope.base.libutils +import rope.base.oi.soi +import rope.base.pyscopes +from rope.base import ( + pynamesdef as pynames, + exceptions, + ast, + astutils, + pyobjects, + fscommands, + arguments, + utils, +) +from rope.base.utils import pycompat + + + +@path C:/Repos/ekr-rope/rope/base/ +"""Project file system commands. + +This modules implements file system operations used by rope. Different +version control systems can be supported by implementing the interface +provided by `FileSystemCommands` class. See `SubversionCommands` and +`MercurialCommands` for example. + +""" +import re +import os +import shutil +import subprocess + +import rope.base.utils.pycompat as pycompat +import typing + + +FileContent = typing.NewType("FileContent", bytes) + + +@others +@language python +@tabwidth -4 + +import rope.base.builtins +import rope.base.codeanalyze +import rope.base.evaluate +import rope.base.libutils +import rope.base.oi.soi +import rope.base.pyscopes +from rope.base import ( + pynamesdef as pynames, + exceptions, + ast, + astutils, + pyobjects, + fscommands, + arguments, + utils, +) +from rope.base.utils import pycompat + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,5 @@ + def _For(self, node): +- names = self._update_evaluated( +- node.target, node.iter, ".__iter__().next()" # noqa +- ) ++ self._update_evaluated(node.target, node.iter, ".__iter__().next()") + for child in node.body + node.orelse: + ast.walk(child, self) + +@language python + +def _For(self, node): + names = self._update_evaluated( + node.target, node.iter, ".__iter__().next()" # noqa + ) + for child in node.body + node.orelse: + ast.walk(child, self) + + +def _For(self, node): + self._update_evaluated(node.target, node.iter, ".__iter__().next()") + for child in node.body + node.orelse: + ast.walk(child, self) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,6 @@ + from itertools import chain + + from rope.base import ast +-from rope.base.utils import pycompat + + + def find_visible(node, lines): +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,6 @@ + from itertools import chain + + from rope.base import ast +-from rope.base.utils import pycompat + + + @others +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +from itertools import chain + +from rope.base import ast +from rope.base.utils import pycompat + + +@others +@language python +@tabwidth -4 + +@path C:/Repos/ekr-rope/rope/refactor/ +from itertools import chain + +from rope.base import ast +from rope.base.utils import pycompat + + +@others +@language python +@tabwidth -4 + +def find_visible(node, lines): + """Return the line which is visible from all `lines`""" + root = ast_suite_tree(node) + return find_visible_for_suite(root, lines) + + + +@path C:/Repos/ekr-rope/rope/base/ +"""Project file system commands. + +This modules implements file system operations used by rope. Different +version control systems can be supported by implementing the interface +provided by `FileSystemCommands` class. See `SubversionCommands` and +`MercurialCommands` for example. + +""" +import re +import os +import shutil +import subprocess + +import rope.base.utils.pycompat as pycompat +import typing + + +FileContent = typing.NewType("FileContent", bytes) + + +@others +@language python +@tabwidth -4 + +def find_visible_for_suite(root, lines): + if len(lines) == 1: + return lines[0] + line1 = lines[0] + line2 = find_visible_for_suite(root, lines[1:]) + suite1 = root.find_suite(line1) + suite2 = root.find_suite(line2) + + @others + if valid(suite1) and not valid(suite2): + return line1 + if not valid(suite1) and valid(suite2): + return line2 + if not valid(suite1) and not valid(suite2): + return None + while suite1 != suite2 and suite1.parent != suite2.parent: + if suite1._get_level() < suite2._get_level(): + line2 = suite2.get_start() + suite2 = suite2.parent + elif suite1._get_level() > suite2._get_level(): + line1 = suite1.get_start() + suite1 = suite1.parent + else: + line1 = suite1.get_start() + line2 = suite2.get_start() + suite1 = suite1.parent + suite2 = suite2.parent + if suite1 == suite2: + return min(line1, line2) + return min(suite1.get_start(), suite2.get_start()) + + + +def valid(suite): + return suite is not None and not suite.ignored + + +def ast_suite_tree(node): + if hasattr(node, "lineno"): + lineno = node.lineno + else: + lineno = 1 + return Suite(node.body, lineno) + + + +class Suite: + @others + +def __init__(self, child_nodes, lineno, parent=None, ignored=False): + self.parent = parent + self.lineno = lineno + self.child_nodes = child_nodes + self._children = None + self.ignored = ignored + + +def get_start(self): + if self.parent is None: + if self.child_nodes: + return self.local_start() + else: + return 1 + return self.lineno + + +def get_children(self): + if self._children is None: + walker = _SuiteWalker(self) + for child in self.child_nodes: + ast.walk(child, walker) + self._children = walker.suites + return self._children + + +def local_start(self): + return self.child_nodes[0].lineno + + +def local_end(self): + end = self.child_nodes[-1].lineno + if self.get_children(): + end = max(end, self.get_children()[-1].local_end()) + return end + + +def find_suite(self, line): + if line is None: + return None + for child in self.get_children(): + if child.local_start() <= line <= child.local_end(): + return child.find_suite(line) + return self + + +def create_fscommands(root): + dirlist = os.listdir(root) + commands = { + ".hg": MercurialCommands, + ".svn": SubversionCommands, + ".git": GITCommands, + "_svn": SubversionCommands, + "_darcs": DarcsCommands, + } + for key in commands: + if key in dirlist: + try: + return commands[key](root) + except (ImportError, OSError): + pass + return FileSystemCommands() + + + +def _get_level(self): + if self.parent is None: + return 0 + return self.parent._get_level() + 1 + + + +class _SuiteWalker: + @others + +def __init__(self, suite): + self.suite = suite + self.suites = [] + + +def _If(self, node): + self._add_if_like_node(node) + + +def _For(self, node): + self._add_if_like_node(node) + + +def _While(self, node): + self._add_if_like_node(node) + + +def _With(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite)) + + +def _AsyncWith(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite)) + + +def _Match(self, node): + case_bodies = list( + chain.from_iterable([[case.pattern] + case.body for case in node.cases]) + ) + self.suites.append(Suite(case_bodies, node.lineno, self.suite)) + + +def _TryFinally(self, node): + proceed_to_except_handler = False + if len(node.finalbody) == 1: + try: + proceed_to_except_handler = isinstance( + node.handlers[0], ast.ExceptHandler + ) + except IndexError: + pass + if proceed_to_except_handler: + self._TryExcept(node) + else: + self.suites.append(Suite(node.body, node.lineno, self.suite)) + self.suites.append(Suite(node.finalbody, node.lineno, self.suite)) + + +class FileSystemCommands: + @others + +def _Try(self, node): + if len(node.finalbody) == 1: + self._TryFinally(node) + else: + self._TryExcept(node) + + +def _TryExcept(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite)) + for handler in node.handlers: + self.suites.append(Suite(handler.body, node.lineno, self.suite)) + if node.orelse: + self.suites.append(Suite(node.orelse, node.lineno, self.suite)) + + +def _add_if_like_node(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite)) + if node.orelse: + self.suites.append(Suite(node.orelse, node.lineno, self.suite)) + + +def _FunctionDef(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) + + +def _AsyncFunctionDef(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) + + +def _ClassDef(self, node): + self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,12 +1,9 @@ + from textwrap import dedent ++import unittest + + from rope.base.builtins import Str +- +-import unittest +- + import rope.base.libutils + import rope.base.oi +-from rope.base.utils import pycompat + from ropetest import testutils + + +@@ -1052,9 +1049,10 @@ + l = {} + v = l["key"] + """)) +- pymod1 = self.project.get_pymodule(mod1) # noqa +- var = pymod1["v"].get_object() # noqa +- ++ pymod1 = self.project.get_pymodule(mod1) ++ var = pymod1["v"].get_object() ++ self.assertTrue(pymod1 is not None) ++ self.assertTrue(var is not None) + def test_always_returning_containing_class_for_selfs(self): + code = dedent("""\ + class A(object): +@@ -1100,3 +1098,4 @@ + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + x_var = pymod["x"].pyobject.get() ++ self.assertTrue(x_var is not None) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,13 +1,10 @@ + @path C:/Repos/ekr-rope/ropetest/ + from textwrap import dedent ++import unittest + + from rope.base.builtins import Str +- +-import unittest +- + import rope.base.libutils + import rope.base.oi +-from rope.base.utils import pycompat + from ropetest import testutils + + +@language python + +def create_file(self, path): + open(path, "w").close() + + +@path C:/Repos/ekr-rope/ropetest/ +from textwrap import dedent + +from rope.base.builtins import Str + +import unittest + +import rope.base.libutils +import rope.base.oi +from rope.base.utils import pycompat +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +@path C:/Repos/ekr-rope/ropetest/ +from textwrap import dedent + +from rope.base.builtins import Str + +import unittest + +import rope.base.libutils +import rope.base.oi +from rope.base.utils import pycompat +from ropetest import testutils + + +@others +@language python +@tabwidth -4 + +class DynamicOITest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project(validate_objectdb=True) + self.pycore = self.project.pycore + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_simple_dti(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + return eval("arg") + a_var = a_func(a_func) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + self.assertEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) + + +def test_module_dti(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + code = dedent("""\ + import mod1 + def a_func(arg): + return eval("arg") + a_var = a_func(mod1) + """) + mod2.write(code) + self.pycore.run_module(mod2).wait_process() + pymod2 = self.project.get_pymodule(mod2) + self.assertEqual(self.project.get_pymodule(mod1), pymod2["a_var"].get_object()) + + +def test_class_from_another_module_dti(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + code1 = dedent("""\ + class AClass(object): + pass + """) + code2 = dedent("""\ + from mod1 import AClass + + def a_func(arg): + return eval("arg") + a_var = a_func(AClass) + """) + mod1.write(code1) + mod2.write(code2) + self.pycore.run_module(mod2).wait_process() + # pymod1 = self.project.get_pymodule(mod1) + pymod2 = self.project.get_pymodule(mod2) + self.assertEqual(pymod2["AClass"].get_object(), pymod2["a_var"].get_object()) + + +def test_class_dti(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class AClass(object): + pass + + def a_func(arg): + return eval("arg") + a_var = a_func(AClass) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + self.assertEqual(pymod["AClass"].get_object(), pymod["a_var"].get_object()) + + +def test_instance_dti(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class AClass(object): + pass + + def a_func(arg): + return eval("arg()") + a_var = a_func(AClass) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + self.assertEqual( + pymod["AClass"].get_object(), pymod["a_var"].get_object().get_type() + ) + + +def create_folder(self, path): + os.mkdir(path) + + +def test_method_dti(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class AClass(object): + def a_method(self, arg): + return eval("arg()") + an_instance = AClass() + a_var = an_instance.a_method(AClass) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + self.assertEqual( + pymod["AClass"].get_object(), pymod["a_var"].get_object().get_type() + ) + + +def test_function_argument_dti(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + pass + a_func(a_func) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pyscope = self.project.get_pymodule(mod).get_scope() + self.assertEqual( + pyscope["a_func"].get_object(), pyscope.get_scopes()[0]["arg"].get_object() + ) + + +def test_classes_with_the_same_name(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + class AClass(object): + pass + return eval("arg") + class AClass(object): + pass + a_var = a_func(AClass) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + self.assertEqual(pymod["AClass"].get_object(), pymod["a_var"].get_object()) + + +def test_nested_classes(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(): + class AClass(object): + pass + return AClass + def another_func(arg): + return eval("arg") + a_var = another_func(a_func()) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pyscope = self.project.get_pymodule(mod).get_scope() + self.assertEqual( + pyscope.get_scopes()[0]["AClass"].get_object(), + pyscope["a_var"].get_object(), + ) + + +def test_function_argument_dti2(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg, a_builtin_type): + pass + a_func(a_func, []) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pyscope = self.project.get_pymodule(mod).get_scope() + self.assertEqual( + pyscope["a_func"].get_object(), pyscope.get_scopes()[0]["arg"].get_object() + ) + + +def test_dti_and_concluded_data_invalidation(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + return eval("arg") + a_var = a_func(a_func) + """) + mod.write(code) + pymod = self.project.get_pymodule(mod) + pymod["a_var"].get_object() + self.pycore.run_module(mod).wait_process() + self.assertEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) + + +def test_list_objects_and_dynamicoi(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + pass + def a_func(arg): + return eval("arg") + a_var = a_func([C()])[0] + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_for_loops_and_dynamicoi(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + pass + def a_func(arg): + return eval("arg") + for c in a_func([C()]): + a_var = c + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_dict_objects_and_dynamicoi(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + pass + def a_func(arg): + return eval("arg") + a_var = a_func({1: C()})[1] + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_dict_keys_and_dynamicoi(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + pass + def a_func(arg): + return eval("arg") + a_var = list(a_func({C(): 1}))[0] + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def move(self, path, new_location): + shutil.move(path, new_location) + + +def test_dict_keys_and_dynamicoi2(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(arg): + return eval("arg") + a, b = a_func((C1(), C2())) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_strs_and_dynamicoi(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + return eval("arg") + a_var = a_func("hey") + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + a_var = pymod["a_var"].get_object() + self.assertTrue(isinstance(a_var.get_type(), rope.base.builtins.Str)) + + +def test_textual_transformations(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + pass + def f(): + pass + a_var = C() + a_list = [C()] + a_str = "hey" + a_file = open("file.txt") + """) + mod.write(code) + to_pyobject = rope.base.oi.transform.TextualToPyObject(self.project) + to_textual = rope.base.oi.transform.PyObjectToTextual(self.project) + pymod = self.project.get_pymodule(mod) + + def complex_to_textual(pyobject): + return to_textual.transform( + to_pyobject.transform(to_textual.transform(pyobject)) + ) + + test_variables = [ + ("C", ("defined", "mod.py", "C")), + ("f", ("defined", "mod.py", "f")), + ("a_var", ("instance", ("defined", "mod.py", "C"))), + ("a_list", ("builtin", "list", ("instance", ("defined", "mod.py", "C")))), + ("a_str", ("builtin", "str")), + ("a_file", ("builtin", "file")), + ] + test_cases = [(pymod[v].get_object(), r) for v, r in test_variables] + test_cases += [ + (pymod, ("defined", "mod.py")), + ( + rope.base.builtins.builtins["enumerate"].get_object(), + ("builtin", "function", "enumerate"), + ), + ] + for var, result in test_cases: + self.assertEqual(to_textual.transform(var), result) + self.assertEqual(complex_to_textual(var), result) + + +def test_arguments_with_keywords(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(arg): + return eval("arg") + a = a_func(arg=C1()) + b = a_func(arg=C2()) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_a_function_with_different_returns(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(arg): + return eval("arg") + a = a_func(C1()) + b = a_func(C2()) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_a_function_with_different_returns2(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(p): + if p == C1: + return C1() + else: + return C2() + a = a_func(C1) + b = a_func(C2) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_ignoring_star_args(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(p, *args): + if p == C1: + return C1() + else: + return C2() + a = a_func(C1, 1) + b = a_func(C2, 2) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_ignoring_double_star_args(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(p, *kwds, **args): + if p == C1: + return C1() + else: + return C2() + a = a_func(C1, kwd=1) + b = a_func(C2, kwd=2) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + pymod = self.project.get_pymodule(mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_invalidating_data_after_changing(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + def a_func(arg): + return eval("arg") + a_var = a_func(a_func) + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + mod.write(code.replace("a_func", "newfunc")) + mod.write(code) + pymod = self.project.get_pymodule(mod) + self.assertNotEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) + + +def test_invalidating_data_after_moving(self): + mod2 = testutils.create_module(self.project, "mod2") + mod2.write("class C(object):\n pass\n") + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + import mod2 + def a_func(arg): + return eval(arg) + a_var = a_func("mod2.C") + """) + mod.write(code) + self.pycore.run_module(mod).wait_process() + mod.move("newmod.py") + pymod = self.project.get_module("newmod") + pymod2 = self.project.get_pymodule(mod2) + self.assertEqual(pymod2["C"].get_object(), pymod["a_var"].get_object()) + + + +def remove(self, path): + if os.path.isfile(path): + os.remove(path) + else: + shutil.rmtree(path) + + +class NewStaticOITest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = testutils.sample_project(validate_objectdb=True) + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_static_oi_for_simple_function_calls(self): + code = dedent("""\ + class C(object): + pass + def f(p): + pass + f(C()) + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + f_scope = pymod["f"].get_object().get_scope() + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(c_class, p_type) + + +def test_static_oi_not_failing_when_callin_callables(self): + code = dedent("""\ + class C(object): + pass + C() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + + +def test_static_oi_for_nested_calls(self): + code = dedent("""\ + class C(object): + pass + def f(p): + pass + def g(p): + return p + f(g(C())) + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + f_scope = pymod["f"].get_object().get_scope() + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(c_class, p_type) + + +def test_static_oi_class_methods(self): + code = dedent("""\ + class C(object): + def f(self, p): + pass + C().f(C())""") + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + f_scope = c_class["f"].get_object().get_scope() + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(c_class, p_type) + + +def test_static_oi_preventing_soi_maximum_recursion_exceptions(self): + code = dedent("""\ + item = {} + for item in item.keys(): + pass + """) + self.mod.write(code) + try: + self.pycore.analyze_module(self.mod) + except RuntimeError as e: + self.fail(str(e)) + + +def test_static_oi_for_infer_return_typs_from_funcs_based_on_params(self): + code = dedent("""\ + class C(object): + pass + def func(p): + return p + a_var = func(C()) + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_a_function_with_different_returns(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + def a_func(arg): + return arg + a = a_func(C1()) + b = a_func(C2()) + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -927,7 +927,7 @@ + break + else: + self._skip_comment() +- except (ValueError, TypeError) as e: ++ except (ValueError, TypeError): + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) +@language python + +def write(self, path, data): + file_ = open(path, "wb") + try: + file_.write(data) + finally: + file_.close() + + +def test_not_reporting_out_of_date_information(self): + code = dedent("""\ + class C1(object): + pass + def f(arg): + return C1() + a_var = f() + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + + self.mod.write(code.replace("C1", "C2")) + pymod = self.project.get_pymodule(self.mod) + c2_class = pymod["C2"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c2_class, a_var.get_type()) + + +def test_invalidating_concluded_data_in_a_function(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write(dedent("""\ + def func(arg): + temp = arg + return temp + """)) + mod2.write(dedent("""\ + import mod1 + class C1(object): + pass + class C2(object): + pass + a_var = mod1.func(C1()) + """)) + pymod2 = self.project.get_pymodule(mod2) + c1_class = pymod2["C1"].get_object() + a_var = pymod2["a_var"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + + mod2.write(mod2.read()[: mod2.read().rfind("C1()")] + "C2())\n") + pymod2 = self.project.get_pymodule(mod2) + c2_class = pymod2["C2"].get_object() + a_var = pymod2["a_var"].get_object() + self.assertEqual(c2_class, a_var.get_type()) + + +def test_handling_generator_functions_for_strs(self): + self.mod.write(dedent("""\ + class C(object): + pass + def f(p): + yield p() + for c in f(C): + a_var = c + """)) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +# TODO: Returning a generator for functions that yield unknowns +@unittest.skip("Returning a generator that yields unknowns") +def xxx_test_handl_generator_functions_when_unknown_type_is_yielded(self): + self.mod.write(dedent("""\ + class C(object): + pass + def f(): + yield eval("C()") + a_var = f() + """)) + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["a_var"].get_object() + self.assertTrue(isinstance(a_var.get_type(), rope.base.builtins.Generator)) + + +def test_static_oi_for_lists_depending_on_append_function(self): + code = dedent("""\ + class C(object): + pass + l = list() + l.append(C()) + a_var = l.pop() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_static_oi_for_lists_per_object_for_get_item(self): + code = dedent("""\ + class C(object): + pass + l = list() + l.append(C()) + a_var = l[0] + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_static_oi_for_lists_per_object_for_fields(self): + code = dedent("""\ + class C(object): + pass + class A(object): + def __init__(self): + self.l = [] + def set(self): + self.l.append(C()) + a = A() + a.set() + a_var = a.l[0] + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_static_oi_for_lists_per_object_for_set_item(self): + code = dedent("""\ + class C(object): + pass + l = [None] + l[0] = C() + a_var = l[0] + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_static_oi_for_lists_per_object_for_extending_lists(self): + code = dedent("""\ + class C(object): + pass + l = [] + l.append(C()) + l2 = [] + l2.extend(l) + a_var = l2[0] + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_static_oi_for_lists_per_object_for_iters(self): + code = dedent("""\ + class C(object): + pass + l = [] + l.append(C()) + for c in l: + a_var = c + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def read(self, path): + with open(path, "rb") as handle: + return handle.read() + + + +def test_static_oi_for_dicts_depending_on_append_function(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {} + d[C1()] = C2() + a, b = d.popitem() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_static_oi_for_dicts_depending_on_for_loops(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {} + d[C1()] = C2() + for k, v in d.items(): + a = k + b = v + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_static_oi_for_dicts_depending_on_update(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {} + d[C1()] = C2() + d2 = {} + d2.update(d) + a, b = d2.popitem() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_static_oi_for_dicts_depending_on_update_on_seqs(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + pass + d = {} + d.update([(C1(), C2())]) + a, b = d.popitem() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + c2_class = pymod["C2"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertEqual(c2_class, b_var.get_type()) + + +def test_static_oi_for_sets_per_object_for_set_item(self): + code = dedent("""\ + class C(object): + pass + s = set() + s.add(C()) + a_var = s.pop() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c_class, a_var.get_type()) + + +def test_properties_and_calling_get_property(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + c1 = C1() + def get_c1(self): + return self.c1 + p = property(get_c1) + c2 = C2() + a_var = c2.p + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + + +def test_soi_on_constructors(self): + code = dedent("""\ + class C1(object): + pass + class C2(object): + def __init__(self, arg): + self.attr = arg + c2 = C2(C1()) + a_var = c2.attr""") + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a_var"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + + +def test_soi_on_literal_assignment(self): + code = 'a_var = ""' + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["a_var"].get_object() + self.assertEqual(Str, type(a_var.get_type())) + + +@testutils.only_for_versions_higher("3.6") +def test_soi_on_typed_assignment(self): + code = "a_var: str" + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + a_var = pymod["a_var"].get_object() + self.assertEqual(Str, type(a_var.get_type())) + + +def test_not_saving_unknown_function_returns(self): + mod2 = testutils.create_module(self.project, "mod2") + self.mod.write(dedent("""\ + class C(object): + pass + l = [] + l.append(C()) + """)) + mod2.write(dedent("""\ + import mod + def f(): + return mod.l.pop() + a_var = f() + """)) + pymod = self.project.get_pymodule(self.mod) + pymod2 = self.project.get_pymodule(mod2) + c_class = pymod["C"].get_object() + a_var = pymod2["a_var"] + + self.pycore.analyze_module(mod2) + self.assertNotEqual(c_class, a_var.get_object().get_type()) + + self.pycore.analyze_module(self.mod) + self.assertEqual(c_class, a_var.get_object().get_type()) + + +class SubversionCommands: + @others + +def test_using_the_best_callinfo(self): + code = dedent("""\ + class C1(object): + pass + def f(arg1, arg2, arg3): + pass + f("", None, C1()) + f("", C1(), None) + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + f_scope = pymod["f"].get_object().get_scope() + arg2 = f_scope["arg2"].get_object() + self.assertEqual(c1_class, arg2.get_type()) + + +def test_call_function_and_parameters(self): + code = dedent("""\ + class A(object): + def __call__(self, p): + pass + A()("") + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + scope = self.project.get_pymodule(self.mod).get_scope() + p_object = scope.get_scopes()[0].get_scopes()[0]["p"].get_object() + self.assertTrue(isinstance(p_object.get_type(), rope.base.builtins.Str)) + + +def test_report_change_in_libutils(self): + self.project.prefs["automatic_soa"] = True + code = dedent("""\ + class C(object): + pass + def f(p): + pass + f(C()) + """) + with open(self.mod.real_path, "w") as mod_file: + mod_file.write(code) + + rope.base.libutils.report_change(self.project, self.mod.real_path, "") + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + f_scope = pymod["f"].get_object().get_scope() + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(c_class, p_type) + + +def test_report_libutils_and_analyze_all_modules(self): + code = dedent("""\ + class C(object): + pass + def f(p): + pass + f(C()) + """) + self.mod.write(code) + rope.base.libutils.analyze_modules(self.project) + pymod = self.project.get_pymodule(self.mod) + c_class = pymod["C"].get_object() + f_scope = pymod["f"].get_object().get_scope() + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(c_class, p_type) + + +def test_validation_problems_for_objectdb_retrievals(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write(dedent("""\ + l = [] + var = l.pop() + """)) + mod2.write(dedent("""\ + import mod1 + + class C(object): + pass + mod1.l.append(C()) + """)) + self.pycore.analyze_module(mod2) + + pymod2 = self.project.get_pymodule(mod2) + c_class = pymod2["C"].get_object() + pymod1 = self.project.get_pymodule(mod1) + var_pyname = pymod1["var"] + self.assertEqual(c_class, var_pyname.get_object().get_type()) + mod2.write(dedent("""\ + import mod1 + + mod1.l.append("") + """)) + self.assertNotEqual( + c_class, var_pyname.get_object().get_type(), "Class `C` no more exists" + ) + + +def test_always_returning_containing_class_for_selfs(self): + code = dedent("""\ + class A(object): + def f(p): + return p + class B(object): + pass + b = B() + b.f() + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod) + pymod = self.project.get_pymodule(self.mod) + a_class = pymod["A"].get_object() + f_scope = a_class.get_scope().get_scopes()[0] + p_type = f_scope["p"].get_object().get_type() + self.assertEqual(a_class, p_type) + + +def test_following_function_calls_when_asked_to(self): + code = dedent("""\ + class A(object): + pass + class C(object): + def __init__(self, arg): + self.attr = arg + def f(p): + return C(p) + c = f(A()) + x = c.attr + """) + self.mod.write(code) + self.pycore.analyze_module(self.mod, followed_calls=1) + pymod = self.project.get_pymodule(self.mod) + a_class = pymod["A"].get_object() + x_var = pymod["x"].get_object().get_type() + self.assertEqual(a_class, x_var) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -10,6 +10,7 @@ + l = {} + v = l["key"] + """)) +- pymod1 = self.project.get_pymodule(mod1) # noqa +- var = pymod1["v"].get_object() # noqa +- ++ pymod1 = self.project.get_pymodule(mod1) ++ var = pymod1["v"].get_object() ++ self.assertTrue(pymod1 is not None) ++ self.assertTrue(var is not None) +@language python + +def __init__(self, *args): + self.normal_actions = FileSystemCommands() + import pysvn + + self.client = pysvn.Client() + + +def test_validation_problems_for_changing_builtin_types(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + l = [] + l.append("") + """)) + self.pycore.analyze_module(mod1) + + mod1.write(dedent("""\ + l = {} + v = l["key"] + """)) + pymod1 = self.project.get_pymodule(mod1) # noqa + var = pymod1["v"].get_object() # noqa + + +def test_validation_problems_for_changing_builtin_types(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write(dedent("""\ + l = [] + l.append("") + """)) + self.pycore.analyze_module(mod1) + + mod1.write(dedent("""\ + l = {} + v = l["key"] + """)) + pymod1 = self.project.get_pymodule(mod1) # noqa + var = pymod1["v"].get_object() # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,3 +6,4 @@ + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + x_var = pymod["x"].pyobject.get() ++ self.assertTrue(x_var is not None) +@language python + +def test_set_comprehension(self): + code = dedent("""\ + x = {s.strip() for s in X()} + x.add('x') + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + x_var = pymod["x"].pyobject.get() + +def test_set_comprehension(self): + code = dedent("""\ + x = {s.strip() for s in X()} + x.add('x') + """) + self.mod.write(code) + pymod = self.project.get_pymodule(self.mod) + x_var = pymod["x"].pyobject.get() + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,6 +2,7 @@ + from .pickle import AutoImport as _PickleAutoImport + from .sqlite import AutoImport as _SqliteAutoImport + ++assert _SqliteAutoImport # Workaround for an apparent pyflakes bug. + + AutoImport = _PickleAutoImport +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -3,6 +3,7 @@ + from .pickle import AutoImport as _PickleAutoImport + from .sqlite import AutoImport as _SqliteAutoImport + ++assert _SqliteAutoImport # Workaround for an apparent pyflakes bug. + + AutoImport = _PickleAutoImport + +@language python + +@path C:/Repos/ekr-rope/rope/ +"""AutoImport module for rope.""" +from .pickle import AutoImport as _PickleAutoImport +from .sqlite import AutoImport as _SqliteAutoImport + + +AutoImport = _PickleAutoImport + +__all__ = ["AutoImport"] +@language python +@tabwidth -4 + +def create_file(self, path): + self.normal_actions.create_file(path) + self.client.add(path, force=True) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -45,8 +45,11 @@ + monitoring the progress of refactorings. + + """ +-from rope.refactor.importutils import ImportOrganizer # noqa +-from rope.refactor.topackage import ModuleToPackage # noqa ++from rope.refactor.importutils import ImportOrganizer # essential. ++from rope.refactor.topackage import ModuleToPackage # essential. ++ ++assert ImportOrganizer ++assert ModuleToPackage + + + __all__ = [ +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -46,8 +46,11 @@ + monitoring the progress of refactorings. + + """ +-from rope.refactor.importutils import ImportOrganizer # noqa +-from rope.refactor.topackage import ModuleToPackage # noqa ++from rope.refactor.importutils import ImportOrganizer # essential. ++from rope.refactor.topackage import ModuleToPackage # essential. ++ ++assert ImportOrganizer ++assert ModuleToPackage + + + __all__ = [ +@language python + +@path C:/Repos/ekr-rope/rope/ +"""rope refactor package + +This package contains modules that perform python refactorings. +Refactoring classes perform refactorings in 4 steps: + +1. Collect some data for performing the refactoring and use them + to construct a refactoring class. Like:: + + renamer = Rename(project, resource, offset) + +2. Some refactorings give you useful information about the + refactoring after their construction. Like:: + + print(renamer.get_old_name()) + +3. Give the refactoring class more information about how to + perform the refactoring and get the changes this refactoring is + going to make. This is done by calling `get_changes` method of the + refactoring class. Like:: + + changes = renamer.get_changes(new_name) + +4. You can commit the changes. Like:: + + project.do(changes) + +These steps are like the steps IDEs usually do for performing a +refactoring. These are the things an IDE does in each step: + +1. Construct a refactoring object by giving it information like + resource, offset and ... . Some of the refactoring problems (like + performing rename refactoring on language keywords) can be reported + here. +2. Print some information about the refactoring and ask the user + about the information that are necessary for completing the + refactoring (like new name). +3. Call the `get_changes` by passing it information asked from + the user (if necessary) and get and preview the changes returned by + it. +4. perform the refactoring. + +From ``0.5m5`` release the `get_changes()` method of some time- +consuming refactorings take an optional `rope.base.taskhandle. +TaskHandle` parameter. You can use this object for stopping or +monitoring the progress of refactorings. + +""" +from rope.refactor.importutils import ImportOrganizer # noqa +from rope.refactor.topackage import ModuleToPackage # noqa + + +__all__ = [ + "rename", + "move", + "inline", + "extract", + "restructure", + "topackage", + "importutils", + "usefunction", + "change_signature", + "encapsulate_field", + "introduce_factory", + "introduce_parameter", + "localtofield", + "method_object", + "multiproject", +] +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -22,7 +22,6 @@ + import rope.base.exceptions + import rope.refactor.functionutils + from rope.base import ( +- ast, + pynames, + pyobjects, + codeanalyze, +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -23,7 +23,6 @@ + import rope.base.exceptions + import rope.refactor.functionutils + from rope.base import ( +- ast, + pynames, + pyobjects, + codeanalyze, +@language python + +@path C:/Repos/ekr-rope/rope/refactor/ +# Known Bugs when inlining a function/method +# The values passed to function are inlined using _inlined_variable. +# This may cause two problems, illustrated in the examples below +# +# def foo(var1): +# var1 = var1*10 +# return var1 +# +# If a call to foo(20) is inlined, the result of inlined function is 20, +# but it should be 200. +# +# def foo(var1): +# var2 = var1*10 +# return var2 +# +# 2- If a call to foo(10+10) is inlined the result of inlined function is 110 +# but it should be 200. + +import re +from typing import List + +import rope.base.exceptions +import rope.refactor.functionutils +from rope.base import ( + ast, + pynames, + pyobjects, + codeanalyze, + taskhandle, + evaluate, + worder, + utils, + libutils, +) +from rope.base.change import ChangeSet, ChangeContents +from rope.refactor import ( + occurrences, + rename, + sourceutils, + importutils, + move, + change_signature, +) + + +@others +@language python +@tabwidth -4 + +def create_folder(self, path): + self.normal_actions.create_folder(path) + self.client.add(path, force=True) + + +@path C:/Repos/ekr-rope/rope/refactor/ +# Known Bugs when inlining a function/method +# The values passed to function are inlined using _inlined_variable. +# This may cause two problems, illustrated in the examples below +# +# def foo(var1): +# var1 = var1*10 +# return var1 +# +# If a call to foo(20) is inlined, the result of inlined function is 20, +# but it should be 200. +# +# def foo(var1): +# var2 = var1*10 +# return var2 +# +# 2- If a call to foo(10+10) is inlined the result of inlined function is 110 +# but it should be 200. + +import re +from typing import List + +import rope.base.exceptions +import rope.refactor.functionutils +from rope.base import ( + ast, + pynames, + pyobjects, + codeanalyze, + taskhandle, + evaluate, + worder, + utils, + libutils, +) +from rope.base.change import ChangeSet, ChangeContents +from rope.refactor import ( + occurrences, + rename, + sourceutils, + importutils, + move, + change_signature, +) + + +@others +@language python +@tabwidth -4 + +def unique_prefix(): + n = 0 + while True: + yield "__" + str(n) + "__" + n += 1 + + + +def create_inline(project, resource, offset): + """Create a refactoring object for inlining + + Based on `resource` and `offset` it returns an instance of + `InlineMethod`, `InlineVariable` or `InlineParameter`. + + """ + pyname = _get_pyname(project, resource, offset) + message = ( + "Inline refactoring should be performed on " + "a method, local variable or parameter." + ) + if pyname is None: + raise rope.base.exceptions.RefactoringError(message) + if isinstance(pyname, pynames.ImportedName): + pyname = pyname._get_imported_pyname() + if isinstance(pyname, pynames.AssignedName): + return InlineVariable(project, resource, offset) + if isinstance(pyname, pynames.ParameterName): + return InlineParameter(project, resource, offset) + if isinstance(pyname.get_object(), pyobjects.PyFunction): + return InlineMethod(project, resource, offset) + else: + raise rope.base.exceptions.RefactoringError(message) + + + +class _Inliner: + @others + +def __init__(self, project, resource, offset): + self.project = project + self.pyname = _get_pyname(project, resource, offset) + range_finder = worder.Worder(resource.read(), True) + self.region = range_finder.get_primary_range(offset) + self.name = range_finder.get_word_at(offset) + self.offset = offset + self.original = resource + + +def get_changes(self, *args, **kwds): + pass + + +def get_kind(self): + """Return either 'variable', 'method' or 'parameter'""" + + + +class InlineMethod(_Inliner): + @others + +def __init__(self, *args, **kwds): + super().__init__(*args, **kwds) + self.pyfunction = self.pyname.get_object() + self.pymodule = self.pyfunction.get_module() + self.resource = self.pyfunction.get_module().get_resource() + self.occurrence_finder = occurrences.create_finder( + self.project, self.name, self.pyname + ) + self.normal_generator = _DefinitionGenerator(self.project, self.pyfunction) + self._init_imports() + + +def _init_imports(self): + body = sourceutils.get_body(self.pyfunction) + body, imports = move.moving_code_with_imports(self.project, self.resource, body) + self.imports = imports + self.others_generator = _DefinitionGenerator( + self.project, self.pyfunction, body=body + ) + + +def move(self, path, new_location): + self.client.move(path, new_location, force=True) + + +def _get_scope_range(self): + scope = self.pyfunction.get_scope() + lines = self.pymodule.lines + start_line = scope.get_start() + if self.pyfunction.decorators: + decorators = self.pyfunction.decorators + if hasattr(decorators[0], "lineno"): + start_line = decorators[0].lineno + start_offset = lines.get_line_start(start_line) + end_offset = min( + lines.get_line_end(scope.end) + 1, len(self.pymodule.source_code) + ) + return (start_offset, end_offset) + + +def get_changes( + self, + remove=True, + only_current=False, + resources=None, + task_handle=taskhandle.NullTaskHandle(), +): + """Get the changes this refactoring makes + + If `remove` is `False` the definition will not be removed. If + `only_current` is `True`, the the current occurrence will be + inlined, only. + """ + changes = ChangeSet("Inline method <%s>" % self.name) + if resources is None: + resources = self.project.get_python_files() + if only_current: + resources = [self.original] + if remove: + resources.append(self.resource) + job_set = task_handle.create_jobset("Collecting Changes", len(resources)) + for file in resources: + job_set.started_job(file.path) + if file == self.resource: + changes.add_change( + self._defining_file_changes( + changes, remove=remove, only_current=only_current + ) + ) + else: + aim = None + if only_current and self.original == file: + aim = self.offset + handle = _InlineFunctionCallsForModuleHandle( + self.project, file, self.others_generator, aim + ) + result = move.ModuleSkipRenamer( + self.occurrence_finder, file, handle + ).get_changed_module() + if result is not None: + result = _add_imports(self.project, result, file, self.imports) + if remove: + result = _remove_from(self.project, self.pyname, result, file) + changes.add_change(ChangeContents(file, result)) + job_set.finished_job() + return changes + + +def _get_removed_range(self): + scope = self.pyfunction.get_scope() + lines = self.pymodule.lines + start, end = self._get_scope_range() + end_line = scope.get_end() + for i in range(end_line + 1, lines.length()): + if lines.get_line(i).strip() == "": + end_line = i + else: + break + end = min(lines.get_line_end(end_line) + 1, len(self.pymodule.source_code)) + return (start, end) + + +def _defining_file_changes(self, changes, remove, only_current): + start_offset, end_offset = self._get_removed_range() + aim = None + if only_current: + if self.resource == self.original: + aim = self.offset + else: + # we don't want to change any of them + aim = len(self.resource.read()) + 100 + handle = _InlineFunctionCallsForModuleHandle( + self.project, self.resource, self.normal_generator, aim_offset=aim + ) + replacement = None + if remove: + replacement = self._get_method_replacement() + result = move.ModuleSkipRenamer( + self.occurrence_finder, + self.resource, + handle, + start_offset, + end_offset, + replacement, + ).get_changed_module() + return ChangeContents(self.resource, result) + + +def _get_method_replacement(self): + if self._is_the_last_method_of_a_class(): + indents = sourceutils.get_indents( + self.pymodule.lines, self.pyfunction.get_scope().get_start() + ) + return " " * indents + "pass\n" + return "" + + +def _is_the_last_method_of_a_class(self): + pyclass = self.pyfunction.parent + if not isinstance(pyclass, pyobjects.PyClass): + return False + class_start, class_end = sourceutils.get_body_region(pyclass) + source = self.pymodule.source_code + func_start, func_end = self._get_scope_range() + return ( + source[class_start:func_start].strip() == "" + and source[func_end:class_end].strip() == "" + ) + + +def get_kind(self): + return "method" + + + +class InlineVariable(_Inliner): + @others + +def __init__(self, *args, **kwds): + super().__init__(*args, **kwds) + self.pymodule = self.pyname.get_definition_location()[0] + self.resource = self.pymodule.get_resource() + self._check_exceptional_conditions() + self._init_imports() + + +def _check_exceptional_conditions(self): + if len(self.pyname.assignments) != 1: + raise rope.base.exceptions.RefactoringError( + "Local variable should be assigned once for inlining." + ) + + +def remove(self, path): + self.client.remove(path, force=True) + + +def get_changes( + self, + remove=True, + only_current=False, + resources=None, + docs=False, + task_handle=taskhandle.NullTaskHandle(), +): + if resources is None: + if rename._is_local(self.pyname): + resources = [self.resource] + else: + resources = self.project.get_python_files() + if only_current: + resources = [self.original] + if remove and self.original != self.resource: + resources.append(self.resource) + changes = ChangeSet("Inline variable <%s>" % self.name) + jobset = task_handle.create_jobset("Calculating changes", len(resources)) + + for resource in resources: + jobset.started_job(resource.path) + if resource == self.resource: + source = self._change_main_module(remove, only_current, docs) + changes.add_change(ChangeContents(self.resource, source)) + else: + result = self._change_module(resource, remove, only_current) + if result is not None: + result = _add_imports(self.project, result, resource, self.imports) + changes.add_change(ChangeContents(resource, result)) + jobset.finished_job() + return changes + + +def _change_main_module(self, remove, only_current, docs): + region = None + if only_current and self.original == self.resource: + region = self.region + return _inline_variable( + self.project, + self.pymodule, + self.pyname, + self.name, + remove=remove, + region=region, + docs=docs, + ) + + +def _init_imports(self): + vardef = _getvardef(self.pymodule, self.pyname) + self.imported, self.imports = move.moving_code_with_imports( + self.project, self.resource, vardef + ) + + +def _change_module(self, resource, remove, only_current): + filters = [occurrences.NoImportsFilter(), occurrences.PyNameFilter(self.pyname)] + if only_current and resource == self.original: + + @others + filters.insert(0, check_aim) + finder = occurrences.Finder(self.project, self.name, filters=filters) + changed = rename.rename_in_module( + finder, self.imported, resource=resource, replace_primary=True + ) + if changed and remove: + changed = _remove_from(self.project, self.pyname, changed, resource) + return changed + + +def check_aim(occurrence): + start, end = occurrence.get_primary_range() + if self.offset < start or end < self.offset: + return False + + +def get_kind(self): + return "variable" + + + +class InlineParameter(_Inliner): + @others + +def __init__(self, *args, **kwds): + super().__init__(*args, **kwds) + resource, offset = self._function_location() + index = self.pyname.index + self.changers = [change_signature.ArgumentDefaultInliner(index)] + self.signature = change_signature.ChangeSignature( + self.project, resource, offset + ) + + +def _function_location(self): + pymodule, lineno = self.pyname.get_definition_location() + resource = pymodule.get_resource() + start = pymodule.lines.get_line_start(lineno) + word_finder = worder.Worder(pymodule.source_code) + offset = word_finder.find_function_offset(start) + return resource, offset + + +def get_changes(self, **kwds): + """Get the changes needed by this refactoring + + See `rope.refactor.change_signature.ChangeSignature.get_changes()` + for arguments. + """ + return self.signature.get_changes(self.changers, **kwds) + + +def write(self, path, data): + self.normal_actions.write(path, data) + + +def get_kind(self): + return "parameter" + + + +def _join_lines(lines: List[str]) -> str: + return "\n".join(lines) + + +class _ComplexExpressionVisitor: + def __init__(self): + self.is_complex_expression = False + + def _Set(self, node): + self.is_complex_expression = True + + def _List(self, node): + self.is_complex_expression = True + + def _Tuple(self, node): + self.is_complex_expression = True + + def _Dict(self, node): + self.is_complex_expression = True + + + +class _DefinitionGenerator: + unique_prefix = unique_prefix() + + @others + +def __init__(self, project, pyfunction, body=None): + self.project = project + self.pyfunction = pyfunction + self.pymodule = pyfunction.get_module() + self.resource = self.pymodule.get_resource() + self.definition_info = self._get_definition_info() + self.definition_params = self._get_definition_params() + self._calculated_definitions = {} + if body is not None: + self.body = body + else: + self.body = sourceutils.get_body(self.pyfunction) + + +def _get_definition_info(self): + return rope.refactor.functionutils.DefinitionInfo.read(self.pyfunction) + + +def _get_definition_params(self): + definition_info = self.definition_info + paramdict = dict([pair for pair in definition_info.args_with_defaults]) + if ( + definition_info.args_arg is not None + or definition_info.keywords_arg is not None + ): + raise rope.base.exceptions.RefactoringError( + "Cannot inline functions with list and keyword arguements." + ) + if self.pyfunction.get_kind() == "classmethod": + paramdict[ + definition_info.args_with_defaults[0][0] + ] = self.pyfunction.parent.get_name() + return paramdict + + +def get_function_name(self): + return self.pyfunction.get_name() + + +def get_definition(self, primary, pyname, call, host_vars=[], returns=False): + # caching already calculated definitions + return self._calculate_definition(primary, pyname, call, host_vars, returns) + + +def _calculate_header(self, primary, pyname, call): + # A header is created which initializes parameters + # to the values passed to the function. + call_info = rope.refactor.functionutils.CallInfo.read( + primary, pyname, self.definition_info, call + ) + paramdict = self.definition_params + mapping = rope.refactor.functionutils.ArgumentMapping( + self.definition_info, call_info + ) + for param_name, value in mapping.param_dict.items(): + paramdict[param_name] = value + header = "" + to_be_inlined = [] + for name, value in paramdict.items(): + if name != value and value is not None: + header += name + " = " + value.replace("\n", " ") + "\n" + to_be_inlined.append(name) + return header, to_be_inlined + + +def _calculate_definition(self, primary, pyname, call, host_vars, returns): + + header, to_be_inlined = self._calculate_header(primary, pyname, call) + + source = header + self.body + mod = libutils.get_string_module(self.project, source) + name_dict = mod.get_scope().get_names() + all_names = [ + x + for x in name_dict + if not isinstance(name_dict[x], rope.base.builtins.BuiltinName) + ] + + # If there is a name conflict, all variable names + # inside the inlined function are renamed + if len(set(all_names).intersection(set(host_vars))) > 0: + + prefix = next(_DefinitionGenerator.unique_prefix) + guest = libutils.get_string_module(self.project, source, self.resource) + + to_be_inlined = [prefix + item for item in to_be_inlined] + for item in all_names: + pyname = guest[item] + occurrence_finder = occurrences.create_finder( + self.project, item, pyname + ) + source = rename.rename_in_module( + occurrence_finder, prefix + item, pymodule=guest + ) + guest = libutils.get_string_module(self.project, source, self.resource) + + # parameters not reassigned inside the functions are now inlined. + for name in to_be_inlined: + pymodule = libutils.get_string_module(self.project, source, self.resource) + pyname = pymodule[name] + source = _inline_variable(self.project, pymodule, pyname, name) + + return self._replace_returns_with(source, returns) + + +def read(self, path): + return self.normal_actions.read(path) + + + +def _replace_returns_with(self, source, returns): + result = [] + returned = None + last_changed = 0 + for match in _DefinitionGenerator._get_return_pattern().finditer(source): + for key, value in match.groupdict().items(): + if value and key == "return": + result.append(source[last_changed : match.start("return")]) + if returns: + self._check_nothing_after_return(source, match.end("return")) + beg_idx = match.end("return") + returned = _join_lines( + source[beg_idx : len(source)].lstrip().splitlines(), + ) + last_changed = len(source) + else: + current = match.end("return") + while current < len(source) and source[current] in " \t": + current += 1 + last_changed = current + if current == len(source) or source[current] == "\n": + result.append("pass") + result.append(source[last_changed:]) + return "".join(result), returned + + +def _check_nothing_after_return(self, source, offset): + lines = codeanalyze.SourceLinesAdapter(source) + lineno = lines.get_line_number(offset) + logical_lines = codeanalyze.LogicalLineFinder(lines) + lineno = logical_lines.logical_line_in(lineno)[1] + if source[lines.get_line_end(lineno) : len(source)].strip() != "": + raise rope.base.exceptions.RefactoringError( + "Cannot inline functions with statements " + "after return statement." + ) + + +@classmethod +def _get_return_pattern(cls): + if not hasattr(cls, "_return_pattern"): + + @others + comment_pattern = named_pattern("comment", [r"#[^\n]*"]) + string_pattern = named_pattern("string", [codeanalyze.get_string_pattern()]) + return_pattern = r"\b(?P<return>return)\b" + cls._return_pattern = re.compile( + comment_pattern + "|" + string_pattern + "|" + return_pattern + ) + return cls._return_pattern + + + +def named_pattern(name, list_): + return "(?P<%s>" % name + "|".join(list_) + ")" + + +class _InlineFunctionCallsForModuleHandle: + @others + +def __init__(self, project, resource, definition_generator, aim_offset=None): + """Inlines occurrences + + If `aim` is not `None` only the occurrences that intersect + `aim` offset will be inlined. + + """ + self.project = project + self.generator = definition_generator + self.resource = resource + self.aim = aim_offset + + +def occurred_inside_skip(self, change_collector, occurrence): + if not occurrence.is_defined(): + raise rope.base.exceptions.RefactoringError( + "Cannot inline functions that reference themselves" + ) + + +def occurred_outside_skip(self, change_collector, occurrence): + start, end = occurrence.get_primary_range() + # we remove out of date imports later + if occurrence.is_in_import_statement(): + return + # the function is referenced outside an import statement + if not occurrence.is_called(): + raise rope.base.exceptions.RefactoringError( + "Reference to inlining function other than function call" + " in <file: %s, offset: %d>" % (self.resource.path, start) + ) + if self.aim is not None and (self.aim < start or self.aim > end): + return + end_parens = self._find_end_parens(self.source, end - 1) + lineno = self.lines.get_line_number(start) + start_line, end_line = self.pymodule.logical_lines.logical_line_in(lineno) + line_start = self.lines.get_line_start(start_line) + line_end = self.lines.get_line_end(end_line) + + returns = ( + self.source[line_start:start].strip() != "" + or self.source[end_parens:line_end].strip() != "" + ) + indents = sourceutils.get_indents(self.lines, start_line) + primary, pyname = occurrence.get_primary_and_pyname() + + host = self.pymodule + scope = host.scope.get_inner_scope_for_line(lineno) + definition, returned = self.generator.get_definition( + primary, + pyname, + self.source[start:end_parens], + scope.get_names(), + returns=returns, + ) + + end = min(line_end + 1, len(self.source)) + change_collector.add_change( + line_start, end, sourceutils.fix_indentation(definition, indents) + ) + if returns: + name = returned + if name is None: + name = "None" + change_collector.add_change( + line_end, + end, + self.source[line_start:start] + name + self.source[end_parens:end], + ) + + +def _find_end_parens(self, source, offset): + finder = worder.Worder(source) + return finder.get_word_parens_range(offset)[1] + + +@property +@utils.saveit +def pymodule(self): + return self.project.get_pymodule(self.resource) + + + +class MercurialCommands: + @others + +@property +@utils.saveit +def source(self): + if self.resource is not None: + return self.resource.read() + else: + return self.pymodule.source_code + + +@property +@utils.saveit +def lines(self): + return self.pymodule.lines + + + +def _inline_variable( + project, pymodule, pyname, name, remove=True, region=None, docs=False +): + definition = _getvardef(pymodule, pyname) + start, end = _assigned_lineno(pymodule, pyname) + + occurrence_finder = occurrences.create_finder(project, name, pyname, docs=docs) + changed_source = rename.rename_in_module( + occurrence_finder, + definition, + pymodule=pymodule, + replace_primary=True, + writes=False, + region=region, + ) + if changed_source is None: + changed_source = pymodule.source_code + if remove: + lines = codeanalyze.SourceLinesAdapter(changed_source) + source = ( + changed_source[: lines.get_line_start(start)] + + changed_source[lines.get_line_end(end) + 1 :] + ) + else: + source = changed_source + return source + + + +def _getvardef(pymodule, pyname): + assignment = pyname.assignments[0] + lines = pymodule.lines + start, end = _assigned_lineno(pymodule, pyname) + definition_with_assignment = _join_lines( + [lines.get_line(n) for n in range(start, end + 1)], + ) + if assignment.levels: + raise rope.base.exceptions.RefactoringError("Cannot inline tuple assignments.") + definition = definition_with_assignment[ + definition_with_assignment.index("=") + 1 : + ].strip() + return definition + + + +def _assigned_lineno(pymodule, pyname): + definition_line = pyname.assignments[0].ast_node.lineno + return pymodule.logical_lines.logical_line_in(definition_line) + + + +def _add_imports(project, source, resource, imports): + if not imports: + return source + pymodule = libutils.get_string_module(project, source, resource) + module_import = importutils.get_module_imports(project, pymodule) + for import_info in imports: + module_import.add_import(import_info) + source = module_import.get_changed_source() + pymodule = libutils.get_string_module(project, source, resource) + import_tools = importutils.ImportTools(project) + return import_tools.organize_imports(pymodule, unused=False, sort=False) + + + +def _get_pyname(project, resource, offset): + pymodule = project.get_pymodule(resource) + pyname = evaluate.eval_location(pymodule, offset) + if isinstance(pyname, pynames.ImportedName): + pyname = pyname._get_imported_pyname() + return pyname + + + +def _remove_from(project, pyname, source, resource): + pymodule = libutils.get_string_module(project, source, resource) + module_import = importutils.get_module_imports(project, pymodule) + module_import.remove_pyname(pyname) + return module_import.get_changed_source() + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -485,8 +485,9 @@ + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a"].get_object() +- b_var = pymod["b"].get_object() # noqa ++ b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) ++ self.assertTrue(b_var is not None) + + def test_enumerate_builtin_function(self): + self.mod.write(dedent("""\ +@language python + + +def __init__(self, root): + self.hg = self._import_mercurial() + self.normal_actions = FileSystemCommands() + try: + self.ui = self.hg.ui.ui( + verbose=False, + debug=False, + quiet=True, + interactive=False, + traceback=False, + report_untrusted=False, + ) + except: + self.ui = self.hg.ui.ui() + self.ui.setconfig("ui", "interactive", "no") + self.ui.setconfig("ui", "debug", "no") + self.ui.setconfig("ui", "traceback", "no") + self.ui.setconfig("ui", "verbose", "no") + self.ui.setconfig("ui", "report_untrusted", "no") + self.ui.setconfig("ui", "quiet", "yes") + + self.repo = self.hg.hg.repository(self.ui, root) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -8,6 +8,7 @@ + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a"].get_object() +- b_var = pymod["b"].get_object() # noqa ++ b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) ++ self.assertTrue(b_var is not None) + +@language python + +def test_wrong_arguments_to_zip_function(self): + self.mod.write(dedent("""\ + class C1(object): + pass + c1_list = [C1()] + a, b = zip(c1_list, 1)[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() # noqa + self.assertEqual(c1_class, a_var.get_type()) + + +def test_wrong_arguments_to_zip_function(self): + self.mod.write(dedent("""\ + class C1(object): + pass + c1_list = [C1()] + a, b = zip(c1_list, 1)[0] + """)) + pymod = self.project.get_pymodule(self.mod) + c1_class = pymod["C1"].get_object() + a_var = pymod["a"].get_object() + b_var = pymod["b"].get_object() + self.assertEqual(c1_class, a_var.get_type()) + self.assertTrue(b_var is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -335,7 +335,8 @@ + + def test_getting_primary_and_strings_at_the_end_of_line(self): + code = "f('\\'')\n" +- result = self._find_primary(code, len(code) - 1) # noqa ++ result = self._find_primary(code, len(code) - 1) ++ self.assertTrue(result is not None) + + def test_getting_primary_and_not_crossing_newlines(self): + code = "\na = (b + c)\n(4 + 1).x\n" +@@ -753,7 +754,7 @@ + mod1 = testutils.create_module(self.project, "mod1") + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) +- mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa ++ mod2 = testutils.create_module(self.project, "mod2", pkg2) + mod1.write("import pkg1.pkg2.mod2") + + mod1_scope = self.project.get_pymodule(mod1).get_scope() +@@ -761,6 +762,7 @@ + pkg2_pyobject = self.project.get_pymodule(pkg2) + found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) + self.assertEqual(pkg2_pyobject, found_pyname.get_object()) ++ self.assertTrue(mod2 is not None) + + def test_get_pyname_at_on_language_keywords(self): + code = dedent("""\ +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,5 @@ + def test_getting_primary_and_strings_at_the_end_of_line(self): + code = "f('\\'')\n" +- result = self._find_primary(code, len(code) - 1) # noqa ++ result = self._find_primary(code, len(code) - 1) ++ self.assertTrue(result is not None) + +@language python + +def test_getting_primary_and_strings_at_the_end_of_line(self): + code = "f('\\'')\n" + result = self._find_primary(code, len(code) - 1) # noqa + + +def test_getting_primary_and_strings_at_the_end_of_line(self): + code = "f('\\'')\n" + result = self._find_primary(code, len(code) - 1) + self.assertTrue(result is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,7 @@ + mod1 = testutils.create_module(self.project, "mod1") + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) +- mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa ++ mod2 = testutils.create_module(self.project, "mod2", pkg2) + mod1.write("import pkg1.pkg2.mod2") + + mod1_scope = self.project.get_pymodule(mod1).get_scope() +@@ -10,4 +10,5 @@ + pkg2_pyobject = self.project.get_pymodule(pkg2) + found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) + self.assertEqual(pkg2_pyobject, found_pyname.get_object()) ++ self.assertTrue(mod2 is not None) + +@language python + +def test_relative_modules_after_from_statements2(self): + mod1 = testutils.create_module(self.project, "mod1") + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) + mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa + mod1.write("import pkg1.pkg2.mod2") + + mod1_scope = self.project.get_pymodule(mod1).get_scope() + name_finder = rope.base.evaluate.ScopeNameFinder(mod1_scope.pyobject) + pkg2_pyobject = self.project.get_pymodule(pkg2) + found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) + self.assertEqual(pkg2_pyobject, found_pyname.get_object()) + + +def _import_mercurial(self): + import mercurial.commands + import mercurial.hg + import mercurial.ui + + return mercurial + + +def test_relative_modules_after_from_statements2(self): + mod1 = testutils.create_module(self.project, "mod1") + pkg1 = testutils.create_package(self.project, "pkg1") + pkg2 = testutils.create_package(self.project, "pkg2", pkg1) + mod2 = testutils.create_module(self.project, "mod2", pkg2) + mod1.write("import pkg1.pkg2.mod2") + + mod1_scope = self.project.get_pymodule(mod1).get_scope() + name_finder = rope.base.evaluate.ScopeNameFinder(mod1_scope.pyobject) + pkg2_pyobject = self.project.get_pymodule(pkg2) + found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) + self.assertEqual(pkg2_pyobject, found_pyname.get_object()) + self.assertTrue(mod2 is not None) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,4 @@ + """Tests for autoimport utility functions, written in pytest""" +- +-from sys import platform +- +-import pytest + + from rope.contrib.autoimport import utils + from rope.contrib.autoimport.defs import Package, PackageType, Source +@@ -59,5 +55,5 @@ + def test_get_package_tuple_compiled(compiled_lib): + lib_name, lib_path = compiled_lib + assert Package( +- lib_name, Source.STANDARD, lib_path, PackageType.COMPILED ++ lib_name, Source.STANDARD, lib_path, PackageType.COMPILED + ) == utils.get_package_tuple(lib_path) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,5 @@ + @path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ + """Tests for autoimport utility functions, written in pytest""" +- +-from sys import platform +- +-import pytest + + from rope.contrib.autoimport import utils + from rope.contrib.autoimport.defs import Package, PackageType, Source +@language python + +@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ +"""Tests for autoimport utility functions, written in pytest""" + +from sys import platform + +import pytest + +from rope.contrib.autoimport import utils +from rope.contrib.autoimport.defs import Package, PackageType, Source + + +@others +@language python +@tabwidth -4 + +@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ +"""Tests for autoimport utility functions, written in pytest""" + +from sys import platform + +import pytest + +from rope.contrib.autoimport import utils +from rope.contrib.autoimport.defs import Package, PackageType, Source + + +@others +@language python +@tabwidth -4 + +def test_get_package_source(mod1_path, project): + assert utils.get_package_source(mod1_path, project, "") == Source.PROJECT + + + +def test_get_package_source_not_project(mod1_path): + assert utils.get_package_source(mod1_path, None, "") == Source.UNKNOWN + + + +def test_get_package_source_pytest(build_path): + # pytest is not installed as part of the standard library + # but should be installed into site_packages, + # so it should return Source.SITE_PACKAGE + assert utils.get_package_source(build_path, None, "build") == Source.SITE_PACKAGE + + + +def create_file(self, path): + self.normal_actions.create_file(path) + self.hg.commands.add(self.ui, self.repo, path) + + +def test_get_package_source_typing(typing_path): + + assert utils.get_package_source(typing_path, None, "typing") == Source.STANDARD + + + +def test_get_modname_project_no_add(mod1_path, project_path): + + assert utils.get_modname_from_path(mod1_path, project_path, False) == "mod1" + + + +def test_get_modname_single_file(typing_path): + + assert utils.get_modname_from_path(typing_path, typing_path) == "typing" + + + +def test_get_modname_folder(build_path, build_env_path): + + assert utils.get_modname_from_path(build_env_path, build_path) == "build.env" + + + +def test_get_package_tuple_sample(project_path): + assert Package( + "sample_project", Source.UNKNOWN, project_path, PackageType.STANDARD + ) == utils.get_package_tuple(project_path) + + + +def test_get_package_tuple_typing(typing_path): + + assert Package( + "typing", Source.STANDARD, typing_path, PackageType.SINGLE_FILE + ) == utils.get_package_tuple(typing_path) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def test_get_package_tuple_compiled(compiled_lib): + lib_name, lib_path = compiled_lib + assert Package( +- lib_name, Source.STANDARD, lib_path, PackageType.COMPILED ++ lib_name, Source.STANDARD, lib_path, PackageType.COMPILED + ) == utils.get_package_tuple(lib_path) +@language python + +def test_get_package_tuple_compiled(compiled_lib): + lib_name, lib_path = compiled_lib + assert Package( + lib_name, Source.STANDARD, lib_path, PackageType.COMPILED + ) == utils.get_package_tuple(lib_path) + +def test_get_package_tuple_compiled(compiled_lib): + lib_name, lib_path = compiled_lib + assert Package( + lib_name, Source.STANDARD, lib_path, PackageType.COMPILED + ) == utils.get_package_tuple(lib_path) + +def create_folder(self, path): + self.normal_actions.create_folder(path) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -718,7 +718,8 @@ + pass + my_""") + result = self._assist(code) +- proposals = sorted_proposals(result, typepref=["function"]) # noqa ++ proposals = sorted_proposals(result, typepref=["function"]) ++ self.assertTrue(proposals is not None) + + def test_get_pydoc_unicode(self): + src = dedent('''\ +@@ -824,7 +825,8 @@ + s = "hey" + s.replace() + """) +- doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa ++ doc = get_doc(self.project, src, src.rindex("replace") + 1) ++ self.assertTrue(doc is not None) + + def test_proposing_variables_defined_till_the_end_of_scope(self): + code = dedent("""\ +@@ -928,7 +930,8 @@ + except: + pass + """) +- result = self._assist(code, code.index("."), maxfixes=1) # noqa ++ result = self._assist(code, code.index("."), maxfixes=1) ++ self.assertTrue(result is not None) + + def test_nested_blocks(self): + code = dedent("""\ +@@ -951,7 +954,8 @@ + code = dedent("""\ + f = 1 + f(p""") +- result = self._assist(code) # noqa ++ result = self._assist(code) ++ self.assertTrue(result is not None) + + def test_proposing_function_keywords_when_calling_extra_spaces(self): + code = dedent("""\ +@@ -1337,7 +1341,8 @@ + """) + samplemod.write(code) + package = testutils.create_package(self.project, "package") +- nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa ++ nestedmod = testutils.create_module(self.project, "nestedmod", package) ++ self.assertTrue(nestedmod is not None) + + def tearDown(self): + testutils.remove_project(self.project) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,5 +5,6 @@ + pass + my_""") + result = self._assist(code) +- proposals = sorted_proposals(result, typepref=["function"]) # noqa ++ proposals = sorted_proposals(result, typepref=["function"]) ++ self.assertTrue(proposals is not None) + +@language python + +def test_proposals_sorter_and_missing_type_in_typepref(self): + code = dedent("""\ + my_global_var = 1 + def my_global_func(): + pass + my_""") + result = self._assist(code) + proposals = sorted_proposals(result, typepref=["function"]) # noqa + + +def test_proposals_sorter_and_missing_type_in_typepref(self): + code = dedent("""\ + my_global_var = 1 + def my_global_func(): + pass + my_""") + result = self._assist(code) + proposals = sorted_proposals(result, typepref=["function"]) + self.assertTrue(proposals is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,5 +4,6 @@ + s = "hey" + s.replace() + """) +- doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa ++ doc = get_doc(self.project, src, src.rindex("replace") + 1) ++ self.assertTrue(doc is not None) + +@language python + +def test_commenting_errors_before_offset(self): + src = dedent("""\ + lsjd lsjdf + s = "hey" + s.replace() + """) + doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa + + +def test_commenting_errors_before_offset(self): + src = dedent("""\ + lsjd lsjdf + s = "hey" + s.replace() + """) + doc = get_doc(self.project, src, src.rindex("replace") + 1) + self.assertTrue(doc is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,5 +5,6 @@ + except: + pass + """) +- result = self._assist(code, code.index("."), maxfixes=1) # noqa ++ result = self._assist(code, code.index("."), maxfixes=1) ++ self.assertTrue(result is not None) + +@language python + +def test_and_normal_complete_blocks_and_single_fixing(self): + code = dedent("""\ + try: + range. + except: + pass + """) + result = self._assist(code, code.index("."), maxfixes=1) # noqa + + +def move(self, path, new_location): + self.hg.commands.rename(self.ui, self.repo, path, new_location, after=False) + + +def test_and_normal_complete_blocks_and_single_fixing(self): + code = dedent("""\ + try: + range. + except: + pass + """) + result = self._assist(code, code.index("."), maxfixes=1) + self.assertTrue(result is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,5 +2,6 @@ + code = dedent("""\ + f = 1 + f(p""") +- result = self._assist(code) # noqa ++ result = self._assist(code) ++ self.assertTrue(result is not None) + +@language python + +def test_proposing_function_keywords_when_calling_for_non_functions(self): + code = dedent("""\ + f = 1 + f(p""") + result = self._assist(code) # noqa + + +def test_proposing_function_keywords_when_calling_for_non_functions(self): + code = dedent("""\ + f = 1 + f(p""") + result = self._assist(code) + self.assertTrue(result is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -18,5 +18,6 @@ + """) + samplemod.write(code) + package = testutils.create_package(self.project, "package") +- nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa ++ nestedmod = testutils.create_module(self.project, "nestedmod", package) ++ self.assertTrue(nestedmod is not None) + +@language python + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + samplemod = testutils.create_module(self.project, "samplemod") + code = dedent("""\ + class SampleClass(object): + def sample_method(): + pass + + def sample_func(): + pass + sample_var = 10 + + def _underlined_func(): + pass + + """) + samplemod.write(code) + package = testutils.create_package(self.project, "package") + nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa + + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + samplemod = testutils.create_module(self.project, "samplemod") + code = dedent("""\ + class SampleClass(object): + def sample_method(): + pass + + def sample_func(): + pass + sample_var = 10 + + def _underlined_func(): + pass + + """) + samplemod.write(code) + package = testutils.create_package(self.project, "package") + nestedmod = testutils.create_module(self.project, "nestedmod", package) + self.assertTrue(nestedmod is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -42,11 +42,12 @@ + + def test_handling_nested_modules(self): + pkg = create_package(self.project, "xkg") +- mod = create_module(self.project, "xkg.xod") # noqa ++ mod = create_module(self.project, "xkg.xod") + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + self.assertFalse(pkg.exists()) + self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) + self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) ++ self.assertTrue(mod is not None) + + + def _fixer(name): +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,10 @@ + def test_handling_nested_modules(self): + pkg = create_package(self.project, "xkg") +- mod = create_module(self.project, "xkg.xod") # noqa ++ mod = create_module(self.project, "xkg.xod") + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + self.assertFalse(pkg.exists()) + self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) + self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) ++ self.assertTrue(mod is not None) + + +@language python + +def remove(self, path): + self.hg.commands.remove(self.ui, self.repo, path) + + +def test_handling_nested_modules(self): + pkg = create_package(self.project, "xkg") + mod = create_module(self.project, "xkg.xod") # noqa + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + self.assertFalse(pkg.exists()) + self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) + self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) + + + +def test_handling_nested_modules(self): + pkg = create_package(self.project, "xkg") + mod = create_module(self.project, "xkg.xod") + self.project.do(FixModuleNames(self.project).get_changes(_fixer)) + self.assertFalse(pkg.exists()) + self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) + self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) + self.assertTrue(mod is not None) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -373,7 +373,7 @@ + self.assertFalse(myfile.exists()) + + def test_writing_and_reading_history(self): +- history_file = self.project.get_file("history.pickle") # noqa ++ history_file = self.project.get_file("history.pickle") + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") +@@ -383,9 +383,10 @@ + history = rope.base.history.History(self.project) + history.undo() + self.assertFalse(myfile.exists()) ++ self.assertTrue(history_file is not None) + + def test_writing_and_reading_history2(self): +- history_file = self.project.get_file("history.pickle") # noqa ++ history_file = self.project.get_file("history.pickle") + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") +@@ -396,3 +397,4 @@ + history = rope.base.history.History(self.project) + history.redo() + self.assertTrue(myfile.exists()) ++ self.assertTrue(history_file is not None) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def test_writing_and_reading_history(self): +- history_file = self.project.get_file("history.pickle") # noqa ++ history_file = self.project.get_file("history.pickle") + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") +@@ -9,4 +9,5 @@ + history = rope.base.history.History(self.project) + history.undo() + self.assertFalse(myfile.exists()) ++ self.assertTrue(history_file is not None) + +@language python + +def test_writing_and_reading_history(self): + history_file = self.project.get_file("history.pickle") # noqa + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") + history.do(rope.base.change.CreateResource(myfile)) + history.write() + + history = rope.base.history.History(self.project) + history.undo() + self.assertFalse(myfile.exists()) + + +def test_writing_and_reading_history(self): + history_file = self.project.get_file("history.pickle") + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") + history.do(rope.base.change.CreateResource(myfile)) + history.write() + + history = rope.base.history.History(self.project) + history.undo() + self.assertFalse(myfile.exists()) + self.assertTrue(history_file is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def test_writing_and_reading_history2(self): +- history_file = self.project.get_file("history.pickle") # noqa ++ history_file = self.project.get_file("history.pickle") + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") +@@ -10,3 +10,4 @@ + history = rope.base.history.History(self.project) + history.redo() + self.assertTrue(myfile.exists()) ++ self.assertTrue(history_file is not None) +@language python + +def test_writing_and_reading_history2(self): + history_file = self.project.get_file("history.pickle") # noqa + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") + history.do(rope.base.change.CreateResource(myfile)) + history.undo() + history.write() + + history = rope.base.history.History(self.project) + history.redo() + self.assertTrue(myfile.exists()) + +def test_writing_and_reading_history2(self): + history_file = self.project.get_file("history.pickle") + self.project.set("save_history", True) + history = rope.base.history.History(self.project) + myfile = self.project.get_file("myfile.txt") + history.do(rope.base.change.CreateResource(myfile)) + history.undo() + history.write() + + history = rope.base.history.History(self.project) + history.redo() + self.assertTrue(myfile.exists()) + self.assertTrue(history_file is not None) + +def write(self, path, data): + self.normal_actions.write(path, data) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -285,7 +285,8 @@ + """) + mod = libutils.get_string_module(self.project, code) + +- a = mod["a"].get_object() # noqa ++ a = mod["a"].get_object() ++ self.assertTrue(a is not None) + + def test_handling_generator_functions(self): + code = dedent("""\ +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,5 +5,6 @@ + """) + mod = libutils.get_string_module(self.project, code) + +- a = mod["a"].get_object() # noqa ++ a = mod["a"].get_object() ++ self.assertTrue(a is not None) + +@language python + +def test_empty_tuples(self): + code = dedent("""\ + t = () + a, b = t + """) + mod = libutils.get_string_module(self.project, code) + + a = mod["a"].get_object() # noqa + + +def test_empty_tuples(self): + code = dedent("""\ + t = () + a, b = t + """) + mod = libutils.get_string_module(self.project, code) + + a = mod["a"].get_object() + self.assertTrue(a is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,8 +1,7 @@ + import os.path + import shutil + from textwrap import dedent +- +-import pytest ++import unittest + + from rope.base.exceptions import RopeError, ResourceNotFoundError + from rope.base.fscommands import FileSystemCommands +@@ -10,9 +9,6 @@ + from rope.base.project import Project, NoProject, _realpath + from rope.base.resourceobserver import FilteredResourceObserver + from ropetest import testutils +- +- +-import unittest + + + class ProjectTest(unittest.TestCase): +@@ -705,7 +701,7 @@ + def test_revalidating_folders(self): + root = self.project.root + my_folder = root.create_folder("myfolder") +- my_file = my_folder.create_file("myfile.txt") # noqa ++ my_file = my_folder.create_file("myfile.txt") + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [my_folder]) +@@ -714,6 +710,7 @@ + self.project.validate(root) + self.assertEqual(my_folder, sample_observer.last_removed) + self.assertEqual(1, sample_observer.change_count) ++ self.assertTrue(my_file is not None) + + def test_removing_and_adding_resources_to_filtered_observer(self): + my_file = self.project.root.create_file("my_file.txt") +@@ -812,7 +809,7 @@ + self.assertEqual(1, sample_observer.change_count) + + def test_changes_and_adding_resources(self): +- root = self.project.root # noqa ++ # root = self.project.root + file1 = self.project.get_file("file1.txt") + file2 = self.project.get_file("file2.txt") + file1.create() +@@ -826,7 +823,7 @@ + self.assertEqual((file1, file2), sample_observer.last_moved) + + def test_validating_get_files_list(self): +- root = self.project.root # noqa ++ # root = self.project.root + self.assertEqual(0, len(self.project.get_files())) + file = open(os.path.join(self.project.address, "myfile.txt"), "w") + file.close() +@@ -1040,8 +1037,9 @@ + self.project = testutils.sample_project( + ignored_resources=["myfile.txt"], ropefolder=None + ) +- myfile = self.project.root.create_file("myfile.txt") # noqa ++ myfile = self.project.root.create_file("myfile.txt") + self.assertEqual(0, len(self.project.get_files())) ++ self.assertTrue(myfile is not None) + + def test_setting_ignored_resources_patterns(self): + self.project = testutils.sample_project(ignored_resources=["m?file.*"]) +@@ -1162,7 +1160,8 @@ + ) + mod = testutils.create_module(self.project, "mod") + mod.write("xyz print") +- pymod = self.project.get_pymodule(mod) # noqa ++ pymod = self.project.get_pymodule(mod) ++ self.assertTrue(pymod is not None) + + def test_compressed_history(self): + self.project = testutils.sample_project(compress_history=True) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,8 +2,7 @@ + import os.path + import shutil + from textwrap import dedent +- +-import pytest ++import unittest + + from rope.base.exceptions import RopeError, ResourceNotFoundError + from rope.base.fscommands import FileSystemCommands +@@ -13,9 +12,6 @@ + from ropetest import testutils + + +-import unittest +- +- + @others + @language python + @tabwidth -4 +@language python + +@path C:/Repos/ekr-rope/ropetest/ +import os.path +import shutil +from textwrap import dedent + +import pytest + +from rope.base.exceptions import RopeError, ResourceNotFoundError +from rope.base.fscommands import FileSystemCommands +from rope.base.libutils import path_to_resource +from rope.base.project import Project, NoProject, _realpath +from rope.base.resourceobserver import FilteredResourceObserver +from ropetest import testutils + + +import unittest + + +@others +@language python +@tabwidth -4 + +@path C:/Repos/ekr-rope/ropetest/ +import os.path +import shutil +from textwrap import dedent + +import pytest + +from rope.base.exceptions import RopeError, ResourceNotFoundError +from rope.base.fscommands import FileSystemCommands +from rope.base.libutils import path_to_resource +from rope.base.project import Project, NoProject, _realpath +from rope.base.resourceobserver import FilteredResourceObserver +from ropetest import testutils + + +import unittest + + +@others +@language python +@tabwidth -4 + +def read(self, path): + return self.normal_actions.read(path) + + + +class ProjectTest(unittest.TestCase): + @others + +def setUp(self): + unittest.TestCase.setUp(self) + self.project = testutils.sample_project( + foldername="sampleproject", ropefolder=None + ) + self.project_root = self.project.address + self._make_sample_project() + self.no_project = NoProject() + + +def _make_sample_project(self): + self.sample_file = "sample_file.txt" + self.sample_path = os.path.join(self.project_root, "sample_file.txt") + if not os.path.exists(self.project_root): + os.mkdir(self.project_root) + self.sample_folder = "sample_folder" + os.mkdir(os.path.join(self.project_root, self.sample_folder)) + sample = open(self.sample_path, "w") + sample.write("sample text\n") + sample.close() + + +def tearDown(self): + testutils.remove_project(self.project) + unittest.TestCase.tearDown(self) + + +def test_project_creation(self): + self.assertEqual(_realpath(self.project_root), self.project.address) + + +def test_getting_project_file(self): + project_file = self.project.get_resource(self.sample_file) + self.assertTrue(project_file is not None) + + +def test_project_file_reading(self): + projectFile = self.project.get_resource(self.sample_file) + self.assertEqual("sample text\n", projectFile.read()) + + +def test_getting_not_existing_project_file(self): + with self.assertRaises(ResourceNotFoundError): + self.project.get_resource("DoesNotExistFile.txt") + + +def test_writing_in_project_files(self): + project_file = self.project.get_resource(self.sample_file) + project_file.write("another text\n") + self.assertEqual("another text\n", project_file.read()) + + +def test_creating_files(self): + project_file = "newfile.txt" + self.project.root.create_file(project_file) + newFile = self.project.get_resource(project_file) + self.assertTrue(newFile is not None) + + +class GITCommands: + @others + +def test_creating_files_that_already_exist(self): + with self.assertRaises(RopeError): + self.project.root.create_file(self.sample_file) + + +def test_making_root_folder_if_it_does_not_exist(self): + project = Project("sampleproject2") + try: + self.assertTrue( + os.path.exists("sampleproject2") and os.path.isdir("sampleproject2") + ) + finally: + testutils.remove_project(project) + + +def test_failure_when_project_root_exists_and_is_a_file(self): + project_root = "sampleproject2" + try: + open(project_root, "w").close() + with self.assertRaises(RopeError): + Project(project_root) + finally: + testutils.remove_recursively(project_root) + + +def test_creating_folders(self): + folderName = "SampleFolder" + self.project.root.create_folder(folderName) + folderPath = os.path.join(self.project.address, folderName) + self.assertTrue(os.path.exists(folderPath) and os.path.isdir(folderPath)) + + +def test_making_folder_that_already_exists(self): + folderName = "SampleFolder" + with self.assertRaises(RopeError): + self.project.root.create_folder(folderName) + self.project.root.create_folder(folderName) + + +def test_failing_if_creating_folder_while_file_already_exists(self): + folderName = "SampleFolder" + with self.assertRaises(RopeError): + self.project.root.create_file(folderName) + self.project.root.create_folder(folderName) + + +def test_creating_file_inside_folder(self): + folder_name = "sampleFolder" + file_name = "sample2.txt" + file_path = folder_name + "/" + file_name + parent_folder = self.project.root.create_folder(folder_name) + parent_folder.create_file(file_name) + file = self.project.get_resource(file_path) + file.write("sample notes") + self.assertEqual(file_path, file.path) + self.assertEqual( + "sample notes", open(os.path.join(self.project.address, file_path)).read() + ) + + +def test_failing_when_creating_file_inside_non_existent_folder(self): + with self.assertRaises(ResourceNotFoundError): + self.project.root.create_file("NonexistentFolder/SomeFile.txt") + + +def test_nested_directories(self): + folder_name = "SampleFolder" + parent = self.project.root.create_folder(folder_name) + parent.create_folder(folder_name) + folder_path = os.path.join(self.project.address, folder_name, folder_name) + self.assertTrue(os.path.exists(folder_path) and os.path.isdir(folder_path)) + + +def test_removing_files(self): + self.assertTrue(os.path.exists(self.sample_path)) + self.project.get_resource(self.sample_file).remove() + self.assertFalse(os.path.exists(self.sample_path)) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,7 +6,7 @@ + break + else: + self._skip_comment() +- except (ValueError, TypeError) as e: ++ except (ValueError, TypeError): + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) +@language python + +def __init__(self, root): + self.root = root + self._do(["version"]) + self.normal_actions = FileSystemCommands() + + +def test_removing_files_invalidating_in_project_resource_pool(self): + root_folder = self.project.root + my_file = root_folder.create_file("my_file.txt") + my_file.remove() + self.assertFalse(root_folder.has_child("my_file.txt")) + + +def test_removing_directories(self): + self.assertTrue( + os.path.exists(os.path.join(self.project.address, self.sample_folder)) + ) + self.project.get_resource(self.sample_folder).remove() + self.assertFalse( + os.path.exists(os.path.join(self.project.address, self.sample_folder)) + ) + + +def test_removing_non_existent_files(self): + with self.assertRaises(ResourceNotFoundError): + self.project.get_resource("NonExistentFile.txt").remove() + + +def test_removing_nested_files(self): + file_name = self.sample_folder + "/sample_file.txt" + self.project.root.create_file(file_name) + self.project.get_resource(file_name).remove() + self.assertTrue( + os.path.exists(os.path.join(self.project.address, self.sample_folder)) + ) + self.assertTrue( + not os.path.exists(os.path.join(self.project.address, file_name)) + ) + + +def test_file_get_name(self): + file = self.project.get_resource(self.sample_file) + self.assertEqual(self.sample_file, file.name) + file_name = "nestedFile.txt" + parent = self.project.get_resource(self.sample_folder) + filePath = self.sample_folder + "/" + file_name + parent.create_file(file_name) + nestedFile = self.project.get_resource(filePath) + self.assertEqual(file_name, nestedFile.name) + + +def test_folder_get_name(self): + folder = self.project.get_resource(self.sample_folder) + self.assertEqual(self.sample_folder, folder.name) + + +def test_file_get_path(self): + file = self.project.get_resource(self.sample_file) + self.assertEqual(self.sample_file, file.path) + fileName = "nestedFile.txt" + parent = self.project.get_resource(self.sample_folder) + filePath = self.sample_folder + "/" + fileName + parent.create_file(fileName) + nestedFile = self.project.get_resource(filePath) + self.assertEqual(filePath, nestedFile.path) + + +def test_folder_get_path(self): + folder = self.project.get_resource(self.sample_folder) + self.assertEqual(self.sample_folder, folder.path) + + +def test_is_folder(self): + self.assertTrue(self.project.get_resource(self.sample_folder).is_folder()) + self.assertTrue(not self.project.get_resource(self.sample_file).is_folder()) + + +def testget_children(self): + children = self.project.get_resource(self.sample_folder).get_children() + self.assertEqual([], children) + + +def create_file(self, path): + self.normal_actions.create_file(path) + self._do(["add", self._in_dir(path)]) + + +def test_nonempty_get_children(self): + file_name = "nestedfile.txt" + filePath = self.sample_folder + "/" + file_name + parent = self.project.get_resource(self.sample_folder) + parent.create_file(file_name) + children = parent.get_children() + self.assertEqual(1, len(children)) + self.assertEqual(filePath, children[0].path) + + +def test_nonempty_get_children2(self): + file_name = "nestedfile.txt" + folder_name = "nestedfolder.txt" + filePath = self.sample_folder + "/" + file_name + folderPath = self.sample_folder + "/" + folder_name + parent = self.project.get_resource(self.sample_folder) + parent.create_file(file_name) + parent.create_folder(folder_name) + children = parent.get_children() + self.assertEqual(2, len(children)) + self.assertTrue(filePath == children[0].path or filePath == children[1].path) + self.assertTrue( + folderPath == children[0].path or folderPath == children[1].path + ) + + +def test_does_not_fail_for_permission_denied(self): + bad_dir = os.path.join(self.sample_folder, "bad_dir") + os.makedirs(bad_dir) + self.addCleanup(shutil.rmtree, bad_dir) + os.chmod(bad_dir, 0o000) + try: + parent = self.project.get_resource(self.sample_folder) + + parent.get_children() + + finally: + os.chmod(bad_dir, 0o755) + + +def test_getting_files(self): + files = self.project.root.get_files() + self.assertEqual(1, len(files)) + self.assertTrue(self.project.get_resource(self.sample_file) in files) + + +def test_getting_folders(self): + folders = self.project.root.get_folders() + self.assertEqual(1, len(folders)) + self.assertTrue(self.project.get_resource(self.sample_folder) in folders) + + +def test_nested_folder_get_files(self): + parent = self.project.root.create_folder("top") + parent.create_file("file1.txt") + parent.create_file("file2.txt") + files = parent.get_files() + self.assertEqual(2, len(files)) + self.assertTrue(self.project.get_resource("top/file2.txt") in files) + self.assertEqual(0, len(parent.get_folders())) + + +def test_nested_folder_get_folders(self): + parent = self.project.root.create_folder("top") + parent.create_folder("dir1") + parent.create_folder("dir2") + folders = parent.get_folders() + self.assertEqual(2, len(folders)) + self.assertTrue(self.project.get_resource("top/dir1") in folders) + self.assertEqual(0, len(parent.get_files())) + + +def test_root_folder(self): + root_folder = self.project.root + self.assertEqual(2, len(root_folder.get_children())) + self.assertEqual("", root_folder.path) + self.assertEqual("", root_folder.name) + + +def test_get_all_files(self): + files = tuple(self.project.get_files()) + self.assertEqual(1, len(files)) + self.assertEqual(self.sample_file, files[0].name) + + +def test_get_all_files_after_changing(self): + self.assertEqual(1, len(self.project.get_files())) + myfile = self.project.root.create_file("myfile.txt") + self.assertEqual(2, len(self.project.get_files())) + myfile.move("newfile.txt") + self.assertEqual(2, len(self.project.get_files())) + self.project.get_file("newfile.txt").remove() + self.assertEqual(1, len(self.project.get_files())) + + +def create_folder(self, path): + self.normal_actions.create_folder(path) + + +def test_multifile_get_all_files(self): + fileName = "nestedFile.txt" + parent = self.project.get_resource(self.sample_folder) + parent.create_file(fileName) + files = list(self.project.get_files()) + self.assertEqual(2, len(files)) + self.assertTrue(fileName == files[0].name or fileName == files[1].name) + + +def test_ignoring_dot_pyc_files_in_get_files(self): + root = self.project.address + src_folder = os.path.join(root, "src") + os.mkdir(src_folder) + test_pyc = os.path.join(src_folder, "test.pyc") + open(test_pyc, "w").close() + for x in self.project.get_files(): + self.assertNotEqual("src/test.pyc", x.path) + + +def test_folder_creating_files(self): + projectFile = "NewFile.txt" + self.project.root.create_file(projectFile) + new_file = self.project.get_resource(projectFile) + self.assertTrue(new_file is not None and not new_file.is_folder()) + + +def test_folder_creating_nested_files(self): + project_file = "NewFile.txt" + parent_folder = self.project.get_resource(self.sample_folder) + parent_folder.create_file(project_file) + new_file = self.project.get_resource(self.sample_folder + "/" + project_file) + self.assertTrue(new_file is not None and not new_file.is_folder()) + + +def test_folder_creating_files2(self): + projectFile = "newfolder" + self.project.root.create_folder(projectFile) + new_folder = self.project.get_resource(projectFile) + self.assertTrue(new_folder is not None and new_folder.is_folder()) + + +def test_folder_creating_nested_files2(self): + project_file = "newfolder" + parent_folder = self.project.get_resource(self.sample_folder) + parent_folder.create_folder(project_file) + new_folder = self.project.get_resource(self.sample_folder + "/" + project_file) + self.assertTrue(new_folder is not None and new_folder.is_folder()) + + +def test_folder_get_child(self): + folder = self.project.root + folder.create_file("myfile.txt") + folder.create_folder("myfolder") + self.assertEqual( + self.project.get_resource("myfile.txt"), folder.get_child("myfile.txt") + ) + self.assertEqual( + self.project.get_resource("myfolder"), folder.get_child("myfolder") + ) + + +def test_folder_get_child_nested(self): + root = self.project.root + folder = root.create_folder("myfolder") + folder.create_file("myfile.txt") + folder.create_folder("myfolder") + self.assertEqual( + self.project.get_resource("myfolder/myfile.txt"), + folder.get_child("myfile.txt"), + ) + self.assertEqual( + self.project.get_resource("myfolder/myfolder"), folder.get_child("myfolder") + ) + + +def test_project_root_is_root_folder(self): + self.assertEqual("", self.project.root.path) + + +def test_moving_files(self): + root_folder = self.project.root + my_file = root_folder.create_file("my_file.txt") + my_file.move("my_other_file.txt") + self.assertFalse(my_file.exists()) + root_folder.get_child("my_other_file.txt") + + +def move(self, path, new_location): + self._do(["mv", self._in_dir(path), self._in_dir(new_location)]) + + +def test_moving_folders(self): + root_folder = self.project.root + my_folder = root_folder.create_folder("my_folder") + my_file = my_folder.create_file("my_file.txt") + my_folder.move("new_folder") + self.assertFalse(root_folder.has_child("my_folder")) + self.assertFalse(my_file.exists()) + self.assertTrue(root_folder.get_child("new_folder") is not None) + + +def test_moving_destination_folders(self): + root_folder = self.project.root + my_folder = root_folder.create_folder("my_folder") + my_file = root_folder.create_file("my_file.txt") + my_file.move("my_folder") + self.assertFalse(root_folder.has_child("my_file.txt")) + self.assertFalse(my_file.exists()) + my_folder.get_child("my_file.txt") + + +def test_moving_files_and_resource_objects(self): + root_folder = self.project.root + my_file = root_folder.create_file("my_file.txt") + old_hash = hash(my_file) + my_file.move("my_other_file.txt") + self.assertEqual(old_hash, hash(my_file)) + + +def test_file_encoding_reading(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = ( + b"# -*- coding: utf-8 -*-\n" + + br"#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" + ).decode("utf8") + file = open(sample_file.real_path, "wb") + file.write(contents.encode("utf-8")) + file.close() + self.assertEqual(contents, sample_file.read()) + + +def test_file_encoding_writing(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = ( + b"# -*- coding: utf-8 -*-\n" + br"\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" + ).decode("utf8") + sample_file.write(contents) + self.assertEqual(contents, sample_file.read()) + + +def test_using_utf8_when_writing_in_case_of_errors(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = br"\n\N{LATIN SMALL LETTER I WITH DIAERESIS}\n".decode("utf8") + sample_file.write(contents) + self.assertEqual(contents, sample_file.read()) + + +def test_encoding_declaration_in_the_second_line(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"\n# -*- coding: latin-1 -*-\n\xa9\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertEqual(contents, sample_file.read().encode("latin-1")) + + +def test_not_an_encoding_declaration(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"def my_method(self, encoding='latin-1'):\n var = {}\n\xc2\xa9\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertEqual(contents, sample_file.read().encode("utf-8")) + self.assertNotEqual(contents, sample_file.read().encode("latin-1")) + + +def test_read_bytes(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"\n# -*- coding: latin-1 -*-\n\xa9\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertEqual(contents, sample_file.read_bytes()) + + +def test_file_with_unix_line_ending(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"1\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertIsNone(sample_file.newlines) + self.assertEqual("1\n", sample_file.read()) + self.assertEqual("\n", sample_file.newlines) + + sample_file.write("1\n") + self.assertEqual(b"1\n", sample_file.read_bytes()) + + +def remove(self, path): + self._do(["rm", self._in_dir(path)]) + + +def test_file_with_dos_line_ending(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"1\r\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertIsNone(sample_file.newlines) + self.assertEqual("1\n", sample_file.read()) + self.assertEqual("\r\n", sample_file.newlines) + + sample_file.write("1\n") + self.assertEqual(b"1\r\n", sample_file.read_bytes()) + + +def test_file_with_mac_line_ending(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"1\r" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertIsNone(sample_file.newlines) + self.assertEqual("1\n", sample_file.read()) + self.assertEqual("\r", sample_file.newlines) + + sample_file.write("1\n") + self.assertEqual(b"1\r", sample_file.read_bytes()) + + +def test_file_binary(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"1\r\n" + file = open(sample_file.real_path, "wb") + file.write(contents) + file.close() + self.assertIsNone(sample_file.newlines) + self.assertEqual(b"1\r\n", sample_file.read_bytes()) + self.assertIsNone(sample_file.newlines) + + sample_file.write(b"1\nx\r") + self.assertEqual((b"1\nx\r"), sample_file.read_bytes()) + + +# TODO: Detecting utf-16 encoding +def xxx_test_using_utf16(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = b"# -*- coding: utf-16 -*-\n# This is a sample file ...\n" + file = open(sample_file.real_path, "w") + file.write(contents.encode("utf-16")) + file.close() + sample_file.write(contents) + self.assertEqual(contents, sample_file.read()) + + +# XXX: supporting utf_8_sig +def xxx_test_file_encoding_reading_for_notepad_styles(self): + sample_file = self.project.root.create_file("my_file.txt") + contents = "#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" + file = open(sample_file.real_path, "w") + # file.write('\xef\xbb\xbf') + file.write(contents.encode("utf-8-sig")) + file.close() + self.assertEqual(contents, sample_file.read()) + + +def test_using_project_get_file(self): + myfile = self.project.get_file(self.sample_file) + self.assertTrue(myfile.exists()) + + +def test_using_file_create(self): + myfile = self.project.get_file("myfile.txt") + self.assertFalse(myfile.exists()) + myfile.create() + self.assertTrue(myfile.exists()) + self.assertFalse(myfile.is_folder()) + + +def test_using_folder_create(self): + myfolder = self.project.get_folder("myfolder") + self.assertFalse(myfolder.exists()) + myfolder.create() + self.assertTrue(myfolder.exists()) + self.assertTrue(myfolder.is_folder()) + + +def test_exception_when_creating_twice(self): + with self.assertRaises(RopeError): + myfile = self.project.get_file("myfile.txt") + myfile.create() + myfile.create() + + +def test_exception_when_parent_does_not_exist(self): + with self.assertRaises(ResourceNotFoundError): + myfile = self.project.get_file("myfolder/myfile.txt") + myfile.create() + + +def write(self, path, data): + # XXX: should we use ``git add``? + self.normal_actions.write(path, data) + + +def test_simple_path_to_resource(self): + myfile = self.project.root.create_file("myfile.txt") + self.assertEqual(myfile, path_to_resource(self.project, myfile.real_path)) + self.assertEqual( + myfile, path_to_resource(self.project, myfile.real_path, type="file") + ) + myfolder = self.project.root.create_folder("myfolder") + self.assertEqual(myfolder, path_to_resource(self.project, myfolder.real_path)) + self.assertEqual( + myfolder, path_to_resource(self.project, myfolder.real_path, type="folder") + ) + + +@testutils.skipNotPOSIX() +def test_ignoring_symlinks_inside_project(self): + project2 = testutils.sample_project(folder_name="sampleproject2") + mod = project2.root.create_file("mod.py") + try: + path = os.path.join(self.project.address, "linkedfile.txt") + os.symlink(mod.real_path, path) + files = self.project.root.get_files() + self.assertEqual(1, len(files)) + finally: + testutils.remove_project(project2) + + +def test_getting_empty_source_folders(self): + self.assertEqual([], self.project.get_source_folders()) + + +def test_root_source_folder(self): + self.project.root.create_file("sample.py") + source_folders = self.project.get_source_folders() + self.assertEqual(1, len(source_folders)) + self.assertTrue(self.project.root in source_folders) + + +def test_root_source_folder2(self): + self.project.root.create_file("mod1.py") + self.project.root.create_file("mod2.py") + source_folders = self.project.get_source_folders() + self.assertEqual(1, len(source_folders)) + self.assertTrue(self.project.root in source_folders) + + +def test_src_source_folder(self): + src = self.project.root.create_folder("src") + src.create_file("sample.py") + source_folders = self.project.get_source_folders() + self.assertEqual(1, len(source_folders)) + self.assertTrue(self.project.get_resource("src") in source_folders) + + +def test_packages(self): + src = self.project.root.create_folder("src") + pkg = src.create_folder("package") + pkg.create_file("__init__.py") + source_folders = self.project.get_source_folders() + self.assertEqual(1, len(source_folders)) + self.assertTrue(src in source_folders) + + +def test_multi_source_folders(self): + src = self.project.root.create_folder("src") + package = src.create_folder("package") + package.create_file("__init__.py") + test = self.project.root.create_folder("test") + test.create_file("alltests.py") + source_folders = self.project.get_source_folders() + self.assertEqual(2, len(source_folders)) + self.assertTrue(src in source_folders) + self.assertTrue(test in source_folders) + + +def test_multi_source_folders2(self): + testutils.create_module(self.project, "mod1") + src = self.project.root.create_folder("src") + package = testutils.create_package(self.project, "package", src) + testutils.create_module(self.project, "mod2", package) + source_folders = self.project.get_source_folders() + self.assertEqual(2, len(source_folders)) + self.assertTrue(self.project.root in source_folders and src in source_folders) + + + +class ResourceObserverTest(unittest.TestCase): + @others + +def read(self, path): + return self.normal_actions.read(path) + + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + + +def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + +def test_resource_change_observer(self): + sample_file = self.project.root.create_file("my_file.txt") + sample_file.write("a sample file version 1") + sample_observer = _SampleObserver() + self.project.add_observer(sample_observer) + sample_file.write("a sample file version 2") + self.assertEqual(1, sample_observer.change_count) + self.assertEqual(sample_file, sample_observer.last_changed) + + +def test_resource_change_observer_after_removal(self): + sample_file = self.project.root.create_file("my_file.txt") + sample_file.write("text") + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [sample_file]) + ) + sample_file.remove() + self.assertEqual(1, sample_observer.change_count) + self.assertEqual(sample_file, sample_observer.last_removed) + + +def test_resource_change_observer2(self): + sample_file = self.project.root.create_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(sample_observer) + self.project.remove_observer(sample_observer) + sample_file.write("a sample file version 2") + self.assertEqual(0, sample_observer.change_count) + + +def test_resource_change_observer_for_folders(self): + root_folder = self.project.root + my_folder = root_folder.create_folder("my_folder") + my_folder_observer = _SampleObserver() + root_folder_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(my_folder_observer, [my_folder]) + ) + self.project.add_observer( + FilteredResourceObserver(root_folder_observer, [root_folder]) + ) + my_file = my_folder.create_file("my_file.txt") + self.assertEqual(1, my_folder_observer.change_count) + my_file.move("another_file.txt") + self.assertEqual(2, my_folder_observer.change_count) + self.assertEqual(1, root_folder_observer.change_count) + self.project.get_resource("another_file.txt").remove() + self.assertEqual(2, my_folder_observer.change_count) + self.assertEqual(2, root_folder_observer.change_count) + + +def test_resource_change_observer_after_moving(self): + sample_file = self.project.root.create_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(sample_observer) + sample_file.move("new_file.txt") + self.assertEqual(1, sample_observer.change_count) + self.assertEqual( + (sample_file, self.project.get_resource("new_file.txt")), + sample_observer.last_moved, + ) + + +def test_revalidating_files(self): + root = self.project.root + my_file = root.create_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) + os.remove(my_file.real_path) + self.project.validate(root) + self.assertEqual(my_file, sample_observer.last_removed) + self.assertEqual(1, sample_observer.change_count) + + +def test_revalidating_files_and_no_changes2(self): + root = self.project.root + my_file = root.create_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) + self.project.validate(root) + self.assertEqual(None, sample_observer.last_moved) + self.assertEqual(0, sample_observer.change_count) + + +def _do(self, args): + _execute(["git"] + args, cwd=self.root) + + +def test_removing_and_adding_resources_to_filtered_observer(self): + my_file = self.project.root.create_file("my_file.txt") + sample_observer = _SampleObserver() + filtered_observer = FilteredResourceObserver(sample_observer) + self.project.add_observer(filtered_observer) + my_file.write("1") + self.assertEqual(0, sample_observer.change_count) + filtered_observer.add_resource(my_file) + my_file.write("2") + self.assertEqual(1, sample_observer.change_count) + filtered_observer.remove_resource(my_file) + my_file.write("3") + self.assertEqual(1, sample_observer.change_count) + + +def test_validation_and_changing_files(self): + my_file = self.project.root.create_file("my_file.txt") + sample_observer = _SampleObserver() + timekeeper = _MockChangeIndicator() + filtered_observer = FilteredResourceObserver( + sample_observer, [my_file], timekeeper=timekeeper + ) + self.project.add_observer(filtered_observer) + self._write_file(my_file.real_path) + timekeeper.set_indicator(my_file, 1) + self.project.validate(self.project.root) + self.assertEqual(1, sample_observer.change_count) + + +def test_validation_and_changing_files2(self): + my_file = self.project.root.create_file("my_file.txt") + sample_observer = _SampleObserver() + timekeeper = _MockChangeIndicator() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [my_file], timekeeper=timekeeper) + ) + timekeeper.set_indicator(my_file, 1) + my_file.write("hey") + self.assertEqual(1, sample_observer.change_count) + self.project.validate(self.project.root) + self.assertEqual(1, sample_observer.change_count) + + +def test_not_reporting_multiple_changes_to_folders(self): + root = self.project.root + file1 = root.create_file("file1.txt") + file2 = root.create_file("file2.txt") + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [root, file1, file2]) + ) + os.remove(file1.real_path) + os.remove(file2.real_path) + self.assertEqual(0, sample_observer.change_count) + self.project.validate(self.project.root) + self.assertEqual(3, sample_observer.change_count) + + +def _write_file(self, path): + my_file = open(path, "w") + my_file.write("\n") + my_file.close() + + +def test_moving_and_being_interested_about_a_folder_and_a_child(self): + my_folder = self.project.root.create_folder("my_folder") + my_file = my_folder.create_file("my_file.txt") + sample_observer = _SampleObserver() + filtered_observer = FilteredResourceObserver( + sample_observer, [my_folder, my_file] + ) + self.project.add_observer(filtered_observer) + my_folder.move("new_folder") + self.assertEqual(2, sample_observer.change_count) + + +def test_contains_for_folders(self): + folder1 = self.project.root.create_folder("folder") + folder2 = self.project.root.create_folder("folder2") + self.assertFalse(folder1.contains(folder2)) + + +def test_validating_when_created(self): + root = self.project.root + my_file = self.project.get_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) + open(my_file.real_path, "w").close() + self.project.validate(root) + self.assertEqual(my_file, sample_observer.last_created) + self.assertEqual(1, sample_observer.change_count) + + +def test_validating_twice_when_created(self): + root = self.project.root + my_file = self.project.get_file("my_file.txt") + sample_observer = _SampleObserver() + self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) + open(my_file.real_path, "w").close() + self.project.validate(root) + self.project.validate(root) + self.assertEqual(my_file, sample_observer.last_created) + self.assertEqual(1, sample_observer.change_count) + + +def _in_dir(self, path): + if path.startswith(self.root): + return path[len(self.root) + 1 :] + return self.root + + + +def test_clear_observered_resources_for_filtered_observers(self): + sample_file = self.project.root.create_file("myfile.txt") + sample_observer = _SampleObserver() + filtered = FilteredResourceObserver(sample_observer) + self.project.add_observer(filtered) + filtered.add_resource(sample_file) + filtered.clear_resources() + sample_file.write("1") + self.assertEqual(0, sample_observer.change_count) + + + +class _MockChangeIndicator: + @others + +def __init__(self): + self.times = {} + + +def set_indicator(self, resource, time): + self.times[resource] = time + + +def get_indicator(self, resource): + return self.times.get(resource, 0) + + + +class _SampleObserver: + @others + +def __init__(self): + self.change_count = 0 + self.last_changed = None + self.last_moved = None + self.last_created = None + self.last_removed = None + + +def resource_changed(self, resource): + self.last_changed = resource + self.change_count += 1 + + +def resource_moved(self, resource, new_resource): + self.last_moved = (resource, new_resource) + self.change_count += 1 + + +class DarcsCommands: + @others + +def resource_created(self, resource): + self.last_created = resource + self.change_count += 1 + + +def resource_removed(self, resource): + self.last_removed = resource + self.change_count += 1 + + + +class OutOfProjectTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.test_directory = "temp_test_directory" + testutils.remove_recursively(self.test_directory) + os.mkdir(self.test_directory) + self.project = testutils.sample_project() + self.no_project = NoProject() + + +def tearDown(self): + testutils.remove_project(self.project) + testutils.remove_recursively(self.test_directory) + super().tearDown() + + +def test_simple_out_of_project_file(self): + sample_file_path = os.path.join(self.test_directory, "sample.txt") + sample_file = open(sample_file_path, "w") + sample_file.write("sample content\n") + sample_file.close() + sample_resource = self.no_project.get_resource(sample_file_path) + self.assertEqual("sample content\n", sample_resource.read()) + + +def test_simple_out_of_project_folder(self): + sample_folder_path = os.path.join(self.test_directory, "sample_folder") + os.mkdir(sample_folder_path) + sample_folder = self.no_project.get_resource(sample_folder_path) + self.assertEqual([], sample_folder.get_children()) + + sample_file_path = os.path.join(sample_folder_path, "sample.txt") + open(sample_file_path, "w").close() + sample_resource = self.no_project.get_resource(sample_file_path) + self.assertEqual(sample_resource, sample_folder.get_children()[0]) + + +def test_using_absolute_path(self): + sample_file_path = os.path.join(self.test_directory, "sample.txt") + open(sample_file_path, "w").close() + normal_sample_resource = self.no_project.get_resource(sample_file_path) + absolute_sample_resource = self.no_project.get_resource( + os.path.abspath(sample_file_path) + ) + self.assertEqual(normal_sample_resource, absolute_sample_resource) + + +def test_folder_get_child(self): + sample_folder_path = os.path.join(self.test_directory, "sample_folder") + os.mkdir(sample_folder_path) + sample_folder = self.no_project.get_resource(sample_folder_path) + self.assertEqual([], sample_folder.get_children()) + + sample_file_path = os.path.join(sample_folder_path, "sample.txt") + open(sample_file_path, "w").close() + sample_resource = self.no_project.get_resource(sample_file_path) + self.assertTrue(sample_folder.has_child("sample.txt")) + self.assertFalse(sample_folder.has_child("doesnothave.txt")) + self.assertEqual(sample_resource, sample_folder.get_child("sample.txt")) + + +def test_out_of_project_files_and_path_to_resource(self): + sample_file_path = os.path.join(self.test_directory, "sample.txt") + sample_file = open(sample_file_path, "w") + sample_file.write("sample content\n") + sample_file.close() + sample_resource = self.no_project.get_resource(sample_file_path) + self.assertEqual( + sample_resource, path_to_resource(self.project, sample_file_path) + ) + + + +def consume(self, token, skip_comment=True): + try: + while True: + new_offset = self.source.index(token, self.offset) + if self._good_token(token, new_offset) or not skip_comment: + break + else: + self._skip_comment() + except (ValueError, TypeError) as e: + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) + self.offset = new_offset + len(token) + return (new_offset, self.offset) + + +def __init__(self, root): + self.root = root + self.normal_actions = FileSystemCommands() + + +class _MockFSCommands: + @others + +def __init__(self): + self.log = "" + self.fscommands = FileSystemCommands() + + +def create_file(self, path): + self.log += "create_file " + self.fscommands.create_file(path) + + +def create_folder(self, path): + self.log += "create_folder " + self.fscommands.create_folder(path) + + +def move(self, path, new_location): + self.log += "move " + self.fscommands.move(path, new_location) + + +def remove(self, path): + self.log += "remove " + self.fscommands.remove(path) + + +def read(self, path): + self.log += "read " + return self.fscommands.read(path) + + + +class _DeprecatedFSCommands: + @others + +def __init__(self): + self.log = "" + self.fscommands = FileSystemCommands() + + +def create_file(self, path): + self.log += "create_file " + self.fscommands.create_file(path) + + +def create_file(self, path): + self.normal_actions.create_file(path) + self._do(["add", path]) + + +def create_folder(self, path): + self.log += "create_folder " + self.fscommands.create_folder(path) + + +def move(self, path, new_location): + self.log += "move " + self.fscommands.move(path, new_location) + + +def remove(self, path): + self.log += "remove " + self.fscommands.remove(path) + + + +class RopeFolderTest(unittest.TestCase): + @others + +def setUp(self): + super().setUp() + self.project = None + + +def tearDown(self): + if self.project: + testutils.remove_project(self.project) + super().tearDown() + + +def test_none_project_rope_folder(self): + self.project = testutils.sample_project(ropefolder=None) + self.assertTrue(self.project.ropefolder is None) + + +def test_getting_project_rope_folder(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + self.assertTrue(self.project.ropefolder.exists()) + self.assertTrue(".ropeproject", self.project.ropefolder.path) + + +def test_setting_ignored_resources(self): + self.project = testutils.sample_project(ignored_resources=["myfile.txt"]) + myfile = self.project.get_file("myfile.txt") + file2 = self.project.get_file("file2.txt") + self.assertTrue(self.project.is_ignored(myfile)) + self.assertFalse(self.project.is_ignored(file2)) + + +def test_ignored_folders(self): + self.project = testutils.sample_project(ignored_resources=["myfolder"]) + myfolder = self.project.root.create_folder("myfolder") + self.assertTrue(self.project.is_ignored(myfolder)) + myfile = myfolder.create_file("myfile.txt") + self.assertTrue(self.project.is_ignored(myfile)) + + +def create_folder(self, path): + self.normal_actions.create_folder(path) + self._do(["add", path]) + + +def test_ignored_resources_and_get_files(self): + self.project = testutils.sample_project( + ignored_resources=["myfile.txt"], ropefolder=None + ) + myfile = self.project.get_file("myfile.txt") + self.assertEqual(0, len(self.project.get_files())) + myfile.create() + self.assertEqual(0, len(self.project.get_files())) + + +def test_setting_ignored_resources_patterns(self): + self.project = testutils.sample_project(ignored_resources=["m?file.*"]) + myfile = self.project.get_file("myfile.txt") + file2 = self.project.get_file("file2.txt") + self.assertTrue(self.project.is_ignored(myfile)) + self.assertFalse(self.project.is_ignored(file2)) + + +def test_star_should_not_include_slashes(self): + self.project = testutils.sample_project(ignored_resources=["f*.txt"]) + folder = self.project.root.create_folder("folder") + file1 = folder.create_file("myfile.txt") + file2 = folder.create_file("file2.txt") + self.assertFalse(self.project.is_ignored(file1)) + self.assertTrue(self.project.is_ignored(file2)) + + +def test_normal_fscommands(self): + fscommands = _MockFSCommands() + self.project = testutils.sample_project(fscommands=fscommands) + myfile = self.project.get_file("myfile.txt") + myfile.create() + self.assertTrue("create_file ", fscommands.log) + + +def test_fscommands_and_ignored_resources(self): + fscommands = _MockFSCommands() + self.project = testutils.sample_project( + fscommands=fscommands, ignored_resources=["myfile.txt"], ropefolder=None + ) + myfile = self.project.get_file("myfile.txt") + myfile.create() + self.assertEqual("", fscommands.log) + + +def test_deprecated_fscommands(self): + fscommands = _DeprecatedFSCommands() + self.project = testutils.sample_project(fscommands=fscommands) + myfile = self.project.get_file("myfile.txt") + myfile.create() + self.assertTrue("create_file ", fscommands.log) + + +def test_ignored_resources_and_prefixes(self): + self.project = testutils.sample_project(ignored_resources=[".hg"]) + myfile = self.project.root.create_file(".hgignore") + self.assertFalse(self.project.is_ignored(myfile)) + + +def test_loading_config_dot_py(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + config = self.project.get_file(".ropeproject/config.py") + if not config.exists(): + config.create() + config.write(dedent("""\ + def set_prefs(prefs): + prefs["ignored_resources"] = ["myfile.txt"] + def project_opened(project): + project.root.create_file("loaded") + """)) + self.project.close() + self.project = Project(self.project.address, ropefolder=".ropeproject") + self.assertTrue(self.project.get_file("loaded").exists()) + myfile = self.project.get_file("myfile.txt") + self.assertTrue(self.project.is_ignored(myfile)) + + +def test_loading_pyproject(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + config = self.project.get_file("pyproject.toml") + if not config.exists(): + config.create() + config.write(dedent("""\ + [tool.rope] + ignored_resources=["pyproject.py"] + """)) + self.project.close() + self.project = Project(self.project.address, ropefolder=".ropeproject") + myfile = self.project.get_file("pyproject.py") + self.assertTrue(self.project.is_ignored(myfile)) + + +def move(self, path, new_location): + self._do(["mv", path, new_location]) + + +def test_loading_pyproject_empty_file(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + config = self.project.get_file("pyproject.toml") + if not config.exists(): + config.create() + config.write("") + self.project.close() + self.project = Project(self.project.address, ropefolder=".ropeproject") + myfile = self.project.get_file("pyproject.py") + self.assertFalse(self.project.is_ignored(myfile)) + + +def test_loading_pyproject_no_tool_section(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + config = self.project.get_file("pyproject.toml") + if not config.exists(): + config.create() + config.write(dedent("""\ + [project] + name = 'testproject' + """)) + self.project.close() + self.project = Project(self.project.address, ropefolder=".ropeproject") + myfile = self.project.get_file("pyproject.py") + self.assertFalse(self.project.is_ignored(myfile)) + + +def test_loading_pyproject_no_tool_rope_section(self): + self.project = testutils.sample_project(ropefolder=".ropeproject") + config = self.project.get_file("pyproject.toml") + if not config.exists(): + config.create() + config.write(dedent("""\ + [tool.anothertool] + name = 'testproject' + """)) + self.project.close() + self.project = Project(self.project.address, ropefolder=".ropeproject") + myfile = self.project.get_file("pyproject.py") + self.assertFalse(self.project.is_ignored(myfile)) + + +def test_compressed_history(self): + self.project = testutils.sample_project(compress_history=True) + mod = testutils.create_module(self.project, "mod") + mod.write("") + + +def test_compressed_objectdb(self): + self.project = testutils.sample_project(compress_objectdb=True) + mod = testutils.create_module(self.project, "mod") + self.project.pycore.analyze_module(mod) + + +def test_nested_dot_ropeproject_folder(self): + self.project = testutils.sample_project(ropefolder=".f1/f2") + ropefolder = self.project.ropefolder + self.assertEqual(".f1/f2", ropefolder.path) + self.assertTrue(ropefolder.exists()) + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,7 @@ + def test_revalidating_folders(self): + root = self.project.root + my_folder = root.create_folder("myfolder") +- my_file = my_folder.create_file("myfile.txt") # noqa ++ my_file = my_folder.create_file("myfile.txt") + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [my_folder]) +@@ -10,4 +10,5 @@ + self.project.validate(root) + self.assertEqual(my_folder, sample_observer.last_removed) + self.assertEqual(1, sample_observer.change_count) ++ self.assertTrue(my_file is not None) + +@language python + +def test_revalidating_folders(self): + root = self.project.root + my_folder = root.create_folder("myfolder") + my_file = my_folder.create_file("myfile.txt") # noqa + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [my_folder]) + ) + testutils.remove_recursively(my_folder.real_path) + self.project.validate(root) + self.assertEqual(my_folder, sample_observer.last_removed) + self.assertEqual(1, sample_observer.change_count) + + +def test_revalidating_folders(self): + root = self.project.root + my_folder = root.create_folder("myfolder") + my_file = my_folder.create_file("myfile.txt") # noqa + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [my_folder]) + ) + testutils.remove_recursively(my_folder.real_path) + self.project.validate(root) + self.assertEqual(my_folder, sample_observer.last_removed) + self.assertEqual(1, sample_observer.change_count) + + +def remove(self, path): + self.normal_actions.remove(path) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def test_changes_and_adding_resources(self): +- root = self.project.root # noqa ++ # root = self.project.root + file1 = self.project.get_file("file1.txt") + file2 = self.project.get_file("file2.txt") + file1.create() +@language python + +def test_changes_and_adding_resources(self): + root = self.project.root # noqa + file1 = self.project.get_file("file1.txt") + file2 = self.project.get_file("file2.txt") + file1.create() + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [file1, file2]) + ) + file1.move(file2.path) + self.assertEqual(2, sample_observer.change_count) + self.assertEqual(file2, sample_observer.last_created) + self.assertEqual((file1, file2), sample_observer.last_moved) + + +def test_changes_and_adding_resources(self): + root = self.project.root # noqa + file1 = self.project.get_file("file1.txt") + file2 = self.project.get_file("file2.txt") + file1.create() + sample_observer = _SampleObserver() + self.project.add_observer( + FilteredResourceObserver(sample_observer, [file1, file2]) + ) + file1.move(file2.path) + self.assertEqual(2, sample_observer.change_count) + self.assertEqual(file2, sample_observer.last_created) + self.assertEqual((file1, file2), sample_observer.last_moved) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ + def test_validating_get_files_list(self): +- root = self.project.root # noqa ++ # root = self.project.root + self.assertEqual(0, len(self.project.get_files())) + file = open(os.path.join(self.project.address, "myfile.txt"), "w") + file.close() +@language python + +def test_validating_get_files_list(self): + root = self.project.root # noqa + self.assertEqual(0, len(self.project.get_files())) + file = open(os.path.join(self.project.address, "myfile.txt"), "w") + file.close() + self.project.validate() + self.assertEqual(1, len(self.project.get_files())) + + +def test_validating_get_files_list(self): + root = self.project.root # noqa + self.assertEqual(0, len(self.project.get_files())) + file = open(os.path.join(self.project.address, "myfile.txt"), "w") + file.close() + self.project.validate() + self.assertEqual(1, len(self.project.get_files())) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,6 +2,7 @@ + self.project = testutils.sample_project( + ignored_resources=["myfile.txt"], ropefolder=None + ) +- myfile = self.project.root.create_file("myfile.txt") # noqa ++ myfile = self.project.root.create_file("myfile.txt") + self.assertEqual(0, len(self.project.get_files())) ++ self.assertTrue(myfile is not None) + +@language python + +def test_ignored_resources_and_get_files2(self): + self.project = testutils.sample_project( + ignored_resources=["myfile.txt"], ropefolder=None + ) + myfile = self.project.root.create_file("myfile.txt") # noqa + self.assertEqual(0, len(self.project.get_files())) + + +def test_ignored_resources_and_get_files2(self): + self.project = testutils.sample_project( + ignored_resources=["myfile.txt"], ropefolder=None + ) + myfile = self.project.root.create_file("myfile.txt") # noqa + self.assertEqual(0, len(self.project.get_files())) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,5 +4,6 @@ + ) + mod = testutils.create_module(self.project, "mod") + mod.write("xyz print") +- pymod = self.project.get_pymodule(mod) # noqa ++ pymod = self.project.get_pymodule(mod) ++ self.assertTrue(pymod is not None) + +@language python + +def read(self, path): + return self.normal_actions.read(path) + + +def test_ignoring_syntax_errors(self): + self.project = testutils.sample_project( + ropefolder=None, ignore_syntax_errors=True + ) + mod = testutils.create_module(self.project, "mod") + mod.write("xyz print") + pymod = self.project.get_pymodule(mod) # noqa + + +def test_ignoring_syntax_errors(self): + self.project = testutils.sample_project( + ropefolder=None, ignore_syntax_errors=True + ) + mod = testutils.create_module(self.project, "mod") + mod.write("xyz print") + pymod = self.project.get_pymodule(mod) # noqa + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -31,18 +31,19 @@ + + def test_nested_modules(self): + pkg = testutils.create_package(self.project, "pkg") +- mod = testutils.create_module(self.project, "mod", pkg) # noqa ++ mod = testutils.create_module(self.project, "mod", pkg) + package = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), package.get_type()) + self.assertEqual(1, len(package.get_attributes())) + module = package["mod"].get_object() + self.assertEqual(get_base_type("Module"), module.get_type()) +- ++ self.assertTrue(mod is not None) + def test_package(self): + pkg = testutils.create_package(self.project, "pkg") +- mod = testutils.create_module(self.project, "mod", pkg) # noqa ++ mod = testutils.create_module(self.project, "mod", pkg) + result = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), result.type) ++ self.assertTrue(mod is not None) + + def test_simple_class(self): + mod = testutils.create_module(self.project, "mod") +@@ -101,7 +102,8 @@ + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["SampleClass"].get_object() +- var = sample_class["var"] # noqa ++ var = sample_class["var"] ++ self.assertTrue(var is not None) + + def test_class_attributes_set_in_init(self): + mod = testutils.create_module(self.project, "mod") +@@ -112,7 +114,8 @@ + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["C"].get_object() +- var = sample_class["var"] # noqa ++ var = sample_class["var"] ++ self.assertTrue(var is not None) + + def test_class_attributes_set_in_init_overwriting_a_defined(self): + mod = testutils.create_module(self.project, "mod") +@@ -174,7 +177,8 @@ + + def test_get_string_module_with_extra_spaces(self): + code = "a = 10\n " +- mod = libutils.get_string_module(self.project, code) # noqa ++ mod = libutils.get_string_module(self.project, code) ++ self.assertTrue(mod is not None) + + def test_parameter_info_for_functions(self): + code = dedent("""\ +@@ -264,9 +268,10 @@ + self.assertEqual(self.project.get_resource("module.py"), new_module) + + def test_packaged_module_creation(self): +- package = self.project.root.create_folder("package") # noqa ++ package = self.project.root.create_folder("package") + new_module = testutils.create_module(self.project, "package.module") + self.assertEqual(self.project.get_resource("package/module.py"), new_module) ++ self.assertTrue(package is not None) + + def test_packaged_module_creation_with_nested_src(self): + src = self.project.root.create_folder("src") +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,9 +1,9 @@ + def test_nested_modules(self): + pkg = testutils.create_package(self.project, "pkg") +- mod = testutils.create_module(self.project, "mod", pkg) # noqa ++ mod = testutils.create_module(self.project, "mod", pkg) + package = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), package.get_type()) + self.assertEqual(1, len(package.get_attributes())) + module = package["mod"].get_object() + self.assertEqual(get_base_type("Module"), module.get_type()) +- ++ self.assertTrue(mod is not None) +@language python + +def test_nested_modules(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) # noqa + package = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), package.get_type()) + self.assertEqual(1, len(package.get_attributes())) + module = package["mod"].get_object() + self.assertEqual(get_base_type("Module"), module.get_type()) + + +def test_nested_modules(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) + package = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), package.get_type()) + self.assertEqual(1, len(package.get_attributes())) + module = package["mod"].get_object() + self.assertEqual(get_base_type("Module"), module.get_type()) + self.assertTrue(mod is not None) + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,6 +1,7 @@ + def test_package(self): + pkg = testutils.create_package(self.project, "pkg") +- mod = testutils.create_module(self.project, "mod", pkg) # noqa ++ mod = testutils.create_module(self.project, "mod", pkg) + result = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), result.type) ++ self.assertTrue(mod is not None) + +@language python + +def test_package(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) # noqa + result = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), result.type) + + +def test_package(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) + result = self.project.get_module("pkg") + self.assertEqual(get_base_type("Module"), result.type) + self.assertTrue(mod is not None) + + +def write(self, path, data): + self.normal_actions.write(path, data) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -6,5 +6,6 @@ + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["SampleClass"].get_object() +- var = sample_class["var"] # noqa ++ var = sample_class["var"] ++ self.assertTrue(var is not None) + +@language python + +def test_class_variables(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + class SampleClass(object): + var = 10 + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["SampleClass"].get_object() + var = sample_class["var"] # noqa + + +def test_class_variables(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + class SampleClass(object): + var = 10 + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["SampleClass"].get_object() + var = sample_class["var"] + self.assertTrue(var is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -7,5 +7,6 @@ + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["C"].get_object() +- var = sample_class["var"] # noqa ++ var = sample_class["var"] ++ self.assertTrue(var is not None) + +@language python + +def test_class_attributes_set_in_init(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + class C(object): + def __init__(self): + self.var = 20 + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["C"].get_object() + var = sample_class["var"] # noqa + + +def test_class_attributes_set_in_init(self): + mod = testutils.create_module(self.project, "mod") + mod.write(dedent("""\ + class C(object): + def __init__(self): + self.var = 20 + """)) + mod_element = self.project.get_module("mod") + sample_class = mod_element["C"].get_object() + var = sample_class["var"] + self.assertTrue(var is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,4 +1,5 @@ + def test_get_string_module_with_extra_spaces(self): + code = "a = 10\n " +- mod = libutils.get_string_module(self.project, code) # noqa ++ mod = libutils.get_string_module(self.project, code) ++ self.assertTrue(mod is not None) + +@language python + +def test_get_string_module_with_extra_spaces(self): + code = "a = 10\n " + mod = libutils.get_string_module(self.project, code) # noqa + + +def test_get_string_module_with_extra_spaces(self): + code = "a = 10\n " + mod = libutils.get_string_module(self.project, code) + self.assertTrue(mod is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,6 @@ + def test_packaged_module_creation(self): +- package = self.project.root.create_folder("package") # noqa ++ package = self.project.root.create_folder("package") + new_module = testutils.create_module(self.project, "package.module") + self.assertEqual(self.project.get_resource("package/module.py"), new_module) ++ self.assertTrue(package is not None) + +@language python + +def _do(self, args): + _execute(["darcs"] + args, cwd=self.root) + + + +def test_packaged_module_creation(self): + package = self.project.root.create_folder("package") # noqa + new_module = testutils.create_module(self.project, "package.module") + self.assertEqual(self.project.get_resource("package/module.py"), new_module) + + +def test_packaged_module_creation(self): + package = self.project.root.create_folder("package") + new_module = testutils.create_module(self.project, "package.module") + self.assertEqual(self.project.get_resource("package/module.py"), new_module) + self.assertTrue(package is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -53,6 +53,7 @@ + get_base_type("Type"), + sample_func_scope["SampleClass"].get_object().get_type(), + ) ++ self.assertTrue(sample_func_scope is not None) + + def test_list_comprehension_scope_inside_assignment(self): + code = "a_var = [b_var + d_var for b_var, c_var in e_var]\n" +@@ -468,12 +469,13 @@ + """) + scope = libutils.get_string_scope(self.project, code) + +- a_scope = scope["A"].get_object().get_scope() # noqa ++ a_scope = scope["A"].get_object().get_scope() + b_scope = scope["B"].get_object().get_scope() + self.assertTrue("a" in b_scope.get_names()) + self.assertTrue("b" in b_scope.get_names()) + self.assertTrue("a" not in b_scope.get_defined_names()) + self.assertTrue("b" in b_scope.get_defined_names()) ++ self.assertTrue(a_scope is not None) + + def test_getting_defined_names_for_modules(self): + code = dedent("""\ +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -12,4 +12,5 @@ + get_base_type("Type"), + sample_func_scope["SampleClass"].get_object().get_type(), + ) ++ self.assertTrue(sample_func_scope is not None) + +@language python + +def test_classes_inside_function_scopes(self): + code = dedent("""\ + def sample_func(): + class SampleClass(object): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(1, len(scope.get_scopes())) + sample_func_scope = scope.get_scopes()[0] + self.assertEqual( + get_base_type("Type"), + sample_func_scope["SampleClass"].get_object().get_type(), + ) + + +def test_classes_inside_function_scopes(self): + code = dedent("""\ + def sample_func(): + class SampleClass(object): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + self.assertEqual(1, len(scope.get_scopes())) + sample_func_scope = scope.get_scopes()[0] + self.assertEqual( + get_base_type("Type"), + sample_func_scope["SampleClass"].get_object().get_type(), + ) + self.assertTrue(sample_func_scope is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -9,10 +9,11 @@ + """) + scope = libutils.get_string_scope(self.project, code) + +- a_scope = scope["A"].get_object().get_scope() # noqa ++ a_scope = scope["A"].get_object().get_scope() + b_scope = scope["B"].get_object().get_scope() + self.assertTrue("a" in b_scope.get_names()) + self.assertTrue("b" in b_scope.get_names()) + self.assertTrue("a" not in b_scope.get_defined_names()) + self.assertTrue("b" in b_scope.get_defined_names()) ++ self.assertTrue(a_scope is not None) + +@language python + +def test_getting_defined_names_for_classes(self): + code = dedent("""\ + class A(object): + def a(self): + pass + class B(A): + def b(self): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + a_scope = scope["A"].get_object().get_scope() # noqa + b_scope = scope["B"].get_object().get_scope() + self.assertTrue("a" in b_scope.get_names()) + self.assertTrue("b" in b_scope.get_names()) + self.assertTrue("a" not in b_scope.get_defined_names()) + self.assertTrue("b" in b_scope.get_defined_names()) + + +def test_getting_defined_names_for_classes(self): + code = dedent("""\ + class A(object): + def a(self): + pass + class B(A): + def b(self): + pass + """) + scope = libutils.get_string_scope(self.project, code) + + a_scope = scope["A"].get_object().get_scope() + b_scope = scope["B"].get_object().get_scope() + self.assertTrue("a" in b_scope.get_names()) + self.assertTrue("b" in b_scope.get_names()) + self.assertTrue("a" not in b_scope.get_defined_names()) + self.assertTrue("b" in b_scope.get_defined_names()) + self.assertTrue(a_scope is not None) + + +def _execute(args, cwd=None): + process = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE) + process.wait() + return process.returncode + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -4,23 +4,12 @@ + + import rope.base.taskhandle + import rope.refactor.introduce_parameter +-import ropetest.refactor.extracttest +-import ropetest.refactor.importutilstest +-import ropetest.refactor.inlinetest +-import ropetest.refactor.movetest +-import ropetest.refactor.multiprojecttest +-import ropetest.refactor.patchedasttest +-import ropetest.refactor.renametest +-import ropetest.refactor.restructuretest +-import ropetest.refactor.suitestest +-import ropetest.refactor.usefunctiontest + from rope.base.exceptions import RefactoringError, InterruptedTaskError + from rope.refactor.encapsulate_field import EncapsulateField + from rope.refactor.introduce_factory import IntroduceFactory + from rope.refactor.localtofield import LocalToField + from rope.refactor.method_object import MethodObject + from ropetest import testutils +-from ropetest.refactor import change_signature_test, similarfindertest + + + class MethodObjectTest(unittest.TestCase): +@@ -1093,8 +1082,9 @@ + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) +- jobs = handle.create_jobset() # noqa ++ jobs = handle.create_jobset() + self.assertEqual(1, observer.called) ++ self.assertTrue(jobs is not None) + + def test_calling_the_observer_when_starting_and_finishing_jobs(self): + handle = rope.base.taskhandle.TaskHandle() +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -5,23 +5,12 @@ + + import rope.base.taskhandle + import rope.refactor.introduce_parameter +-import ropetest.refactor.extracttest +-import ropetest.refactor.importutilstest +-import ropetest.refactor.inlinetest +-import ropetest.refactor.movetest +-import ropetest.refactor.multiprojecttest +-import ropetest.refactor.patchedasttest +-import ropetest.refactor.renametest +-import ropetest.refactor.restructuretest +-import ropetest.refactor.suitestest +-import ropetest.refactor.usefunctiontest + from rope.base.exceptions import RefactoringError, InterruptedTaskError + from rope.refactor.encapsulate_field import EncapsulateField + from rope.refactor.introduce_factory import IntroduceFactory + from rope.refactor.localtofield import LocalToField + from rope.refactor.method_object import MethodObject + from ropetest import testutils +-from ropetest.refactor import change_signature_test, similarfindertest + + + class MethodObjectTest(unittest.TestCase): +@@ -1094,8 +1083,9 @@ + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) +- jobs = handle.create_jobset() # noqa ++ jobs = handle.create_jobset() + self.assertEqual(1, observer.called) ++ self.assertTrue(jobs is not None) + + def test_calling_the_observer_when_starting_and_finishing_jobs(self): + handle = rope.base.taskhandle.TaskHandle() +@language python + +@path C:/Repos/ekr-rope/rope/ +from textwrap import dedent + +import unittest + +import rope.base.taskhandle +import rope.refactor.introduce_parameter +import ropetest.refactor.extracttest +import ropetest.refactor.importutilstest +import ropetest.refactor.inlinetest +import ropetest.refactor.movetest +import ropetest.refactor.multiprojecttest +import ropetest.refactor.patchedasttest +import ropetest.refactor.renametest +import ropetest.refactor.restructuretest +import ropetest.refactor.suitestest +import ropetest.refactor.usefunctiontest +from rope.base.exceptions import RefactoringError, InterruptedTaskError +from rope.refactor.encapsulate_field import EncapsulateField +from rope.refactor.introduce_factory import IntroduceFactory +from rope.refactor.localtofield import LocalToField +from rope.refactor.method_object import MethodObject +from ropetest import testutils +from ropetest.refactor import change_signature_test, similarfindertest + + +class MethodObjectTest(unittest.TestCase): + def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + def test_empty_method(self): + code = dedent("""\ + def func(): + pass + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __call__(self): + pass + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_trivial_return(self): + code = dedent("""\ + def func(): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_multi_line_header(self): + code = dedent("""\ + def func( + ): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_a_single_parameter(self): + code = dedent("""\ + def func(param): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, param): + self.param = param + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_self_parameter(self): + code = dedent("""\ + def func(self): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, host): + self.self = host + + def __call__(self): + return 1 + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_simple_using_passed_parameters(self): + code = dedent("""\ + def func(param): + return param + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, param): + self.param = param + + def __call__(self): + return self.param + """) + self.assertEqual( + expected, + replacer.get_new_class("_New"), + ) + + def test_self_keywords_and_args_parameters(self): + code = dedent("""\ + def func(arg, *args, **kwds): + result = arg + args[0] + kwds[arg] + return result + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + expected = dedent("""\ + class _New(object): + + def __init__(self, arg, args, kwds): + self.arg = arg + self.args = args + self.kwds = kwds + + def __call__(self): + result = self.arg + self.args[0] + self.kwds[self.arg] + return result + """) + self.assertEqual(expected, replacer.get_new_class("_New")) + + def test_performing_on_not_a_function(self): + code = dedent("""\ + my_var = 10 + """) + self.mod.write(code) + with self.assertRaises(RefactoringError): + MethodObject(self.project, self.mod, code.index("my_var")) + + def test_changing_the_module(self): + code = dedent("""\ + def func(): + return 1 + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + self.project.do(replacer.get_changes("_New")) + expected = dedent("""\ + def func(): + return _New()() + + + class _New(object): + + def __call__(self): + return 1 + """) + self.assertEqual(expected, self.mod.read()) + + def test_changing_the_module_and_class_methods(self): + code = dedent("""\ + class C(object): + + def a_func(self): + return 1 + + def another_func(self): + pass + """) + self.mod.write(code) + replacer = MethodObject(self.project, self.mod, code.index("func")) + self.project.do(replacer.get_changes("_New")) + expected = dedent("""\ + class C(object): + + def a_func(self): + return _New(self)() + + def another_func(self): + pass + + + class _New(object): + + def __init__(self, host): + self.self = host + + def __call__(self): + return 1 + """) + self.assertEqual(expected, self.mod.read()) + + +class IntroduceFactoryTest(unittest.TestCase): + def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + + def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + def _introduce_factory(self, resource, offset, *args, **kwds): + factory_introducer = IntroduceFactory(self.project, resource, offset) + changes = factory_introducer.get_changes(*args, **kwds) + self.project.do(changes) + + def test_adding_the_method(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + def test_changing_occurrences_in_the_main_module(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + a_var = AClass()""") + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + a_var = AClass.create()""") + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + def test_changing_occurrences_with_arguments(self): + code = dedent("""\ + class AClass(object): + def __init__(self, arg): + pass + a_var = AClass(10) + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + def __init__(self, arg): + pass + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + a_var = AClass.create(10) + """) + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + def test_changing_occurrences_in_other_modules(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("import mod1\na_var = mod1.AClass()\n") + self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = dedent("""\ + import mod1 + a_var = mod1.AClass.create() + """) + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + def test_raising_exception_for_non_classes(self): + mod = testutils.create_module(self.project, "mod") + mod.write("def a_func():\n pass\n") + with self.assertRaises(RefactoringError): + self._introduce_factory(mod, mod.read().index("a_func") + 1, "create") + + def test_undoing_introduce_factory(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + code1 = dedent("""\ + class AClass(object): + an_attr = 10 + """) + mod1.write(code1) + code2 = dedent("""\ + from mod1 import AClass + a_var = AClass() + """) + mod2.write(code2) + self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") + self.project.history.undo() + self.assertEqual(code1, mod1.read()) + self.assertEqual(code2, mod2.read()) + + def test_using_on_an_occurrence_outside_the_main_module(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("import mod1\na_var = mod1.AClass()\n") + self._introduce_factory(mod2, mod2.read().index("AClass") + 1, "create") + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = "import mod1\n" "a_var = mod1.AClass.create()\n" + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + def test_introduce_factory_in_nested_scopes(self): + code = dedent("""\ + def create_var(): + class AClass(object): + an_attr = 10 + return AClass() + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + def create_var(): + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + return AClass.create() + """) + self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") + self.assertEqual(expected, mod.read()) + + def test_adding_factory_for_global_factories(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + self._introduce_factory( + mod, mod.read().index("AClass") + 1, "create", global_factory=True + ) + self.assertEqual(expected, mod.read()) + + def test_get_name_for_factories(self): + code = dedent("""\ + class C(object): + pass + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + factory = IntroduceFactory(self.project, mod, mod.read().index("C") + 1) + self.assertEqual("C", factory.get_name()) + + def test_raising_exception_for_global_factory_for_nested_classes(self): + code = dedent("""\ + def create_var(): + class AClass(object): + an_attr = 10 + return AClass() + """) + mod = testutils.create_module(self.project, "mod") + mod.write(code) + with self.assertRaises(RefactoringError): + self._introduce_factory( + mod, mod.read().index("AClass") + 1, "create", global_factory=True + ) + + def test_changing_occurrences_in_the_main_module_for_global_factories(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + a_var = AClass()""") + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + a_var = create()""") + self._introduce_factory( + mod, mod.read().index("AClass") + 1, "create", global_factory=True + ) + self.assertEqual(expected, mod.read()) + + def test_changing_occurrences_in_other_modules_for_global_factories(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("import mod1\na_var = mod1.AClass()\n") + self._introduce_factory( + mod1, mod1.read().index("AClass") + 1, "create", global_factory=True + ) + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = "import mod1\n" "a_var = mod1.create()\n" + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + def test_import_if_necessary_in_other_mods_for_global_factories(self): + mod1 = testutils.create_module(self.project, "mod1") + mod2 = testutils.create_module(self.project, "mod2") + mod1.write("class AClass(object):\n an_attr = 10\n") + mod2.write("from mod1 import AClass\npair = AClass(), AClass\n") + self._introduce_factory( + mod1, mod1.read().index("AClass") + 1, "create", global_factory=True + ) + expected1 = dedent("""\ + class AClass(object): + an_attr = 10 + + def create(*args, **kwds): + return AClass(*args, **kwds) + """) + expected2 = dedent("""\ + from mod1 import AClass, create + pair = create(), AClass + """) + self.assertEqual(expected1, mod1.read()) + self.assertEqual(expected2, mod2.read()) + + def test_changing_occurrences_for_renamed_classes(self): + code = dedent("""\ + class AClass(object): + an_attr = 10 + a_class = AClass + a_var = a_class()""") + mod = testutils.create_module(self.project, "mod") + mod.write(code) + expected = dedent("""\ + class AClass(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return AClass(*args, **kwds) + a_class = AClass + a_var = a_class()""") + self._introduce_factory(mod, mod.read().index("a_class") + 1, "create") + self.assertEqual(expected, mod.read()) + + def test_changing_occurrs_in_the_same_module_with_conflict_ranges(self): + mod = testutils.create_module(self.project, "mod") + code = dedent("""\ + class C(object): + def create(self): + return C() + """) + mod.write(code) + self._introduce_factory(mod, mod.read().index("C"), "create_c", True) + expected = dedent("""\ + class C(object): + def create(self): + return create_c() + """) + self.assertTrue(mod.read().startswith(expected)) + + def _transform_module_to_package(self, resource): + self.project.do( + rope.refactor.ModuleToPackage(self.project, resource).get_changes() + ) + + def test_transform_module_to_package(self): + mod1 = testutils.create_module(self.project, "mod1") + mod1.write("import mod2\nfrom mod2 import AClass\n") + mod2 = testutils.create_module(self.project, "mod2") + mod2.write("class AClass(object):\n pass\n") + self._transform_module_to_package(mod2) + mod2 = self.project.get_resource("mod2") + root_folder = self.project.root + self.assertFalse(root_folder.has_child("mod2.py")) + self.assertEqual( + "class AClass(object):\n pass\n", + root_folder.get_child("mod2").get_child("__init__.py").read(), + ) + + def test_transform_module_to_package_undoing(self): + pkg = testutils.create_package(self.project, "pkg") + mod = testutils.create_module(self.project, "mod", pkg) + self._transform_module_to_package(mod) + self.assertFalse(pkg.has_child("mod.py")) + self.assertTrue(pkg.get_child("mod").has_child("__init__.py")) + self.project.history.undo() + self.assertTrue(pkg.has_child("mod.py")) + self.assertFalse(pkg.has_child("mod")) + + def test_transform_module_to_package_with_relative_imports(self): + pkg = testutils.create_package(self.project, "pkg") + mod1 = testutils.create_module(self.project, "mod1", pkg) + mod1.write("import mod2\nfrom mod2 import AClass\n") + mod2 = testutils.create_module(self.project, "mod2", pkg) + mod2.write("class AClass(object):\n pass\n") + self._transform_module_to_package(mod1) + new_init = self.project.get_resource("pkg/mod1/__init__.py") + self.assertEqual( + "import pkg.mod2\nfrom pkg.mod2 import AClass\n", new_init.read() + ) + + def test_resources_parameter(self): + code = dedent("""\ + class A(object): + an_attr = 10 + """) + code1 = dedent("""\ + import mod + a = mod.A() + """) + mod = testutils.create_module(self.project, "mod") + mod1 = testutils.create_module(self.project, "mod1") + mod.write(code) + mod1.write(code1) + expected = dedent("""\ + class A(object): + an_attr = 10 + + @staticmethod + def create(*args, **kwds): + return A(*args, **kwds) + """) + self._introduce_factory( + mod, mod.read().index("A") + 1, "create", resources=[mod] + ) + self.assertEqual(expected, mod.read()) + self.assertEqual(code1, mod1.read()) + + +class EncapsulateFieldTest(unittest.TestCase): + def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + self.mod1 = testutils.create_module(self.project, "mod1") + self.a_class = dedent("""\ + class A(object): + def __init__(self): + self.attr = 1 + """) + self.added_methods = ( + "\n" + " def get_attr(self):\n" + " return self.attr\n\n" + " def set_attr(self, value):\n" + " self.attr = value\n" + ) + self.encapsulated = self.a_class + self.added_methods + + def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + def _encapsulate(self, resource, offset, **args): + changes = EncapsulateField(self.project, resource, offset).get_changes(**args) + self.project.do(changes) + + def test_adding_getters_and_setters(self): + code = self.a_class + self.mod.write(code) + self._encapsulate(self.mod, code.index("attr") + 1) + self.assertEqual(self.encapsulated, self.mod.read()) + + def test_changing_getters_in_other_modules(self): + code = dedent("""\ + import mod + a_var = mod.A() + range(a_var.attr) + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + range(a_var.get_attr()) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_setters_in_other_modules(self): + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(1) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_getters_in_setters(self): + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + a_var.attr + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(1 + a_var.get_attr()) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_appending_to_class_end(self): + self.mod1.write(self.a_class + "a_var = A()\n") + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + self.assertEqual(self.encapsulated + "a_var = A()\n", self.mod1.read()) + + def test_performing_in_other_modules(self): + code = dedent("""\ + import mod + a_var = mod.A() + range(a_var.attr) + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + self.assertEqual(self.encapsulated, self.mod.read()) + expected = dedent("""\ + import mod + a_var = mod.A() + range(a_var.get_attr()) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_main_module_occurrences(self): + code = self.a_class + "a_var = A()\n" "a_var.attr = a_var.attr * 2\n" + self.mod1.write(code) + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + expected = ( + self.encapsulated + "a_var = A()\n" "a_var.set_attr(a_var.get_attr() * 2)\n" + ) + self.assertEqual(expected, self.mod1.read()) + + def test_raising_exception_when_performed_on_non_attributes(self): + self.mod1.write("attr = 10") + with self.assertRaises(RefactoringError): + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + + def test_raising_exception_on_tuple_assignments(self): + self.mod.write(self.a_class) + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + a_var.attr, b = 1, 2 + """) + self.mod1.write(code) + with self.assertRaises(RefactoringError): + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + + def test_raising_exception_on_tuple_assignments2(self): + self.mod.write(self.a_class) + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr = 1 + b, a_var.attr = 1, 2 + """) + self.mod1.write(code) + with self.assertRaises(RefactoringError): + self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) + + def test_tuple_assignments_and_function_calls(self): + code = dedent("""\ + import mod + def func(a1=0, a2=0): + pass + a_var = mod.A() + func(a_var.attr, a2=2) + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + def func(a1=0, a2=0): + pass + a_var = mod.A() + func(a_var.get_attr(), a2=2) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_tuple_assignments(self): + code = dedent("""\ + import mod + a_var = mod.A() + a, b = a_var.attr, 1 + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a, b = a_var.get_attr(), 1 + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_augmented_assignments(self): + code = "import mod\n" "a_var = mod.A()\n" "a_var.attr += 1\n" + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(a_var.get_attr() + 1) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_augmented_assignments2(self): + code = dedent("""\ + import mod + a_var = mod.A() + a_var.attr <<= 1 + """) + self.mod1.write(code) + self.mod.write(self.a_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = dedent("""\ + import mod + a_var = mod.A() + a_var.set_attr(a_var.get_attr() << 1) + """) + self.assertEqual(expected, self.mod1.read()) + + def test_changing_occurrences_inside_the_class(self): + new_class = ( + self.a_class + "\n" " def a_func(self):\n" " self.attr = 1\n" + ) + self.mod.write(new_class) + self._encapsulate(self.mod, self.mod.read().index("attr") + 1) + expected = ( + self.a_class + "\n" + " def a_func(self):\n" + " self.set_attr(1)\n" + self.added_methods + ) + self.assertEqual(expected, self.mod.read()) + + def test_getter_and_setter_parameters(self): + self.mod.write(self.a_class) + self._encapsulate( + self.mod, + self.mod.read().index("attr") + 1, + getter="getAttr", + setter="setAttr", + ) + new_methods = self.added_methods.replace("get_attr", "getAttr").replace( + "set_attr", "setAttr" + ) + expected = self.a_class + new_methods + self.assertEqual(expected, self.mod.read()) + + def test_using_resources_parameter(self): + self.mod1.write("import mod\na = mod.A()\nvar = a.attr\n") + self.mod.write(self.a_class) + self._encapsulate( + self.mod, self.mod.read().index("attr") + 1, resources=[self.mod] + ) + self.assertEqual("import mod\na = mod.A()\nvar = a.attr\n", self.mod1.read()) + expected = self.a_class + self.added_methods + self.assertEqual(expected, self.mod.read()) + + +class LocalToFieldTest(unittest.TestCase): + def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + def _perform_convert_local_variable_to_field(self, resource, offset): + changes = LocalToField(self.project, resource, offset).get_changes() + self.project.do(changes) + + def test_simple_local_to_field(self): + code = dedent("""\ + class A(object): + def a_func(self): + var = 10 + """) + self.mod.write(code) + self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) + expected = dedent("""\ + class A(object): + def a_func(self): + self.var = 10 + """) + self.assertEqual(expected, self.mod.read()) + + def test_raising_exception_when_performed_on_a_global_var(self): + self.mod.write("var = 10\n") + with self.assertRaises(RefactoringError): + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().index("var") + 1 + ) + + def test_raising_exception_when_performed_on_field(self): + code = dedent("""\ + class A(object): + def a_func(self): + self.var = 10 + """) + self.mod.write(code) + with self.assertRaises(RefactoringError): + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().index("var") + 1 + ) + + def test_raising_exception_when_performed_on_a_parameter(self): + code = dedent("""\ + class A(object): + def a_func(self, var): + a = var + """) + self.mod.write(code) + with self.assertRaises(RefactoringError): + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().index("var") + 1 + ) + + # NOTE: This situation happens alot and is normally not an error + # @testutils.assert_raises(RefactoringError) + def test_not_rais_exception_when_there_is_a_field_with_the_same_name(self): + code = dedent("""\ + class A(object): + def __init__(self): + self.var = 1 + def a_func(self): + var = 10 + """) + self.mod.write(code) + self._perform_convert_local_variable_to_field( + self.mod, self.mod.read().rindex("var") + 1 + ) + + def test_local_to_field_with_self_renamed(self): + code = dedent("""\ + class A(object): + def a_func(myself): + var = 10 + """) + self.mod.write(code) + self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) + expected = dedent("""\ + class A(object): + def a_func(myself): + myself.var = 10 + """) + self.assertEqual(expected, self.mod.read()) + + +class IntroduceParameterTest(unittest.TestCase): + def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.pycore = self.project.pycore + self.mod = testutils.create_module(self.project, "mod") + + def tearDown(self): + testutils.remove_project(self.project) + super().tearDown() + + def _introduce_parameter(self, offset, name): + rope.refactor.introduce_parameter.IntroduceParameter( + self.project, self.mod, offset + ).get_changes(name).do() + + def test_simple_case(self): + code = dedent("""\ + var = 1 + def f(): + b = var + """) + self.mod.write(code) + offset = self.mod.read().rindex("var") + self._introduce_parameter(offset, "var") + expected = dedent("""\ + var = 1 + def f(var=var): + b = var + """) + self.assertEqual(expected, self.mod.read()) + + def test_changing_function_body(self): + code = dedent("""\ + var = 1 + def f(): + b = var + """) + self.mod.write(code) + offset = self.mod.read().rindex("var") + self._introduce_parameter(offset, "p1") + expected = dedent("""\ + var = 1 + def f(p1=var): + b = p1 + """) + self.assertEqual(expected, self.mod.read()) + + def test_unknown_variables(self): + self.mod.write("def f():\n b = var + c\n") + offset = self.mod.read().rindex("var") + with self.assertRaises(RefactoringError): + self._introduce_parameter(offset, "p1") + self.assertEqual("def f(p1=var):\n b = p1 + c\n", self.mod.read()) + + def test_failing_when_not_inside(self): + self.mod.write("var = 10\nb = var\n") + offset = self.mod.read().rindex("var") + with self.assertRaises(RefactoringError): + self._introduce_parameter(offset, "p1") + + def test_attribute_accesses(self): + code = dedent("""\ + class C(object): + a = 10 + c = C() + def f(): + b = c.a + """) + self.mod.write(code) + offset = self.mod.read().rindex("a") + self._introduce_parameter(offset, "p1") + expected = dedent("""\ + class C(object): + a = 10 + c = C() + def f(p1=c.a): + b = p1 + """) + self.assertEqual(expected, self.mod.read()) + + def test_introducing_parameters_for_methods(self): + code = dedent("""\ + var = 1 + class C(object): + def f(self): + b = var + """) + self.mod.write(code) + offset = self.mod.read().rindex("var") + self._introduce_parameter(offset, "p1") + expected = dedent("""\ + var = 1 + class C(object): + def f(self, p1=var): + b = p1 + """) + self.assertEqual(expected, self.mod.read()) + + +class _MockTaskObserver: + def __init__(self): + self.called = 0 + + def __call__(self): + self.called += 1 + + +class TaskHandleTest(unittest.TestCase): + def test_trivial_case(self): + handle = rope.base.taskhandle.TaskHandle() + self.assertFalse(handle.is_stopped()) + + def test_stopping(self): + handle = rope.base.taskhandle.TaskHandle() + handle.stop() + self.assertTrue(handle.is_stopped()) + + def test_job_sets(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset() + self.assertEqual([jobs], handle.get_jobsets()) + + def test_starting_and_finishing_jobs(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset(name="test job set", count=1) + jobs.started_job("job1") + jobs.finished_job() + + def test_test_checking_status(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset() + handle.stop() + with self.assertRaises(InterruptedTaskError): + jobs.check_status() + + def test_test_checking_status_when_starting(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset() + handle.stop() + with self.assertRaises(InterruptedTaskError): + jobs.started_job("job1") + + def test_calling_the_observer_after_stopping(self): + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) + handle.stop() + self.assertEqual(1, observer.called) + + def test_calling_the_observer_after_creating_job_sets(self): + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) + jobs = handle.create_jobset() # noqa + self.assertEqual(1, observer.called) + + def test_calling_the_observer_when_starting_and_finishing_jobs(self): + handle = rope.base.taskhandle.TaskHandle() + observer = _MockTaskObserver() + handle.add_observer(observer) + jobs = handle.create_jobset(name="test job set", count=1) + jobs.started_job("job1") + jobs.finished_job() + self.assertEqual(3, observer.called) + + def test_job_set_get_percent_done(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset(name="test job set", count=2) + self.assertEqual(0, jobs.get_percent_done()) + jobs.started_job("job1") + jobs.finished_job() + self.assertEqual(50, jobs.get_percent_done()) + jobs.started_job("job2") + jobs.finished_job() + self.assertEqual(100, jobs.get_percent_done()) + + def test_getting_job_name(self): + handle = rope.base.taskhandle.TaskHandle() + jobs = handle.create_jobset(name="test job set", count=1) + # recommended name/job_name attribute + self.assertEqual("test job set", jobs.name) + self.assertEqual(None, jobs.job_name) + # deprecated getters + self.assertEqual("test job set", jobs.get_name()) + self.assertEqual(None, jobs.get_active_job_name()) + jobs.started_job("job1") + # recommended name/job_name attribute + self.assertEqual("test job set", jobs.get_name()) + # deprecated getters + self.assertEqual("job1", jobs.get_active_job_name()) +@language python +@tabwidth -4 + +@path C:/Repos/ekr-rope/rope/ +"""rope, a python refactoring library""" + +from pkg_resources import get_distribution, DistributionNotFound + +try: + VERSION = get_distribution("rope").version +except DistributionNotFound: + + def get_fallback_version(): + import re + import pathlib + + pyproject = ( + pathlib.Path(__file__).resolve().parent.parent / "pyproject.toml" + ).read_text() + version = re.search("version.*=.*'(.*)'", pyproject) + return version.group(1) if version else None + + VERSION = get_fallback_version() + + +INFO = __doc__ +COPYRIGHT = """\ +Copyright (C) 2021-2022 Lie Ryan +Copyright (C) 2019-2021 Matej Cepl +Copyright (C) 2015-2018 Nicholas Smith +Copyright (C) 2014-2015 Matej Cepl +Copyright (C) 2006-2012 Ali Gholami Rudi +Copyright (C) 2009-2012 Anton Gritsay + +This program is free software: you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation, either +version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this program. If not, see +<https://www.gnu.org/licenses/>.""" +@language python +@tabwidth -4 + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -21,8 +21,10 @@ + p1 = testutils.create_package(self.project, "p1") + p2 = testutils.create_package(self.project, "p2", p1) + p3 = testutils.create_package(self.project, "p3", p2) +- m1 = testutils.create_module(self.project, "m1", p3) # noqa +- l = testutils.create_module(self.project, "l", p3) # noqa ++ m1 = testutils.create_module(self.project, "m1", p3) ++ mod_l = testutils.create_module(self.project, "l", p3) ++ self.assertTrue(m1 is not None) ++ self.assertTrue(mod_l is not None) + + def tearDown(self): + testutils.remove_project(self.project) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -12,6 +12,8 @@ + p1 = testutils.create_package(self.project, "p1") + p2 = testutils.create_package(self.project, "p2", p1) + p3 = testutils.create_package(self.project, "p3", p2) +- m1 = testutils.create_module(self.project, "m1", p3) # noqa +- l = testutils.create_module(self.project, "l", p3) # noqa ++ m1 = testutils.create_module(self.project, "m1", p3) ++ mod_l = testutils.create_module(self.project, "l", p3) ++ self.assertTrue(m1 is not None) ++ self.assertTrue(mod_l is not None) + +@language python + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.import_tools = ImportTools(self.project) + + self.mod = testutils.create_module(self.project, "mod") + self.pkg1 = testutils.create_package(self.project, "pkg1") + self.mod1 = testutils.create_module(self.project, "mod1", self.pkg1) + self.pkg2 = testutils.create_package(self.project, "pkg2") + self.mod2 = testutils.create_module(self.project, "mod2", self.pkg2) + self.mod3 = testutils.create_module(self.project, "mod3", self.pkg2) + p1 = testutils.create_package(self.project, "p1") + p2 = testutils.create_package(self.project, "p2", p1) + p3 = testutils.create_package(self.project, "p3", p2) + m1 = testutils.create_module(self.project, "m1", p3) # noqa + l = testutils.create_module(self.project, "l", p3) # noqa + + +def setUp(self): + super().setUp() + self.project = testutils.sample_project() + self.import_tools = ImportTools(self.project) + + self.mod = testutils.create_module(self.project, "mod") + self.pkg1 = testutils.create_package(self.project, "pkg1") + self.mod1 = testutils.create_module(self.project, "mod1", self.pkg1) + self.pkg2 = testutils.create_package(self.project, "pkg2") + self.mod2 = testutils.create_module(self.project, "mod2", self.pkg2) + self.mod3 = testutils.create_module(self.project, "mod3", self.pkg2) + p1 = testutils.create_package(self.project, "p1") + p2 = testutils.create_package(self.project, "p2", p1) + p3 = testutils.create_package(self.project, "p3", p2) + m1 = testutils.create_module(self.project, "m1", p3) + mod_l = testutils.create_module(self.project, "l", p3) + self.assertTrue(m1 is not None) + self.assertTrue(mod_l is not None) + + +def unicode_to_file_data(contents: str, encoding=None, newlines=None) -> FileContent: + assert isinstance(contents, str) + if newlines and newlines != "\n": + contents = contents.replace("\n", newlines) + if encoding is None: + encoding = read_str_coding(contents) + if encoding is not None: + return FileContent(contents.encode(encoding)) + try: + return FileContent(contents.encode()) + except UnicodeEncodeError: + return FileContent(contents.encode("utf-8")) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -314,6 +314,7 @@ + mover = move.create_move( + self.project, self.mod1, code.index("CONSTANT") + 1 + ) ++ self.assertTrue(mover is not None) + + def test_raising_exception_for_mov_glob_elemnts_to_the_same_module(self): + self.mod1.write("def a_func():\n pass\n") +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -8,4 +8,5 @@ + mover = move.create_move( + self.project, self.mod1, code.index("CONSTANT") + 1 + ) ++ self.assertTrue(mover is not None) + +@language python + +def test_raising_an_exception_for_moving_non_global_variable(self): + code = dedent("""\ + class TestClass: + CONSTANT = 5 + """) + self.mod1.write(code) + with self.assertRaises(exceptions.RefactoringError): + mover = move.create_move( + self.project, self.mod1, code.index("CONSTANT") + 1 + ) + + +def test_raising_an_exception_for_moving_non_global_variable(self): + code = dedent("""\ + class TestClass: + CONSTANT = 5 + """) + self.mod1.write(code) + with self.assertRaises(exceptions.RefactoringError): + mover = move.create_move( + self.project, self.mod1, code.index("CONSTANT") + 1 + ) + self.assertTrue(mover is not None) + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1558,7 +1558,6 @@ + ")", + ]) + +- + @testutils.only_for_versions_higher("3.10") + def test_match_node_with_match_mapping_match_as(self): + source = dedent("""\ +@@ -1587,8 +1586,6 @@ + "", + "}", + ]) +- +- + class _ResultChecker: + def __init__(self, test_case, ast): + self.test_case = test_case +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -24,7 +24,6 @@ + "", + ")", + ]) +- + + @testutils.only_for_versions_higher("3.10") + def test_match_node_with_match_mapping_match_as(self): +@@ -54,5 +53,3 @@ + "", + "}", + ]) +- +- +@language python + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name(self): + source = dedent("""\ + match x: + case Foo(x) as b: + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "MatchClass", + " ", + "as", + " ", + "b", + ]) + checker.check_children("MatchClass", [ + "Name", + "", + "(", + "", + "MatchAs", + "", + ")", + ]) + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_mapping_match_as(self): + source = dedent("""\ + match x: + case {"a": b} as c: + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "MatchMapping", + " ", + "as", + " ", + "c", + ]) + checker.check_children("MatchMapping", [ + "{", + "", + "Constant", + "", + ":", + " ", + "MatchAs", + "", + "}", + ]) + + + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name(self): + source = dedent("""\ + match x: + case Foo(x) as b: + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "MatchClass", + " ", + "as", + " ", + "b", + ]) + checker.check_children("MatchClass", [ + "Name", + "", + "(", + "", + "MatchAs", + "", + ")", + ]) + +@testutils.only_for_versions_higher("3.10") +def test_match_node_with_match_mapping_match_as(self): + source = dedent("""\ + match x: + case {"a": b} as c: + print(x) + """) + ast_frag = patchedast.get_patched_ast(source, True) + checker = _ResultChecker(self, ast_frag) + self.assert_single_case_match_block(checker, "MatchAs") + checker.check_children("MatchAs", [ + "MatchMapping", + " ", + "as", + " ", + "c", + ]) + checker.check_children("MatchMapping", [ + "{", + "", + "Constant", + "", + ":", + " ", + "MatchAs", + "", + "}", + ]) + +def consume(self, token, skip_comment=True): + try: + while True: + new_offset = self.source.index(token, self.offset) + if self._good_token(token, new_offset) or not skip_comment: + break + else: + self._skip_comment() + except (ValueError, TypeError): + raise MismatchedTokenError( + "Token <{}> at {} cannot be matched".format(token, self._get_location()) + ) + self.offset = new_offset + len(token) + return (new_offset, self.offset) + + +def file_data_to_unicode(data, encoding=None): + result = _decode_data(data, encoding) + newline = "\n" + if "\r\n" in result: + result = result.replace("\r\n", "\n") + newline = "\r\n" + if "\r" in result: + result = result.replace("\r", "\n") + newline = "\r" + return result, newline + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,12 +2,12 @@ + import shutil + import sys + import logging +- +-logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) + import unittest + + import rope.base.project + from rope.contrib import generate ++ ++logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) + + + def sample_project(root=None, foldername=None, **kwds): +@@ -51,7 +51,7 @@ + + # windows sometimes raises exceptions instead of removing files + if os.name == "nt" or sys.platform == "cygwin": +- for i in range(12): ++ for _i in range(12): + try: + _remove_recursively(path) + except OSError as e: +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -3,13 +3,13 @@ + import shutil + import sys + import logging +- +-logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) + import unittest + + import rope.base.project + from rope.contrib import generate + ++logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) ++ + + @others + @language python +@language python + +@path C:/Repos/ekr-rope/ropetest/ +import os.path +import shutil +import sys +import logging + +logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) +import unittest + +import rope.base.project +from rope.contrib import generate + + +@others +@language python +@tabwidth -4 + +@path C:/Repos/ekr-rope/ropetest/ +import os.path +import shutil +import sys +import logging + +logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) +import unittest + +import rope.base.project +from rope.contrib import generate + + +@others +@language python +@tabwidth -4 + +def sample_project(root=None, foldername=None, **kwds): + if root is None: + root = "sample_project" + if foldername: + root = foldername + # HACK: Using ``/dev/shm/`` for faster tests + if os.name == "posix": + if os.path.isdir("/dev/shm") and os.access("/dev/shm", os.W_OK): + root = "/dev/shm/" + root + elif os.path.isdir("/tmp") and os.access("/tmp", os.W_OK): + root = "/tmp/" + root + logging.debug("Using %s as root of the project.", root) + # Using these prefs for faster tests + prefs = { + "save_objectdb": False, + "save_history": False, + "validate_objectdb": False, + "automatic_soa": False, + "ignored_resources": [".ropeproject", "*.pyc"], + "import_dynload_stdmods": False, + } + prefs.update(kwds) + remove_recursively(root) + project = rope.base.project.Project(root, **prefs) + return project + + + +create_module = generate.create_module +create_package = generate.create_package + + + +def remove_project(project): + project.close() + remove_recursively(project.address) + + + +def _remove_recursively(path): + if not os.path.exists(path): + return + if os.path.isfile(path): + os.remove(path) + else: + shutil.rmtree(path) + + + +def _decode_data(data, encoding): + if isinstance(data, str): + return data + if encoding is None: + encoding = read_str_coding(data) + if encoding is None: + # there is no encoding tip, we need to guess. + # PEP263 says that "encoding not explicitly defined" means it is ascii, + # but we will use utf8 instead since utf8 fully covers ascii and btw is + # the only non-latin sane encoding. + encoding = "utf-8" + try: + return data.decode(encoding) + except (UnicodeError, LookupError): + # fallback to latin1: it should never fail + return data.decode("latin1") + + + +def parse_version(version): + return tuple(map(int, version.split("."))) + + + +def only_for(version): + """Should be used as a decorator for a unittest.TestCase test method""" + return unittest.skipIf( + sys.version_info < parse_version(version), + "This test requires at least {0} version of Python.".format(version), + ) + + + +def only_for_versions_lower(version): + """Should be used as a decorator for a unittest.TestCase test method""" + return unittest.skipIf( + sys.version_info > parse_version(version), + "This test requires version of Python lower than {0}".format(version), + ) + + + +def only_for_versions_higher(version): + """Should be used as a decorator for a unittest.TestCase test method""" + return unittest.skipIf( + sys.version_info < parse_version(version), + "This test requires version of Python higher than {0}".format(version), + ) + + + +def skipNotPOSIX(): + return unittest.skipIf(os.name != "posix", "This test works only on POSIX") + + + +def time_limit(timeout): + if not any(procname in sys.argv[0] for procname in {"pytest", "py.test"}): + # no-op when running tests without pytest + return lambda *args, **kwargs: lambda func: func + + # do a local import so we don't import pytest when running without pytest + import pytest + + # this prevents infinite loop/recursion from taking forever in CI + return pytest.mark.time_limit(timeout) + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -3,7 +3,7 @@ + + # windows sometimes raises exceptions instead of removing files + if os.name == "nt" or sys.platform == "cygwin": +- for i in range(12): ++ for _i in range(12): + try: + _remove_recursively(path) + except OSError as e: +@language python + +def remove_recursively(path): + import time + + # windows sometimes raises exceptions instead of removing files + if os.name == "nt" or sys.platform == "cygwin": + for i in range(12): + try: + _remove_recursively(path) + except OSError as e: + if e.errno not in (13, 16, 32): + raise + time.sleep(0.3) + else: + break + else: + _remove_recursively(path) + + + +def remove_recursively(path): + import time + + # windows sometimes raises exceptions instead of removing files + if os.name == "nt" or sys.platform == "cygwin": + for i in range(12): + try: + _remove_recursively(path) + except OSError as e: + if e.errno not in (13, 16, 32): + raise + time.sleep(0.3) + else: + break + else: + _remove_recursively(path) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,3 +1,3 @@ + from setuptools import setup + +-setup()+setup() + +def read_str_coding(source): + # as defined by PEP-263 (https://www.python.org/dev/peps/pep-0263/) + CODING_LINE_PATTERN = b"^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)" + + if type(source) == bytes: + newline = b"\n" + CODING_LINE_PATTERN = re.compile(CODING_LINE_PATTERN) + else: + newline = "\n" + CODING_LINE_PATTERN = re.compile(CODING_LINE_PATTERN.decode("ascii")) + for line in source.split(newline, 2)[:2]: + if re.match(CODING_LINE_PATTERN, line): + return _find_coding(line) + else: + return + + + +def _find_coding(text): + if isinstance(text, str): + text = text.encode("utf-8") + coding = b"coding" + to_chr = chr + try: + start = text.index(coding) + len(coding) + if text[start] not in b"=:": + return + start += 1 + while start < len(text) and to_chr(text[start]).isspace(): + start += 1 + end = start + while end < len(text): + c = text[end] + if not to_chr(c).isalnum() and c not in b"-_": + break + end += 1 + result = text[start:end] + if isinstance(result, bytes): + result = result.decode("utf-8") + return result + except ValueError: + pass + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -30,9 +30,7 @@ + pycore, pyfunction, return_true, return_false, new_followed_calls + ) + +- if not followed_calls: +- _follow = None +- visitor = SOAVisitor(pycore, pydefined, _follow) ++ visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None) + for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): + rope.base.ast.walk(child, visitor) +@language python + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -14,9 +14,7 @@ + pycore, pyfunction, return_true, return_false, new_followed_calls + ) + +- if not followed_calls: +- _follow = None +- visitor = SOAVisitor(pycore, pydefined, _follow) ++ visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None) + for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): + rope.base.ast.walk(child, visitor) + +@language python + +def _analyze_node(pycore, pydefined, should_analyze, search_subscopes, followed_calls): + if search_subscopes(pydefined): + for scope in pydefined.get_scope().get_scopes(): + _analyze_node( + pycore, scope.pyobject, should_analyze, search_subscopes, followed_calls + ) + if should_analyze(pydefined): + new_followed_calls = max(0, followed_calls - 1) + return_true = lambda pydefined: True + return_false = lambda pydefined: False + + def _follow(pyfunction): + _analyze_node( + pycore, pyfunction, return_true, return_false, new_followed_calls + ) + + if not followed_calls: + _follow = None + visitor = SOAVisitor(pycore, pydefined, _follow) + for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): + rope.base.ast.walk(child, visitor) + + + +def _analyze_node(pycore, pydefined, should_analyze, search_subscopes, followed_calls): + if search_subscopes(pydefined): + for scope in pydefined.get_scope().get_scopes(): + _analyze_node( + pycore, scope.pyobject, should_analyze, search_subscopes, followed_calls + ) + if should_analyze(pydefined): + new_followed_calls = max(0, followed_calls - 1) + return_true = lambda pydefined: True + return_false = lambda pydefined: False + + def _follow(pyfunction): + _analyze_node( + pycore, pyfunction, return_true, return_false, new_followed_calls + ) + + visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None) + for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): + rope.base.ast.walk(child, visitor) + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,7 +1,6 @@ + # Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm + # and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py + import re +-from rope.base.utils import pycompat + from rope.base.oi.type_hinting import utils + from rope.base import utils as base_utils + +@@ -268,7 +267,7 @@ + + + @method(symbol("[")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa + return utils.parametrize_type( + self.first.evaluate(pyobject), *[i.evaluate(pyobject) for i in self.second] + ) +@@ -276,7 +275,7 @@ + + # Anonymous Function Calls + @method(symbol("(")) +-def nud(self, parser): ++def nud(self, parser): # noqa + self.second = [] + if parser.token.name != ")": + while 1: +@@ -292,7 +291,7 @@ + + # Function Calls + @method(symbol("(")) +-def led(self, left, parser): ++def led(self, left, parser): # noqa + self.first = left + self.second = [] + if parser.token.name != ")": +@@ -308,14 +307,14 @@ + + + @method(symbol("(")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa + # TODO: Implement me + raise NotImplementedError + + + @method(symbol("or")) + @method(symbol("|")) +-def evaluate(self, pyobject): ++def evaluate(self, pyobject): # noqa + # TODO: Implement me + raise NotImplementedError + +@@ -355,4 +354,4 @@ + return ast.evaluate(pyobject) + + +-evaluate = Evaluator() ++evaluate = Evaluator() # noqa +@language python + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -2,7 +2,6 @@ + # Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm + # and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py + import re +-from rope.base.utils import pycompat + from rope.base.oi.type_hinting import utils + from rope.base import utils as base_utils + +@language python + +@path C:/Repos/ekr-rope/rope/base/ +# Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm +# and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py +import re +from rope.base.utils import pycompat +from rope.base.oi.type_hinting import utils +from rope.base import utils as base_utils + + +class SymbolBase: + + name = None # node/token type name + + def __init__(self): + self.value = None # used by name and literals + self.first = None + self.second = None + self.third = None # used by tree nodes + + def nud(self, parser): + raise SyntaxError("Syntax error (%r)." % self.name) + + def led(self, left, parser): + raise SyntaxError("Unknown operator (%r)." % self.name) + + def evaluate(self, pyobject): + raise NotImplementedError(self.name, self) + + def __repr__(self): + if self.name == "(name)": + return "({} {})".format(self.name[1:-1], self.value) + out = [repr(self.name), self.first, self.second, self.third] + out = [str(i) for i in out if i] + return "(" + " ".join(out) + ")" + + +class SymbolTable: + def multi(func): + def _inner(self, names, *a, **kw): + for name in names.split(): + func(self, name, *a, **kw) + + return _inner + + def __init__(self): + self.symbol_table = {} + + def get(self, name, default=None): + return self.symbol_table.get(name, default) + + def __getitem__(self, name): + return self.symbol_table[name] + + def __iter__(self): + return iter(self.symbol_table) + + def symbol(self, name, bp=0): + try: + s = self.symbol_table[name] + except KeyError: + + class S(SymbolBase): + pass + + s = S + s.__name__ = "symbol-" + name # for debugging + s.name = name + s.lbp = bp + self.symbol_table[name] = s + else: + s.lbp = max(bp, s.lbp) + return s + + @multi + def infix(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def led(self, left, parser): + self.first = left + self.second = parser.expression(bp) + return self + + @multi + def infix_r(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def led(self, left, parser): + self.first = left + self.second = parser.expression(bp - 0.1) + return self + + def ternary(self, name, name2, bp): + symbol = self.symbol(name, bp) + symbol2 = self.symbol(name2) + + @method(symbol) + def led(self, left, parser): + self.first = left + self.second = parser.expression(symbol2.lbp) + parser.advance(symbol2.name) + self.third = parser.expression(symbol2.lbp + 0.1) + return self + + @multi + def prefix(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def nud(self, parser): + self.first = parser.expression(bp) + return self + + @multi + def postfix(self, name, bp): + symbol = self.symbol(name, bp) + + @method(symbol) + def led(self, left, parser): + self.first = left + return self + + multi = staticmethod(multi) # Just for code checker + + +symbol_table = SymbolTable() + + +class Lexer: + + _token_pattern = re.compile( + r""" + \s* + (?: + ( + [,()\[\]|] + | -> + | (?<=\s)(?:or)\b + ) # operator + | ([a-zA-Z](?:\w|\.)*) # name + ) + """, + re.U | re.S | re.X, + ) + + def __init__(self, symbol_table): + self.symbol_table = symbol_table + + def tokenize(self, program): + for name, value in self._tokenize_expr(program): + symbol = symbol_table.get(value) + if symbol: + s = symbol() + elif name == "(name)": + symbol = symbol_table[name] + s = symbol() + s.value = value + else: + raise SyntaxError( + "Unknown operator ({}). Possible operators are {!r}".format( + value, list(self.symbol_table) + ) + ) + + yield s + + def _tokenize_expr(self, program): + if isinstance(program, bytes): + program = program.decode("utf-8") + # import pprint; pprint.pprint(self._token_pattern.findall(program)) + for operator, name in self._token_pattern.findall(program): + if operator: + yield "(operator)", operator + elif name: + yield "(name)", name + else: + raise SyntaxError + yield "(end)", "(end)" + + +class Parser: + + token = None + next = None + + def __init__(self, lexer): + self.lexer = lexer + + def parse(self, program): + generator = self.lexer.tokenize(program) + self.next = generator.__next__ + self.token = self.next() + return self.expression() + + def expression(self, rbp=0): + t = self.token + self.token = self.next() + left = t.nud(self) + while rbp < self.token.lbp: + t = self.token + self.token = self.next() + left = t.led(left, self) + return left + + def advance(self, name=None): + if name and self.token.name != name: + raise SyntaxError(f"Expected {name!r} but found {self.token.name!r}") + self.token = self.next() + + +def method(s): + assert issubclass(s, SymbolBase) + + def bind(fn): + setattr(s, fn.__name__, fn) + return fn + + return bind + + +symbol, infix, infix_r, prefix, postfix, ternary = ( + symbol_table.symbol, + symbol_table.infix, + symbol_table.infix_r, + symbol_table.prefix, + symbol_table.postfix, + symbol_table.ternary, +) + +symbol("(", 270) +symbol(")") +symbol("[", 250) # Parameters +symbol("]") +@others +@language python +@tabwidth -4 + +@path C:/Repos/ekr-rope/rope/base/ +from operator import itemgetter +from typing import Optional, Tuple + +import rope.base.builtins +import rope.base.pynames +import rope.base.pyobjects +from rope.base import ( + ast, + astutils, + exceptions, + pyobjects, + pyobjectsdef, + arguments, + worder, +) + + +BadIdentifierError = exceptions.BadIdentifierError + + +@others +@language python +@tabwidth -4 + +def eval_location(pymodule, offset): + """Find the pyname at the offset""" + return eval_location2(pymodule, offset)[1] + + + +def eval_location2(pymodule, offset): + """Find the primary and pyname at offset""" + pyname_finder = ScopeNameFinder(pymodule) + return pyname_finder.get_primary_and_pyname_at(offset) + + + +def eval_node(scope, node): + """Evaluate a `ast.AST` node and return a PyName + + Return `None` if the expression cannot be evaluated. + """ + return eval_node2(scope, node)[1] + + + +def eval_node2(scope, node): + evaluator = StatementEvaluator(scope) + ast.walk(node, evaluator) + return evaluator.old_result, evaluator.result + + + +def eval_str(holding_scope, name): + return eval_str2(holding_scope, name)[1] + + + +@ignore +@nosearch +@language patch +--- master ++++ HEAD +@@ -1,5 +1,5 @@ +-import ast +-from ast import * ++import ast # noqu ++from ast import * # noqa + + from rope.base import fscommands +@language python + +class ScopeNameFinder: + @others + +def __init__(self, pymodule): + self.module_scope = pymodule.get_scope() + self.lines = pymodule.lines + self.worder = worder.Worder(pymodule.source_code, True) + + +def get_pyname_at(self, offset): + return self.get_primary_and_pyname_at(offset)[1] + + +def _find_module(self, module_name): + dots = 0 + while module_name[dots] == ".": + dots += 1 + return rope.base.pynames.ImportedModule( + self.module_scope.pyobject, module_name[dots:], dots + ) + + + +class StatementEvaluator: + @others + +def __init__(self, scope): + self.scope = scope + self.result = None + self.old_result = None + + +@nosearch + +# Word, Head, Body + +# found 23 nodes +@nosearch + +# Word, Head, Body + +# found 6 nodes +@path C:/Repos/ekr-rope/rope/base/utils/ +import ast +import builtins + + +ast_arg_type = ast.arg + + +def execfile(fn, global_vars=None, local_vars=None): + with open(fn) as f: + code = compile(f.read(), fn, "exec") + exec(code, global_vars or {}, local_vars) + + +def get_ast_arg_arg(node): + if isinstance(node, str): # TODO: G21: Understand the Algorithm (Where it's used?) + return node + return node.arg + + +def get_ast_with_items(node): + return node.items + + + + diff --git a/rope/base/builtins.py b/rope/base/builtins.py index 537ffa98f..cb15668f7 100644 --- a/rope/base/builtins.py +++ b/rope/base/builtins.py @@ -1,4 +1,5 @@ """This module tries to support builtin types and functions.""" +import ast import inspect import io @@ -8,7 +9,6 @@ raw_input = input import rope.base.evaluate -from rope.base.utils import pycompat from rope.base import pynames, pyobjects, arguments, utils @@ -720,15 +720,11 @@ def get_name(self): return "lambda" def get_param_names(self, special_args=True): - result = [ - pycompat.get_ast_arg_arg(node) - for node in self.arguments.args - if isinstance(node, pycompat.ast_arg_type) - ] + result = [node.arg for node in self.arguments.args if isinstance(node, ast.arg)] if self.arguments.vararg: - result.append("*" + pycompat.get_ast_arg_arg(self.arguments.vararg)) + result.append("*" + self.arguments.vararg.arg) if self.arguments.kwarg: - result.append("**" + pycompat.get_ast_arg_arg(self.arguments.kwarg)) + result.append("**" + self.arguments.kwarg.arg) return result @property @@ -869,4 +865,4 @@ def _input_function(args): ), } -builtins = BuiltinModule(pycompat.builtins.__name__, initial=_initial_builtins) +builtins = BuiltinModule("builtins", initial=_initial_builtins) diff --git a/rope/base/fscommands.py b/rope/base/fscommands.py index f69b172e7..85d7a2396 100644 --- a/rope/base/fscommands.py +++ b/rope/base/fscommands.py @@ -10,8 +10,6 @@ import os import shutil import subprocess - -import rope.base.utils.pycompat as pycompat import typing diff --git a/rope/base/oi/runmod.py b/rope/base/oi/runmod.py index 50fb35907..0cdb3c6b8 100644 --- a/rope/base/oi/runmod.py +++ b/rope/base/oi/runmod.py @@ -11,7 +11,6 @@ def __rope_start_everything(): import inspect import types import threading - import rope.base.utils.pycompat as pycompat import base64 import hashlib import hmac @@ -231,7 +230,9 @@ def _realpath(path): if send_info != "-": data_sender = _FunctionCallDataSender(send_info, project_root) del sys.argv[1:4] - pycompat.execfile(file_to_run, run_globals) + with open(file_to_run) as f: + code = compile(f.read(), file_to_run, "exec") + exec(code, run_globals) if send_info != "-": data_sender.close() diff --git a/rope/base/oi/type_hinting/evaluate.py b/rope/base/oi/type_hinting/evaluate.py index 59c578b06..fde695455 100644 --- a/rope/base/oi/type_hinting/evaluate.py +++ b/rope/base/oi/type_hinting/evaluate.py @@ -1,7 +1,6 @@ # Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm # and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py import re -from rope.base.utils import pycompat from rope.base.oi.type_hinting import utils from rope.base import utils as base_utils diff --git a/rope/base/oi/type_hinting/utils.py b/rope/base/oi/type_hinting/utils.py index b59cb6798..6c0ca416c 100644 --- a/rope/base/oi/type_hinting/utils.py +++ b/rope/base/oi/type_hinting/utils.py @@ -8,7 +8,6 @@ from rope.base import evaluate from rope.base.exceptions import AttributeNotFoundError from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject -from rope.base.utils import pycompat def get_super_func(pyfunc): diff --git a/rope/base/prefs.py b/rope/base/prefs.py index 4fdd4aea6..bc630f783 100644 --- a/rope/base/prefs.py +++ b/rope/base/prefs.py @@ -6,9 +6,7 @@ from packaging.requirements import Requirement from pytoolconfig import PyToolConfig, UniversalKey, field from pytoolconfig.sources import Source - from rope.base.resources import Folder -from rope.base.utils import pycompat @dataclass @@ -258,7 +256,9 @@ def _read(self) -> bool: "__file__": config.real_path, } ) - pycompat.execfile(config.real_path, self.run_globals) + with open(config.real_path) as f: + code = compile(f.read(),config.real_path, 'exec') + exec(code, self.run_globals) return True def parse(self) -> Optional[Dict]: diff --git a/rope/base/pyobjectsdef.py b/rope/base/pyobjectsdef.py index 5f6bf9271..9069dab0c 100644 --- a/rope/base/pyobjectsdef.py +++ b/rope/base/pyobjectsdef.py @@ -1,4 +1,3 @@ -from rope.base.pynames import DefinedName import rope.base.builtins import rope.base.codeanalyze import rope.base.evaluate @@ -15,7 +14,6 @@ arguments, utils, ) -from rope.base.utils import pycompat class PyFunction(pyobjects.PyFunction): @@ -79,16 +77,12 @@ def get_name(self): def get_param_names(self, special_args=True): # TODO: handle tuple parameters - result = [ - pycompat.get_ast_arg_arg(node) - for node in self.arguments.args - if isinstance(node, pycompat.ast_arg_type) - ] + result = [node.arg for node in self.arguments.args if isinstance(node, ast.arg)] if special_args: if self.arguments.vararg: - result.append(pycompat.get_ast_arg_arg(self.arguments.vararg)) + result.append(self.arguments.vararg.arg) if self.arguments.kwarg: - result.append(pycompat.get_ast_arg_arg(self.arguments.kwarg)) + result.append(self.arguments.kwarg.arg) return result def get_kind(self): @@ -461,9 +455,7 @@ def _AugAssign(self, node): pass def _For(self, node): - names = self._update_evaluated( - node.target, node.iter, ".__iter__().next()" # noqa - ) + self._update_evaluated(node.target, node.iter, ".__iter__().next()") # noqa for child in node.body + node.orelse: ast.walk(child, self) @@ -496,7 +488,7 @@ def _update_evaluated( return result def _With(self, node): - for item in pycompat.get_ast_with_items(node): + for item in node.items: if item.optional_vars: self._update_evaluated( item.optional_vars, item.context_expr, ".__enter__()" @@ -600,8 +592,8 @@ def _FunctionDef(self, node): if len(node.args.args) > 0: first = node.args.args[0] new_visitor = None - if isinstance(first, pycompat.ast_arg_type): - new_visitor = _ClassInitVisitor(self, pycompat.get_ast_arg_arg(first)) + if isinstance(first, ast.arg): + new_visitor = _ClassInitVisitor(self, first.arg) if new_visitor is not None: for child in ast.get_child_nodes(node): ast.walk(child, new_visitor) diff --git a/rope/refactor/extract.py b/rope/refactor/extract.py index fd5762920..0b5c1d45f 100644 --- a/rope/refactor/extract.py +++ b/rope/refactor/extract.py @@ -5,7 +5,6 @@ from rope.base import ast, codeanalyze from rope.base.change import ChangeSet, ChangeContents from rope.base.exceptions import RefactoringError -from rope.base.utils import pycompat from rope.base.utils.datastructures import OrderedSet from rope.refactor import sourceutils, similarfinder, patchedast, suites, usefunction @@ -948,15 +947,11 @@ def _handle_loop_context(self, node): def _get_argnames(arguments): - result = [ - pycompat.get_ast_arg_arg(node) - for node in arguments.args - if isinstance(node, pycompat.ast_arg_type) - ] + result = [node.arg for node in arguments.args if isinstance(node, ast.arg)] if arguments.vararg: - result.append(pycompat.get_ast_arg_arg(arguments.vararg)) + result.append(vararg.arg) if arguments.kwarg: - result.append(pycompat.get_ast_arg_arg(arguments.kwarg)) + result.append(arguments.kwarg.arg) return result diff --git a/rope/refactor/patchedast.py b/rope/refactor/patchedast.py index f7882e232..9415f7543 100644 --- a/rope/refactor/patchedast.py +++ b/rope/refactor/patchedast.py @@ -5,13 +5,8 @@ from itertools import chain from rope.base import ast, codeanalyze, exceptions -from rope.base.utils import pycompat - -try: - basestring -except NameError: - basestring = (str, bytes) +basestring = (str, bytes) COMMA_IN_WITH_PATTERN = re.compile(r"\(.*?\)|(,)") @@ -574,11 +569,11 @@ def _arguments(self, node): if node.vararg is not None: if args: children.append(",") - children.extend(["*", pycompat.get_ast_arg_arg(node.vararg)]) + children.extend(["*", node.vararg.arg]) if node.kwarg is not None: if args or node.vararg is not None: children.append(",") - children.extend(["**", pycompat.get_ast_arg_arg(node.kwarg)]) + children.extend(["**", node.kwarg.arg]) self._handle(node, children) def _add_args_to_children(self, children, arg, default): @@ -853,7 +848,7 @@ def _handle_with_node(self, node, is_async): if is_async: children.extend(["async"]) - for item in pycompat.get_ast_with_items(node): + for item in node.items: children.extend([self.with_or_comma_context_manager, item.context_expr]) if item.optional_vars: children.extend(["as", item.optional_vars]) diff --git a/rope/refactor/suites.py b/rope/refactor/suites.py index 015902e6f..6e7eb454e 100644 --- a/rope/refactor/suites.py +++ b/rope/refactor/suites.py @@ -1,7 +1,6 @@ from itertools import chain from rope.base import ast -from rope.base.utils import pycompat def find_visible(node, lines): diff --git a/ropetest/advanced_oi_test.py b/ropetest/advanced_oi_test.py index ee9f997f8..94374864f 100644 --- a/ropetest/advanced_oi_test.py +++ b/ropetest/advanced_oi_test.py @@ -6,7 +6,6 @@ import rope.base.libutils import rope.base.oi -from rope.base.utils import pycompat from ropetest import testutils diff --git a/ropetest/refactor/patchedasttest.py b/ropetest/refactor/patchedasttest.py index 25298c453..ebd1fe763 100644 --- a/ropetest/refactor/patchedasttest.py +++ b/ropetest/refactor/patchedasttest.py @@ -3,7 +3,6 @@ from textwrap import dedent from rope.base import ast -from rope.base.utils import pycompat from rope.refactor import patchedast from ropetest import testutils @@ -586,7 +585,7 @@ def f(p1, **p2): "Function", ["def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Expr", "\n ", "Pass"], ) - expected_child = pycompat.ast_arg_type.__name__ + expected_child = ast.arg.__name__ checker.check_children( "arguments", [expected_child, "", ",", " ", "**", "", "p2"] ) @@ -838,7 +837,7 @@ def test_lambda_node(self): checker.check_children( "Lambda", ["lambda", " ", "arguments", "", ":", " ", NameConstant] ) - expected_child = pycompat.ast_arg_type.__name__ + expected_child = ast.arg.__name__ checker.check_children( "arguments", [expected_child, "", ",", " ", expected_child, "", "=", "", "Num", "", ",", " ", "*", "", "z"], From 2a69118cc2445a7a3e9bbd2b7ede3255b7dbb830 Mon Sep 17 00:00:00 2001 From: "Edward K. Ream" Date: Mon, 28 Nov 2022 06:24:04 -0600 Subject: [PATCH 2/4] Delete rope.leo, mistakenly added --- rope.leo | 80392 ----------------------------------------------------- 1 file changed, 80392 deletions(-) delete mode 100644 rope.leo diff --git a/rope.leo b/rope.leo deleted file mode 100644 index e5dab7415..000000000 --- a/rope.leo +++ /dev/null @@ -1,80392 +0,0 @@ - - - - - - - - -Startup - Recursive import script -@button backup -@button diff-master..head -@settings -@bool run-pyflakes-on-write = True -Find panel defaults -@bool ignore-case = False -@bool whole-word = True - - -scripts -script: diff-branches/revs (all files) -script: diff-branches/revs (one file) -script: diff-two-revs-wo-comments -function: make_diff_outlines_ignoring_comments -function: strip_comments - - - -Notes -Installation notes - -Files -@path bin -@clean tag-release.py -get_changelog -remove_headings -insert_date - - -@path docs -@clean conf.py -@clean default_config.py -set_prefs -project_opened - - -@path rope -@clean __init__.py -@path base -@clean __init__.py -@clean arguments.py -class Arguments -Arguments.__init__ -Arguments.get_arguments -Arguments.get_pynames -Arguments.get_instance_pyname -Arguments._evaluate - -create_arguments -class ObjectArguments -ObjectArguments.__init__ -ObjectArguments.get_arguments -ObjectArguments.get_pynames -ObjectArguments.get_instance_pyname - -class MixedArguments -MixedArguments.__init__ -MixedArguments.get_pynames -MixedArguments.get_arguments -MixedArguments.get_instance_pyname - -_is_method_call - -@clean ast.py -parse -walk -get_child_nodes -call_for_nodes -get_children - -@clean builtins.py -class BuiltinModule -BuiltinModule.__init__ -BuiltinModule.parent = None -BuiltinModule.get_attributes -BuiltinModule.get_doc -BuiltinModule.get_name -BuiltinModule.attributes -BuiltinModule.module - -class _BuiltinElement -_BuiltinElement.__init__ -_BuiltinElement.get_doc -_BuiltinElement.get_name -_BuiltinElement.parent - -class BuiltinClass -BuiltinClass.__init__ -BuiltinClass.get_attributes -BuiltinClass.get_module - -class BuiltinFunction -BuiltinFunction.__init__ -BuiltinFunction.get_returned_object -BuiltinFunction.get_param_names - -class BuiltinUnknown -BuiltinUnknown.__init__ -BuiltinUnknown.get_name -BuiltinUnknown.get_attributes - -_object_attributes -_create_builtin_type_getter -_get_builtin - -_create_builtin_getter -class _CallContext -_CallContext.__init__ -_CallContext._get_scope_and_pyname -_CallContext.get_argument -_CallContext.get_pyname -_CallContext.get_arguments -_CallContext.get_pynames -_CallContext.get_per_name -_CallContext.save_per_name - -class _AttributeCollector -_AttributeCollector.__init__ -_AttributeCollector.__call__ -_AttributeCollector.__setitem__ - -class List -List.__init__ -List._new_list -List._list_add -List._self_set -List._list_get -List._iterator_get -List._self_get - -get_list = _create_builtin_getter(List) -class Dict -Dict.__init__ -Dict._new_dict -Dict._dict_add -Dict._item_get -Dict._value_get -Dict._key_get -Dict._value_list -Dict._key_list -Dict._item_list -Dict._value_iter -Dict._key_iter -Dict._item_iter -Dict._self_get -Dict._self_set - -get_dict = _create_builtin_getter(Dict) -class Tuple -Tuple.__init__ -Tuple.get_holding_objects -Tuple._new_tuple - -get_tuple = _create_builtin_getter(Tuple) -class Set -Set.__init__ -Set._new_set -Set._set_add -Set._self_set -Set._set_get -Set._iterator_get -Set._self_get - -get_set = _create_builtin_getter(Set) -class Str -Str.__init__ -Str.get_doc - -get_str = _create_builtin_getter(Str) -class BuiltinName -BuiltinName.__init__ -BuiltinName.get_object -BuiltinName.get_definition_location - -class Iterator -Iterator.__init__ -Iterator.get_attributes -Iterator.get_returned_object - -get_iterator = _create_builtin_getter(Iterator) -class Generator -Generator.__init__ -Generator.get_attributes -Generator.get_returned_object - -get_generator = _create_builtin_getter(Generator) -class File -File.__init__ - -get_file = _create_builtin_getter(File) -class Property -Property.__init__ -Property.get_property_object - -_property_function -class Lambda -Lambda.__init__ -Lambda.get_returned_object -Lambda.get_module -Lambda.get_scope -Lambda.get_kind -Lambda.get_ast -Lambda.get_attributes -Lambda.get_name -Lambda.get_param_names -Lambda.parent - -class BuiltinObject -class BuiltinType -_infer_sequence_for_pyname -_create_builtin -_open_function -_range_function -_reversed_function -_sorted_function -_super_function -_zip_function -_enumerate_function -_iter_function -_input_function - -@clean change.py -class Change -Change.do -Change.undo -Change.get_description -Change.get_changed_resources -Change._operations - -class ChangeSet -ChangeSet.__init__ -ChangeSet.do -ChangeSet.undo -ChangeSet.add_change -ChangeSet.get_description -ChangeSet.__str__ -ChangeSet.get_changed_resources - -_handle_job_set -call - -class ChangeContents -ChangeContents.__init__ -ChangeContents.do -ChangeContents.undo -ChangeContents.__str__ -ChangeContents.get_description -ChangeContents.get_changed_resources - -class MoveResource -MoveResource.__init__ -MoveResource.do -MoveResource.undo -MoveResource.__str__ -MoveResource.get_description -MoveResource.get_changed_resources - -class CreateResource -CreateResource.__init__ -CreateResource.do -CreateResource.undo -CreateResource.__str__ -CreateResource.get_description -CreateResource.get_changed_resources -CreateResource._get_child_path - -class CreateFolder -CreateFolder.__init__ - -class CreateFile -CreateFile.__init__ - -class RemoveResource -RemoveResource.__init__ -RemoveResource.do -RemoveResource.undo -RemoveResource.__str__ -RemoveResource.get_changed_resources - -count_changes -create_job_set -class _ResourceOperations -_ResourceOperations.__init__ -_ResourceOperations._get_fscommands -_ResourceOperations.write_file -_ResourceOperations.move -_ResourceOperations.create -_ResourceOperations.remove -_ResourceOperations._create_resource - -_get_destination_for_move -class ChangeToData -ChangeToData.convertChangeSet -ChangeToData.convertChangeContents -ChangeToData.convertMoveResource -ChangeToData.convertCreateResource -ChangeToData.convertRemoveResource -ChangeToData.__call__ - -class DataToChange -DataToChange.__init__ -DataToChange.makeChangeSet -DataToChange.makeChangeContents -DataToChange.makeMoveResource -DataToChange.makeCreateResource -DataToChange.makeRemoveResource -DataToChange.__call__ - - -@clean codeanalyze.py -class ChangeCollector -ChangeCollector.__init__ -ChangeCollector.add_change -ChangeCollector.get_changed - -class SourceLinesAdapter -SourceLinesAdapter.__init__ -SourceLinesAdapter._initialize_line_starts -SourceLinesAdapter.get_line -SourceLinesAdapter.length -SourceLinesAdapter.get_line_number -SourceLinesAdapter.get_line_start -SourceLinesAdapter.get_line_end - -class ArrayLinesAdapter -ArrayLinesAdapter.__init__ -ArrayLinesAdapter.get_line -ArrayLinesAdapter.length - -class LinesToReadline -LinesToReadline.__init__ -LinesToReadline.readline -LinesToReadline.__call__ - -class _CustomGenerator -_CustomGenerator.__init__ -_CustomGenerator.__call__ -_CustomGenerator.Matches all backslashes before the token, to detect escaped quotes -_CustomGenerator._analyze_line - -custom_generator -class LogicalLineFinder -LogicalLineFinder.__init__ -LogicalLineFinder.logical_line_in -LogicalLineFinder.generate_starts -LogicalLineFinder.generate_regions -LogicalLineFinder._block_logical_line -LogicalLineFinder._calculate_logical -LogicalLineFinder._logical_lines -LogicalLineFinder._first_non_blank - -tokenizer_generator -class CachingLogicalLineFinder -CachingLogicalLineFinder.__init__ -CachingLogicalLineFinder._starts = None -CachingLogicalLineFinder.starts -CachingLogicalLineFinder._ends = None -CachingLogicalLineFinder.ends -CachingLogicalLineFinder._init_logicals -CachingLogicalLineFinder.logical_line_in -CachingLogicalLineFinder.generate_starts - -get_block_start -_block_start_pattern = None -get_block_start_patterns -count_line_indents -get_string_pattern_with_prefix -get_string_pattern -get_formatted_string_pattern -get_any_string_pattern -get_comment_pattern - -@clean evaluate.py -eval_location -eval_location2 -eval_node -eval_node2 -eval_str -eval_str2 -class ScopeNameFinder -ScopeNameFinder.__init__ -ScopeNameFinder._is_defined_in_class_body -ScopeNameFinder._is_function_name_in_function_header -ScopeNameFinder.get_pyname_at -ScopeNameFinder.get_primary_and_pyname_at -ScopeNameFinder.get_enclosing_function -ScopeNameFinder._find_module - -class StatementEvaluator -StatementEvaluator.__init__ -StatementEvaluator._Name -StatementEvaluator._Attribute -StatementEvaluator._Call -StatementEvaluator._Str -StatementEvaluator._Num -StatementEvaluator._Constant -StatementEvaluator._get_builtin_name -StatementEvaluator._BinOp -StatementEvaluator._BoolOp -StatementEvaluator._Repr -StatementEvaluator._UnaryOp -StatementEvaluator._Compare -StatementEvaluator._Dict -StatementEvaluator._List -StatementEvaluator._ListComp -StatementEvaluator._GeneratorExp -StatementEvaluator._what_does_comprehension_hold -StatementEvaluator._make_comprehension_scope -StatementEvaluator._Tuple -StatementEvaluator._get_object_for_node -StatementEvaluator._get_primary_and_object_for_node -StatementEvaluator._Subscript -StatementEvaluator._Slice -StatementEvaluator._call_function -StatementEvaluator._Lambda - -_get_evaluated_names - -@clean exceptions.py -class RopeError -class ResourceNotFoundError -class RefactoringError -class InterruptedTaskError -class HistoryError -class ModuleNotFoundError -class AttributeNotFoundError -class NameNotFoundError -class BadIdentifierError -class ModuleSyntaxError -ModuleSyntaxError.__init__ - -class ModuleDecodeError - -@clean fscommands.py -create_fscommands -class FileSystemCommands -FileSystemCommands.create_file -FileSystemCommands.create_folder -FileSystemCommands.move -FileSystemCommands.remove -FileSystemCommands.write -FileSystemCommands.read - -class SubversionCommands -SubversionCommands.__init__ -SubversionCommands.create_file -SubversionCommands.create_folder -SubversionCommands.move -SubversionCommands.remove -SubversionCommands.write -SubversionCommands.read - -class MercurialCommands -MercurialCommands.__init__ -MercurialCommands._import_mercurial -MercurialCommands.create_file -MercurialCommands.create_folder -MercurialCommands.move -MercurialCommands.remove -MercurialCommands.write -MercurialCommands.read - -class GITCommands -GITCommands.__init__ -GITCommands.create_file -GITCommands.create_folder -GITCommands.move -GITCommands.remove -GITCommands.write -GITCommands.read -GITCommands._do -GITCommands._in_dir - -class DarcsCommands -DarcsCommands.__init__ -DarcsCommands.create_file -DarcsCommands.create_folder -DarcsCommands.move -DarcsCommands.remove -DarcsCommands.read -DarcsCommands.write -DarcsCommands._do - -_execute -unicode_to_file_data -file_data_to_unicode -_decode_data -read_str_coding -_find_coding - -@clean history.py -class History -History.__init__ -History._load_history -History.do -History._remove_extra_items -History._is_change_interesting -History.undo -History.redo -History._move_front -History._find_dependencies -History._perform_undos -History._perform_redos -History.contents_before_current_change -History._search_for_change_contents -History.write -History.get_file_undo_list -History.__str__ -History.undo_list = property(lambda self: self._undo_list) -History.tobe_undone -History.tobe_redone -History.max_undos -History.save -History.compress -History.clear - -class _FindChangeDependencies -_FindChangeDependencies.__init__ -_FindChangeDependencies.__call__ -_FindChangeDependencies._depends_on - - -@clean libutils.py -path_to_resource -path_relative_to_project_root -relative -report_change -analyze_module -analyze_modules -get_string_module -get_string_scope -is_python_file -modname - -@clean prefs.py -class Prefs -Prefs.set -Prefs.add -Prefs.get -Prefs.add_callback -Prefs.__setitem__ -Prefs.__getitem__ - -class _RopeConfigSource -_RopeConfigSource.__init__ -_RopeConfigSource._read -_RopeConfigSource.parse - -get_config - -@clean project.py -class _Project -_Project.__init__ -_Project.get_resource -_Project.get_module -_Project.get_python_path_folders -_Project.get_source_folders -_Project.validate -_Project.add_observer -_Project.remove_observer -_Project.do -_Project.get_pymodule -_Project.get_pycore -_Project.get_file -_Project.get_folder -_Project.get_prefs -_Project.get_relative_module -_Project.find_module -_Project.find_relative_module -_Project.is_ignored -_Project._get_resource_path -_Project.history -_Project.pycore -_Project.close - -class Project -Project.__init__ -Project.__repr__ -Project._init_source_folders -Project.get_files -Project.get_python_files -Project._get_resource_path -Project._init_ropefolder -Project._create_recursively -Project._init_prefs -Project._init_other_parts -Project.is_ignored -Project.sync -Project.close -Project.set -Project.ropefolder -Project.validate - -class NoProject -NoProject.__init__ -NoProject._get_resource_path -NoProject.get_resource -NoProject.get_files -NoProject.get_python_files - -get_no_project -class _FileListCacher -_FileListCacher.__init__ -_FileListCacher.get_files -_FileListCacher._add_files -_FileListCacher._changed -_FileListCacher._invalid - -class _DataFiles -_DataFiles.__init__ -_DataFiles.read_data -_DataFiles.write_data -_DataFiles.add_write_hook -_DataFiles.write -_DataFiles._can_compress -_DataFiles._import_old_files -_DataFiles._get_opener -_DataFiles._get_file - -_realpath -_find_module_in_folder - -@clean pycore.py -class PyCore -PyCore.__init__ -PyCore._init_python_files -PyCore._init_resource_observer -PyCore._init_automatic_soa -PyCore.automatic_soa -PyCore._file_changed_for_soa -PyCore.is_python_file -PyCore.get_module -PyCore._builtin_submodules -PyCore.builtin_module -PyCore.get_relative_module -PyCore.get_string_module -PyCore.get_string_scope -PyCore._invalidate_resource_cache -PyCore.get_python_path_folders -PyCore.find_module -PyCore.find_relative_module -PyCore.get_source_folders -PyCore.resource_to_pyobject (unique) -PyCore.get_python_files -PyCore._is_package -PyCore._find_source_folders -PyCore.run_module -PyCore.analyze_module -PyCore.get_classes -PyCore.__str__ -PyCore.modname -PyCore.extension_modules - -class _ModuleCache -_ModuleCache.__init__ -_ModuleCache._invalidate_resource -_ModuleCache.get_pymodule -_ModuleCache.forget_all_data -_ModuleCache.__str__ - -class _ExtensionCache -_ExtensionCache.__init__ -_ExtensionCache.get_pymodule - -perform_soa_on_changed_scopes -class _TextChangeDetector -_TextChangeDetector.__init__ -_TextChangeDetector._set_diffs -_TextChangeDetector.is_changed -_TextChangeDetector.consume_changes -_TextChangeDetector._get_changed - - -@clean pynames.py -class PyName -PyName.get_object -PyName.get_definition_location - -class DefinedName -DefinedName.__init__ -DefinedName.get_object -DefinedName.get_definition_location - -class AssignedName -AssignedName.__init__ -AssignedName._get_inferred (*** tests self.module is not None) -AssignedName.get_object -AssignedName.get_definition_location -AssignedName.invalidate - -class UnboundName -UnboundName.__init__ -UnboundName.get_object -UnboundName.get_definition_location - -class AssignmentValue -AssignmentValue.__init__ -AssignmentValue.get_lineno - -class EvaluatedName -EvaluatedName.__init__ -EvaluatedName.get_object -EvaluatedName.get_definition_location -EvaluatedName.invalidate - -class ParameterName -ParameterName.__init__ -ParameterName.get_object -ParameterName.get_objects -ParameterName.get_definition_location - -class ImportedModule -ImportedModule.__init__ -ImportedModule._current_folder -ImportedModule._get_pymodule -ImportedModule.get_object -ImportedModule.get_definition_location - -class ImportedName -ImportedName.__init__ -ImportedName._get_imported_pyname -ImportedName.get_object -ImportedName.get_definition_location - -_get_concluded_data -_circular_inference -class _Inferred -_Inferred.__init__ -_Inferred.get -_Inferred.set -_Inferred._get - - -@clean pyobjects.py -class PyObject -PyObject.__init__ -PyObject.get_attributes -PyObject.get_attribute -PyObject.get_type -PyObject.__getitem__ -PyObject.__contains__ -PyObject.__eq__ -PyObject.__ne__ -PyObject.__hash__ -PyObject.__iter__ -PyObject._types = None -PyObject._get_base_type - -get_base_type -get_unknown -class AbstractClass -AbstractClass.__init__ -AbstractClass.get_name -AbstractClass.get_doc -AbstractClass.get_superclasses - -class AbstractFunction -AbstractFunction.__init__ -AbstractFunction.get_name -AbstractFunction.get_doc -AbstractFunction.get_param_names -AbstractFunction.get_returned_object - -class AbstractModule (PyObject) -AbstractModule.__init__ -AbstractModule.get_doc -AbstractModule.get_resource - -class PyDefinedObject -PyDefinedObject.__init__ -PyDefinedObject.__repr__ -PyDefinedObject.absolute_name -PyDefinedObject.visitor_class = None -PyDefinedObject._get_structural_attributes -PyDefinedObject._get_concluded_attributes -PyDefinedObject.get_attributes -PyDefinedObject.get_attribute -PyDefinedObject.get_scope -PyDefinedObject.get_module -PyDefinedObject.get_doc (changed) -PyDefinedObject._get_defined_objects -PyDefinedObject._create_structural_attributes -PyDefinedObject._create_concluded_attributes -PyDefinedObject.get_ast -PyDefinedObject._create_scope - -class PyFunction -class PyComprehension -class PyClass -class _ConcludedData -_ConcludedData.__init__ -_ConcludedData.set -_ConcludedData.get -_ConcludedData.data = property(get, set) -_ConcludedData._invalidate -_ConcludedData.__str__ - -class _PyModule(PyDefinedObject, AbstractModule) -_PyModule.__init__ -_PyModule.absolute_name -_PyModule._get_concluded_data -_PyModule._forget_concluded_data -_PyModule.get_resource - -class PyModule (placeholder, pyobjects.py) -class PyPackage (placeholder, pyobjects.py) -class IsBeingInferredError - -@clean pyobjectsdef.py -<< imports: pyobjectsdef >> -class PyFunction -PyFunction.__init__ -PyFunction._create_structural_attributes -PyFunction._create_concluded_attributes -PyFunction._create_scope -PyFunction._infer_parameters -PyFunction._infer_returned -PyFunction._handle_special_args -PyFunction._set_parameter_pyobjects -PyFunction.get_parameters -PyFunction.get_parameter -PyFunction.get_returned_object -PyFunction.get_name -PyFunction.get_param_names -PyFunction.get_kind -PyFunction.decorators - -class PyComprehension -PyComprehension.__init__ -PyComprehension._create_scope -PyComprehension.get_kind - -class PyClass -PyClass.__init__ -PyClass.get_superclasses -PyClass.get_name -PyClass._create_concluded_attributes -PyClass._get_bases -PyClass._create_scope - -class PyModule (pyobjectsdef.py) -PyModule.__init__ -PyModule._init_source -PyModule._create_concluded_attributes -PyModule._create_scope -PyModule.lines -PyModule.logical_lines -PyModule.get_name - -class PyPackage (real, pyobjectsdef.py) -PyPackage.__init__ -PyPackage._create_structural_attributes -PyPackage._create_concluded_attributes -PyPackage._get_child_resources -PyPackage._get_init_dot_py -PyPackage._create_scope -PyPackage.get_module -PyPackage.get_name - -class _AnnAssignVisitor -_AnnAssignVisitor.__init__ -_AnnAssignVisitor._AnnAssign -_AnnAssignVisitor._assigned -_AnnAssignVisitor._Name -_AnnAssignVisitor._Tuple -_AnnAssignVisitor._Annotation -_AnnAssignVisitor._Attribute -_AnnAssignVisitor._Subscript -_AnnAssignVisitor._Slice - -class _ExpressionVisitor -_ExpressionVisitor.__init__ -_ExpressionVisitor._assigned -_ExpressionVisitor._GeneratorExp -_ExpressionVisitor._SetComp -_ExpressionVisitor._ListComp -_ExpressionVisitor._DictComp -_ExpressionVisitor._NamedExpr - -class _AssignVisitor -_AssignVisitor.__init__ -_AssignVisitor._Assign -_AssignVisitor._assigned -_AssignVisitor._Name -_AssignVisitor._Tuple -_AssignVisitor._Attribute -_AssignVisitor._Subscript -_AssignVisitor._Slice - -class _ScopeVisitor(_ExpressionVisitor) -_ScopeVisitor.__init__ -_ScopeVisitor.get_module (trace) -_ScopeVisitor._ClassDef -_ScopeVisitor._FunctionDef (pyobjectsdef.py) -_ScopeVisitor._AsyncFunctionDef -_ScopeVisitor._Assign -_ScopeVisitor._AnnAssign -_ScopeVisitor._AugAssign -_ScopeVisitor._For -_ScopeVisitor._AsyncFor -_ScopeVisitor._assigned -_ScopeVisitor._update_evaluated -_ScopeVisitor._With -_ScopeVisitor._AsyncWith -_ScopeVisitor._excepthandler -_ScopeVisitor._ExceptHandler -_ScopeVisitor._Import -_ScopeVisitor._ImportFrom (trace) -_ScopeVisitor._is_ignored_import (unique) -_ScopeVisitor._Global - -class _ComprehensionVisitor -_ComprehensionVisitor._comprehension -_ComprehensionVisitor._Name -_ComprehensionVisitor._get_pyobject - -class _GlobalVisitor(_ScopeVisitor) -class _ClassVisitor -_ClassVisitor.__init__ -_ClassVisitor._FunctionDef - -class _FunctionVisitor -_FunctionVisitor.__init__ -_FunctionVisitor._Return -_FunctionVisitor._Yield - -class _ClassInitVisitor -_ClassInitVisitor.__init__ -_ClassInitVisitor._Attribute (changed) -_ClassInitVisitor._Tuple -_ClassInitVisitor._Name -_ClassInitVisitor._FunctionDef -_ClassInitVisitor._ClassDef -_ClassInitVisitor._For -_ClassInitVisitor._With - -class StarImport -StarImport.__init__ -StarImport.get_names - - -@clean pyscopes.py -class Scope -Scope.__init__ -Scope.get_names -Scope.get_defined_names -Scope.get_name -Scope.__getitem__ -Scope.__contains__ -Scope.get_scopes -Scope.lookup -Scope.get_propagated_names -Scope._propagated_lookup -Scope._create_scopes -Scope._get_global_scope -Scope.get_start -Scope.get_body_start -Scope.get_end -Scope.get_logical_end -Scope.start = property(get_start) -Scope.get_kind -Scope.get_region -Scope._calculate_scope_regions_for_module -Scope.in_region - -class GlobalScope -GlobalScope.__init__ -GlobalScope.get_start -GlobalScope.get_kind -GlobalScope.get_name -GlobalScope._calculate_scope_regions -GlobalScope._get_source -GlobalScope.get_names -GlobalScope.get_inner_scope_for_line -GlobalScope.get_inner_scope_for_offset -GlobalScope._scope_finder -GlobalScope.builtin_names - -class ComprehensionScope -ComprehensionScope.__init__ -ComprehensionScope._get_names -ComprehensionScope.get_names -ComprehensionScope._visit_comprehension -ComprehensionScope.get_logical_end -ComprehensionScope.logical_end = property(get_logical_end) -ComprehensionScope.get_body_start - -class FunctionScope -FunctionScope.__init__ -FunctionScope._get_names -FunctionScope._visit_function -FunctionScope._get_returned_asts -FunctionScope._is_generator -FunctionScope.get_names -FunctionScope._create_scopes -FunctionScope.get_kind -FunctionScope.invalidate_data - -class ClassScope -ClassScope.__init__ -ClassScope.get_kind -ClassScope.get_propagated_names - -class _HoldingScopeFinder -_HoldingScopeFinder.__init__ -_HoldingScopeFinder.get_indents -_HoldingScopeFinder._get_scope_indents -_HoldingScopeFinder.get_holding_scope -_HoldingScopeFinder._is_empty_line -_HoldingScopeFinder._get_body_indents -_HoldingScopeFinder.get_holding_scope_for_offset -_HoldingScopeFinder.find_scope_end -_HoldingScopeFinder.lines -_HoldingScopeFinder.code -_HoldingScopeFinder.logical_lines - -class TemporaryScope -TemporaryScope.__init__ -TemporaryScope.get_names -TemporaryScope.get_defined_names -TemporaryScope._create_scopes -TemporaryScope.get_kind - - -@clean resourceobserver.py -class ResourceObserver -ResourceObserver.__init__ -ResourceObserver.resource_changed -ResourceObserver.resource_moved -ResourceObserver.resource_created -ResourceObserver.resource_removed -ResourceObserver.validate - -class FilteredResourceObserver -FilteredResourceObserver.__init__ -FilteredResourceObserver.add_resource -FilteredResourceObserver.remove_resource -FilteredResourceObserver.clear_resources -FilteredResourceObserver.resource_changed -FilteredResourceObserver._update_changes_caused_by_changed -FilteredResourceObserver._update_changes_caused_by_moved -FilteredResourceObserver._is_parent_changed -FilteredResourceObserver.resource_moved -FilteredResourceObserver.resource_created -FilteredResourceObserver._update_changes_caused_by_created -FilteredResourceObserver.resource_removed -FilteredResourceObserver._perform_changes -FilteredResourceObserver.validate -FilteredResourceObserver._search_resource_creations -FilteredResourceObserver._search_resource_moves -FilteredResourceObserver._search_resource_changes -FilteredResourceObserver._is_changed -FilteredResourceObserver._calculate_new_resource - -class ChangeIndicator -ChangeIndicator.get_indicator - -class _Changes -_Changes.__init__ -_Changes.add_changed -_Changes.add_removed -_Changes.add_created - - -@clean resources.py -class Resource -Resource.__init__ -Resource.__repr__ -Resource.move -Resource.remove -Resource.is_folder -Resource.create -Resource.exists -Resource.parent -Resource.path -Resource.name -Resource.real_path -Resource.pathlib -Resource.__eq__ -Resource.__ne__ -Resource.__hash__ -Resource._perform_change - -class File -File.__init__ -File.read -File.read_bytes -File.write -File.is_folder -File.create - -class Folder -Folder.__init__ -Folder.is_folder -Folder.get_children -Folder.create_file -Folder.create_folder -Folder._get_child_path -Folder.get_child -Folder.has_child -Folder.get_files -Folder.get_folders -Folder.contains -Folder.create - -class _ResourceMatcher -_ResourceMatcher.__init__ -_ResourceMatcher.set_patterns -_ResourceMatcher._add_pattern -_ResourceMatcher.does_match -_ResourceMatcher.compiled_patterns - - -@clean simplify.py -real_code -ignored_regions - -@clean stdmods.py -_stdlib_path -standard_modules -python_modules -normalize_so_name -dynload_modules - -@clean taskhandle.py -class BaseJobSet -BaseJobSet.started_job -BaseJobSet.finished_job -BaseJobSet.check_status -BaseJobSet.get_active_job_name -BaseJobSet.get_percent_done -BaseJobSet.get_name -BaseJobSet.increment - -class BaseTaskHandle -BaseTaskHandle.stop -BaseTaskHandle.current_jobset -BaseTaskHandle.add_observer -BaseTaskHandle.is_stopped -BaseTaskHandle.get_jobsets -BaseTaskHandle.create_jobset -BaseTaskHandle._inform_observers - -class TaskHandle -TaskHandle.__init__ -TaskHandle.stop -TaskHandle.current_jobset -TaskHandle.add_observer -TaskHandle.is_stopped -TaskHandle.get_jobsets -TaskHandle.create_jobset -TaskHandle._inform_observers - -class JobSet -JobSet.__init__ -JobSet.started_job -JobSet.finished_job -JobSet.check_status -JobSet.get_active_job_name -JobSet.get_percent_done -JobSet.get_name -JobSet.increment - -class NullTaskHandle -NullTaskHandle.__init__ -NullTaskHandle.is_stopped -NullTaskHandle.stop -NullTaskHandle.create_jobset -NullTaskHandle.get_jobsets -NullTaskHandle.add_observer -NullTaskHandle.current_jobset - -class NullJobSet -NullJobSet.__init__ -NullJobSet.started_job -NullJobSet.finished_job -NullJobSet.check_status -NullJobSet.get_active_job_name -NullJobSet.get_percent_done -NullJobSet.get_name -NullJobSet.increment - - -@clean worder.py -get_name_at -class Worder -Worder.__init__ -Worder._init_ignores -Worder._context_call -Worder.get_primary_at -Worder.get_word_at -Worder.get_primary_range -Worder.get_splitted_primary_before -Worder.get_word_range -Worder.is_function_keyword_parameter -Worder.is_a_class_or_function_name_in_header -Worder.is_from_statement_module -Worder.is_from_aliased -Worder.is_import_statement_aliased_module -Worder.find_parens_start_from_inside -Worder.is_a_name_after_from_import -Worder.is_from_statement -Worder.get_from_aliased -Worder.is_import_statement -Worder.is_assigned_here -Worder.is_a_function_being_called -Worder.get_word_parens_range -Worder.is_name_assigned_in_class_body -Worder.is_on_function_call_keyword -Worder._find_parens_start -Worder.get_parameters -Worder.get_from_module -Worder.is_assigned_in_a_tuple_assignment -Worder.get_assignment_type -Worder.get_function_and_args_in_header -Worder.get_lambda_and_args -Worder.find_function_offset - -class _RealFinder -_RealFinder.__init__ -_RealFinder._find_word_start -_RealFinder._find_word_end -_RealFinder._find_last_non_space_char -_RealFinder.get_word_at -_RealFinder._get_fixed_offset -_RealFinder._is_id_char -_RealFinder._find_string_start -_RealFinder._find_parens_start -_RealFinder._find_atom_start -_RealFinder._find_primary_without_dot_start -_RealFinder._find_primary_start -_RealFinder.get_primary_at -_RealFinder.get_splitted_primary_before -_RealFinder._get_line_start -_RealFinder._get_line_end -_RealFinder.is_name_assigned_in_class_body -_RealFinder.is_a_class_or_function_name_in_header -_RealFinder._find_first_non_space_char -_RealFinder.is_a_function_being_called -_RealFinder._find_import_end -_RealFinder.is_import_statement -_RealFinder.is_from_statement -_RealFinder.is_from_statement_module -_RealFinder.is_import_statement_aliased_module -_RealFinder._has_enough_len_for_as -_RealFinder._find_import_main_part_end -_RealFinder.is_a_name_after_from_import -_RealFinder.get_from_module -_RealFinder.is_from_aliased -_RealFinder.get_from_aliased -_RealFinder.is_function_keyword_parameter -_RealFinder.is_on_function_call_keyword -_RealFinder.find_parens_start_from_inside -_RealFinder.is_assigned_here -_RealFinder.get_assignment_type -_RealFinder.get_primary_range -_RealFinder.get_word_range -_RealFinder.get_word_parens_range -_RealFinder.get_parameters -_RealFinder.__strip_type_hint -_RealFinder.is_assigned_in_a_tuple_assignment -_RealFinder.get_function_and_args_in_header -_RealFinder.find_function_offset -_RealFinder.get_lambda_and_args - - - -@path base/oi -@clean doa.py -_compat_compare_digest -try: -class PythonFileRunner -PythonFileRunner.__init__ -PythonFileRunner.run -PythonFileRunner._init_data_receiving -PythonFileRunner._receive_information -PythonFileRunner.wait_process -PythonFileRunner.kill_process -PythonFileRunner.add_finishing_observer - -class _MessageReceiver -class _SocketReceiver -_SocketReceiver.__init__ -_SocketReceiver.get_send_info -_SocketReceiver.receive_data - -class _FIFOReceiver -_FIFOReceiver.__init__ -_FIFOReceiver._get_file_name -_FIFOReceiver.get_send_info -_FIFOReceiver.receive_data - - -@clean memorydb.py -class MemoryDB -MemoryDB.__init__ -MemoryDB._load_files -MemoryDB.keys -MemoryDB.__iter__ -MemoryDB.__len__ -MemoryDB.__setitem__ -MemoryDB.__contains__ -MemoryDB.__getitem__ -MemoryDB.create -MemoryDB.rename -MemoryDB.__delitem__ -MemoryDB.write -MemoryDB.compress -MemoryDB.persist - -class FileInfo -FileInfo.__init__ -FileInfo.create_scope -FileInfo.keys -FileInfo.__contains__ -FileInfo.__getitem__ -FileInfo.__delitem__ -FileInfo.__iter__ -FileInfo.__len__ -FileInfo.__setitem__ - -class ScopeInfo -ScopeInfo.__init__ -ScopeInfo.get_per_name -ScopeInfo.save_per_name -ScopeInfo.get_returned -ScopeInfo.get_call_infos -ScopeInfo.add_call -ScopeInfo.__getstate__ -ScopeInfo.__setstate__ - - -@clean objectdb.py -class ObjectDB -ObjectDB.__init__ -ObjectDB.validate_files -ObjectDB.validate_file -ObjectDB.file_moved -ObjectDB.get_files -ObjectDB.get_returned -ObjectDB.get_pername -ObjectDB.get_callinfos -ObjectDB.add_callinfo -ObjectDB.add_pername -ObjectDB.add_file_list_observer -ObjectDB.write -ObjectDB._get_scope_info -ObjectDB._file_removed -ObjectDB._file_added -ObjectDB.__str__ - -class _NullScopeInfo -_NullScopeInfo.__init__ -_NullScopeInfo.get_per_name -_NullScopeInfo.save_per_name -_NullScopeInfo.get_returned -_NullScopeInfo.get_call_infos -_NullScopeInfo.add_call - -class FileInfo -class FileDict -class ScopeInfo -ScopeInfo.get_per_name -ScopeInfo.save_per_name -ScopeInfo.get_returned -ScopeInfo.get_call_infos -ScopeInfo.add_call - -class CallInfo -CallInfo.__init__ -CallInfo.get_parameters -CallInfo.get_returned - -class FileListObserver - -@clean objectinfo.py -class ObjectInfoManager -ObjectInfoManager.__init__ -ObjectInfoManager._init_objectdb -ObjectInfoManager._init_validation -ObjectInfoManager._resource_changed -ObjectInfoManager._resource_moved -ObjectInfoManager.get_returned -ObjectInfoManager.get_exact_returned -ObjectInfoManager._args_to_textual -ObjectInfoManager.get_parameter_objects -ObjectInfoManager.get_passed_objects -ObjectInfoManager.doa_data_received -ObjectInfoManager.function_called -ObjectInfoManager.save_per_name -ObjectInfoManager.get_per_name -ObjectInfoManager._save_data -ObjectInfoManager._get_scope -ObjectInfoManager.sync -ObjectInfoManager.__str__ - -class TextualValidation -TextualValidation.__init__ -TextualValidation.is_value_valid -TextualValidation.is_more_valid -TextualValidation.is_file_valid -TextualValidation.is_scope_valid - -class _FileListObserver -_FileListObserver.__init__ -_FileListObserver.removed -_FileListObserver.added - - -@clean runmod.py -__rope_start_everything -class _MessageSender -class _SocketSender -class _FileSender -_cached -class _FunctionCallDataSender -_FunctionCallDataSender.global_trace - -_realpath - - -@clean soa.py -analyze_module -_analyze_node -class SOAVisitor -SOAVisitor.__init__ -SOAVisitor._FunctionDef -SOAVisitor._ClassDef -SOAVisitor._Call -SOAVisitor._args_with_self -SOAVisitor._call -SOAVisitor._parameter_objects -SOAVisitor._AnnAssign -SOAVisitor._Assign -SOAVisitor._evaluate_assign_value - -class _SOAAssignVisitor -_SOAAssignVisitor.__init__ -_SOAAssignVisitor._added - - -@clean soi.py -infer_returned_object -infer_parameter_objects -_handle_first_parameter -infer_assigned_object -get_passed_objects -_infer_returned -_parameter_objects -_infer_assignment & helpers -_follow_levels -_follow_pyname -_follow_evaluations -_get_lineno_for_node -_get_attribute - - -@clean transform.py -class PyObjectToTextual -PyObjectToTextual.__init__ -PyObjectToTextual.transform -PyObjectToTextual.__call__ -PyObjectToTextual.PyObject_to_textual -PyObjectToTextual.PyFunction_to_textual -PyObjectToTextual.PyClass_to_textual -PyObjectToTextual._defined_to_textual -PyObjectToTextual.PyModule_to_textual -PyObjectToTextual.PyPackage_to_textual -PyObjectToTextual.List_to_textual -PyObjectToTextual.Dict_to_textual -PyObjectToTextual.Tuple_to_textual -PyObjectToTextual.Set_to_textual -PyObjectToTextual.Iterator_to_textual -PyObjectToTextual.Generator_to_textual -PyObjectToTextual.Str_to_textual -PyObjectToTextual.File_to_textual -PyObjectToTextual.BuiltinFunction_to_textual -PyObjectToTextual._get_pymodule_path -PyObjectToTextual.resource_to_path - -class TextualToPyObject -TextualToPyObject.__init__ -TextualToPyObject.__call__ -TextualToPyObject.transform -TextualToPyObject.builtin_to_pyobject -TextualToPyObject.builtin_str_to_pyobject -TextualToPyObject.builtin_list_to_pyobject -TextualToPyObject.builtin_dict_to_pyobject -TextualToPyObject.builtin_tuple_to_pyobject -TextualToPyObject.builtin_set_to_pyobject -TextualToPyObject.builtin_iter_to_pyobject -TextualToPyObject.builtin_generator_to_pyobject -TextualToPyObject.builtin_file_to_pyobject -TextualToPyObject.builtin_function_to_pyobject -TextualToPyObject.unknown_to_pyobject -TextualToPyObject.none_to_pyobject -TextualToPyObject._module_to_pyobject -TextualToPyObject._hierarchical_defined_to_pyobject -TextualToPyObject.defined_to_pyobject -TextualToPyObject.instance_to_pyobject -TextualToPyObject._get_pymodule -TextualToPyObject.path_to_resource - -class DOITextualToPyObject -DOITextualToPyObject._function_to_pyobject -DOITextualToPyObject._class_to_pyobject -DOITextualToPyObject.defined_to_pyobject -DOITextualToPyObject._find_occurrence -DOITextualToPyObject.path_to_resource - - -@clean __init__.py -<< docstring: oi/__init__ >> - -@path type_hinting -@@clean __init__.py -@clean oi/type_hinting/evaluate.py -class SymbolBase -SymbolBase.__init__ -SymbolBase.nud -SymbolBase.led -SymbolBase.evaluate -SymbolBase.__repr__ - -class SymbolTable -SymbolTable.multi -SymbolTable.__init__ -SymbolTable.get -SymbolTable.__getitem__ -SymbolTable.__iter__ -SymbolTable.symbol -class S - -infix -infix_r -ternary -prefix -postfix - -symbol_table = SymbolTable() -class Lexer -Lexer.__init__ -Lexer.tokenize -Lexer._tokenize_expr - -class Parser -Parser.__init__ -Parser.parse -Parser.expression -Parser.advance - -method -bind - -symbol, infix, infix_r, prefix, postfix, ternary = ( -nud -evaluate -led -evaluate -nud -led -evaluate -evaluate -class Compiler -Compiler._make_parser -Compiler.__call__ - -compile = Compiler() -class Evaluator -Evaluator.__call__ - - -@clean factory.py -class TypeHintingFactory -TypeHintingFactory.make_param_provider -TypeHintingFactory.make_return_provider -TypeHintingFactory.make_assignment_provider -TypeHintingFactory.make_resolver - -default_type_hinting_factory = TypeHintingFactory() -class TypeHintingFactoryAccessor -TypeHintingFactoryAccessor.__call__ -TypeHintingFactoryAccessor._get_factory - - -@clean interfaces.py -class ITypeHintingFactory -ITypeHintingFactory.make_param_provider -ITypeHintingFactory.make_return_provider -ITypeHintingFactory.make_assignment_provider -ITypeHintingFactory.make_resolver - - -@clean utils.py -get_super_func -get_super_assignment -get_class_with_attr_name -get_lineno_for_node -get_mro -resolve_type (utils.py) -class ParametrizeType -ParametrizeType.__call__ -ParametrizeType._get_type_factory - - -@path providers -@@clean __init__.py -@clean composite.py -class ParamProvider -ParamProvider.__init__ -ParamProvider.__call__ - -class ReturnProvider -ReturnProvider.__init__ -ReturnProvider.__call__ - -class AssignmentProvider -AssignmentProvider.__init__ -AssignmentProvider.__call__ - - -@clean docstrings.py -class ParamProvider -ParamProvider.__init__ -ParamProvider.__call__ - -class ReturnProvider -ReturnProvider.__init__ -ReturnProvider.__call__ - -class AssignmentProvider -AssignmentProvider.__init__ -AssignmentProvider.__call__ - -class IParamParser -class IReturnParser -class DocstringParamParser -DocstringParamParser.__init__ -DocstringParamParser.__call__ - -class DocstringReturnParser -DocstringReturnParser.__init__ -DocstringReturnParser.__call__ - -class RSTRoleStrip -RSTRoleStrip.__call__ - - -@clean inheritance.py -class ParamProvider -ParamProvider.__init__ -ParamProvider.__call__ - -class ReturnProvider -ReturnProvider.__init__ -ReturnProvider.__call__ - -class AssignmentProvider -AssignmentProvider.__init__ -AssignmentProvider.__call__ - - -@clean interfaces.py -class IParamProvider -IParamProvider.__call__ - -class IReturnProvider -IReturnProvider.__call__ - -class IAssignmentProvider -IAssignmentProvider.__call__ - - -@clean numpydocstrings.py -class NumPyDocstringParamParser -NumPyDocstringParamParser.__call__ - -class _DummyParamParser - -@clean pep0484_type_comments.py -class AssignmentProvider -AssignmentProvider.__init__ -AssignmentProvider.PEP0484_TYPE_COMMENT_PATTERNS = (re.compile(r"type:/s*([^/n]+)"),) -AssignmentProvider.__call__ -AssignmentProvider._search_type_in_type_comment - - - -@path resolvers -@@clean __init__.py -@clean composite.py -class Resolver -Resolver.__init__ -Resolver.__call__ - - -@clean interfaces.py -@clean types.py -class Resolver -Resolver.__call__ - - - - - -@path base/utils -@clean __init__.py -saveit -_wrapper - -cacheit = saveit -prevent_recursion -decorator - -ignore_exception -_decorator - -deprecated -_decorator - -cached -decorator - -class _Cached -_Cached.__init__ -_Cached.__call__ - -resolve -guess_def_lineno -is_inline_body - - -@clean astutils.py -class _NodeNameCollector -_NodeNameCollector.__init__ -_NodeNameCollector._add_node -_NodeNameCollector._added -_NodeNameCollector._Name -_NodeNameCollector._ExceptHandler -_NodeNameCollector._Tuple -_NodeNameCollector._Subscript -_NodeNameCollector._Attribute -_NodeNameCollector._Slice - -function: call_for_nodes -function: get_child_nodes -function: get_children -function: get_name_levels -function: parse -function: walk - -@clean datastructures.py -class OrderedSet -OrderedSet.__init__ -OrderedSet.__len__ -OrderedSet.__contains__ -OrderedSet.add -OrderedSet.intersection -OrderedSet.discard -OrderedSet.__iter__ -OrderedSet.__reversed__ -OrderedSet.pop -OrderedSet.__repr__ -OrderedSet.__eq__ - - -@clean pycompat.py - -@path contrib -@clean changestack.py -class ChangeStack -ChangeStack.__init__ -ChangeStack.push -ChangeStack.pop_all -ChangeStack.merged -ChangeStack._basic_changes - - -@clean codeassist.py -code_assist -starting_offset -get_doc -get_calltip -get_definition_location -find_occurrences -get_canonical_path -class CompletionProposal -CompletionProposal.__init__ -CompletionProposal.__str__ -CompletionProposal.__repr__ -CompletionProposal.parameters -CompletionProposal.type -CompletionProposal._get_scope -CompletionProposal.get_doc -CompletionProposal.kind - -leaved for backward compatibility -class NamedParamProposal -NamedParamProposal.__init__ -NamedParamProposal.get_default - -sorted_proposals -starting_expression -default_templates -class _PythonCodeAssist -_PythonCodeAssist.__init__ -_PythonCodeAssist.keywords = keyword.kwlist -_PythonCodeAssist._find_starting_offset -_PythonCodeAssist._matching_keywords -_PythonCodeAssist.__call__ -_PythonCodeAssist._dotted_completions -_PythonCodeAssist._undotted_completions -_PythonCodeAssist._from_import_completions -_PythonCodeAssist._find_module -_PythonCodeAssist._is_defined_after -_PythonCodeAssist._code_completions -_PythonCodeAssist._keyword_parameters - -class _ProposalSorter -_ProposalSorter.__init__ -_ProposalSorter.get_sorted_proposal_list -_ProposalSorter._proposal_key - -class PyDocExtractor -PyDocExtractor.get_doc -PyDocExtractor.get_calltip -PyDocExtractor._get_class_docstring -PyDocExtractor._get_function_docstring -PyDocExtractor._is_method -PyDocExtractor._get_single_function_docstring -PyDocExtractor._get_super_methods -PyDocExtractor._get_function_signature -PyDocExtractor._location -PyDocExtractor._get_module -PyDocExtractor._trim_docstring - -Deprecated classes -class TemplateProposal -class Template -Template.__init__ -Template.variables -Template.substitute -Template.get_cursor_location - - -@clean finderrors.py -find_errors -class _BadAccessFinder -_BadAccessFinder.__init__ -_BadAccessFinder._Name -_BadAccessFinder._Attribute -_BadAccessFinder._add_error -_BadAccessFinder._is_defined_after - -class Error - -@clean findit.py -find_occurrences -is_match - -find_implementations -is_defined -not_self - -find_definition -class Location -_find_locations - -@clean fixmodnames.py -class FixModuleNames -FixModuleNames.__init__ -FixModuleNames.get_changes -FixModuleNames._count_fixes -FixModuleNames._tobe_fixed -FixModuleNames._name - - -@clean fixsyntax.py -class FixSyntax -FixSyntax.__init__ -FixSyntax.get_pymodule -FixSyntax.commenter -FixSyntax.pyname_at - -class _Commenter -_Commenter.__init__ -_Commenter.comment -_Commenter.transfered_offset -_Commenter._last_non_blank -_Commenter._get_block_end -_Commenter._get_stmt_end -_Commenter._fix_incomplete_try_blocks -_Commenter._find_matching_deindent -_Commenter._set -_Commenter._insert - -_logical_start -_get_line_indents - -@clean generate.py -create_generate -create_module -create_package -class _Generate -_Generate.__init__ -_Generate._generate_info -_Generate._check_exceptional_conditions -_Generate.get_changes -_Generate.get_location -_Generate._get_element_kind -_Generate._get_element - -class GenerateFunction -GenerateFunction._generate_info -GenerateFunction._get_element -GenerateFunction._get_element_kind - -class GenerateVariable -class GenerateClass -class GenerateModule -GenerateModule.get_changes -GenerateModule.get_location - -class GeneratePackage -GeneratePackage.get_changes -GeneratePackage.get_location - -_add_import_to_module -_add_relative_import_to_module -class _GenerationInfo -_GenerationInfo.__init__ -_GenerationInfo._init_fields -_GenerationInfo._get_goal_scope -_GenerationInfo._get_goal_module -_GenerationInfo._get_source_scope -_GenerationInfo.get_insertion_lineno -_GenerationInfo.get_insertion_resource -_GenerationInfo.get_insertion_offsets -_GenerationInfo.get_scope_indents -_GenerationInfo.get_blank_lines -_GenerationInfo.get_package -_GenerationInfo.primary_is_found -_GenerationInfo.element_already_exists -_GenerationInfo.get_name - -class _FunctionGenerationInfo -_FunctionGenerationInfo._get_goal_scope -_FunctionGenerationInfo.element_already_exists -_FunctionGenerationInfo.is_static_method -_FunctionGenerationInfo.is_method -_FunctionGenerationInfo.is_constructor -_FunctionGenerationInfo.is_instance -_FunctionGenerationInfo.get_name -_FunctionGenerationInfo.get_passed_args -_FunctionGenerationInfo._is_id - - -@clean __init__.py -@path autoimport -@clean defs.py -class Source -class ModuleInfo -class ModuleFile -class ModuleCompiled -class PackageType -class NameType -class Package -class Name -class PartialName -class SearchResult - -@clean models.py -class FinalQuery -class Query -Query.__init__ -Query.select -Query.select_star -Query.where -Query.insert_into -Query.drop_table -Query.delete_from - -class Name -Name.create_table - -class Package -Package.create_table - - -@clean parse.py -get_type_ast -get_names_from_file -get_type_object -get_names -get_names_from_compiled -combine - -@clean pickle.py -class AutoImport -AutoImport.__init__ -AutoImport.import_assist -AutoImport.get_modules -AutoImport.get_all_names -AutoImport.get_name_locations -AutoImport.generate_cache -AutoImport.generate_modules_cache -AutoImport.clear_cache -AutoImport.find_insertion_line -AutoImport.update_resource -AutoImport.update_module -AutoImport._module_name -AutoImport._add_names -AutoImport._write -AutoImport._changed -AutoImport._moved -AutoImport._removed - -submodules - -@clean sqlite.py -get_future_names -filter_packages -class AutoImport -AutoImport.__init__ -AutoImport._setup_db -AutoImport.import_assist -AutoImport.search -AutoImport.search_full -AutoImport._search_name -AutoImport._search_module -AutoImport.get_modules -AutoImport.get_all_names -AutoImport._dump_all -AutoImport.generate_cache -AutoImport.generate_modules_cache -AutoImport._get_packages_from_modules -AutoImport.update_module -AutoImport.close -AutoImport.get_name_locations -AutoImport.clear_cache -AutoImport.find_insertion_line -AutoImport.update_resource -AutoImport._changed -AutoImport._moved -AutoImport._del_if_exist -AutoImport._get_python_folders -AutoImport._get_available_packages -AutoImport._add_packages -AutoImport._get_packages_from_cache -AutoImport._removed -AutoImport._add_future_names -AutoImport._convert_name -AutoImport._add_names -AutoImport._add_name -AutoImport._find_package_path -AutoImport._resource_to_module -AutoImport._execute -AutoImport._executemany - - -@clean utils.py -get_package_tuple -get_package_source -get_modname_from_path -sort_and_deduplicate -sort_and_deduplicate_tuple -should_parse -get_files - -@clean __init__.py - - -@path refactor -@clean __init__.py -@clean change_signature.py -class ChangeSignature -ChangeSignature.__init__ -ChangeSignature._set_name_and_pyname -ChangeSignature._change_calls -ChangeSignature.get_args -ChangeSignature.is_method -ChangeSignature.get_definition_info -ChangeSignature._definfo -ChangeSignature.normalize -ChangeSignature.remove -ChangeSignature.add -ChangeSignature.inline_default -ChangeSignature.reorder -ChangeSignature.get_changes - -class _FunctionChangers -_FunctionChangers.__init__ -_FunctionChangers._get_changed_definition_infos -_FunctionChangers.change_definition -_FunctionChangers.change_call - -class _ArgumentChanger -class ArgumentNormalizer -class ArgumentRemover -ArgumentRemover.__init__ -ArgumentRemover.change_definition_info -ArgumentRemover.change_argument_mapping - -class ArgumentAdder -ArgumentAdder.__init__ -ArgumentAdder.change_definition_info -ArgumentAdder.change_argument_mapping - -class ArgumentDefaultInliner -ArgumentDefaultInliner.__init__ -ArgumentDefaultInliner.change_definition_info -ArgumentDefaultInliner.change_argument_mapping - -class ArgumentReorderer -ArgumentReorderer.__init__ -ArgumentReorderer.change_definition_info - -class _ChangeCallsInModule -_ChangeCallsInModule.__init__ -_ChangeCallsInModule.get_changed_module -_ChangeCallsInModule.pymodule -_ChangeCallsInModule.source -_ChangeCallsInModule.lines - -class _MultipleFinders -_MultipleFinders.__init__ -_MultipleFinders.find_occurrences - - -@clean encapsulate_field.py -class EncapsulateField -EncapsulateField.__init__ -EncapsulateField.get_changes -EncapsulateField.get_field_name -EncapsulateField._is_an_attribute -EncapsulateField._get_defining_class_scope -EncapsulateField._get_defining_scope -EncapsulateField._change_holding_module - -class GetterSetterRenameInModule -GetterSetterRenameInModule.__init__ -GetterSetterRenameInModule.get_changed_module - -class _FindChangesForModule -_FindChangesForModule.__init__ -_FindChangesForModule.get_changed_module -_FindChangesForModule._manage_writes -_FindChangesForModule._is_assigned_in_a_tuple_assignment -_FindChangesForModule.source -_FindChangesForModule.lines -_FindChangesForModule.worder - - -@clean extract.py -class _ExtractRefactoring -_ExtractRefactoring.__init__ -_ExtractRefactoring._fix_start -_ExtractRefactoring._fix_end -_ExtractRefactoring.get_changes -_ExtractRefactoring._get_kind_from_name -_ExtractRefactoring._validate_kind_prefix -_ExtractRefactoring._get_kind - -class ExtractMethod -ExtractMethod._get_kind - -class ExtractVariable -ExtractVariable.__init__ -ExtractVariable.kind = "variable" -ExtractVariable._get_kind - -class _ExtractInfo -_ExtractInfo.__init__ -_ExtractInfo._init_parts -_ExtractInfo.logical_lines -_ExtractInfo._init_scope -_ExtractInfo._get_scope_region -_ExtractInfo._choose_closest_line_end -_ExtractInfo.one_line -_ExtractInfo.global_ -_ExtractInfo.method -_ExtractInfo.indents -_ExtractInfo.scope_indents -_ExtractInfo.extracted -_ExtractInfo._cached_parsed_extraced = None -_ExtractInfo._parsed_extracted -_ExtractInfo._returned = None -_ExtractInfo.returned -_ExtractInfo._returning_named_expr = None -_ExtractInfo.returning_named_expr -_ExtractInfo._returning_generator = None -_ExtractInfo.returning_generator_exp - -class _ExtractCollector -_ExtractCollector.__init__ - -class _ExtractPerformer -_ExtractPerformer.__init__ -_ExtractPerformer.extract -_ExtractPerformer._replace_occurrences -_ExtractPerformer._collect_info -_ExtractPerformer._find_matches -_ExtractPerformer._is_assignment -_ExtractPerformer._where_to_search -_ExtractPerformer._find_definition_location -_ExtractPerformer._find_definition - -class _DefinitionLocationFinder -_DefinitionLocationFinder.__init__ -_DefinitionLocationFinder.find_lineno -_DefinitionLocationFinder._find_toplevel -_DefinitionLocationFinder.find_indents -_DefinitionLocationFinder._get_before_line -_DefinitionLocationFinder._get_after_scope - -class _ExceptionalConditionChecker -_ExceptionalConditionChecker.__call__ -_ExceptionalConditionChecker.base_conditions -_ExceptionalConditionChecker.one_line_conditions -_ExceptionalConditionChecker.multi_line_conditions -_ExceptionalConditionChecker._is_region_on_a_word -_ExceptionalConditionChecker._is_on_a_word - -class _ExtractMethodParts -_ExtractMethodParts.__init__ -_ExtractMethodParts._get_kind_by_scope -_ExtractMethodParts._check_constraints -_ExtractMethodParts._extacting_from_staticmethod -_ExtractMethodParts._extracting_from_classmethod -_ExtractMethodParts.get_definition -_ExtractMethodParts.get_replacement_pattern -_ExtractMethodParts.get_body_pattern -_ExtractMethodParts._get_body -_ExtractMethodParts._find_temps -_ExtractMethodParts.get_checks -_ExtractMethodParts._create_info_collector -_ExtractMethodParts._get_function_definition -_ExtractMethodParts._append_decorators -_ExtractMethodParts._extracting_classmethod -_ExtractMethodParts._extracting_staticmethod -_ExtractMethodParts._get_function_signature -_ExtractMethodParts._extracting_method -_ExtractMethodParts._get_self_name -_ExtractMethodParts._get_scope_self_name -_ExtractMethodParts._get_function_call -_ExtractMethodParts._get_function_call_prefix -_ExtractMethodParts._get_comma_form -_ExtractMethodParts._get_call -_ExtractMethodParts._find_function_arguments -_ExtractMethodParts._find_function_returns -_ExtractMethodParts._get_unindented_function_body -_ExtractMethodParts._get_multiline_function_body -_ExtractMethodParts._get_single_expression_function_body -_ExtractMethodParts._insert_globals -_ExtractMethodParts._get_globals_in_body - -class _ExtractVariableParts -_ExtractVariableParts.__init__ -_ExtractVariableParts.get_definition -_ExtractVariableParts.get_body_pattern -_ExtractVariableParts.get_replacement_pattern -_ExtractVariableParts.get_checks - -class _FunctionInformationCollector -_FunctionInformationCollector.__init__ -_FunctionInformationCollector._read_variable -_FunctionInformationCollector._written_variable -_FunctionInformationCollector._FunctionDef -_FunctionInformationCollector._Global -_FunctionInformationCollector._AsyncFunctionDef -_FunctionInformationCollector._Name -_FunctionInformationCollector._MatchAs -_FunctionInformationCollector._Assign -_FunctionInformationCollector._AugAssign -_FunctionInformationCollector._ClassDef -_FunctionInformationCollector._ListComp -_FunctionInformationCollector._GeneratorExp -_FunctionInformationCollector._SetComp -_FunctionInformationCollector._DictComp -_FunctionInformationCollector._comp_exp -_FunctionInformationCollector._flatten_nested_tuple_of_names -_FunctionInformationCollector._If -_FunctionInformationCollector._While -_FunctionInformationCollector._For -_FunctionInformationCollector._handle_conditional_node -_FunctionInformationCollector._handle_conditional_context -_FunctionInformationCollector._handle_loop_context - -_get_argnames -class _VariableReadsAndWritesFinder -_VariableReadsAndWritesFinder.__init__ -_VariableReadsAndWritesFinder._Name -_VariableReadsAndWritesFinder._FunctionDef -_VariableReadsAndWritesFinder._Class -_VariableReadsAndWritesFinder.find_reads_and_writes -_VariableReadsAndWritesFinder.find_reads_for_one_liners - -class _BaseErrorFinder -_BaseErrorFinder.has_errors - -class _UnmatchedBreakOrContinueFinder -_UnmatchedBreakOrContinueFinder.__init__ -_UnmatchedBreakOrContinueFinder._For -_UnmatchedBreakOrContinueFinder._While -_UnmatchedBreakOrContinueFinder.loop_encountered -_UnmatchedBreakOrContinueFinder._Break -_UnmatchedBreakOrContinueFinder._Continue -_UnmatchedBreakOrContinueFinder.check_loop -_UnmatchedBreakOrContinueFinder._FunctionDef -_UnmatchedBreakOrContinueFinder._ClassDef - -class _AsyncStatementFinder -_AsyncStatementFinder.__init__ -_AsyncStatementFinder._AsyncFor -_AsyncStatementFinder._AsyncWith -_AsyncStatementFinder._FunctionDef -_AsyncStatementFinder._ClassDef - -class _GlobalFinder -_get_function_kind -_parse_text -_join_lines -_get_single_expression_body - -@clean functionutils.py -class DefinitionInfo -DefinitionInfo.__init__ -DefinitionInfo.to_string -DefinitionInfo.arguments_to_string -DefinitionInfo._read -DefinitionInfo.read - -class CallInfo -CallInfo.__init__ -CallInfo.to_string -CallInfo.read -CallInfo._is_method_call -CallInfo._is_class -CallInfo._is_method -CallInfo._is_classmethod - -class ArgumentMapping -ArgumentMapping.__init__ -ArgumentMapping.to_call_info - -class _FunctionParser -_FunctionParser.__init__ -_FunctionParser.get_parameters -_FunctionParser.get_instance -_FunctionParser.get_function_name -_FunctionParser.is_called_as_a_method - - -@clean inline.py -unique_prefix -create_inline -class _Inliner -_Inliner.__init__ -_Inliner.get_changes -_Inliner.get_kind - -class InlineMethod -InlineMethod.__init__ -InlineMethod._init_imports -InlineMethod._get_scope_range -InlineMethod.get_changes -InlineMethod._get_removed_range -InlineMethod._defining_file_changes -InlineMethod._get_method_replacement -InlineMethod._is_the_last_method_of_a_class -InlineMethod.get_kind - -class InlineVariable -InlineVariable.__init__ -InlineVariable._check_exceptional_conditions -InlineVariable.get_changes -InlineVariable._change_main_module -InlineVariable._init_imports -InlineVariable._change_module -InlineVariable.check_aim - -InlineVariable.get_kind - -class InlineParameter -InlineParameter.__init__ -InlineParameter._function_location -InlineParameter.get_changes -InlineParameter.get_kind - -_join_lines -class _DefinitionGenerator -_DefinitionGenerator.__init__ -_DefinitionGenerator._get_definition_info -_DefinitionGenerator._get_definition_params -_DefinitionGenerator.get_function_name -_DefinitionGenerator.get_definition -_DefinitionGenerator._calculate_header -_DefinitionGenerator._calculate_definition -_DefinitionGenerator._replace_returns_with -_DefinitionGenerator._check_nothing_after_return -_DefinitionGenerator._get_return_pattern -_DefinitionGenerator.named_pattern - - -class _InlineFunctionCallsForModuleHandle -_InlineFunctionCallsForModuleHandle.__init__ -_InlineFunctionCallsForModuleHandle.occurred_inside_skip -_InlineFunctionCallsForModuleHandle.occurred_outside_skip -_InlineFunctionCallsForModuleHandle._find_end_parens -_InlineFunctionCallsForModuleHandle.pymodule -_InlineFunctionCallsForModuleHandle.source -_InlineFunctionCallsForModuleHandle.lines - -_inline_variable -_getvardef -_assigned_lineno -_add_imports -_get_pyname -_remove_from - -@clean introduce_factory.py -class IntroduceFactory -IntroduceFactory.__init__ -IntroduceFactory.get_changes -IntroduceFactory.get_name -IntroduceFactory._change_module -IntroduceFactory._change_resource -IntroduceFactory._get_insertion_offset -IntroduceFactory._get_factory_method -IntroduceFactory._get_scope_indents -IntroduceFactory._new_function_name -IntroduceFactory._rename_occurrences - - -@clean introduce_parameter.py -class IntroduceParameter -IntroduceParameter.__init__ -IntroduceParameter._get_primary -IntroduceParameter._get_name_and_pyname -IntroduceParameter.get_changes -IntroduceParameter._get_header_offsets -IntroduceParameter._change_function_occurrences - - -@clean localtofield.py -class LocalToField -LocalToField.__init__ -LocalToField.get_changes -LocalToField._check_redefinition -LocalToField._get_field_name -LocalToField._is_a_method_local - - -@clean method_object.py -class MethodObject -MethodObject.__init__ -MethodObject.get_new_class -MethodObject.get_changes -MethodObject._get_class_insertion_point -MethodObject._get_body -MethodObject._get_init -MethodObject._get_parameter_names - - -@clean move.py -create_move -class MoveMethod -MoveMethod.__init__ -MoveMethod.get_changes -MoveMethod.get_method_name -MoveMethod._get_used_imports -MoveMethod._get_changes_made_by_old_class -MoveMethod._get_scope_indents -MoveMethod._get_changes_made_by_new_class -MoveMethod.get_new_method -MoveMethod._get_unchanged_body -MoveMethod._get_body -MoveMethod._get_self_name -MoveMethod._get_new_header -MoveMethod._get_passed_arguments_string -MoveMethod._is_host_used - -class MoveGlobal -MoveGlobal.__init__ -MoveGlobal._import_filter -MoveGlobal._check_exceptional_conditions -MoveGlobal._raise_refactoring_error -MoveGlobal._is_global -MoveGlobal._is_variable -MoveGlobal.get_changes -MoveGlobal._calculate_changes -MoveGlobal._source_module_changes -MoveGlobal._new_modname -MoveGlobal._dest_module_changes -MoveGlobal._get_moving_element_with_imports -MoveGlobal._get_module_with_imports -MoveGlobal._get_moving_element -MoveGlobal._get_moving_region -MoveGlobal._add_imports2 - -class MoveModule -MoveModule.__init__ -MoveModule.get_changes -MoveModule._calculate_changes -MoveModule._new_modname -MoveModule._new_import -MoveModule._change_moving_module -MoveModule._change_occurrences_in_module -MoveModule._change_import_statements -MoveModule._handle_moving_in_from_import_stmt - -class _ChangeMoveOccurrencesHandle -_ChangeMoveOccurrencesHandle.__init__ -_ChangeMoveOccurrencesHandle.occurred_inside_skip -_ChangeMoveOccurrencesHandle.occurred_outside_skip - -class _MoveTools -_MoveTools.__init__ -_MoveTools.remove_old_imports -_MoveTools.__call__ - -_MoveTools.rename_in_module -_MoveTools.occurs_in_module -_MoveTools._create_finder -_MoveTools.new_pymodule -_MoveTools.new_source -_MoveTools.add_imports - -_add_imports_to_module -moving_code_with_imports -class ModuleSkipRenamerHandle -class ModuleSkipRenamer -ModuleSkipRenamer.__init__ -ModuleSkipRenamer.get_changed_module - - -@clean multiproject.py -class MultiProjectRefactoring -MultiProjectRefactoring.__init__ -MultiProjectRefactoring.__call__ - -class _MultiRefactoring -_MultiRefactoring.__init__ -_MultiRefactoring.get_all_changes -_MultiRefactoring.__getattr__ -_MultiRefactoring._resources_for_args -_MultiRefactoring._change_project_resource -_MultiRefactoring.project -_MultiRefactoring.main_refactoring - -perform - -@clean occurrences.py -class Finder -Finder.__init__ -Finder.find_occurrences - -create_finder -class Occurrence -Occurrence.__init__ -Occurrence.get_word_range -Occurrence.get_primary_range -Occurrence.get_pyname -Occurrence.get_primary_and_pyname -Occurrence.is_in_import_statement -Occurrence.is_called -Occurrence.is_defined -Occurrence.is_a_fixed_primary -Occurrence.is_written -Occurrence.is_unsure -Occurrence.is_function_keyword_parameter -Occurrence.lineno - -same_pyname -unsure_pyname -class PyNameFilter -PyNameFilter.__init__ -PyNameFilter.__call__ - -class InHierarchyFilter -InHierarchyFilter.__init__ -InHierarchyFilter.__call__ -InHierarchyFilter._get_containing_class -InHierarchyFilter._get_root_classes - -class UnsureFilter -UnsureFilter.__init__ -UnsureFilter.__call__ - -class NoImportsFilter -class CallsFilter -class NoKeywordsFilter -class _TextualFinder -_TextualFinder.__init__ -_TextualFinder.find_offsets -_TextualFinder._re_search -_TextualFinder._search_in_f_string -_TextualFinder._normal_search -_TextualFinder._is_id_char -_TextualFinder._fast_file_query -_TextualFinder._get_source -_TextualFinder._get_occurrence_pattern -_TextualFinder.any - -class _OccurrenceToolsCreator -_OccurrenceToolsCreator.__init__ -_OccurrenceToolsCreator.name_finder -_OccurrenceToolsCreator.source_code -_OccurrenceToolsCreator.word_finder -_OccurrenceToolsCreator.resource -_OccurrenceToolsCreator.pymodule - - -@clean patchedast.py -get_patched_ast -patch_ast -node_region -write_ast -class MismatchedTokenError -class _PatchingASTWalker -_PatchingASTWalker.__init__ -_PatchingASTWalker.Number = object() -_PatchingASTWalker.__call__ -_PatchingASTWalker._handle (changed) -_PatchingASTWalker._handle_parens -_PatchingASTWalker._eat_surrounding_parens -_PatchingASTWalker._count_needed_parens -_PatchingASTWalker._find_next_statement_start -_PatchingASTWalker._join -_PatchingASTWalker._flatten_keywords -_PatchingASTWalker._child_nodes -_PatchingASTWalker._operators = { -_PatchingASTWalker._get_op -_PatchingASTWalker._Attribute -_PatchingASTWalker._Assert -_PatchingASTWalker._Assign -_PatchingASTWalker._AugAssign -_PatchingASTWalker._AnnAssign -_PatchingASTWalker._Repr -_PatchingASTWalker._BinOp -_PatchingASTWalker._BoolOp -_PatchingASTWalker._Break -_PatchingASTWalker._Call (changed) -_PatchingASTWalker._ClassDef -_PatchingASTWalker._Compare -_PatchingASTWalker._Delete -_PatchingASTWalker._Constant -_PatchingASTWalker._Num -_PatchingASTWalker._Str -_PatchingASTWalker._Bytes -_PatchingASTWalker._JoinedStr -_PatchingASTWalker._FormattedValue -_PatchingASTWalker._Continue -_PatchingASTWalker._Dict -_PatchingASTWalker._Ellipsis -_PatchingASTWalker._Expr -_PatchingASTWalker._NamedExpr -_PatchingASTWalker._Exec -_PatchingASTWalker._ExtSlice -_PatchingASTWalker._handle_for_loop_node -_PatchingASTWalker._For -_PatchingASTWalker._AsyncFor -_PatchingASTWalker._ImportFrom -_PatchingASTWalker._alias -_PatchingASTWalker._handle_function_def_node -_PatchingASTWalker._FunctionDef -_PatchingASTWalker._AsyncFunctionDef -_PatchingASTWalker._arguments -_PatchingASTWalker._add_args_to_children -_PatchingASTWalker._add_tuple_parameter -_PatchingASTWalker._GeneratorExp -_PatchingASTWalker._comprehension -_PatchingASTWalker._Global -_PatchingASTWalker._If -_PatchingASTWalker._is_elif -_PatchingASTWalker._IfExp -_PatchingASTWalker._Import -_PatchingASTWalker._keyword -_PatchingASTWalker._Lambda -_PatchingASTWalker._List -_PatchingASTWalker._ListComp -_PatchingASTWalker._Set -_PatchingASTWalker._SetComp -_PatchingASTWalker._DictComp -_PatchingASTWalker._Module -_PatchingASTWalker._Name -_PatchingASTWalker._NameConstant -_PatchingASTWalker._arg -_PatchingASTWalker._Pass -_PatchingASTWalker._Print -_PatchingASTWalker._Raise -_PatchingASTWalker._Return -_PatchingASTWalker._Sliceobj -_PatchingASTWalker._Index -_PatchingASTWalker._Subscript -_PatchingASTWalker._Slice -_PatchingASTWalker._TryFinally -_PatchingASTWalker._TryExcept -_PatchingASTWalker._Try -_PatchingASTWalker._ExceptHandler -_PatchingASTWalker._excepthandler -_PatchingASTWalker._Tuple -_PatchingASTWalker._UnaryOp -_PatchingASTWalker._Await -_PatchingASTWalker._Yield -_PatchingASTWalker._YieldFrom -_PatchingASTWalker._While -_PatchingASTWalker._handle_with_node -_PatchingASTWalker._With -_PatchingASTWalker._AsyncWith -_PatchingASTWalker._Starred -_PatchingASTWalker._Match -_PatchingASTWalker._match_case -_PatchingASTWalker._MatchAs -_PatchingASTWalker._MatchClass -_PatchingASTWalker._MatchValue - -class _Source -_Source.__init__ -_Source.consume (changed) -_Source.consume_joined_string -_Source.consume_string -_Source.consume_number -_Source.consume_empty_tuple -_Source.consume_not_equal -_Source.consume_except_as_or_semicolon -_Source.consume_exec_open_paren_or_space -_Source.consume_exec_in_or_comma -_Source.consume_exec_close_paren_or_space -_Source.consume_with_or_comma_context_manager -_Source._good_token -_Source._skip_comment -_Source._get_location -_Source._consume_pattern -_Source.till_token -_Source.rfind_token -_Source.from_offset -_Source.find_backwards -_Source.__getitem__ -_Source.__getslice__ -_Source._get_number_pattern - - -@clean rename.py -class Rename -Rename.__init__ -Rename.get_old_name -Rename.get_changes -Rename.unsure_func - -Rename._is_allowed_to_move -Rename._is_renaming_a_module -Rename.is_method -Rename._rename_module - -class ChangeOccurrences -ChangeOccurrences.__init__ -ChangeOccurrences.get_old_name -ChangeOccurrences._get_scope_offset -ChangeOccurrences.get_changes - -rename_in_module -_is_local - -@clean restructure.py -class Restructure -Restructure.__init__ -Restructure.get_changes -Restructure._compute_changes -Restructure._add_imports -Restructure._get_import_infos -Restructure.make_checks -Restructure._evaluate -class _BuiltinsStub - - -replace -class _ChangeComputer -_ChangeComputer.__init__ -_ChangeComputer.get_changed -_ChangeComputer._is_expression -_ChangeComputer._get_matched_text -_ChangeComputer._get_node_text -_ChangeComputer._auto_indent -_ChangeComputer._get_nearest_roots - - -@clean similarfinder.py -class BadNameInCheckError -class SimilarFinder -SimilarFinder.__init__ -SimilarFinder.get_matches -SimilarFinder.get_match_regions -SimilarFinder._does_match - -class RawSimilarFinder -RawSimilarFinder.__init__ -RawSimilarFinder._simple_does_match -RawSimilarFinder._init_using_ast -RawSimilarFinder.get_matches -RawSimilarFinder._get_matched_asts -RawSimilarFinder._create_pattern -RawSimilarFinder._replace_wildcards - -class _ASTMatcher -_ASTMatcher.__init__ -_ASTMatcher.find_matches -_ASTMatcher._check_node -_ASTMatcher._check_expression -_ASTMatcher._check_statements -_ASTMatcher.__check_stmt_list -_ASTMatcher._match_nodes -_ASTMatcher._get_children -_ASTMatcher._match_stmts -_ASTMatcher._match_wildcard - -class Match -Match.__init__ -Match.get_region -Match.get_ast - -class ExpressionMatch -class StatementMatch -class CodeTemplate -CodeTemplate.__init__ -CodeTemplate._find_names -CodeTemplate.get_names -CodeTemplate.substitute -CodeTemplate._match_pattern = None -CodeTemplate._get_pattern - -class _RopeVariable -_RopeVariable.get_var -_RopeVariable.is_var -_RopeVariable.get_base -_RopeVariable._get_normal -_RopeVariable._get_any -_RopeVariable._is_normal -_RopeVariable._is_var - -make_pattern -does_match - -_pydefined_to_str - -@clean sourceutils.py -get_indents -find_minimum_indents -indent_lines -fix_indentation -add_methods -get_body -get_body_region -get_indent - -@clean suites.py -find_visible -find_visible_for_suite -valid - -ast_suite_tree -class Suite -Suite.__init__ -Suite.get_start -Suite.get_children -Suite.local_start -Suite.local_end -Suite.find_suite -Suite._get_level - -class _SuiteWalker -_SuiteWalker.__init__ -_SuiteWalker._If -_SuiteWalker._For -_SuiteWalker._While -_SuiteWalker._With -_SuiteWalker._AsyncWith -_SuiteWalker._Match -_SuiteWalker._TryFinally -_SuiteWalker._Try -_SuiteWalker._TryExcept -_SuiteWalker._add_if_like_node -_SuiteWalker._FunctionDef -_SuiteWalker._AsyncFunctionDef -_SuiteWalker._ClassDef - - -@clean topackage.py -class ModuleToPackage -ModuleToPackage.__init__ -ModuleToPackage.get_changes -ModuleToPackage._transform_relatives_to_absolute - - -@clean usefunction.py -class UseFunction -UseFunction.__init__ -UseFunction._check_returns -UseFunction.get_changes -UseFunction.get_function_name -UseFunction._restructure -UseFunction._find_temps -UseFunction._module_name -UseFunction._make_pattern -UseFunction._get_body -UseFunction._make_goal -UseFunction._does_return -UseFunction._is_expression - -find_temps -_returns_last -_namedexpr_last -_yield_count -_return_count -_named_expr_count -class _ReturnOrYieldFinder -_ReturnOrYieldFinder.__init__ -_ReturnOrYieldFinder._Return -_ReturnOrYieldFinder._NamedExpr -_ReturnOrYieldFinder._Yield -_ReturnOrYieldFinder._FunctionDef -_ReturnOrYieldFinder._ClassDef -_ReturnOrYieldFinder.start_walking - - -@clean wildcards.py -class Wildcard -class Suspect -class DefaultWildcard -DefaultWildcard.__init__ -DefaultWildcard.get_name -DefaultWildcard.matches -DefaultWildcard._check_object -DefaultWildcard._check_exact - -parse_arg -class _CheckObject -_CheckObject.__init__ -_CheckObject.__call__ -_CheckObject._get_super_classes -_CheckObject._same_pyobject -_CheckObject._same_pyname -_CheckObject._unsure_pyname -_CheckObject._split_name -_CheckObject._evaluate_node -_CheckObject._evaluate -class _BuiltinsStub - - - -@path importutils -@clean actions.py -class ImportInfoVisitor -ImportInfoVisitor.dispatch -ImportInfoVisitor.visitEmptyImport -ImportInfoVisitor.visitNormalImport -ImportInfoVisitor.visitFromImport - -class RelativeToAbsoluteVisitor -RelativeToAbsoluteVisitor.__init__ -RelativeToAbsoluteVisitor.visitNormalImport -RelativeToAbsoluteVisitor._get_relative_to_absolute_list -RelativeToAbsoluteVisitor.visitFromImport - -class FilteringVisitor -FilteringVisitor.__init__ -FilteringVisitor._transform_can_select -FilteringVisitor.visitNormalImport -FilteringVisitor.visitFromImport - -class RemovingVisitor -RemovingVisitor.__init__ -RemovingVisitor.dispatch - -class AddingVisitor -AddingVisitor.__init__ -AddingVisitor.dispatch -AddingVisitor.visitNormalImport -AddingVisitor.visitFromImport - -class ExpandStarsVisitor -ExpandStarsVisitor.__init__ -ExpandStarsVisitor.visitNormalImport -ExpandStarsVisitor.visitFromImport - -class SelfImportVisitor -SelfImportVisitor.__init__ -SelfImportVisitor.visitNormalImport -SelfImportVisitor.visitFromImport -SelfImportVisitor._importing_names_from_self - -class SortingVisitor -SortingVisitor.__init__ -SortingVisitor.visitNormalImport -SortingVisitor.visitFromImport -SortingVisitor._check_imported_resource - -class LongImportVisitor -LongImportVisitor.__init__ -LongImportVisitor.visitNormalImport -LongImportVisitor._is_long - -class RemovePyNameVisitor -RemovePyNameVisitor.__init__ -RemovePyNameVisitor.visitFromImport -RemovePyNameVisitor.dispatch - -_is_future - -@clean importinfo.py -class ImportStatement -ImportStatement.__init__ -ImportStatement._get_import_info -ImportStatement._set_import_info -ImportStatement.import_info = property(_get_import_info, _set_import_info) -ImportStatement.get_import_statement -ImportStatement.empty_import -ImportStatement.move -ImportStatement.get_old_location -ImportStatement.get_new_start -ImportStatement.is_changed -ImportStatement.accept - -class ImportInfo -ImportInfo.get_imported_primaries -ImportInfo.get_imported_names -ImportInfo.get_import_statement -ImportInfo.is_empty -ImportInfo.__hash__ -ImportInfo._are_name_and_alias_lists_equal -ImportInfo.__eq__ -ImportInfo.__ne__ -ImportInfo.get_empty_import - -class NormalImport -NormalImport.__init__ -NormalImport.get_imported_primaries -NormalImport.get_import_statement -NormalImport.is_empty - -class FromImport -FromImport.__init__ -FromImport.get_imported_primaries -FromImport.get_imported_resource -FromImport.get_imported_module -FromImport.get_import_statement -FromImport.is_empty -FromImport.is_star_import - -class EmptyImport -EmptyImport.is_empty -EmptyImport.get_imported_primaries - -class ImportContext - -@clean module_imports.py -class ModuleImports -ModuleImports.__init__ -ModuleImports.imports -ModuleImports._get_unbound_names -ModuleImports._get_all_star_list -ModuleImports.remove_unused_imports -ModuleImports.get_used_imports -ModuleImports.get_changed_source -ModuleImports._get_import_location -ModuleImports._get_location -ModuleImports._remove_imports -ModuleImports._rewrite_imports -ModuleImports._first_non_blank_line -ModuleImports.add_import -ModuleImports._get_new_import_blanks -ModuleImports._get_new_import_lineno -ModuleImports.filter_names -ModuleImports.expand_stars -ModuleImports.remove_duplicates -ModuleImports.force_single_imports -ModuleImports.get_relative_to_absolute_list -ModuleImports.get_self_import_fix_and_rename_list -ModuleImports._current_folder -ModuleImports.sort_imports -ModuleImports._first_import_line -ModuleImports._get_import_name -ModuleImports._key_imports -ModuleImports._move_imports -ModuleImports.handle_long_imports -ModuleImports.remove_pyname - -get_first_decorator_or_function_start_line -_count_blank_lines -class _OneTimeSelector -_OneTimeSelector.__init__ -_OneTimeSelector.__call__ -_OneTimeSelector._get_dotted_tokens -_OneTimeSelector._can_name_be_added - -class _UnboundNameFinder -_UnboundNameFinder.__init__ -_UnboundNameFinder._visit_child_scope -_UnboundNameFinder._FunctionDef -_UnboundNameFinder._ClassDef -_UnboundNameFinder._Name -_UnboundNameFinder._Attribute -_UnboundNameFinder._get_root -_UnboundNameFinder.is_bound -_UnboundNameFinder.add_unbound - -class _GlobalUnboundNameFinder -_GlobalUnboundNameFinder.__init__ -_GlobalUnboundNameFinder._get_root -_GlobalUnboundNameFinder.is_bound -_GlobalUnboundNameFinder.add_unbound -_GlobalUnboundNameFinder._is_node_interesting - -class _LocalUnboundNameFinder -_LocalUnboundNameFinder.__init__ -_LocalUnboundNameFinder._get_root -_LocalUnboundNameFinder.is_bound -_LocalUnboundNameFinder.add_unbound - -class _GlobalImportFinder -_GlobalImportFinder.__init__ -_GlobalImportFinder.visit_import -_GlobalImportFinder._count_empty_lines_before -_GlobalImportFinder._count_empty_lines_after -_GlobalImportFinder.get_separating_line_count -_GlobalImportFinder._get_text -_GlobalImportFinder.visit_from -_GlobalImportFinder._get_names -_GlobalImportFinder.find_import_statements - - -@clean __init__.py -class ImportOrganizer -ImportOrganizer.__init__ -ImportOrganizer.organize_imports -ImportOrganizer.expand_star_imports -ImportOrganizer.froms_to_imports -ImportOrganizer.relatives_to_absolutes -ImportOrganizer.handle_long_imports -ImportOrganizer._perform_command_on_import_tools -ImportOrganizer._line_filter - -class ImportTools -ImportTools.__init__ -ImportTools.get_import -ImportTools.get_from_import -ImportTools.module_imports -ImportTools.froms_to_imports -ImportTools.expand_stars -ImportTools._from_to_normal -ImportTools._clean_up_imports -ImportTools.relatives_to_absolutes -ImportTools._is_transformable_to_normal -ImportTools.organize_imports -ImportTools._remove_self_imports -ImportTools._rename_in_module -ImportTools.sort_imports -ImportTools.handle_long_imports - -get_imports -get_module_imports -add_import - - - - -@path ropetest -@clean advanced_oi_test.py -class DynamicOITest -DynamicOITest.setUp -DynamicOITest.tearDown -DynamicOITest.test_simple_dti -DynamicOITest.test_module_dti -DynamicOITest.test_class_from_another_module_dti -DynamicOITest.test_class_dti -DynamicOITest.test_instance_dti -DynamicOITest.test_method_dti -DynamicOITest.test_function_argument_dti -DynamicOITest.test_classes_with_the_same_name -DynamicOITest.test_nested_classes -DynamicOITest.test_function_argument_dti2 -DynamicOITest.test_dti_and_concluded_data_invalidation -DynamicOITest.test_list_objects_and_dynamicoi -DynamicOITest.test_for_loops_and_dynamicoi -DynamicOITest.test_dict_objects_and_dynamicoi -DynamicOITest.test_dict_keys_and_dynamicoi -DynamicOITest.test_dict_keys_and_dynamicoi2 -DynamicOITest.test_strs_and_dynamicoi -DynamicOITest.test_textual_transformations -DynamicOITest.test_arguments_with_keywords -DynamicOITest.test_a_function_with_different_returns -DynamicOITest.test_a_function_with_different_returns2 -DynamicOITest.test_ignoring_star_args -DynamicOITest.test_ignoring_double_star_args -DynamicOITest.test_invalidating_data_after_changing -DynamicOITest.test_invalidating_data_after_moving - -class NewStaticOITest -NewStaticOITest.setUp -NewStaticOITest.tearDown -NewStaticOITest.test_static_oi_for_simple_function_calls -NewStaticOITest.test_static_oi_not_failing_when_callin_callables -NewStaticOITest.test_static_oi_for_nested_calls -NewStaticOITest.test_static_oi_class_methods -NewStaticOITest.test_static_oi_preventing_soi_maximum_recursion_exceptions -NewStaticOITest.test_static_oi_for_infer_return_typs_from_funcs_based_on_params -NewStaticOITest.test_a_function_with_different_returns -NewStaticOITest.test_not_reporting_out_of_date_information -NewStaticOITest.test_invalidating_concluded_data_in_a_function -NewStaticOITest.test_handling_generator_functions_for_strs -NewStaticOITest.xxx_test_handl_generator_functions_when_unknown_type_is_yielded -NewStaticOITest.test_static_oi_for_lists_depending_on_append_function -NewStaticOITest.test_static_oi_for_lists_per_object_for_get_item -NewStaticOITest.test_static_oi_for_lists_per_object_for_fields -NewStaticOITest.test_static_oi_for_lists_per_object_for_set_item -NewStaticOITest.test_static_oi_for_lists_per_object_for_extending_lists -NewStaticOITest.test_static_oi_for_lists_per_object_for_iters -NewStaticOITest.test_static_oi_for_dicts_depending_on_append_function -NewStaticOITest.test_static_oi_for_dicts_depending_on_for_loops -NewStaticOITest.test_static_oi_for_dicts_depending_on_update -NewStaticOITest.test_static_oi_for_dicts_depending_on_update_on_seqs -NewStaticOITest.test_static_oi_for_sets_per_object_for_set_item -NewStaticOITest.test_properties_and_calling_get_property -NewStaticOITest.test_soi_on_constructors -NewStaticOITest.test_soi_on_literal_assignment -NewStaticOITest.test_soi_on_typed_assignment -NewStaticOITest.test_not_saving_unknown_function_returns -NewStaticOITest.test_using_the_best_callinfo -NewStaticOITest.test_call_function_and_parameters -NewStaticOITest.test_report_change_in_libutils -NewStaticOITest.test_report_libutils_and_analyze_all_modules -NewStaticOITest.test_validation_problems_for_objectdb_retrievals -NewStaticOITest.test_validation_problems_for_changing_builtin_types -NewStaticOITest.test_always_returning_containing_class_for_selfs -NewStaticOITest.test_following_function_calls_when_asked_to -NewStaticOITest.test_set_comprehension - - -@clean builtinstest.py -class BuiltinTypesTest -BuiltinTypesTest.setUp -BuiltinTypesTest.tearDown -BuiltinTypesTest.test_simple_case -BuiltinTypesTest.test_holding_type_information -BuiltinTypesTest.test_get_items -BuiltinTypesTest.test_get_items_for_lists -BuiltinTypesTest.test_get_items_from_slices -BuiltinTypesTest.test_simple_for_loops -BuiltinTypesTest.test_definition_location_for_loop_variables -BuiltinTypesTest.test_simple_case_for_dicts -BuiltinTypesTest.test_get_item_for_dicts -BuiltinTypesTest.test_dict_function_parent -BuiltinTypesTest.test_popping_dicts -BuiltinTypesTest.test_getting_keys_from_dicts -BuiltinTypesTest.test_getting_values_from_dicts -BuiltinTypesTest.test_getting_iterkeys_from_dicts -BuiltinTypesTest.test_getting_itervalues_from_dicts -BuiltinTypesTest.test_using_copy_for_dicts -BuiltinTypesTest.test_tuple_assignments_for_items -BuiltinTypesTest.test_tuple_assignment_for_lists -BuiltinTypesTest.test_tuple_assignments_for_iteritems_in_fors -BuiltinTypesTest.test_simple_tuple_assignments -BuiltinTypesTest.test_overriding_builtin_names -BuiltinTypesTest.test_simple_builtin_scope_test -BuiltinTypesTest.test_simple_sets -BuiltinTypesTest.test_making_lists_using_the_passed_argument_to_init -BuiltinTypesTest.test_making_tuples_using_the_passed_argument_to_init -BuiltinTypesTest.test_making_sets_using_the_passed_argument_to_init -BuiltinTypesTest.test_making_dicts_using_the_passed_argument_to_init -BuiltinTypesTest.test_range_builtin_function -BuiltinTypesTest.test_reversed_builtin_function -BuiltinTypesTest.test_sorted_builtin_function -BuiltinTypesTest.test_super_builtin_function -BuiltinTypesTest.test_file_builtin_type -BuiltinTypesTest.test_property_builtin_type -BuiltinTypesTest.test_lambda_functions -BuiltinTypesTest.test_lambda_function_definition -BuiltinTypesTest.test_lambdas_that_return_unknown -BuiltinTypesTest.test_builtin_zip_function -BuiltinTypesTest.test_builtin_zip_function_with_more_than_two_args -BuiltinTypesTest.test_wrong_arguments_to_zip_function -BuiltinTypesTest.test_enumerate_builtin_function -BuiltinTypesTest.test_builtin_class_get_name -BuiltinTypesTest.test_star_args_and_double_star_args -BuiltinTypesTest.test_simple_list_comprehension_test -BuiltinTypesTest.test_simple_list_generator_expression -BuiltinTypesTest.test_iter_builtin_function -BuiltinTypesTest.test_simple_int_type -BuiltinTypesTest.test_simple_float_type -BuiltinTypesTest.test_simple_float_type2 -BuiltinTypesTest.test_simple_complex_type -BuiltinTypesTest.test_handling_unaryop_on_ints -BuiltinTypesTest.test_handling_binop_on_ints -BuiltinTypesTest.test_handling_compares -BuiltinTypesTest.test_handling_boolops -BuiltinTypesTest.test_binary_or_left_value_unknown -BuiltinTypesTest.test_unknown_return_object -BuiltinTypesTest.test_abstractmethods_attribute - -class BuiltinModulesTest -BuiltinModulesTest.setUp -BuiltinModulesTest.tearDown -BuiltinModulesTest.test_simple_case -BuiltinModulesTest.test_ignored_extensions -BuiltinModulesTest.test_ignored_extensions_2 -BuiltinModulesTest.test_nonexistent_modules -BuiltinModulesTest.test_nonexistent_modules_2 -BuiltinModulesTest.test_time_in_std_mods -BuiltinModulesTest.test_timemodule_normalizes_to_time - - -@clean codeanalyzetest.py -class SourceLinesAdapterTest -SourceLinesAdapterTest.test_source_lines_simple -SourceLinesAdapterTest.test_source_lines_get_line_number -SourceLinesAdapterTest.test_source_lines_get_line_start -SourceLinesAdapterTest.test_source_lines_get_line_end -SourceLinesAdapterTest.test_source_lines_last_line_with_no_new_line - -class WordRangeFinderTest -WordRangeFinderTest._find_primary -WordRangeFinderTest._annotated_code -WordRangeFinderTest._make_offset_annotation -WordRangeFinderTest.assert_equal_annotation -WordRangeFinderTest.test_keyword_before_parens -WordRangeFinderTest.test_inside_parans -WordRangeFinderTest.test_simple_names -WordRangeFinderTest.test_function_calls -WordRangeFinderTest.test_attribute_accesses -WordRangeFinderTest.test_word_finder_on_word_beginning -WordRangeFinderTest.test_word_finder_on_primary_beginning -WordRangeFinderTest.test_word_finder_on_word_ending -WordRangeFinderTest.test_word_finder_on_primary_ending -WordRangeFinderTest.test_word_finder_on_primaries_with_dots_inside_parens -WordRangeFinderTest.test_word_finder_on_primary_like_keyword -WordRangeFinderTest.test_keyword_before_parens_no_space -WordRangeFinderTest.test_strings -WordRangeFinderTest.test_function_calls2 -WordRangeFinderTest.test_parens -WordRangeFinderTest.test_function_with_no_param -WordRangeFinderTest.test_function_with_multiple_param -WordRangeFinderTest.test_param_expressions -WordRangeFinderTest.test_string_parens -WordRangeFinderTest.test_extra_spaces -WordRangeFinderTest.test_relative_import -WordRangeFinderTest.test_functions_on_ending_parens -WordRangeFinderTest.test_splitted_statement -WordRangeFinderTest.test_empty_splitted_statement -WordRangeFinderTest.test_empty_splitted_statement2 -WordRangeFinderTest.test_empty_splitted_statement3 -WordRangeFinderTest.test_empty_splitted_statement4 -WordRangeFinderTest.test_empty_splitted_statement5 -WordRangeFinderTest.test_operators_inside_parens -WordRangeFinderTest.test_dictionaries -WordRangeFinderTest.test_following_parens -WordRangeFinderTest.test_comments_for_finding_statements -WordRangeFinderTest.test_str_in_comments_for_finding_statements -WordRangeFinderTest.test_comments_for_finding_statements2 -WordRangeFinderTest.test_comments_for_finding_statements3 -WordRangeFinderTest.test_is_import_statement -WordRangeFinderTest.test_is_import_statement_finding -WordRangeFinderTest.test_is_import_statement_finding2 -WordRangeFinderTest.test_word_parens_range -WordRangeFinderTest.test_getting_primary_before_get_index -WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line -WordRangeFinderTest.test_getting_primary_and_not_crossing_newlines -WordRangeFinderTest.xxx_test_getting_primary_cancatenating_strs -WordRangeFinderTest.test_is_a_function_being_called_with_parens_on_next_line -WordRangeFinderTest.xxx_test_triple_quotes -WordRangeFinderTest.test_triple_quotes_spanning_multiple_lines -WordRangeFinderTest.test_get_word_parens_range_and_string_literals -WordRangeFinderTest.test_is_assigned_here_for_equality_test -WordRangeFinderTest.test_is_assigned_here_for_not_equal_test -WordRangeFinderTest.xxx_test_is_assigned_here_for_tuple_assignment -WordRangeFinderTest.test_is_from_statement -WordRangeFinderTest.test_is_from_statement_module -WordRangeFinderTest.test_is_import_statement_aliased_module -WordRangeFinderTest.test_is_from_aliased -WordRangeFinderTest.test_is_from_with_from_import_and_multiline_parens -WordRangeFinderTest.test_is_from_with_from_import_and_line_breaks_in_the_middle -WordRangeFinderTest.test_is_function_keyword_parameter -WordRangeFinderTest.test_one_letter_is_function_keyword_parameter -WordRangeFinderTest.test_find_parens_start -WordRangeFinderTest.test_underlined_find_parens_start -WordRangeFinderTest.test_find_parens_start_with_multiple_entries -WordRangeFinderTest.test_find_parens_start_with_nested_parens -WordRangeFinderTest.test_find_parens_start_with_parens_in_strs -WordRangeFinderTest.test_find_parens_start_with_parens_in_strs_in_multiple_lines -WordRangeFinderTest.test_is_on_function_call_keyword -WordRangeFinderTest.test_is_on_function_keyword_partial -WordRangeFinderTest.test_get_word_range_with_fstring - -class ScopeNameFinderTest -ScopeNameFinderTest.setUp -ScopeNameFinderTest.tearDown -ScopeNameFinderTest.xxx_test_global_name_in_class_body -ScopeNameFinderTest.test_class_variable_attribute_in_class_body -ScopeNameFinderTest.test_class_variable_attribute_in_class_body2 -ScopeNameFinderTest.test_class_method_attribute_in_class_body -ScopeNameFinderTest.test_inner_class_attribute_in_class_body -ScopeNameFinderTest.test_class_method_in_class_body_but_not_indexed -ScopeNameFinderTest.test_function_but_not_indexed -ScopeNameFinderTest.test_modules_after_from_statements -ScopeNameFinderTest.test_renaming_functions_with_from_import_and_parens -ScopeNameFinderTest.test_relative_modules_after_from_statements -ScopeNameFinderTest.test_relative_modules_after_from_statements2 -ScopeNameFinderTest.test_get_pyname_at_on_language_keywords -ScopeNameFinderTest.test_one_liners -ScopeNameFinderTest.test_one_liners_with_line_breaks -ScopeNameFinderTest.test_one_liners_with_line_breaks2 -ScopeNameFinderTest.test_var_in_list_comprehension_differs_from_var_outside - -class LogicalLineFinderTest -LogicalLineFinderTest._logical_finder -LogicalLineFinderTest.test_normal_lines -LogicalLineFinderTest.test_normal_lines2 -LogicalLineFinderTest.test_implicit_continuation -LogicalLineFinderTest.test_explicit_continuation -LogicalLineFinderTest.test_explicit_continuation_comments -LogicalLineFinderTest.test_multiple_indented_ifs -LogicalLineFinderTest.test_list_comprehensions_and_fors -LogicalLineFinderTest.test_generator_expressions_and_fors -LogicalLineFinderTest.test_fors_and_block_start -LogicalLineFinderTest.test_problems_with_inner_indentations -LogicalLineFinderTest.test_problems_with_inner_indentations2 -LogicalLineFinderTest.test_logical_lines_for_else -LogicalLineFinderTest.test_logical_lines_for_lines_with_wrong_continues -LogicalLineFinderTest.test_logical_lines_for_multiline_string_with_extra_quotes_front -LogicalLineFinderTest.test_logical_lines_for_multiline_string_with_escaped_quotes -LogicalLineFinderTest.test_generating_line_starts -LogicalLineFinderTest.test_generating_line_starts2 -LogicalLineFinderTest.test_generating_line_starts3 -LogicalLineFinderTest.test_generating_line_starts_for_multi_line_statements -LogicalLineFinderTest.test_generating_line_starts_and_unmatched_deindents -LogicalLineFinderTest.test_false_triple_quoted_string - -class TokenizerLogicalLineFinderTest -class CustomLogicalLineFinderTest - -@clean doatest.py -cve_2014_3539_attacker -class DOATest -DOATest.try_CVE_2014_3539_exploit -DOATest.test_CVE_2014_3539_no_encoding -DOATest.test_CVE_2014_3539_signature_mismatch -DOATest.test_CVE_2014_3539_sanity -DOATest.test_compare_digest_compat - - -@clean historytest.py -class HistoryTest -HistoryTest.setUp -HistoryTest.tearDown -HistoryTest.test_undoing_writes -HistoryTest.test_moving_files -HistoryTest.test_moving_files_to_folders -HistoryTest.test_writing_files_that_does_not_change_contents - -class IsolatedHistoryTest -IsolatedHistoryTest.setUp -IsolatedHistoryTest.tearDown -IsolatedHistoryTest.test_simple_undo -IsolatedHistoryTest.test_tobe_undone -IsolatedHistoryTest.test_tobe_redone -IsolatedHistoryTest.test_undo_limit -IsolatedHistoryTest.test_simple_redo -IsolatedHistoryTest.test_simple_re_undo -IsolatedHistoryTest.test_multiple_undos -IsolatedHistoryTest.test_undo_list_underflow -IsolatedHistoryTest.test_redo_list_underflow -IsolatedHistoryTest.test_dropping_undone_changes -IsolatedHistoryTest.test_undoing_choosen_changes -IsolatedHistoryTest.test_undoing_choosen_changes2 -IsolatedHistoryTest.test_undoing_choosen_changes_not_undoing_others -IsolatedHistoryTest.test_undoing_writing_after_moving -IsolatedHistoryTest.test_undoing_folder_movements_for_undoing_writes_inside_it -IsolatedHistoryTest.test_undoing_changes_that_depend_on_a_dependant_change -IsolatedHistoryTest.test_undoing_writes_for_undoing_folder_movements_containing_it -IsolatedHistoryTest.test_undoing_not_available_change -IsolatedHistoryTest.test_ignoring_ignored_resources -IsolatedHistoryTest.test_get_file_undo_list_simple -IsolatedHistoryTest.test_get_file_undo_list_for_moves -IsolatedHistoryTest.xxx_test_get_file_undo_list_and_moving_its_contining_folder -IsolatedHistoryTest.test_clearing_redo_list_after_do -IsolatedHistoryTest.test_undoing_a_not_yet_performed_change -IsolatedHistoryTest.test_clearing_up_the_history -IsolatedHistoryTest.test_redoing_choosen_changes_not_undoing_others - -class SavingHistoryTest -SavingHistoryTest.setUp -SavingHistoryTest.tearDown -SavingHistoryTest.test_simple_set_saving -SavingHistoryTest.test_simple_change_content_saving -SavingHistoryTest.test_move_resource_saving -SavingHistoryTest.test_move_resource_saving_for_folders -SavingHistoryTest.test_create_file_saving -SavingHistoryTest.test_create_folder_saving -SavingHistoryTest.test_create_resource_saving -SavingHistoryTest.test_remove_resource_saving -SavingHistoryTest.test_change_set_saving -SavingHistoryTest.test_writing_and_reading_history -SavingHistoryTest.test_writing_and_reading_history2 - - -@clean objectdbtest.py -_do_for_all_dbs -class _MockValidation -_MockValidation.is_value_valid -_MockValidation.is_more_valid -_MockValidation.is_file_valid -_MockValidation.is_scope_valid - -class _MockFileListObserver -_MockFileListObserver.added -_MockFileListObserver.removed - -class ObjectDBTest -ObjectDBTest.setUp -ObjectDBTest.tearDown -ObjectDBTest.test_simple_per_name -ObjectDBTest.test_simple_per_name_does_not_exist -ObjectDBTest.test_simple_per_name_after_syncing -ObjectDBTest.test_getting_returned -ObjectDBTest.test_getting_returned_when_does_not_match -ObjectDBTest.test_getting_call_info -ObjectDBTest.test_invalid_per_name -ObjectDBTest.test_overwriting_per_name -ObjectDBTest.test_not_overwriting_with_invalid_per_name -ObjectDBTest.test_getting_invalid_returned -ObjectDBTest.test_not_overwriting_with_invalid_returned -ObjectDBTest.test_get_files -ObjectDBTest.test_validating_files -ObjectDBTest.test_validating_file_for_scopes -ObjectDBTest.test_validating_file_moved -ObjectDBTest.test_using_file_list_observer - - -@clean objectinfertest.py -class ObjectInferTest -ObjectInferTest.setUp -ObjectInferTest.tearDown -ObjectInferTest.test_simple_type_inferencing -ObjectInferTest.test_simple_type_inferencing_classes_defined_in_holding_scope -ObjectInferTest.test_simple_type_inferencing_classes_in_class_methods -ObjectInferTest.test_simple_type_inferencing_class_attributes -ObjectInferTest.test_simple_type_inferencing_for_in_class_assignments -ObjectInferTest.test_simple_type_inferencing_for_chained_assignments -ObjectInferTest.test_following_chained_assignments_avoiding_circles -ObjectInferTest.test_function_returned_object_static_type_inference1 -ObjectInferTest.test_function_returned_object_static_type_inference2 -ObjectInferTest.test_recursive_function_returned_object_static_type_inference -ObjectInferTest.test_func_returned_obj_using_call_spec_func_static_type_infer -ObjectInferTest.test_list_type_inferencing -ObjectInferTest.test_attributed_object_inference -ObjectInferTest.test_getting_property_attributes -ObjectInferTest.test_getting_property_attributes_with_method_getters -ObjectInferTest.test_lambda_functions -ObjectInferTest.test_mixing_subscript_with_tuple_assigns -ObjectInferTest.test_mixing_ass_attr_with_tuple_assignment -ObjectInferTest.test_mixing_slice_with_tuple_assigns -ObjectInferTest.test_nested_tuple_assignments -ObjectInferTest.test_empty_tuples -ObjectInferTest.test_handling_generator_functions -ObjectInferTest.test_handling_generator_functions_for_strs -ObjectInferTest.test_considering_nones_to_be_unknowns -ObjectInferTest.test_basic_list_comprehensions -ObjectInferTest.test_basic_generator_expressions -ObjectInferTest.test_list_comprehensions_and_loop_var -ObjectInferTest.test_list_comprehensions_and_multiple_loop_var -ObjectInferTest.test_list_comprehensions_and_multiple_iters -ObjectInferTest.test_we_know_the_type_of_catched_exceptions -ObjectInferTest.test_we_know_the_type_of_catched_multiple_excepts -ObjectInferTest.test_using_property_as_decorators -ObjectInferTest.test_using_property_as_decorators_and_passing_parameter - - -@clean projecttest.py -class ProjectTest -ProjectTest.setUp -ProjectTest._make_sample_project -ProjectTest.tearDown -ProjectTest.test_project_creation -ProjectTest.test_getting_project_file -ProjectTest.test_project_file_reading -ProjectTest.test_getting_not_existing_project_file -ProjectTest.test_writing_in_project_files -ProjectTest.test_creating_files -ProjectTest.test_creating_files_that_already_exist -ProjectTest.test_making_root_folder_if_it_does_not_exist -ProjectTest.test_failure_when_project_root_exists_and_is_a_file -ProjectTest.test_creating_folders -ProjectTest.test_making_folder_that_already_exists -ProjectTest.test_failing_if_creating_folder_while_file_already_exists -ProjectTest.test_creating_file_inside_folder -ProjectTest.test_failing_when_creating_file_inside_non_existent_folder -ProjectTest.test_nested_directories -ProjectTest.test_removing_files -ProjectTest.test_removing_files_invalidating_in_project_resource_pool -ProjectTest.test_removing_directories -ProjectTest.test_removing_non_existent_files -ProjectTest.test_removing_nested_files -ProjectTest.test_file_get_name -ProjectTest.test_folder_get_name -ProjectTest.test_file_get_path -ProjectTest.test_folder_get_path -ProjectTest.test_is_folder -ProjectTest.testget_children -ProjectTest.test_nonempty_get_children -ProjectTest.test_nonempty_get_children2 -ProjectTest.test_does_not_fail_for_permission_denied -ProjectTest.test_getting_files -ProjectTest.test_getting_folders -ProjectTest.test_nested_folder_get_files -ProjectTest.test_nested_folder_get_folders -ProjectTest.test_root_folder -ProjectTest.test_get_all_files -ProjectTest.test_get_all_files_after_changing -ProjectTest.test_multifile_get_all_files -ProjectTest.test_ignoring_dot_pyc_files_in_get_files -ProjectTest.test_folder_creating_files -ProjectTest.test_folder_creating_nested_files -ProjectTest.test_folder_creating_files2 -ProjectTest.test_folder_creating_nested_files2 -ProjectTest.test_folder_get_child -ProjectTest.test_folder_get_child_nested -ProjectTest.test_project_root_is_root_folder -ProjectTest.test_moving_files -ProjectTest.test_moving_folders -ProjectTest.test_moving_destination_folders -ProjectTest.test_moving_files_and_resource_objects -ProjectTest.test_file_encoding_reading -ProjectTest.test_file_encoding_writing -ProjectTest.test_using_utf8_when_writing_in_case_of_errors -ProjectTest.test_encoding_declaration_in_the_second_line -ProjectTest.test_not_an_encoding_declaration -ProjectTest.test_read_bytes -ProjectTest.test_file_with_unix_line_ending -ProjectTest.test_file_with_dos_line_ending -ProjectTest.test_file_with_mac_line_ending -ProjectTest.test_file_binary -ProjectTest.xxx_test_using_utf16 -ProjectTest.xxx_test_file_encoding_reading_for_notepad_styles -ProjectTest.test_using_project_get_file -ProjectTest.test_using_file_create -ProjectTest.test_using_folder_create -ProjectTest.test_exception_when_creating_twice -ProjectTest.test_exception_when_parent_does_not_exist -ProjectTest.test_simple_path_to_resource -ProjectTest.test_ignoring_symlinks_inside_project -ProjectTest.test_getting_empty_source_folders -ProjectTest.test_root_source_folder -ProjectTest.test_root_source_folder2 -ProjectTest.test_src_source_folder -ProjectTest.test_packages -ProjectTest.test_multi_source_folders -ProjectTest.test_multi_source_folders2 - -class ResourceObserverTest -ResourceObserverTest.setUp -ResourceObserverTest.tearDown -ResourceObserverTest.test_resource_change_observer -ResourceObserverTest.test_resource_change_observer_after_removal -ResourceObserverTest.test_resource_change_observer2 -ResourceObserverTest.test_resource_change_observer_for_folders -ResourceObserverTest.test_resource_change_observer_after_moving -ResourceObserverTest.test_revalidating_files -ResourceObserverTest.test_revalidating_files_and_no_changes2 -ResourceObserverTest.test_revalidating_folders -ResourceObserverTest.test_removing_and_adding_resources_to_filtered_observer -ResourceObserverTest.test_validation_and_changing_files -ResourceObserverTest.test_validation_and_changing_files2 -ResourceObserverTest.test_not_reporting_multiple_changes_to_folders -ResourceObserverTest._write_file -ResourceObserverTest.test_moving_and_being_interested_about_a_folder_and_a_child -ResourceObserverTest.test_contains_for_folders -ResourceObserverTest.test_validating_when_created -ResourceObserverTest.test_validating_twice_when_created -ResourceObserverTest.test_changes_and_adding_resources -ResourceObserverTest.test_validating_get_files_list -ResourceObserverTest.test_clear_observered_resources_for_filtered_observers - -class _MockChangeIndicator -_MockChangeIndicator.__init__ -_MockChangeIndicator.set_indicator -_MockChangeIndicator.get_indicator - -class _SampleObserver -_SampleObserver.__init__ -_SampleObserver.resource_changed -_SampleObserver.resource_moved -_SampleObserver.resource_created -_SampleObserver.resource_removed - -class OutOfProjectTest -OutOfProjectTest.setUp -OutOfProjectTest.tearDown -OutOfProjectTest.test_simple_out_of_project_file -OutOfProjectTest.test_simple_out_of_project_folder -OutOfProjectTest.test_using_absolute_path -OutOfProjectTest.test_folder_get_child -OutOfProjectTest.test_out_of_project_files_and_path_to_resource - -class _MockFSCommands -_MockFSCommands.__init__ -_MockFSCommands.create_file -_MockFSCommands.create_folder -_MockFSCommands.move -_MockFSCommands.remove -_MockFSCommands.read - -class _DeprecatedFSCommands -_DeprecatedFSCommands.__init__ -_DeprecatedFSCommands.create_file -_DeprecatedFSCommands.create_folder -_DeprecatedFSCommands.move -_DeprecatedFSCommands.remove - -class RopeFolderTest -RopeFolderTest.setUp -RopeFolderTest.tearDown -RopeFolderTest.test_none_project_rope_folder -RopeFolderTest.test_getting_project_rope_folder -RopeFolderTest.test_setting_ignored_resources -RopeFolderTest.test_ignored_folders -RopeFolderTest.test_ignored_resources_and_get_files -RopeFolderTest.test_ignored_resources_and_get_files2 -RopeFolderTest.test_setting_ignored_resources_patterns -RopeFolderTest.test_star_should_not_include_slashes -RopeFolderTest.test_normal_fscommands -RopeFolderTest.test_fscommands_and_ignored_resources -RopeFolderTest.test_deprecated_fscommands -RopeFolderTest.test_ignored_resources_and_prefixes -RopeFolderTest.test_loading_config_dot_py -RopeFolderTest.test_loading_pyproject -RopeFolderTest.test_loading_pyproject_empty_file -RopeFolderTest.test_loading_pyproject_no_tool_section -RopeFolderTest.test_loading_pyproject_no_tool_rope_section -RopeFolderTest.test_ignoring_syntax_errors -RopeFolderTest.test_compressed_history -RopeFolderTest.test_compressed_objectdb -RopeFolderTest.test_nested_dot_ropeproject_folder - - -@clean pycoretest.py -class PyCoreTest -PyCoreTest.setUp -PyCoreTest.tearDown -PyCoreTest.test_simple_module -PyCoreTest.test_nested_modules -PyCoreTest.test_package -PyCoreTest.test_simple_class -PyCoreTest.test_simple_function -PyCoreTest.test_class_methods -PyCoreTest.test_global_variable_without_type_annotation -PyCoreTest.test_global_variable_with_type_annotation -PyCoreTest.test_class_variables -PyCoreTest.test_class_attributes_set_in_init -PyCoreTest.test_class_attributes_set_in_init_overwriting_a_defined -PyCoreTest.test_classes_inside_other_classes -PyCoreTest.test_non_existent_module -PyCoreTest.test_imported_names -PyCoreTest.test_imported_as_names -PyCoreTest.test_get_string_module -PyCoreTest.test_get_string_module_with_extra_spaces -PyCoreTest.test_parameter_info_for_functions -PyCoreTest.xxx_test_not_found_module_is_module -PyCoreTest.test_mixing_scopes_and_objects_hierarchy -PyCoreTest.test_inheriting_base_class_attributes -PyCoreTest.test_inheriting_multiple_base_class_attributes -PyCoreTest.test_inherit_multiple_base_class_attrs_with_the_same_name -PyCoreTest.test_inheriting_unknown_base_class -PyCoreTest.test_module_creation -PyCoreTest.test_packaged_module_creation -PyCoreTest.test_packaged_module_creation_with_nested_src -PyCoreTest.test_package_creation -PyCoreTest.test_nested_package_creation -PyCoreTest.test_packaged_package_creation_with_nested_src -PyCoreTest.test_find_module -PyCoreTest.test_find_nested_module -PyCoreTest.test_find_multiple_module -PyCoreTest.test_find_module_packages -PyCoreTest.test_find_module_when_module_and_package_with_the_same_name -PyCoreTest.test_source_folders_preference -PyCoreTest.test_get_pyname_definition_location -PyCoreTest.test_get_pyname_definition_location_functions -PyCoreTest.test_get_pyname_definition_location_class -PyCoreTest.test_get_pyname_definition_location_local_variables -PyCoreTest.test_get_pyname_definition_location_reassigning -PyCoreTest.test_get_pyname_definition_location_importes -PyCoreTest.test_get_pyname_definition_location_imports -PyCoreTest.test_get_pyname_definition_location_parameters -PyCoreTest.test_module_get_resource -PyCoreTest.test_get_pyname_definition_location_class2 -PyCoreTest.test_import_not_found_module_get_definition_location -PyCoreTest.test_from_not_found_module_get_definition_location -PyCoreTest.test_from_package_import_module_get_definition_location -PyCoreTest.test_get_module_for_defined_pyobjects -PyCoreTest.test_get_definition_location_for_packages -PyCoreTest.test_get_definition_location_for_filtered_packages -PyCoreTest.test_out_of_project_modules -PyCoreTest.test_file_encoding_reading -PyCoreTest.test_global_keyword -PyCoreTest.test_not_leaking_for_vars_inside_parent_scope -PyCoreTest.test_not_leaking_for_vars_inside_parent_scope2 -PyCoreTest.test_variables_defined_in_excepts -PyCoreTest.test_not_leaking_tuple_assigned_names_inside_parent_scope -PyCoreTest.test_with_statement_variables -PyCoreTest.test_with_statement_variables_and_tuple_assignment -PyCoreTest.test_with_statement_variable_type -PyCoreTest.test_nested_with_statement_variable_type -PyCoreTest.test_with_statement_with_no_vars -PyCoreTest.test_with_statement -PyCoreTest.test_check_for_else_block -PyCoreTest.test_check_names_defined_in_whiles -PyCoreTest.test_get_definition_location_in_tuple_assnames -PyCoreTest.test_syntax_errors_in_code -PyCoreTest.test_holding_error_location_information -PyCoreTest.test_no_exceptions_on_module_encoding_problems -PyCoreTest.test_syntax_errors_when_cannot_decode_file2 -PyCoreTest.test_syntax_errors_when_null_bytes -PyCoreTest.test_syntax_errors_when_bad_strs -PyCoreTest.test_not_reaching_maximum_recursions_with_from_star_imports -PyCoreTest.test_not_reaching_maximum_recursions_when_importing_variables -PyCoreTest.test_not_reaching_maximum_recursions_when_importing_variables2 -PyCoreTest.test_pyobject_equality_should_compare_types - -class PyCoreInProjectsTest -PyCoreInProjectsTest.setUp -PyCoreInProjectsTest.tearDown -PyCoreInProjectsTest.test_simple_import -PyCoreInProjectsTest.test_from_import_class -PyCoreInProjectsTest.test_from_import_star -PyCoreInProjectsTest.test_from_import_star_overwriting -PyCoreInProjectsTest.test_from_import_star_not_imporing_underlined -PyCoreInProjectsTest.test_from_import_star_imports_in_functions -PyCoreInProjectsTest.test_from_package_import_mod -PyCoreInProjectsTest.xxx_test_from_package_import_star -PyCoreInProjectsTest.test_unknown_when_module_cannot_be_found -PyCoreInProjectsTest.test_from_import_function -PyCoreInProjectsTest.test_circular_imports -PyCoreInProjectsTest.test_circular_imports2 -PyCoreInProjectsTest.test_multi_dot_imports -PyCoreInProjectsTest.test_multi_dot_imports2 -PyCoreInProjectsTest.test_multi_dot_imports3 -PyCoreInProjectsTest.test_multi_dot_imports_as -PyCoreInProjectsTest.xxx_test_from_package_import_package -PyCoreInProjectsTest.test_invalidating_cache_after_resource_change -PyCoreInProjectsTest.test_invalidating_cache_after_resource_change_for_init_dot_pys -PyCoreInProjectsTest.test_invalidating_cache_after_rsrc_chng_for_nested_init_dot_pys -PyCoreInProjectsTest.test_from_import_nonexistent_module -PyCoreInProjectsTest.test_from_import_nonexistent_name -PyCoreInProjectsTest.test_not_considering_imported_names_as_sub_scopes -PyCoreInProjectsTest.test_not_considering_imported_modules_as_sub_scopes -PyCoreInProjectsTest.test_inheriting_dotted_base_class -PyCoreInProjectsTest.test_self_in_methods -PyCoreInProjectsTest.test_none_assignments_in_classes -PyCoreInProjectsTest.test_self_in_methods_with_decorators -PyCoreInProjectsTest.test_location_of_imports_when_importing -PyCoreInProjectsTest.test_nested_modules -PyCoreInProjectsTest.test_reading_init_dot_py -PyCoreInProjectsTest.test_relative_imports -PyCoreInProjectsTest.test_relative_froms -PyCoreInProjectsTest.test_relative_imports_for_string_modules -PyCoreInProjectsTest.test_relative_imports_for_string_scopes -PyCoreInProjectsTest.test_new_style_relative_imports1 -PyCoreInProjectsTest.test_new_style_relative_imports2 -PyCoreInProjectsTest.test_invalidating_cache_for_from_imports_after_resource_change -PyCoreInProjectsTest.test_invalidating_superclasses_after_change -PyCoreInProjectsTest.test_caching_pymodule_with_syntax_errors - -class TextChangeDetectorTest -TextChangeDetectorTest.test_trivial_case -TextChangeDetectorTest.test_one_line_change -TextChangeDetectorTest.test_line_expansion -TextChangeDetectorTest.test_line_removals -TextChangeDetectorTest.test_multi_line_checks -TextChangeDetectorTest.test_consume_change - -class PyCoreProjectConfigsTest -PyCoreProjectConfigsTest.setUp -PyCoreProjectConfigsTest.tearDown -PyCoreProjectConfigsTest.test_python_files_config -PyCoreProjectConfigsTest.test_ignore_bad_imports -PyCoreProjectConfigsTest.test_ignore_bad_imports_for_froms -PyCoreProjectConfigsTest.test_reporting_syntax_errors_with_force_errors -PyCoreProjectConfigsTest.test_reporting_syntax_errors_in_strings_with_force_errors -PyCoreProjectConfigsTest.test_not_raising_errors_for_strings_with_ignore_errors -PyCoreProjectConfigsTest.test_reporting_syntax_errors_with_force_errors_for_packages - - -@clean pyscopestest.py -class PyCoreScopesTest -PyCoreScopesTest.setUp -PyCoreScopesTest.tearDown -PyCoreScopesTest.test_simple_scope -PyCoreScopesTest.test_simple_function_scope -PyCoreScopesTest.test_classes_inside_function_scopes -PyCoreScopesTest.test_list_comprehension_scope_inside_assignment -PyCoreScopesTest.test_list_comprehension_scope -PyCoreScopesTest.test_set_comprehension_scope -PyCoreScopesTest.test_generator_comprehension_scope -PyCoreScopesTest.test_dict_comprehension_scope -PyCoreScopesTest.test_inline_assignment -PyCoreScopesTest.test_inline_assignment_in_comprehensions -PyCoreScopesTest.test_nested_comprehension -PyCoreScopesTest.test_simple_class_scope -PyCoreScopesTest.test_get_lineno -PyCoreScopesTest.test_scope_kind -PyCoreScopesTest.test_function_parameters_in_scope_names -PyCoreScopesTest.test_get_names_contains_only_names_defined_in_a_scope -PyCoreScopesTest.test_scope_lookup -PyCoreScopesTest.test_function_scopes -PyCoreScopesTest.test_function_scopes_classes -PyCoreScopesTest.test_function_getting_scope -PyCoreScopesTest.test_scopes_in_function_scopes -PyCoreScopesTest.test_for_variables_in_scopes -PyCoreScopesTest.test_assists_inside_fors -PyCoreScopesTest.test_first_parameter_of_a_method -PyCoreScopesTest.test_first_parameter_of_static_methods -PyCoreScopesTest.test_first_parameter_of_class_methods -PyCoreScopesTest.test_first_parameter_with_self_as_name_and_unknown_decorator -PyCoreScopesTest.test_inside_class_scope_attribute_lookup -PyCoreScopesTest.test_inside_class_scope_attribute_lookup2 -PyCoreScopesTest.test_get_inner_scope_for_staticmethods -PyCoreScopesTest.test_get_scope_for_offset_for_comprehension -PyCoreScopesTest.test_get_scope_for_offset_for_in_nested_comprehension -PyCoreScopesTest.test_get_scope_for_offset_for_scope_with_indent -PyCoreScopesTest.test_get_scope_for_offset_for_function_scope_and_async_with_statement -PyCoreScopesTest.test_getting_overwritten_scopes -PyCoreScopesTest.test_assigning_builtin_names -PyCoreScopesTest.test_get_inner_scope_and_logical_lines -PyCoreScopesTest.test_getting_defined_names_for_classes -PyCoreScopesTest.test_getting_defined_names_for_modules -PyCoreScopesTest.test_get_inner_scope_for_list_comprhension_with_many_targets -PyCoreScopesTest.test_get_inner_scope_for_generator -PyCoreScopesTest.test_get_inner_scope_for_set_comprehension -PyCoreScopesTest.test_get_inner_scope_for_dict_comprehension -PyCoreScopesTest.test_get_inner_scope_for_nested_list_comprhension -PyCoreScopesTest.test_get_scope_region -PyCoreScopesTest.test_only_get_inner_scope_region - - -@clean reprtest.py -project -mod -mod1 -test_repr_project -test_repr_file -test_repr_folder -test_repr_pyobjectsdef_pymodule -test_repr_pyobjectsdef_pymodule_without_associated_resource -test_repr_pyobjectsdef_pypackage -test_repr_pyobjectsdef_pypackage_without_associated_resource -test_repr_pyobjectsdef_pyfunction -test_repr_pyobjectsdef_pyfunction_without_associated_resource -test_repr_pyobjectsdef_pyclass -test_repr_pyobjectsdef_pyclass_without_associated_resource -test_repr_pyobjectsdef_pycomprehension -test_repr_pyobjectsdef_pycomprehension_without_associated_resource - -@clean runmodtest.py -class PythonFileRunnerTest -PythonFileRunnerTest.setUp -PythonFileRunnerTest.tearDown -PythonFileRunnerTest.make_sample_python_file -PythonFileRunnerTest.get_output_file_content -PythonFileRunnerTest.test_making_runner -PythonFileRunnerTest.test_passing_arguments -PythonFileRunnerTest.test_passing_arguments_with_spaces -PythonFileRunnerTest.test_killing_runner -PythonFileRunnerTest.test_running_nested_files -PythonFileRunnerTest.test_setting_process_input -PythonFileRunnerTest.test_setting_process_output -PythonFileRunnerTest.test_setting_pythonpath -PythonFileRunnerTest.test_making_runner_when_doi_is_disabled - - -@clean simplifytest.py -class SimplifyTest -SimplifyTest.test_trivial_case -SimplifyTest.test_empty_strs -SimplifyTest.test_blanking_strs -SimplifyTest.test_changing_to_double_quotes -SimplifyTest.test_changing_to_double_quotes2 -SimplifyTest.test_removing_comments -SimplifyTest.test_removing_comments_that_contain_strings -SimplifyTest.test_removing_strings_containing_comments -SimplifyTest.test_joining_implicit_continuations -SimplifyTest.test_joining_explicit_continuations -SimplifyTest.test_replacing_tabs -SimplifyTest.test_replacing_semicolons -SimplifyTest.test_simplifying_f_string -SimplifyTest.test_simplifying_f_string_containing_quotes -SimplifyTest.test_simplifying_uppercase_f_string_containing_quotes - - -@clean testutils.py -sample_project -create_module = generate.create_module -remove_project -remove_recursively -_remove_recursively -parse_version -only_for -only_for_versions_lower -only_for_versions_higher -skipNotPOSIX -time_limit - -@clean type_hinting_test.py -class AbstractHintingTest -AbstractHintingTest.setUp -AbstractHintingTest.tearDown -AbstractHintingTest._assist -AbstractHintingTest.assert_completion_in_result -AbstractHintingTest.assert_completion_not_in_result -AbstractHintingTest.run - -class DocstringParamHintingTest -DocstringParamHintingTest.test_hint_param -DocstringParamHintingTest.test_hierarchical_hint_param - -class DocstringReturnHintingTest -DocstringReturnHintingTest.test_hierarchical_hint_rtype - -class AbstractAssignmentHintingTest -AbstractAssignmentHintingTest._make_class_hint -AbstractAssignmentHintingTest._make_constructor_hint -AbstractAssignmentHintingTest.test_hint_attr -AbstractAssignmentHintingTest.test_hierarchical_hint_attr -AbstractAssignmentHintingTest.test_hint_defined_by_constructor -AbstractAssignmentHintingTest.test_hint_attr_redefined_by_constructor -AbstractAssignmentHintingTest.test_hierarchical_hint_attr_redefined_by_constructor -AbstractAssignmentHintingTest.test_hint_attr_for_pre_defined_type -AbstractAssignmentHintingTest.test_hint_attr_for_post_defined_type -AbstractAssignmentHintingTest.test_hint_parametrized_list -AbstractAssignmentHintingTest.test_hint_parametrized_tuple -AbstractAssignmentHintingTest.test_hint_parametrized_set -AbstractAssignmentHintingTest.test_hint_parametrized_iterable -AbstractAssignmentHintingTest.test_hint_parametrized_iterator -AbstractAssignmentHintingTest.test_hint_parametrized_dict_key -AbstractAssignmentHintingTest.test_hint_parametrized_dict_value -AbstractAssignmentHintingTest.test_hint_parametrized_nested_tuple_list -AbstractAssignmentHintingTest.test_hint_or -AbstractAssignmentHintingTest.test_hint_nonexistent -AbstractAssignmentHintingTest.test_hint_invalid_syntax - -class DocstringNoneAssignmentHintingTest -DocstringNoneAssignmentHintingTest._make_class_hint -DocstringNoneAssignmentHintingTest._make_constructor_hint - -class DocstringNotImplementedAssignmentHintingTest -DocstringNotImplementedAssignmentHintingTest._make_class_hint -DocstringNotImplementedAssignmentHintingTest._make_constructor_hint - -class PEP0484CommentNoneAssignmentHintingTest -class PEP0484CommentNotImplementedAssignmentHintingTest -class EvaluateTest -EvaluateTest.test_parser - -class RegressionHintingTest -RegressionHintingTest.test_hierarchical_hint_for_mutable_attr_type - - -@clean __init__.py -suite - -@path contrib -@clean autoimporttest.py -class AutoImportTest -AutoImportTest.setUp -AutoImportTest.tearDown -AutoImportTest.test_simple_case -AutoImportTest.test_update_resource -AutoImportTest.test_update_non_existent_module -AutoImportTest.test_module_with_syntax_errors -AutoImportTest.test_excluding_imported_names -AutoImportTest.test_get_modules -AutoImportTest.test_get_modules_inside_packages -AutoImportTest.test_trivial_insertion_line -AutoImportTest.test_insertion_line -AutoImportTest.test_insertion_line_with_pydocs -AutoImportTest.test_insertion_line_with_multiple_imports -AutoImportTest.test_insertion_line_with_blank_lines -AutoImportTest.test_empty_cache -AutoImportTest.test_not_caching_underlined_names -AutoImportTest.test_caching_underlined_names_passing_to_the_constructor -AutoImportTest.test_name_locations -AutoImportTest.test_name_locations_with_multiple_occurrences -AutoImportTest.test_handling_builtin_modules -AutoImportTest.test_search_submodule -AutoImportTest.test_search_module -AutoImportTest.test_search -AutoImportTest.test_generate_full_cache - -class AutoImportObservingTest -AutoImportObservingTest.setUp -AutoImportObservingTest.tearDown -AutoImportObservingTest.test_writing_files -AutoImportObservingTest.test_moving_files -AutoImportObservingTest.test_removing_files - - -@clean changestacktest.py -class ChangeStackTest -ChangeStackTest.setUp -ChangeStackTest.tearDown -ChangeStackTest.test_change_stack - - -@clean codeassisttest.py -class CodeAssistTest -CodeAssistTest.setUp -CodeAssistTest.tearDown -CodeAssistTest._assist -CodeAssistTest.test_simple_assist -CodeAssistTest.assert_completion_in_result -CodeAssistTest.assert_completion_not_in_result -CodeAssistTest.test_completing_global_variables -CodeAssistTest.test_not_proposing_unmatched_vars -CodeAssistTest.test_not_proposing_unmatched_vars_with_underlined_starting -CodeAssistTest.test_not_proposing_local_assigns_as_global_completions -CodeAssistTest.test_proposing_functions -CodeAssistTest.test_proposing_classes -CodeAssistTest.test_proposing_each_name_at_most_once -CodeAssistTest.test_throwing_exception_in_case_of_syntax_errors -CodeAssistTest.test_fixing_errors_with_maxfixes -CodeAssistTest.test_ignoring_errors_in_current_line -CodeAssistTest.test_not_reporting_variables_in_current_line -CodeAssistTest.test_completion_result -CodeAssistTest.test_completing_imported_names -CodeAssistTest.test_completing_imported_names_with_as -CodeAssistTest.test_not_completing_imported_names_with_as -CodeAssistTest.test_including_matching_builtins_types -CodeAssistTest.test_including_matching_builtins_functions -CodeAssistTest.test_builtin_instances -CodeAssistTest.test_including_keywords -CodeAssistTest.test_not_reporting_proposals_after_dot -CodeAssistTest.test_proposing_local_variables_in_functions -CodeAssistTest.test_local_variables_override_global_ones -CodeAssistTest.test_not_including_class_body_variables -CodeAssistTest.test_nested_functions -CodeAssistTest.test_scope_endpoint_selection -CodeAssistTest.test_scope_better_endpoint_selection -CodeAssistTest.test_imports_inside_function -CodeAssistTest.test_imports_inside_function_dont_mix_with_globals -CodeAssistTest.test_nested_classes_local_names -CodeAssistTest.test_nested_classes_global -CodeAssistTest.test_nested_classes_global_function -CodeAssistTest.test_proposing_function_parameters_in_functions -CodeAssistTest.test_proposing_function_keyword_parameters_in_functions -CodeAssistTest.test_not_proposing_unmatching_function_parameters_in_functions -CodeAssistTest.test_ignoring_current_statement -CodeAssistTest.test_ignoring_current_statement_brackets_continuation -CodeAssistTest.test_ignoring_current_statement_explicit_continuation -CodeAssistTest.test_ignor_current_statement_while_the_first_stmnt_of_the_block -CodeAssistTest.test_ignor_current_stmnt_while_current_line_ends_with_a_colon -CodeAssistTest.test_ignoring_string_contents -CodeAssistTest.test_ignoring_comment_contents -CodeAssistTest.test_ignoring_string_contents_backslash_plus_quotes -CodeAssistTest.test_ignoring_string_contents_backslash_plus_backslash -CodeAssistTest.test_not_proposing_later_defined_variables_in_current_block -CodeAssistTest.test_not_proposing_later_defined_variables_in_current_function -CodeAssistTest.test_ignoring_string_contents_with_triple_quotes -CodeAssistTest.test_ignoring_string_contents_with_triple_quotes_and_backslash -CodeAssistTest.test_ignor_str_contents_with_triple_quotes_and_double_backslash -CodeAssistTest.test_reporting_params_when_in_the_first_line_of_a_function -CodeAssistTest.test_code_assist_when_having_a_two_line_function_header -CodeAssistTest.test_code_assist_with_function_with_two_line_return -CodeAssistTest.test_get_definition_location -CodeAssistTest.test_get_definition_location_underlined_names -CodeAssistTest.test_get_definition_location_dotted_names_method -CodeAssistTest.test_get_definition_location_dotted_names_property -CodeAssistTest.test_get_definition_location_dotted_names_free_function -CodeAssistTest.test_get_definition_location_dotted_names_async_def -CodeAssistTest.test_get_definition_location_dotted_names_class -CodeAssistTest.test_get_definition_location_dotted_names_with_space -CodeAssistTest.test_get_definition_location_dotted_names_inline_body -CodeAssistTest.test_get_definition_location_dotted_names_inline_body_split_arg -CodeAssistTest.test_get_definition_location_dotted_module_names -CodeAssistTest.test_get_definition_location_for_nested_packages -CodeAssistTest.test_get_definition_location_unknown -CodeAssistTest.test_get_definition_location_dot_spaces -CodeAssistTest.test_get_definition_location_dot_line_break_inside_parens -CodeAssistTest.test_if_scopes_in_other_scopes_for_get_definition_location -CodeAssistTest.test_get_definition_location_false_triple_quoted_string -CodeAssistTest.test_code_assists_in_parens -CodeAssistTest.test_simple_type_inferencing -CodeAssistTest.test_proposals_sorter -CodeAssistTest.test_proposals_sorter_for_methods_and_attributes -CodeAssistTest.test_proposals_sorter_for_global_methods_and_funcs -CodeAssistTest.test_proposals_sorter_underlined_methods -CodeAssistTest.test_proposals_sorter_and_scope_prefs -CodeAssistTest.test_proposals_sorter_and_type_prefs -CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref -CodeAssistTest.test_get_pydoc_unicode -CodeAssistTest.test_get_pydoc_utf8_bytestring -CodeAssistTest.test_get_pydoc_for_functions -CodeAssistTest.test_get_pydoc_for_classes -CodeAssistTest.test_get_pydoc_for_classes_with_init -CodeAssistTest.test_get_pydoc_for_modules -CodeAssistTest.test_get_pydoc_for_builtins -CodeAssistTest.test_get_pydoc_for_methods_should_include_class_name -CodeAssistTest.test_get_pydoc_for_meths_should_inc_methods_from_super_classes -CodeAssistTest.test_get_pydoc_for_classes_should_name_super_classes -CodeAssistTest.test_get_pydoc_for_builtin_functions -CodeAssistTest.test_commenting_errors_before_offset -CodeAssistTest.test_proposing_variables_defined_till_the_end_of_scope -CodeAssistTest.test_completing_in_uncomplete_try_blocks -CodeAssistTest.test_completing_in_uncomplete_try_blocks_in_functions -CodeAssistTest.test_already_complete_try_blocks_with_finally -CodeAssistTest.test_already_complete_try_blocks_with_finally2 -CodeAssistTest.test_already_complete_try_blocks_with_except -CodeAssistTest.test_already_complete_try_blocks_with_except2 -CodeAssistTest.test_completing_ifs_in_uncomplete_try_blocks -CodeAssistTest.test_completing_ifs_in_uncomplete_try_blocks2 -CodeAssistTest.test_completing_excepts_in_uncomplete_try_blocks -CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing -CodeAssistTest.test_nested_blocks -CodeAssistTest.test_proposing_function_keywords_when_calling -CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions -CodeAssistTest.test_proposing_function_keywords_when_calling_extra_spaces -CodeAssistTest.test_proposing_function_keywords_when_calling_on_second_argument -CodeAssistTest.test_proposing_function_keywords_when_calling_not_proposing_args -CodeAssistTest.test_propos_function_kwrds_when_call_with_no_noth_after_parens -CodeAssistTest.test_propos_function_kwrds_when_call_with_no_noth_after_parens2 -CodeAssistTest.test_codeassists_before_opening_of_parens -CodeAssistTest.test_codeassist_before_single_line_indents -CodeAssistTest.test_codeassist_before_line_indents_in_a_blank_line -CodeAssistTest.test_simple_get_calltips -CodeAssistTest.test_get_calltips_for_classes -CodeAssistTest.test_get_calltips_for_objects_with_call -CodeAssistTest.test_get_calltips_and_including_module_name -CodeAssistTest.test_get_calltips_and_including_module_name_2 -CodeAssistTest.test_removing_self_parameter -CodeAssistTest.test_removing_self_parameter_and_more_than_one_parameter -CodeAssistTest.test_lambda_calltip -CodeAssistTest.test_keyword_before_parens -CodeAssistTest.TESTING PROPOSAL'S KINDS AND TYPES. -CodeAssistTest.test_local_variable_completion_proposal -CodeAssistTest.test_global_variable_completion_proposal -CodeAssistTest.test_builtin_variable_completion_proposal -CodeAssistTest.test_attribute_variable_completion_proposal -CodeAssistTest.test_local_class_completion_proposal -CodeAssistTest.test_global_class_completion_proposal -CodeAssistTest.test_builtin_class_completion_proposal -CodeAssistTest.test_attribute_class_completion_proposal -CodeAssistTest.test_local_function_completion_proposal -CodeAssistTest.test_global_function_completion_proposal -CodeAssistTest.test_builtin_function_completion_proposal -CodeAssistTest.test_attribute_function_completion_proposal -CodeAssistTest.test_local_module_completion_proposal -CodeAssistTest.test_global_module_completion_proposal -CodeAssistTest.test_attribute_module_completion_proposal -CodeAssistTest.test_builtin_exception_completion_proposal -CodeAssistTest.test_keyword_completion_proposal -CodeAssistTest.test_parameter_keyword_completion_proposal -CodeAssistTest.test_object_path_global -CodeAssistTest.test_object_path_attribute -CodeAssistTest.test_object_path_subclass -CodeAssistTest.test_object_path_method_parameter -CodeAssistTest.test_object_path_variable - -class CodeAssistInProjectsTest -CodeAssistInProjectsTest.setUp -CodeAssistInProjectsTest.tearDown -CodeAssistInProjectsTest._assist -CodeAssistInProjectsTest.assert_completion_in_result -CodeAssistInProjectsTest.assert_completion_not_in_result -CodeAssistInProjectsTest.test_simple_import -CodeAssistInProjectsTest.test_from_import_class -CodeAssistInProjectsTest.test_from_import_function -CodeAssistInProjectsTest.test_from_import_variable -CodeAssistInProjectsTest.test_from_imports_inside_functions -CodeAssistInProjectsTest.test_from_import_only_imports_imported -CodeAssistInProjectsTest.test_from_import_star -CodeAssistInProjectsTest.test_from_import_star2 -CodeAssistInProjectsTest.test_from_import_star_not_imporing_underlined -CodeAssistInProjectsTest.test_from_package_import_mod -CodeAssistInProjectsTest.test_completing_after_dot -CodeAssistInProjectsTest.test_completing_after_multiple_dots -CodeAssistInProjectsTest.test_completing_after_self_dot -CodeAssistInProjectsTest.test_result_start_offset_for_dotted_completions -CodeAssistInProjectsTest.test_backslash_after_dots -CodeAssistInProjectsTest.test_not_proposing_global_names_after_dot -CodeAssistInProjectsTest.test_assist_on_relative_imports -CodeAssistInProjectsTest.test_get_location_on_relative_imports -CodeAssistInProjectsTest.test_get_definition_location_for_builtins -CodeAssistInProjectsTest.test_get_doc_on_relative_imports -CodeAssistInProjectsTest.test_get_doc_on_from_import_module -CodeAssistInProjectsTest.test_fixing_errors_with_maxfixes_in_resources -CodeAssistInProjectsTest.test_completing_names_after_from_import -CodeAssistInProjectsTest.test_completing_names_after_from_import_and_sorted_proposals -CodeAssistInProjectsTest.test_completing_names_after_from_import2 -CodeAssistInProjectsTest.test_starting_expression - - -@clean finderrorstest.py -class FindErrorsTest -FindErrorsTest.setUp -FindErrorsTest.tearDown -FindErrorsTest.test_unresolved_variables -FindErrorsTest.test_defined_later -FindErrorsTest.test_ignoring_builtins -FindErrorsTest.test_ignoring_none -FindErrorsTest.test_bad_attributes - - -@clean findittest.py -class FindItTest -FindItTest.setUp -FindItTest.tearDown -FindItTest.test_finding_occurrences -FindItTest.test_finding_occurrences_in_more_than_one_module -FindItTest.test_finding_occurrences_matching_when_unsure -FindItTest.test_find_occurrences_resources_parameter -FindItTest.test_find_occurrences_and_class_hierarchies -FindItTest.test_trivial_find_implementations -FindItTest.test_find_implementations_and_not_returning_parents -FindItTest.test_find_implementations_real_implementation -FindItTest.test_find_implementations_real_implementation_simple -FindItTest.test_trivial_find_definition -FindItTest.test_find_definition_in_other_modules - - -@clean fixmodnamestest.py -class FixModuleNamesTest -FixModuleNamesTest.setUp -FixModuleNamesTest.tearDown -FixModuleNamesTest.test_simple_module_renaming -FixModuleNamesTest.test_packages_module_renaming -FixModuleNamesTest.test_fixing_contents -FixModuleNamesTest.test_handling_nested_modules - -_fixer - -@clean generatetest.py -class GenerateTest -GenerateTest.setUp -GenerateTest.tearDown -GenerateTest._get_generate -GenerateTest._get_generate_class -GenerateTest._get_generate_module -GenerateTest._get_generate_package -GenerateTest._get_generate_function -GenerateTest.test_getting_location -GenerateTest.test_generating_variable -GenerateTest.test_generating_variable_inserting_before_statement -GenerateTest.test_generating_variable_in_local_scopes -GenerateTest.test_generating_variable_in_other_modules -GenerateTest.test_generating_variable_in_classes -GenerateTest.test_generating_variable_in_classes_removing_pass -GenerateTest.test_generating_variable_in_packages -GenerateTest.test_generating_classes -GenerateTest.test_generating_classes_in_other_module -GenerateTest.test_generating_modules -GenerateTest.test_generating_packages -GenerateTest.test_generating_function -GenerateTest.test_generating_modules_with_empty_primary -GenerateTest.test_generating_variable_already_exists -GenerateTest.test_generating_variable_primary_cannot_be_determined -GenerateTest.test_generating_modules_when_already_exists -GenerateTest.test_generating_static_methods -GenerateTest.test_generating_methods -GenerateTest.test_generating_constructors -GenerateTest.test_generating_calls -GenerateTest.test_generating_calls_in_other_modules -GenerateTest.test_generating_function_handling_arguments -GenerateTest.test_generating_function_handling_keyword_xarguments -GenerateTest.test_generating_function_handling_arguments_better_naming -GenerateTest.test_generating_variable_in_other_modules2 -GenerateTest.test_generating_function_in_a_suite -GenerateTest.test_generating_function_in_a_suite_in_a_function -GenerateTest.test_create_generate_class_with_goal_resource -GenerateTest.test_create_generate_class_without_goal_resource - - -@clean __init__.py -suite - -@path autoimport -@clean conftest.py -project -mod1 -mod1_path -project_path -typing_path -build_env_path -build_path -compiled_lib - -@clean modeltest.py -class QueryTest -class NameModelTest -NameModelTest.test_name_objects -NameModelTest.test_query_strings - -class PackageModelTest -PackageModelTest.test_query_strings - - -@clean parsetest.py -test_typing_names -test_find_sys -test_find_underlined - -@clean utilstest.py -test_get_package_source -test_get_package_source_not_project -test_get_package_source_pytest -test_get_package_source_typing -test_get_modname_project_no_add -test_get_modname_single_file -test_get_modname_folder -test_get_package_tuple_sample -test_get_package_tuple_typing -test_get_package_tuple_compiled - - - -@path refactor -@clean __init__.py -class MethodObjectTest -MethodObjectTest.setUp -MethodObjectTest.tearDown -MethodObjectTest.test_empty_method -MethodObjectTest.test_trivial_return -MethodObjectTest.test_multi_line_header -MethodObjectTest.test_a_single_parameter -MethodObjectTest.test_self_parameter -MethodObjectTest.test_simple_using_passed_parameters -MethodObjectTest.test_self_keywords_and_args_parameters -MethodObjectTest.test_performing_on_not_a_function -MethodObjectTest.test_changing_the_module -MethodObjectTest.test_changing_the_module_and_class_methods - -class IntroduceFactoryTest -IntroduceFactoryTest.setUp -IntroduceFactoryTest.tearDown -IntroduceFactoryTest._introduce_factory -IntroduceFactoryTest.test_adding_the_method -IntroduceFactoryTest.test_changing_occurrences_in_the_main_module -IntroduceFactoryTest.test_changing_occurrences_with_arguments -IntroduceFactoryTest.test_changing_occurrences_in_other_modules -IntroduceFactoryTest.test_raising_exception_for_non_classes -IntroduceFactoryTest.test_undoing_introduce_factory -IntroduceFactoryTest.test_using_on_an_occurrence_outside_the_main_module -IntroduceFactoryTest.test_introduce_factory_in_nested_scopes -IntroduceFactoryTest.test_adding_factory_for_global_factories -IntroduceFactoryTest.test_get_name_for_factories -IntroduceFactoryTest.test_raising_exception_for_global_factory_for_nested_classes -IntroduceFactoryTest.test_changing_occurrences_in_the_main_module_for_global_factories -IntroduceFactoryTest.test_changing_occurrences_in_other_modules_for_global_factories -IntroduceFactoryTest.test_import_if_necessary_in_other_mods_for_global_factories -IntroduceFactoryTest.test_changing_occurrences_for_renamed_classes -IntroduceFactoryTest.test_changing_occurrs_in_the_same_module_with_conflict_ranges -IntroduceFactoryTest._transform_module_to_package -IntroduceFactoryTest.test_transform_module_to_package -IntroduceFactoryTest.test_transform_module_to_package_undoing -IntroduceFactoryTest.test_transform_module_to_package_with_relative_imports -IntroduceFactoryTest.test_resources_parameter - -class EncapsulateFieldTest -EncapsulateFieldTest.setUp -EncapsulateFieldTest.tearDown -EncapsulateFieldTest._encapsulate -EncapsulateFieldTest.test_adding_getters_and_setters -EncapsulateFieldTest.test_changing_getters_in_other_modules -EncapsulateFieldTest.test_changing_setters_in_other_modules -EncapsulateFieldTest.test_changing_getters_in_setters -EncapsulateFieldTest.test_appending_to_class_end -EncapsulateFieldTest.test_performing_in_other_modules -EncapsulateFieldTest.test_changing_main_module_occurrences -EncapsulateFieldTest.test_raising_exception_when_performed_on_non_attributes -EncapsulateFieldTest.test_raising_exception_on_tuple_assignments -EncapsulateFieldTest.test_raising_exception_on_tuple_assignments2 -EncapsulateFieldTest.test_tuple_assignments_and_function_calls -EncapsulateFieldTest.test_tuple_assignments -EncapsulateFieldTest.test_changing_augmented_assignments -EncapsulateFieldTest.test_changing_augmented_assignments2 -EncapsulateFieldTest.test_changing_occurrences_inside_the_class -EncapsulateFieldTest.test_getter_and_setter_parameters -EncapsulateFieldTest.test_using_resources_parameter - -class LocalToFieldTest -LocalToFieldTest.setUp -LocalToFieldTest.tearDown -LocalToFieldTest._perform_convert_local_variable_to_field -LocalToFieldTest.test_simple_local_to_field -LocalToFieldTest.test_raising_exception_when_performed_on_a_global_var -LocalToFieldTest.test_raising_exception_when_performed_on_field -LocalToFieldTest.test_raising_exception_when_performed_on_a_parameter -LocalToFieldTest.test_not_rais_exception_when_there_is_a_field_with_the_same_name -LocalToFieldTest.test_local_to_field_with_self_renamed - -class IntroduceParameterTest -IntroduceParameterTest.setUp -IntroduceParameterTest.tearDown -IntroduceParameterTest._introduce_parameter -IntroduceParameterTest.test_simple_case -IntroduceParameterTest.test_changing_function_body -IntroduceParameterTest.test_unknown_variables -IntroduceParameterTest.test_failing_when_not_inside -IntroduceParameterTest.test_attribute_accesses -IntroduceParameterTest.test_introducing_parameters_for_methods - -class _MockTaskObserver -class TaskHandleTest -TaskHandleTest.test_trivial_case -TaskHandleTest.test_stopping -TaskHandleTest.test_job_sets -TaskHandleTest.test_starting_and_finishing_jobs -TaskHandleTest.test_test_checking_status -TaskHandleTest.test_test_checking_status_when_starting -TaskHandleTest.test_calling_the_observer_after_stopping -TaskHandleTest.test_calling_the_observer_after_creating_job_sets -TaskHandleTest.test_calling_the_observer_when_starting_and_finishing_jobs -TaskHandleTest.test_job_set_get_percent_done -TaskHandleTest.test_getting_job_name (changed) - - -@clean change_signature_test.py -class ChangeSignatureTest -ChangeSignatureTest.setUp -ChangeSignatureTest.tearDown -ChangeSignatureTest.test_normalizing_parameters_for_trivial_case -ChangeSignatureTest.test_normalizing_parameters_for_trivial_case2 -ChangeSignatureTest.test_normalizing_parameters_for_unneeded_keyword -ChangeSignatureTest.test_normalizing_parameters_for_unneeded_keyword_for_methods -ChangeSignatureTest.test_normalizing_parameters_for_unsorted_keyword -ChangeSignatureTest.test_raising_exceptions_for_non_functions -ChangeSignatureTest.test_normalizing_parameters_for_args_parameter -ChangeSignatureTest.test_normalizing_parameters_for_args_parameter_and_keywords -ChangeSignatureTest.test_normalizing_functions_from_other_modules -ChangeSignatureTest.test_normalizing_parameters_for_keyword_parameters -ChangeSignatureTest.test_removing_arguments -ChangeSignatureTest.test_removing_arguments_with_multiple_args -ChangeSignatureTest.test_removing_arguments_passed_as_keywords -ChangeSignatureTest.test_removing_arguments_with_defaults -ChangeSignatureTest.test_removing_arguments_star_args -ChangeSignatureTest.test_removing_keyword_arg -ChangeSignatureTest.test_removing_keyword_arg2 -ChangeSignatureTest.xxx_test_removing_arguments_star_args2 -ChangeSignatureTest.xxx_test_removing_arguments_star_args3 -ChangeSignatureTest.test_adding_arguments_for_normal_args_changing_definition -ChangeSignatureTest.test_adding_arguments_for_normal_args_with_defaults -ChangeSignatureTest.test_adding_arguments_for_normal_args_changing_calls -ChangeSignatureTest.test_adding_arguments_for_norm_args_chang_calls_with_kwords -ChangeSignatureTest.test_adding_arguments_for_norm_args_chang_calls_with_no_value -ChangeSignatureTest.test_adding_duplicate_parameter_and_raising_exceptions -ChangeSignatureTest.test_inlining_default_arguments -ChangeSignatureTest.test_inlining_default_arguments2 -ChangeSignatureTest.test_preserving_args_and_keywords_order -ChangeSignatureTest.test_change_order_for_only_one_parameter -ChangeSignatureTest.test_change_order_for_two_parameter -ChangeSignatureTest.test_reordering_multi_line_function_headers -ChangeSignatureTest.test_changing_order_with_static_params -ChangeSignatureTest.test_doing_multiple_changes -ChangeSignatureTest.test_doing_multiple_changes2 -ChangeSignatureTest.test_changing_signature_in_subclasses -ChangeSignatureTest.test_differentiating_class_accesses_from_instance_accesses -ChangeSignatureTest.test_changing_signature_for_constructors -ChangeSignatureTest.test_changing_signature_for_constructors2 -ChangeSignatureTest.test_changing_signature_for_constructors_when_using_super -ChangeSignatureTest.test_redordering_arguments_reported_by_mft -ChangeSignatureTest.test_resources_parameter -ChangeSignatureTest.test_reordering_and_automatic_defaults - - -@clean extracttest.py -class ExtractMethodTest -ExtractMethodTest.setUp -ExtractMethodTest.tearDown -ExtractMethodTest.do_extract_method -ExtractMethodTest.do_extract_variable -ExtractMethodTest._convert_line_range_to_offset -ExtractMethodTest.test_simple_extract_function -ExtractMethodTest.test_simple_extract_function_one_line -ExtractMethodTest.test_extract_function_at_the_end_of_file -ExtractMethodTest.test_extract_function_after_scope -ExtractMethodTest.test_extract_function_containing_dict_generalized_unpacking -ExtractMethodTest.test_simple_extract_function_with_parameter -ExtractMethodTest.test_not_unread_variables_as_parameter -ExtractMethodTest.test_simple_extract_function_with_two_parameter -ExtractMethodTest.test_simple_extract_function_with_return_value -ExtractMethodTest.test_extract_function_with_multiple_return_values -ExtractMethodTest.test_simple_extract_method -ExtractMethodTest.test_extract_method_with_args_and_returns -ExtractMethodTest.test_extract_method_with_self_as_argument -ExtractMethodTest.test_extract_method_with_no_self_as_argument -ExtractMethodTest.test_extract_method_with_multiple_methods -ExtractMethodTest.test_extract_function_with_function_returns -ExtractMethodTest.test_simple_extract_global_function -ExtractMethodTest.test_extract_global_function_inside_ifs -ExtractMethodTest.test_extract_function_while_inner_function_reads -ExtractMethodTest.test_extract_method_bad_range -ExtractMethodTest.test_extract_method_bad_range2 -ExtractMethodTest.test_extract_method_containing_return -ExtractMethodTest.test_extract_method_containing_yield -ExtractMethodTest.test_extract_method_containing_uncomplete_lines -ExtractMethodTest.test_extract_method_containing_uncomplete_lines2 -ExtractMethodTest.test_extract_function_and_argument_as_paramenter -ExtractMethodTest.test_extract_function_and_end_as_the_start_of_a_line -ExtractMethodTest.test_extract_function_and_indented_blocks -ExtractMethodTest.test_extract_method_and_multi_line_headers -ExtractMethodTest.test_single_line_extract_function -ExtractMethodTest.test_single_line_extract_function2 -ExtractMethodTest.test_single_line_extract_method_and_logical_lines -ExtractMethodTest.test_single_line_extract_method_and_logical_lines2 -ExtractMethodTest.test_single_line_extract_method_with_large_multiline_expression -ExtractMethodTest.test_single_line_extract_method -ExtractMethodTest.test_single_line_extract_function_if_condition -ExtractMethodTest.test_unneeded_params -ExtractMethodTest.test_breaks_and_continues_inside_loops -ExtractMethodTest.test_breaks_and_continues_outside_loops -ExtractMethodTest.test_for_loop_variable_scope -ExtractMethodTest.test_for_loop_variable_scope_read_then_write -ExtractMethodTest.test_for_loop_variable_scope_write_then_read -ExtractMethodTest.test_for_loop_variable_scope_write_only -ExtractMethodTest.test_variable_writes_followed_by_variable_reads_after_extraction -ExtractMethodTest.test_var_writes_followed_by_var_reads_inside_extraction -ExtractMethodTest.test_extract_variable -ExtractMethodTest.test_extract_variable_f_string -ExtractMethodTest.test_extract_variable_multiple_lines -ExtractMethodTest.test_extract_variable_in_the_middle_of_statements -ExtractMethodTest.test_extract_variable_for_a_tuple -ExtractMethodTest.test_extract_variable_for_a_string -ExtractMethodTest.test_extract_variable_inside_ifs -ExtractMethodTest.test_extract_variable_inside_ifs_and_logical_lines -ExtractMethodTest.xxx_test_extract_variable_for_a_subexpression -ExtractMethodTest.test_extract_variable_starting_from_the_start_of_the_line -ExtractMethodTest.test_extract_variable_on_the_last_line_of_a_function -ExtractMethodTest.test_extract_variable_on_the_indented_function_statement -ExtractMethodTest.test_extract_method_on_the_last_line_of_a_function -ExtractMethodTest.test_raising_exception_when_on_incomplete_variables -ExtractMethodTest.test_raising_exception_when_on_incomplete_variables_on_end -ExtractMethodTest.test_raising_exception_on_bad_parens -ExtractMethodTest.test_raising_exception_on_bad_operators -ExtractMethodTest.xxx_test_raising_exception_on_function_parens -ExtractMethodTest.test_extract_method_and_extra_blank_lines -ExtractMethodTest.test_extract_method_f_string_extract_method -ExtractMethodTest.test_extract_method_f_string_extract_method_complex_expression -ExtractMethodTest.test_extract_method_f_string_false_comment -ExtractMethodTest.test_extract_method_f_string_false_format_value_in_regular_string -ExtractMethodTest.test_variable_writes_in_the_same_line_as_variable_read -ExtractMethodTest.test_variable_writes_in_the_same_line_as_variable_read2 -ExtractMethodTest.test_variable_writes_in_the_same_line_as_variable_read3 -ExtractMethodTest.test_variable_writes_only -ExtractMethodTest.test_variable_and_similar_expressions -ExtractMethodTest.test_definition_should_appear_before_the_first_use -ExtractMethodTest.test_extract_method_and_similar_expressions -ExtractMethodTest.test_simple_extract_method_and_similar_statements -ExtractMethodTest.test_extract_method_and_similar_statements2 -ExtractMethodTest.test_extract_method_and_similar_sttemnts_return_is_different -ExtractMethodTest.test_extract_method_and_similar_sttemnts_overlapping_regions -ExtractMethodTest.test_definition_should_appear_where_it_is_visible -ExtractMethodTest.test_extract_variable_and_similar_statements_in_classes -ExtractMethodTest.test_extract_method_in_staticmethods -ExtractMethodTest.test_extract_normal_method_with_staticmethods -ExtractMethodTest.test_extract_variable_with_no_new_lines_at_the_end -ExtractMethodTest.test_extract_method_containing_return_in_functions -ExtractMethodTest.test_extract_method_and_varying_first_parameter -ExtractMethodTest.test_extract_method_when_an_attribute_exists_in_function_scope -ExtractMethodTest.test_global_option_for_extract_method -ExtractMethodTest.test_global_extract_method -ExtractMethodTest.test_global_extract_method_with_multiple_methods -ExtractMethodTest.test_where_to_seach_when_extracting_global_names -ExtractMethodTest.test_extracting_pieces_with_distinct_temp_names -ExtractMethodTest.test_extract_methods_in_glob_funcs_should_be_glob -ExtractMethodTest.test_extract_methods_in_glob_funcs_should_be_glob_2 -ExtractMethodTest.test_extract_method_and_try_blocks -ExtractMethodTest.test_extract_method_and_augmentedj_assignment_in_try_block -ExtractMethodTest.test_extract_and_not_passing_global_functions -ExtractMethodTest.test_extracting_with_only_one_return -ExtractMethodTest.test_extracting_variable_and_implicit_continuations -ExtractMethodTest.test_extracting_method_and_implicit_continuations -ExtractMethodTest.test_passing_conditional_updated_vars_in_extracted -ExtractMethodTest.test_returning_conditional_updated_vars_in_extracted -ExtractMethodTest.test_extract_method_with_variables_possibly_written_to -ExtractMethodTest.test_extract_method_with_list_comprehension -ExtractMethodTest.test_extract_method_with_list_comprehension_in_class_method -ExtractMethodTest.test_extract_method_with_list_comprehension_and_iter -ExtractMethodTest.test_extract_method_with_list_comprehension_and_orelse -ExtractMethodTest.test_extract_method_with_list_comprehension_multiple_targets -ExtractMethodTest.test_extract_function_with_for_else_statemant -ExtractMethodTest.test_extract_function_with_for_else_statemant_more -ExtractMethodTest.test_extract_function_with_for_else_statemant_outside_loops -ExtractMethodTest.test_extract_function_with_inline_assignment_in_method -ExtractMethodTest.test_extract_function_statement_with_inline_assignment_in_condition -ExtractMethodTest.test_extract_function_expression_with_inline_assignment_in_condition -ExtractMethodTest.test_extract_function_expression_with_inline_assignment_complex -ExtractMethodTest.test_extract_function_expression_with_inline_assignment_in_inner_expression -ExtractMethodTest.test_extract_exec -ExtractMethodTest.test_extract_exec_statement -ExtractMethodTest.test_extract_async_function -ExtractMethodTest.test_extract_inner_async_function -ExtractMethodTest.test_extract_around_inner_async_function -ExtractMethodTest.test_extract_refactor_around_async_for_loop -ExtractMethodTest.test_extract_refactor_containing_async_for_loop_should_error_before_py38 -ExtractMethodTest.test_extract_refactor_containing_async_for_loop_is_supported_after_py38 -ExtractMethodTest.test_extract_await_expression -ExtractMethodTest.test_extract_to_staticmethod -ExtractMethodTest.test_extract_to_staticmethod_when_self_in_body -ExtractMethodTest.test_extract_from_function_to_staticmethod_raises_exception -ExtractMethodTest.test_extract_method_in_classmethods -ExtractMethodTest.test_extract_from_function_to_classmethod_raises_exception -ExtractMethodTest.test_extract_to_classmethod_when_self_in_body -ExtractMethodTest.test_extract_to_classmethod -ExtractMethodTest.test_extract_to_classmethod_when_name_starts_with_at_sign -ExtractMethodTest.test_extract_to_staticmethod_when_name_starts_with_dollar_sign -ExtractMethodTest.test_raises_exception_when_sign_in_name_and_kind_mismatch -ExtractMethodTest.test_extracting_from_static_with_function_arg -ExtractMethodTest.test_extract_with_list_comprehension -ExtractMethodTest.test_extract_with_generator -ExtractMethodTest.test_extract_with_generator_2 -ExtractMethodTest.test_extract_with_set_comprehension -ExtractMethodTest.test_extract_with_dict_comprehension -ExtractMethodTest.test_extract_function_expression_with_assignment_to_attribute -ExtractMethodTest.test_extract_function_expression_with_assignment_index -ExtractMethodTest.test_extraction_method_with_global_variable -ExtractMethodTest.test_extraction_method_with_global_variable_and_global_declaration -ExtractMethodTest.test_extraction_one_line_with_global_variable_read_only -ExtractMethodTest.test_extraction_one_line_with_global_variable -ExtractMethodTest.test_extraction_one_line_with_global_variable_has_postread -ExtractMethodTest.test_extract_method_with_nested_double_with_as -ExtractMethodTest.test_extract_method_with_double_with_as -ExtractMethodTest.test_extract_method_with_nested_double_with_as_and_misleading_comment -ExtractMethodTest.test_extract_method_async_with_simple -ExtractMethodTest.test_extract_method_containing_async_with -ExtractMethodTest.test_extract_method_containing_structural_pattern_match -ExtractMethodTest.test_extract_method_containing_structural_pattern_match_2 -ExtractMethodTest.test_extract_method_containing_structural_pattern_match_3 - - -@clean importutilstest.py -class ImportUtilsTest -ImportUtilsTest.setUp -ImportUtilsTest.tearDown -ImportUtilsTest.test_get_import_for_module -ImportUtilsTest.test_get_import_for_module_in_nested_modules -ImportUtilsTest.test_get_import_for_module_in_init_dot_py -ImportUtilsTest.test_get_from_import_for_module -ImportUtilsTest.test_get_from_import_for_module_in_nested_modules -ImportUtilsTest.test_get_from_import_for_module_in_init_dot_py -ImportUtilsTest.test_get_import_statements -ImportUtilsTest.test_get_import_statements_with_alias -ImportUtilsTest.test_get_import_statements_for_froms -ImportUtilsTest.test_get_multi_line_import_statements_for_froms -ImportUtilsTest.test_get_import_statements_for_from_star -ImportUtilsTest.test_get_import_statements_for_new_relatives -ImportUtilsTest.test_ignoring_indented_imports -ImportUtilsTest.test_import_get_names -ImportUtilsTest.test_import_get_names_with_alias -ImportUtilsTest.test_import_get_names_with_alias2 -ImportUtilsTest.test_empty_getting_used_imports -ImportUtilsTest.test_empty_getting_used_imports2 -ImportUtilsTest.test_simple_getting_used_imports -ImportUtilsTest.test_simple_getting_used_imports2 -ImportUtilsTest.test_getting_used_imports_for_nested_scopes -ImportUtilsTest.test_getting_used_imports_for_nested_scopes2 -ImportUtilsTest.test_empty_removing_unused_imports -ImportUtilsTest.test_simple_removing_unused_imports -ImportUtilsTest.test_simple_removing_unused_imports_for_froms -ImportUtilsTest.test_simple_removing_unused_imports_for_from_stars -ImportUtilsTest.test_simple_removing_unused_imports_for_nested_modules -ImportUtilsTest.test_removing_unused_imports_and_functions_of_the_same_name -ImportUtilsTest.test_removing_unused_imports_for_from_import_with_as -ImportUtilsTest.test_not_removing_imports_that_conflict_with_class_names -ImportUtilsTest.test_adding_imports -ImportUtilsTest.test_adding_imports_no_pull_to_top -ImportUtilsTest.test_adding_from_imports -ImportUtilsTest.test_adding_to_star_imports -ImportUtilsTest.test_adding_star_imports -ImportUtilsTest.test_adding_imports_and_preserving_spaces_after_imports -ImportUtilsTest.test_not_changing_the_format_of_unchanged_imports -ImportUtilsTest.test_not_changing_the_format_of_unchanged_imports2 -ImportUtilsTest.test_removing_unused_imports_and_reoccuring_names -ImportUtilsTest.test_removing_unused_imports_and_reoccuring_names2 -ImportUtilsTest.test_removing_unused_imports_and_common_packages -ImportUtilsTest.test_removing_unused_imports_and_common_packages_reversed -ImportUtilsTest.test_removing_unused_imports_and_common_packages2 -ImportUtilsTest.test_removing_unused_imports_and_froms -ImportUtilsTest.test_removing_unused_imports_and_froms2 -ImportUtilsTest.test_removing_unused_imports_and_froms3 -ImportUtilsTest.test_removing_unused_imports_and_froms4 -ImportUtilsTest.test_removing_unused_imports_and_getting_attributes -ImportUtilsTest.test_removing_unused_imports_function_parameters -ImportUtilsTest.test_trivial_expanding_star_imports -ImportUtilsTest.test_expanding_star_imports -ImportUtilsTest.test_removing_duplicate_imports -ImportUtilsTest.test_removing_duplicates_and_reoccuring_names -ImportUtilsTest.test_removing_duplicate_imports_for_froms -ImportUtilsTest.test_transforming_froms_to_normal_changing_imports -ImportUtilsTest.test_transforming_froms_to_normal_changing_occurrences -ImportUtilsTest.test_transforming_froms_to_normal_for_multi_imports -ImportUtilsTest.test_transform_froms_to_norm_for_multi_imports_inside_parens -ImportUtilsTest.test_transforming_froms_to_normal_from_stars -ImportUtilsTest.test_transforming_froms_to_normal_from_stars2 -ImportUtilsTest.test_transforming_froms_to_normal_from_with_alias -ImportUtilsTest.test_transforming_froms_to_normal_for_relatives -ImportUtilsTest.test_transforming_froms_to_normal_for_os_path -ImportUtilsTest.test_transform_relatives_imports_to_abs_imports_doing_nothing -ImportUtilsTest.test_transform_relatives_to_absolute_imports_for_normal_imports -ImportUtilsTest.test_transform_relatives_imports_to_absolute_imports_for_froms -ImportUtilsTest.test_transform_rel_imports_to_abs_imports_for_new_relatives -ImportUtilsTest.test_transform_relatives_to_absolute_imports_for_normal_imports2 -ImportUtilsTest.test_transform_relatives_to_absolute_imports_for_aliases -ImportUtilsTest.test_organizing_imports -ImportUtilsTest.test_organizing_imports_without_deduplication -ImportUtilsTest.test_splitting_imports -ImportUtilsTest.test_splitting_imports_no_pull_to_top -ImportUtilsTest.test_splitting_imports_with_filter -ImportUtilsTest.test_splitting_duplicate_imports -ImportUtilsTest.test_splitting_duplicate_imports2 -ImportUtilsTest.test_removing_self_imports -ImportUtilsTest.test_removing_self_imports2 -ImportUtilsTest.test_removing_self_imports_with_as -ImportUtilsTest.test_removing_self_imports_for_froms -ImportUtilsTest.test_removing_self_imports_for_froms_with_as -ImportUtilsTest.test_removing_self_imports_for_froms2 -ImportUtilsTest.test_removing_self_imports_for_froms3 -ImportUtilsTest.test_removing_self_imports_for_froms4 -ImportUtilsTest.test_removing_self_imports_with_no_dot_after_mod -ImportUtilsTest.test_removing_self_imports_with_no_dot_after_mod2 -ImportUtilsTest.test_removing_self_imports_for_from_import_star -ImportUtilsTest.test_not_removing_future_imports -ImportUtilsTest.test_sorting_empty_imports -ImportUtilsTest.test_sorting_one_import -ImportUtilsTest.test_sorting_imports_alphabetically -ImportUtilsTest.test_sorting_imports_purely_alphabetically -ImportUtilsTest.test_sorting_imports_and_froms -ImportUtilsTest.test_sorting_imports_and_standard_modules -ImportUtilsTest.test_sorting_imports_and_standard_modules2 -ImportUtilsTest.test_sorting_only_standard_modules -ImportUtilsTest.test_sorting_third_party -ImportUtilsTest.test_sorting_only_third_parties -ImportUtilsTest.test_simple_handling_long_imports -ImportUtilsTest.test_handling_long_imports_for_many_dots -ImportUtilsTest.test_handling_long_imports_for_their_length -ImportUtilsTest.test_handling_long_imports_for_many_dots2 -ImportUtilsTest.test_handling_long_imports_with_one_letter_last -ImportUtilsTest.test_empty_removing_unused_imports_and_eating_blank_lines -ImportUtilsTest.test_sorting_imports_moving_to_top -ImportUtilsTest.test_sorting_imports_moving_to_top2 -ImportUtilsTest.test_sorting_imports_no_pull_to_top -ImportUtilsTest.test_sorting_imports_moving_to_top_and_module_docs -ImportUtilsTest.test_sorting_imports_moving_to_top_and_module_docs2 -ImportUtilsTest.test_get_changed_source_preserves_blank_lines -ImportUtilsTest.test_sorting_future_imports -ImportUtilsTest.test_organizing_imports_all_star -ImportUtilsTest.test_organizing_imports_all_star_with_variables -ImportUtilsTest.test_organizing_imports_all_star_with_inline_if -ImportUtilsTest.test_organizing_imports_all_star_tolerates_non_list_of_str_1 -ImportUtilsTest.test_organizing_imports_all_star_assigned_name_alias -ImportUtilsTest.test_organizing_imports_all_star_imported_name_alias -ImportUtilsTest.test_organizing_imports_all_star_tolerates_non_list_of_str_2 -ImportUtilsTest.test_organizing_imports_all_star_plusjoin -ImportUtilsTest.test_organizing_imports_all_star_starjoin -ImportUtilsTest.test_organizing_imports_all_star_no_infinite_loop -ImportUtilsTest.test_organizing_imports_all_star_resolve_imported_name -ImportUtilsTest.test_organizing_imports_undefined_variable -ImportUtilsTest.test_organizing_imports_undefined_variable_with_imported_name -ImportUtilsTest.test_organizing_indirect_all_star_import -ImportUtilsTest.test_customized_import_organization -ImportUtilsTest.test_customized_import_organization2 -ImportUtilsTest.test_customized_import_organization3 -ImportUtilsTest.test_trivial_filtered_expand_stars -ImportUtilsTest._line_filter -ImportUtilsTest.test_filtered_expand_stars -ImportUtilsTest.test_filtered_relative_to_absolute -ImportUtilsTest.test_filtered_froms_to_normals -ImportUtilsTest.test_filtered_froms_to_normals2 -ImportUtilsTest.test_filtered_handle_long_imports -ImportUtilsTest.test_filtering_and_import_actions_with_more_than_one_phase -ImportUtilsTest.test_non_existent_module_and_used_imports - -class AddImportTest -AddImportTest.setUp -AddImportTest.tearDown -AddImportTest.test_normal_imports -AddImportTest.test_not_reimporting_a_name -AddImportTest.test_adding_import_when_siblings_are_imported -AddImportTest.test_adding_import_when_the_package_is_imported -AddImportTest.test_adding_import_for_modules_instead_of_names -AddImportTest.test_adding_import_for_modules_with_normal_duplicate_imports - - -@clean inlinetest.py -class InlineTest -InlineTest.setUp -InlineTest.tearDown -InlineTest._inline -InlineTest._inline2 -InlineTest.test_simple_case -InlineTest.test_empty_case -InlineTest.test_long_definition -InlineTest.test_explicit_continuation -InlineTest.test_implicit_continuation -InlineTest.test_inlining_at_the_end_of_input -InlineTest.test_on_classes -InlineTest.test_multiple_assignments -InlineTest.test_tuple_assignments -InlineTest.test_on_unknown_vars -InlineTest.test_attribute_inlining -InlineTest.test_attribute_inlining2 -InlineTest.test_a_function_with_no_occurrence -InlineTest.test_a_function_with_no_occurrence2 -InlineTest.test_replacing_calls_with_function_definition_in_other_modules -InlineTest.test_replacing_calls_with_function_definition_in_other_modules2 -InlineTest.test_replacing_calls_with_method_definition_in_other_modules -InlineTest.test_replacing_calls_with_function_definition_in_defining_module -InlineTest.test_replac_calls_with_function_definition_in_defining_module2 -InlineTest.test_replacing_calls_with_method_definition_in_defining_modules -InlineTest.test_parameters_with_the_same_name_as_passed -InlineTest.test_parameters_with_the_same_name_as_passed2 -InlineTest.test_simple_parameters_renaming -InlineTest.test_simple_parameters_renaming_for_multiple_params -InlineTest.test_parameters_renaming_for_passed_constants -InlineTest.test_parameters_renaming_for_passed_statements -InlineTest.test_simple_parameters_renam_for_multiple_params_using_keywords -InlineTest.test_simple_params_renam_for_multi_params_using_mixed_keywords -InlineTest.test_simple_putting_in_default_arguments -InlineTest.test_overriding_default_arguments -InlineTest.test_arguments_containing_comparisons -InlineTest.test_badly_formatted_text -InlineTest.test_passing_first_arguments_for_methods -InlineTest.test_passing_first_arguments_for_methods2 -InlineTest.test_passing_first_arguments_for_methods3 -InlineTest.test_inlining_staticmethods -InlineTest.test_static_methods2 -InlineTest.test_inlining_classmethods -InlineTest.test_inlining_classmethods2 -InlineTest.test_simple_return_values_and_inlining_functions -InlineTest.test_simple_return_values_and_inlining_lonely_functions -InlineTest.test_empty_returns_and_inlining_lonely_functions -InlineTest.test_multiple_returns -InlineTest.test_multiple_returns_and_not_using_the_value -InlineTest.test_raising_exception_for_list_arguments -InlineTest.test_raising_exception_for_list_keywods -InlineTest.test_function_parameters_and_returns_in_other_functions -InlineTest.test_function_references_other_than_call -InlineTest.test_function_referencing_itself -InlineTest.test_recursive_functions -InlineTest.xxx_test_inlining_function_default_parameters -InlineTest.test_simple_inlining_after_extra_indented_lines -InlineTest.test_inlining_a_function_with_pydoc -InlineTest.test_inlining_methods -InlineTest.test_simple_returns_with_backslashes -InlineTest.test_a_function_with_pass_body -InlineTest.test_inlining_the_last_method_of_a_class -InlineTest.test_adding_needed_imports_in_the_dest_module -InlineTest.test_adding_needed_imports_in_the_dest_module_removing_selfs -InlineTest.test_handling_relative_imports_when_inlining -InlineTest.test_adding_needed_imports_for_elements_in_source -InlineTest.test_relative_imports_and_changing_inlining_body -InlineTest.test_inlining_with_different_returns -InlineTest.test_not_removing_definition_for_variables -InlineTest.test_not_removing_definition_for_methods -InlineTest.test_only_current_for_methods -InlineTest.test_only_current_for_variables -InlineTest.test_inlining_one_line_functions -InlineTest.test_inlining_one_line_functions_with_breaks -InlineTest.test_inlining_one_line_functions_with_breaks2 -InlineTest.test_resources_parameter -InlineTest.test_inlining_parameters -InlineTest.test_inlining_function_with_line_breaks_in_args -InlineTest.test_inlining_variables_before_comparison -InlineTest.test_inlining_variables_in_other_modules -InlineTest.test_inlining_variables_and_back_importing -InlineTest.test_inlining_variables_and_importing_used_imports -InlineTest.test_inlining_variables_and_removing_old_froms -InlineTest.test_inlining_method_and_removing_old_froms -InlineTest.test_inlining_functions_in_other_modules_and_only_current -InlineTest.test_inlining_variables_in_other_modules_and_only_current -InlineTest.test_inlining_does_not_change_string_constants -InlineTest.test_inlining_does_change_string_constants_if_docs_is_set -InlineTest.test_inlining_into_format_string -InlineTest.test_inlining_into_format_string_containing_quotes -InlineTest.test_parameters_with_the_same_name_as_passed_with_type_hints -InlineTest.test_parameters_with_the_same_name_as_passed_as_kwargs_with_type_hints -InlineTest.test_simple_parameters_renaming_with_type_hints -InlineTest.test_simple_parameters_renaming_for_multiple_params_with_type_hints -InlineTest.test_parameters_renaming_for_passed_constants_with_type_hints -InlineTest.test_parameters_renaming_for_passed_statements_with_type_hints -InlineTest.test_simple_parameters_renaming_for_multiple_params_using_keywords_with_type_hints -InlineTest.test_simple_params_renaming_for_multi_params_using_mixed_keywords_with_type_hints -InlineTest.test_simple_putting_in_default_arguments_with_type_hints -InlineTest.test_overriding_default_arguments_with_type_hints - - -@clean movetest.py -class MoveRefactoringTest -MoveRefactoringTest.setUp -MoveRefactoringTest.tearDown -MoveRefactoringTest._move -MoveRefactoringTest.test_move_constant -MoveRefactoringTest.test_move_constant_2 -MoveRefactoringTest.test_move_constant_multiline -MoveRefactoringTest.test_move_constant_multiple_statements -MoveRefactoringTest.test_simple_moving -MoveRefactoringTest.test_moving_with_comment_prefix -MoveRefactoringTest.test_moving_with_comment_prefix_imports -MoveRefactoringTest.test_changing_other_modules_replacing_normal_imports -MoveRefactoringTest.test_changing_other_modules_adding_normal_imports -MoveRefactoringTest.test_adding_imports_prefer_from_module -MoveRefactoringTest.test_adding_imports_noprefer_from_module -MoveRefactoringTest.test_adding_imports_prefer_from_module_top_level_module -MoveRefactoringTest.test_changing_other_modules_removing_from_imports -MoveRefactoringTest.test_changing_source_module -MoveRefactoringTest.test_changing_destination_module -MoveRefactoringTest.test_folder_destination -MoveRefactoringTest.test_raising_exception_for_moving_non_global_elements -MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable -MoveRefactoringTest.test_raising_exception_for_mov_glob_elemnts_to_the_same_module -MoveRefactoringTest.test_moving_used_imports_to_destination_module -MoveRefactoringTest.test_moving_used_names_to_destination_module2 -MoveRefactoringTest.test_moving_used_underlined_names_to_destination_module -MoveRefactoringTest.test_moving_and_used_relative_imports -MoveRefactoringTest.test_moving_modules -MoveRefactoringTest.test_moving_modules_and_removing_out_of_date_imports -MoveRefactoringTest.test_moving_modules_and_removing_out_of_date_froms -MoveRefactoringTest.test_moving_modules_and_removing_out_of_date_froms2 -MoveRefactoringTest.test_moving_modules_and_relative_import -MoveRefactoringTest.test_moving_module_kwarg_same_name_as_old -MoveRefactoringTest.test_moving_packages -MoveRefactoringTest.test_moving_modules_with_self_imports -MoveRefactoringTest.test_moving_modules_with_from_imports -MoveRefactoringTest.test_moving_modules_with_from_import -MoveRefactoringTest.test_moving_modules_with_multi_from_imports -MoveRefactoringTest.test_moving_modules_with_from_and_normal_imports -MoveRefactoringTest.test_moving_modules_with_normal_and_from_imports -MoveRefactoringTest.test_moving_modules_from_import_variable -MoveRefactoringTest.test_moving_modules_normal_import -MoveRefactoringTest.test_moving_package_with_from_and_normal_imports -MoveRefactoringTest.test_moving_package_with_from_and_normal_imports2 -MoveRefactoringTest.test_moving_package_and_retaining_blank_lines -MoveRefactoringTest.test_moving_functions_to_imported_module -MoveRefactoringTest.test_moving_resources_using_move_module_refactoring -MoveRefactoringTest.test_moving_resources_using_move_module_for_packages -MoveRefactoringTest.test_moving_resources_using_move_module_for_init_dot_py -MoveRefactoringTest.test_moving_module_and_star_imports -MoveRefactoringTest.test_moving_module_and_not_removing_blanks_after_imports -MoveRefactoringTest.test_moving_module_refactoring_and_nonexistent_destinations -MoveRefactoringTest.test_moving_methods_choosing_the_correct_class -MoveRefactoringTest.test_moving_methods_getting_new_method_for_empty_methods -MoveRefactoringTest.test_moving_methods_getting_new_method_for_constant_methods -MoveRefactoringTest.test_moving_methods_getting_new_method_passing_simple_paremters -MoveRefactoringTest.test_moving_methods_getting_new_method_using_main_object -MoveRefactoringTest.test_moving_methods_getting_new_method_renaming_main_object -MoveRefactoringTest.test_moving_methods_gettin_new_method_with_keyword_arguments -MoveRefactoringTest.test_moving_methods_gettin_new_method_with_many_kinds_arguments -MoveRefactoringTest.test_moving_methods_getting_new_method_for_multi_line_methods -MoveRefactoringTest.test_moving_methods_getting_old_method_for_constant_methods -MoveRefactoringTest.test_moving_methods_getting_getting_changes_for_goal_class -MoveRefactoringTest.test_moving_methods_getting_getting_changes_for_goal_class2 -MoveRefactoringTest.test_moving_methods_and_nonexistent_attributes -MoveRefactoringTest.test_unknown_attribute_type -MoveRefactoringTest.test_moving_methods_and_moving_used_imports -MoveRefactoringTest.test_moving_methods_getting_getting_changes_for_goal_class3 -MoveRefactoringTest.test_moving_methods_and_source_class_with_parameters -MoveRefactoringTest.test_moving_globals_to_a_module_with_only_docstrings -MoveRefactoringTest.test_moving_globals_to_a_module_with_only_docstrings2 -MoveRefactoringTest.test_moving_a_global_when_it_is_used_after_a_multiline_str -MoveRefactoringTest.test_raising_an_exception_when_moving_non_package_folders -MoveRefactoringTest.test_moving_to_a_module_with_encoding_cookie -MoveRefactoringTest.test_moving_decorated_function -MoveRefactoringTest.test_moving_decorated_class - - -@clean multiprojecttest.py -class MultiProjectRefactoringTest -MultiProjectRefactoringTest.setUp -MultiProjectRefactoringTest.tearDown -MultiProjectRefactoringTest.test_trivial_rename -MultiProjectRefactoringTest.test_rename -MultiProjectRefactoringTest.test_move -MultiProjectRefactoringTest.test_rename_from_the_project_not_containing_the_change - - -@clean patchedasttest.py -class PatchedASTTest -PatchedASTTest.setUp -PatchedASTTest.tearDown -PatchedASTTest.assert_single_case_match_block -PatchedASTTest.test_bytes_string -PatchedASTTest.test_integer_literals_and_region -PatchedASTTest.test_negative_integer_literals_and_region -PatchedASTTest.test_scientific_integer_literals_and_region -PatchedASTTest.test_hex_integer_literals_and_region -PatchedASTTest.test_long_literals_and_region -PatchedASTTest.test_octal_integer_literals_and_region -PatchedASTTest.test_integer_literals_and_sorted_children -PatchedASTTest.test_ellipsis -PatchedASTTest.test_ass_name_node -PatchedASTTest.test_assign_node -PatchedASTTest.test_ann_assign_node_without_target -PatchedASTTest.test_ann_assign_node_with_target -PatchedASTTest.test_add_node -PatchedASTTest.test_lshift_node -PatchedASTTest.test_and_node -PatchedASTTest.test_matmult_node -PatchedASTTest.test_basic_closing_parens -PatchedASTTest.test_basic_opening_parens -PatchedASTTest.test_basic_opening_biway -PatchedASTTest.test_basic_opening_double -PatchedASTTest.test_handling_comments -PatchedASTTest.test_handling_parens_with_spaces -PatchedASTTest.test_handling_strings -PatchedASTTest.test_handling_implicit_string_concatenation -PatchedASTTest.test_handling_implicit_string_concatenation_line_breaks -PatchedASTTest.test_handling_explicit_string_concatenation_line_breaks -PatchedASTTest.test_not_concatenating_strings_on_separate_lines -PatchedASTTest.test_handling_raw_strings -PatchedASTTest.test_handling_format_strings_basic -PatchedASTTest.test_handling_format_strings_with_implicit_join -PatchedASTTest.test_handling_format_strings_with_format_spec -PatchedASTTest.test_handling_format_strings_with_inner_format_spec -PatchedASTTest.test_handling_format_strings_with_expression -PatchedASTTest.test_long_integer_literals -PatchedASTTest.test_complex_number_literals -PatchedASTTest.test_ass_attr_node -PatchedASTTest.test_ass_list_node -PatchedASTTest.test_ass_tuple -PatchedASTTest.test_ass_tuple2 -PatchedASTTest.test_assert -PatchedASTTest.test_assert2 -PatchedASTTest.test_aug_assign_node -PatchedASTTest.test_back_quotenode -PatchedASTTest.test_bitand -PatchedASTTest.test_bitor -PatchedASTTest.test_call_func -PatchedASTTest.test_call_func_and_keywords -PatchedASTTest.test_call_func_and_star_args -PatchedASTTest.test_call_func_and_star_argspython35 -PatchedASTTest.test_call_func_and_only_dstar_args -PatchedASTTest.test_call_func_and_only_dstar_args_python35 -PatchedASTTest.test_call_func_and_both_varargs_and_kwargs -PatchedASTTest.test_call_func_and_both_varargs_and_kwargs_python35 -PatchedASTTest.test_class_node -PatchedASTTest.test_class_with_no_bases -PatchedASTTest.test_simple_compare -PatchedASTTest.test_multiple_compare -PatchedASTTest.test_decorators_node -PatchedASTTest.test_decorators_for_classes -PatchedASTTest.test_both_varargs_and_kwargs -PatchedASTTest.test_function_node -PatchedASTTest.test_async_function_node -PatchedASTTest.test_function_node2 -PatchedASTTest.test_function_node_and_tuple_parameters -PatchedASTTest.test_dict_node -PatchedASTTest.test_dict_node_with_unpacking -PatchedASTTest.test_div_node -PatchedASTTest.test_simple_exec_node -PatchedASTTest.test_exec_node -PatchedASTTest.test_exec_node_with_parens -PatchedASTTest.test_for_node -PatchedASTTest.test_async_for_node -PatchedASTTest.test_named_expr_node -PatchedASTTest.test_normal_from_node -PatchedASTTest.test_from_node -PatchedASTTest.test_from_node_relative_import -PatchedASTTest.test_simple_gen_expr_node -PatchedASTTest.test_gen_expr_node_handling_surrounding_parens -PatchedASTTest.test_gen_expr_node2 -PatchedASTTest.test_get_attr_node -PatchedASTTest.test_global_node -PatchedASTTest.test_if_node -PatchedASTTest.test_if_node2 -PatchedASTTest.test_if_node3 -PatchedASTTest.test_import_node -PatchedASTTest.test_lambda_node -PatchedASTTest.test_list_node -PatchedASTTest.test_list_comp_node -PatchedASTTest.test_list_comp_node_with_multiple_comprehensions -PatchedASTTest.test_set_node -PatchedASTTest.test_set_comp_node -PatchedASTTest.test_dict_comp_node -PatchedASTTest.test_ext_slice_node -PatchedASTTest.test_simple_module_node -PatchedASTTest.test_module_node -PatchedASTTest.test_not_and_or_nodes -PatchedASTTest.test_print_node -PatchedASTTest.test_printnl_node -PatchedASTTest.test_raise_node_for_python2 -PatchedASTTest.test_raise_node_for_python3 -PatchedASTTest.test_return_node -PatchedASTTest.test_empty_return_node -PatchedASTTest.test_simple_slice_node -PatchedASTTest.test_slice_node2 -PatchedASTTest.test_simple_subscript -PatchedASTTest.test_tuple_node -PatchedASTTest.test_tuple_node2 -PatchedASTTest.test_tuple_with_complex_parentheses1 -PatchedASTTest.test_tuple_with_complex_parentheses2 -PatchedASTTest.test_tuple_with_complex_parentheses3 -PatchedASTTest.test_one_item_tuple_node -PatchedASTTest.test_empty_tuple_node -PatchedASTTest.test_empty_tuple_node2 -PatchedASTTest.test_empty_tuple_node3 -PatchedASTTest.test_yield_node -PatchedASTTest.test_yield_from_node -PatchedASTTest.test_while_node -PatchedASTTest.test_with_node -PatchedASTTest.test_async_with_node -PatchedASTTest.test_try_finally_node -PatchedASTTest.test_try_except_node -PatchedASTTest.test_try_except_node__with_as_syntax -PatchedASTTest.test_try_except_and_finally_node -PatchedASTTest.test_ignoring_comments -PatchedASTTest.test_simple_sliceobj -PatchedASTTest.test_ignoring_strings_that_start_with_a_char -PatchedASTTest.test_how_to_handle_old_not_equals -PatchedASTTest.test_semicolon -PatchedASTTest.test_if_exp_node -PatchedASTTest.test_delete_node -PatchedASTTest.test_starargs_before_keywords_legacy -PatchedASTTest.test_starargs_in_keywords_legacy -PatchedASTTest.test_starargs_after_keywords_legacy -PatchedASTTest.test_starargs_before_keywords -PatchedASTTest.test_starargs_in_keywords -PatchedASTTest.test_starargs_in_positional -PatchedASTTest.test_starargs_after_keywords -PatchedASTTest.test_await_node -PatchedASTTest.test_match_node_with_constant_match_value -PatchedASTTest.test_match_node_match_case_with_guard -PatchedASTTest.test_match_node_with_match_class -PatchedASTTest.test_match_node_with_wildcard -PatchedASTTest.test_match_node_with_match_as_capture_pattern -PatchedASTTest.test_match_node_with_match_as_capture_pattern_with_explicit_name -PatchedASTTest.test_match_node_with_match_class_simple_match_as_capture_pattern -PatchedASTTest.test_match_node_with_match_class_named_argument -PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name - -class _ResultChecker -_ResultChecker.__init__ -_ResultChecker.check_region -_ResultChecker._find_node -_ResultChecker.__call__ - -_ResultChecker.check_children - - -@clean renametest.py -class RenameRefactoringTest -RenameRefactoringTest.setUp -RenameRefactoringTest.tearDown -RenameRefactoringTest._local_rename -RenameRefactoringTest._rename -RenameRefactoringTest.test_local_variable_but_not_parameter -RenameRefactoringTest.test_simple_global_variable_renaming -RenameRefactoringTest.test_variable_renaming_only_in_its_scope -RenameRefactoringTest.test_not_renaming_dot_name -RenameRefactoringTest.test_renaming_multiple_names_in_the_same_line -RenameRefactoringTest.test_renaming_names_when_getting_some_attribute -RenameRefactoringTest.test_renaming_names_when_getting_some_attribute2 -RenameRefactoringTest.test_renaming_function_parameters1 -RenameRefactoringTest.test_renaming_function_parameters2 -RenameRefactoringTest.test_renaming_occurrences_inside_functions -RenameRefactoringTest.test_renaming_comprehension_loop_variables -RenameRefactoringTest.test_renaming_list_comprehension_loop_variables_in_assignment -RenameRefactoringTest.test_renaming_generator_comprehension_loop_variables -RenameRefactoringTest.test_renaming_comprehension_loop_variables_scope -RenameRefactoringTest.test_renaming_inline_assignment -RenameRefactoringTest.test_renaming_arguments_for_normal_args_changing_calls -RenameRefactoringTest.test_renaming_function_parameters_of_class_init -RenameRefactoringTest.test_rename_functions_parameters_and_occurences_in_other_modules -RenameRefactoringTest.test_renaming_with_backslash_continued_names -RenameRefactoringTest.test_renaming_occurrence_in_f_string -RenameRefactoringTest.test_renaming_occurrence_in_nested_f_string -RenameRefactoringTest.test_not_renaming_string_contents_in_f_string -RenameRefactoringTest.test_not_renaming_string_contents -RenameRefactoringTest.test_not_renaming_comment_contents -RenameRefactoringTest.test_renaming_all_occurrences_in_containing_scope -RenameRefactoringTest.test_renaming_a_variable_with_arguement_name -RenameRefactoringTest.test_renaming_an_arguement_with_variable_name -RenameRefactoringTest.test_renaming_function_with_local_variable_name -RenameRefactoringTest.test_renaming_functions -RenameRefactoringTest.test_renaming_async_function -RenameRefactoringTest.test_renaming_await -RenameRefactoringTest.test_renaming_functions_across_modules -RenameRefactoringTest.test_renaming_functions_across_modules_from_import -RenameRefactoringTest.test_renaming_functions_from_another_module -RenameRefactoringTest.test_applying_all_changes_together -RenameRefactoringTest.test_renaming_modules -RenameRefactoringTest.test_renaming_modules_aliased -RenameRefactoringTest.test_renaming_packages -RenameRefactoringTest.test_module_dependencies -RenameRefactoringTest.test_renaming_class_attributes -RenameRefactoringTest.test_renaming_class_attributes2 -RenameRefactoringTest.test_renaming_methods_in_subclasses -RenameRefactoringTest.test_renaming_methods_in_sibling_classes -RenameRefactoringTest.test_not_renaming_methods_in_hierarchies -RenameRefactoringTest.test_undoing_refactorings -RenameRefactoringTest.test_undoing_renaming_modules -RenameRefactoringTest.test_rename_in_module_renaming_one_letter_names_for_expressions -RenameRefactoringTest.test_renaming_for_loop_variable -RenameRefactoringTest.test_renaming_async_for_loop_variable -RenameRefactoringTest.test_renaming_async_with_context_manager -RenameRefactoringTest.test_renaming_async_with_as_variable -RenameRefactoringTest.test_renaming_parameters -RenameRefactoringTest.test_renaming_assigned_parameters -RenameRefactoringTest.test_renaming_parameters_not_renaming_others -RenameRefactoringTest.test_renaming_parameters_not_renaming_others2 -RenameRefactoringTest.test_renaming_parameters_with_multiple_params -RenameRefactoringTest.test_renaming_parameters_with_multiple_params2 -RenameRefactoringTest.test_renaming_parameters_on_calls -RenameRefactoringTest.test_renaming_parameters_spaces_before_call -RenameRefactoringTest.test_renaming_parameter_like_objects_after_keywords -RenameRefactoringTest.test_renaming_variables_in_init_dot_pys -RenameRefactoringTest.test_renaming_variables_in_init_dot_pys2 -RenameRefactoringTest.test_renaming_variables_in_init_dot_pys3 -RenameRefactoringTest.test_renaming_resources_using_rename_module_refactoring -RenameRefactoringTest.test_renam_resources_using_rename_module_refactor_for_packages -RenameRefactoringTest.test_renam_resources_use_rename_module_refactor_for_init_dot_py -RenameRefactoringTest.test_renaming_global_variables -RenameRefactoringTest.test_renaming_global_variables2 -RenameRefactoringTest.test_renaming_when_unsure -RenameRefactoringTest._true -RenameRefactoringTest.test_renaming_when_unsure_with_confirmation -RenameRefactoringTest.test_renaming_when_unsure_not_renaming_knowns -RenameRefactoringTest.test_renaming_in_strings_and_comments -RenameRefactoringTest.test_not_renaming_in_strings_and_comments_where_not_visible -RenameRefactoringTest.test_not_renaming_all_text_occurrences_in_strings_and_comments -RenameRefactoringTest.test_renaming_occurrences_in_overwritten_scopes -RenameRefactoringTest.test_renaming_occurrences_in_overwritten_scopes2 -RenameRefactoringTest.test_renaming_in_generalized_dict_unpacking -RenameRefactoringTest.test_dos_line_ending_and_renaming -RenameRefactoringTest.test_multi_byte_strs_and_renaming -RenameRefactoringTest.test_resources_parameter -RenameRefactoringTest.test_resources_parameter_not_changing_defining_module -RenameRefactoringTest.xxx_test_with_statement_variables_should_not_leak -RenameRefactoringTest.test_rename_in_list_comprehension -RenameRefactoringTest.test_renaming_modules_aliased_with_dots -RenameRefactoringTest.test_renaming_modules_aliased_many_dots - -class ChangeOccurrencesTest -ChangeOccurrencesTest.setUp -ChangeOccurrencesTest.tearDown -ChangeOccurrencesTest.test_simple_case -ChangeOccurrencesTest.test_only_performing_inside_scopes -ChangeOccurrencesTest.test_only_performing_on_calls -ChangeOccurrencesTest.test_only_performing_on_reads - -class ImplicitInterfacesTest -ImplicitInterfacesTest.setUp -ImplicitInterfacesTest.tearDown -ImplicitInterfacesTest._rename -ImplicitInterfacesTest.test_performing_rename_on_parameters - - -@clean restructuretest.py -class RestructureTest -RestructureTest.setUp -RestructureTest.tearDown -RestructureTest.test_trivial_case -RestructureTest.test_replacing_simple_patterns -RestructureTest.test_replacing_patterns_with_normal_names -RestructureTest.test_replacing_patterns_with_any_names -RestructureTest.test_replacing_patterns_with_any_names2 -RestructureTest.test_replacing_patterns_with_checks -RestructureTest.test_replacing_assignments_with_sets -RestructureTest.test_replacing_sets_with_assignments -RestructureTest.test_using_make_checks -RestructureTest.test_using_make_checking_builtin_types -RestructureTest.test_auto_indentation_when_no_indentation -RestructureTest.test_auto_indentation -RestructureTest.test_auto_indentation_and_not_indenting_blanks -RestructureTest.test_importing_names -RestructureTest.test_not_importing_names_when_there_are_no_changes -RestructureTest.test_handling_containing_matches -RestructureTest.test_handling_overlapping_matches -RestructureTest.test_preventing_stack_overflow_when_matching -RestructureTest.test_performing_a_restructuring_to_all_modules -RestructureTest.test_performing_a_restructuring_to_selected_modules -RestructureTest.test_unsure_argument_of_default_wildcard -RestructureTest.test_statement_after_string_and_column -RestructureTest.test_yield_from - - -@clean similarfindertest.py -class SimilarFinderTest -SimilarFinderTest.setUp -SimilarFinderTest.tearDown -SimilarFinderTest._create_finder -SimilarFinderTest.test_trivial_case -SimilarFinderTest.test_constant_integer -SimilarFinderTest.test_bool_is_not_similar_to_integer -SimilarFinderTest.test_simple_addition -SimilarFinderTest.test_simple_addition2 -SimilarFinderTest.test_simple_assign_statements -SimilarFinderTest.test_simple_multiline_statements -SimilarFinderTest.test_multiple_matches -SimilarFinderTest.test_multiple_matches2 -SimilarFinderTest.test_restricting_the_region_to_search -SimilarFinderTest.test_matching_basic_patterns -SimilarFinderTest.test_match_get_ast -SimilarFinderTest.test_match_get_ast_for_statements -SimilarFinderTest.test_matching_multiple_patterns -SimilarFinderTest.test_matching_any_patterns -SimilarFinderTest.test_matching_any_patterns_repeating -SimilarFinderTest.test_matching_any_patterns_not_matching_different_nodes -SimilarFinderTest.test_matching_normal_names_and_assname -SimilarFinderTest.test_matching_normal_names_and_assname2 -SimilarFinderTest.test_matching_normal_names_and_attributes -SimilarFinderTest.test_functions_not_matching_when_only_first_parameters -SimilarFinderTest.test_matching_nested_try_finally -SimilarFinderTest.test_matching_dicts_inside_functions - -class CheckingFinderTest -CheckingFinderTest.setUp -CheckingFinderTest.tearDown -CheckingFinderTest.test_trivial_case -CheckingFinderTest.test_simple_finding -CheckingFinderTest.test_not_matching_when_the_name_does_not_match -CheckingFinderTest.test_not_matching_unknowns_finding -CheckingFinderTest.test_finding_and_matching_pyobjects -CheckingFinderTest.test_finding_and_matching_types -CheckingFinderTest.test_checking_the_type_of_an_ass_name_node -CheckingFinderTest.test_checking_instance_of_an_ass_name_node -CheckingFinderTest.test_checking_equality_of_imported_pynames - -class TemplateTest -TemplateTest.test_simple_templates -TemplateTest.test_ignoring_matches_in_comments -TemplateTest.test_ignoring_matches_in_strings -TemplateTest.test_simple_substitution -TemplateTest.test_substituting_multiple_names - - -@clean suitestest.py -class SuiteTest -SuiteTest.setUp -SuiteTest.tearDown -SuiteTest.test_trivial_case -SuiteTest.test_simple_ifs -SuiteTest.test_simple_else -SuiteTest.test_for -SuiteTest.test_while -SuiteTest.test_with -SuiteTest.test_try_finally -SuiteTest.test_try_except -SuiteTest.test_try_except_finally -SuiteTest.test_local_start_and_end -SuiteTest.test_find_suite -SuiteTest.test_find_suite_for_ifs -SuiteTest.test_find_suite_for_between_suites -SuiteTest.test_simple_find_visible -SuiteTest.test_simple_find_visible_ifs -SuiteTest.test_simple_find_visible_for_else -SuiteTest.test_simple_find_visible_for_different_suites -SuiteTest.test_not_always_selecting_scope_start -SuiteTest.test_ignoring_functions -SuiteTest.test_ignoring_classes -SuiteTest.test_match_case - -source_suite_tree - -@clean usefunctiontest.py -class UseFunctionTest -UseFunctionTest.setUp -UseFunctionTest.tearDown -UseFunctionTest.test_simple_case -UseFunctionTest.test_simple_function -UseFunctionTest.test_simple_function2 -UseFunctionTest.test_functions_with_multiple_statements -UseFunctionTest.test_returning -UseFunctionTest.test_returning_a_single_expression -UseFunctionTest.test_occurrences_in_other_modules -UseFunctionTest.test_when_performing_on_non_functions -UseFunctionTest.test_differing_in_the_inner_temp_names -UseFunctionTest.xxx_test_being_a_bit_more_intelligent_when_returning_assigneds -UseFunctionTest.test_exception_when_performing_a_function_with_yield -UseFunctionTest.test_exception_when_performing_a_function_two_returns -UseFunctionTest.test_exception_when_returns_is_not_the_last_statement - - - - - - -Recent files - - - - - - - - -Recent code ---- Old/closed PRs -=== PR #5: (closed) Remove python2 code -=== PR #540: (closed) closed: ekr-clean-pyflakes - ---- To do: create new issues ---- Possible bugs (new rope issues?) ---- possible bug in AbstractClass.get_name - - ---- class hierarch for _PyModule - - - - - ---- possible bug in utils.py: resolve_type - - - -=== PR/issue: xxx Fix pylint errors -=== PR/issue: fix minor flake8 errors ---- flake8 minor errors - -=== PR/issue: xxx Full coverage -=== PR/issue: xxx Remove @deprecated -=== PR/issue: xxx Remove only_for decorator - -Found 38:only_for ---- 2.x - - - - - - - - - - - - - - - - - - - ---- 3.x - - - - - - - - - - - - - - - - - - - - - - -=== PR/Issue: xxx Use f-strings -Found 49:".*{} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -=== PR #539: ekr-dummy-classes -=== PR #528: ekr-walk-special cases ---- self.module: None vs. "" ---- recent - - - - - -Found 7:def get_module - - - - - - - - -Found 4:def get_pymodule - - - - - -Found 9:def get_object - - - - - - - - - - - ---- traces - - - ------- testing sequence - - - - - - - - - -Results - -Found 8:ImportFrom - - - - - - -Found 23:PyModule - - - - - - - - - - - - - - - - -Found 8:PyPackage - - - - - - - - - - -diff master..HEAD (ekr-walk-special-case) -diff: rope/base/ast.py -diff: Changed -diff: walk -Old:walk - - - - -diff: rope/base/pyobjectsdef.py -diff: Changed -diff: _ScopeVisitor._ImportFrom (trace) -Old:_ScopeVisitor._ImportFrom (trace) - - - - - - - -diff master..HEAD (ekr-reorg) ---- Deleted -Deleted: rope/base/ast.py -Deleted: rope/base/pynamesdef.py - ---- New (rewritten) -diff: rope/base/astutils.py -diff: Changed -diff: rope/base/astutils.py:HEAD -Old:rope/base/astutils.py:HEAD - - -diff: _NodeNameCollector._Tuple -Old:_NodeNameCollector._Tuple - - -diff: _NodeNameCollector._Slice -Old:_NodeNameCollector._Slice - - - - - ---- Changed docstrings -diff: rope/base/oi/type_hinting/providers/composite.py -diff: Changed -diff: AssignmentProvider.__call__ -Old:AssignmentProvider.__call__ - - - - -diff: rope/base/oi/type_hinting/providers/docstrings.py -diff: Changed -diff: AssignmentProvider.__call__ -Old:AssignmentProvider.__call__ - - - - -diff: rope/base/oi/type_hinting/providers/inheritance.py -diff: Changed -diff: AssignmentProvider.__call__ -Old:AssignmentProvider.__call__ - - - - -diff: rope/base/oi/type_hinting/providers/interfaces.py -diff: Changed -diff: ITypeHintingFactory.make_assignment_provider -Old:ITypeHintingFactory.make_assignment_provider - - - - -diff: rope/base/oi/type_hinting/providers/pep0484_type_comments.py -diff: Changed -diff: AssignmentProvider.__call__ -Old:AssignmentProvider.__call__ - - - - -diff: rope/base/oi/type_hinting/utils.py -diff: Changed -diff: path_relative_to_project_root -Old:path_relative_to_project_root - - -diff: relative -Old:relative - - - - - ---- Cleaned imports -diff: rope/base/pycore.py -diff: Changed -diff: rope/base/pycore.py:HEAD -Old:rope/base/pycore.py:HEAD - - - - - ---- Major changes -diff: rope/base/pynames.py -diff: Changed -diff: rope/base/pynames.py:HEAD -Old:rope/base/pynames.py:HEAD - - -diff: AssignedName.__init__ -Old:AssignedName.__init__ - - -diff: ParameterName.__init__ -Old:ParameterName.__init__ - - - - - ---- Changed imports & qualifiers -diff: rope/base/arguments.py -diff: Changed -diff: rope/base/arguments.py:HEAD -Old:rope/base/arguments.py:HEAD - - - - -diff: rope/base/evaluate.py -diff: Changed -diff: rope/base/evaluate.py:HEAD -Old:rope/base/evaluate.py:HEAD - - -diff: eval_node2 -Old:eval_node2 - - -diff: eval_str2 -Old:eval_str2 - - -diff: ScopeNameFinder.get_primary_and_pyname_at -Old:ScopeNameFinder.get_primary_and_pyname_at - - -diff: ScopeNameFinder._find_module -Old:ScopeNameFinder._find_module - - -diff: StatementEvaluator._Attribute -Old:StatementEvaluator._Attribute - - -diff: StatementEvaluator._Call -Old:StatementEvaluator._Call - - -diff: StatementEvaluator._Str -Old:StatementEvaluator._Str - - -diff: StatementEvaluator._get_builtin_name -Old:StatementEvaluator._get_builtin_name - - -diff: StatementEvaluator._BinOp -Old:StatementEvaluator._BinOp - - -diff: StatementEvaluator._BoolOp -Old:StatementEvaluator._BoolOp - - -diff: StatementEvaluator._UnaryOp -Old:StatementEvaluator._UnaryOp - - -diff: StatementEvaluator._Dict -Old:StatementEvaluator._Dict - - -diff: StatementEvaluator._List -Old:StatementEvaluator._List - - -diff: StatementEvaluator._ListComp -Old:StatementEvaluator._ListComp - - -diff: StatementEvaluator._GeneratorExp -Old:StatementEvaluator._GeneratorExp - - -diff: StatementEvaluator._Tuple -Old:StatementEvaluator._Tuple - - -diff: StatementEvaluator._call_function -Old:StatementEvaluator._call_function - - -diff: StatementEvaluator._Lambda -Old:StatementEvaluator._Lambda - - -diff: _get_evaluated_names -Old:_get_evaluated_names - - - - -diff: rope/base/oi/soa.py -diff: Changed -diff: rope/base/oi/soa.py:HEAD -Old:rope/base/oi/soa.py:HEAD - - -diff: _analyze_node -Old:_analyze_node - - -diff: SOAVisitor._Call -Old:SOAVisitor._Call - - -diff: SOAVisitor._AnnAssign -Old:SOAVisitor._AnnAssign - - -diff: SOAVisitor._Assign -Old:SOAVisitor._Assign - - -diff: SOAVisitor._evaluate_assign_value -Old:SOAVisitor._evaluate_assign_value - - -diff: class _SOAAssignVisitor -Old:class _SOAAssignVisitor - - -diff: _SOAAssignVisitor._added -Old:_SOAAssignVisitor._added - - - - -diff: rope/base/oi/soi.py -diff: Changed -diff: rope/base/oi/soi.py:HEAD -Old:rope/base/oi/soi.py:HEAD - - -diff: _infer_assignment & helpers -Old:_infer_assignment & helpers - - -diff: _follow_pyname -Old:_follow_pyname - - - - -diff: rope/base/pyobjects.py -diff: Changed -diff: rope/base/pyobjects.py:HEAD -Old:rope/base/pyobjects.py:HEAD - - -diff: PyDefinedObject.get_doc (changed) -Old:PyDefinedObject.get_doc (changed) - - -diff: PyDefinedObject._create_structural_attributes -Old:PyDefinedObject._create_structural_attributes - - - - -diff: rope/base/pyobjectsdef.py -diff: Changed -diff: << imports: pyobjectsdef >> -Old:<< imports: pyobjectsdef >> - - -diff: PyModule.__init__ -Old:PyModule.__init__ - - -diff: PyModule._init_source -Old:PyModule._init_source - - -diff: PyPackage.__init__ -Old:PyPackage.__init__ - - -diff: _AnnAssignVisitor._AnnAssign -Old:_AnnAssignVisitor._AnnAssign - - -diff: _AnnAssignVisitor._Tuple -Old:_AnnAssignVisitor._Tuple - - -diff: _ExpressionVisitor._NamedExpr -Old:_ExpressionVisitor._NamedExpr - - -diff: _AssignVisitor._Assign -Old:_AssignVisitor._Assign - - -diff: _AssignVisitor._Tuple -Old:_AssignVisitor._Tuple - - -diff: _ScopeVisitor._Assign -Old:_ScopeVisitor._Assign - - -diff: _ScopeVisitor._AnnAssign -Old:_ScopeVisitor._AnnAssign - - -diff: _ScopeVisitor._For -Old:_ScopeVisitor._For - - -diff: _ScopeVisitor._update_evaluated -Old:_ScopeVisitor._update_evaluated - - -diff: _ScopeVisitor._With -Old:_ScopeVisitor._With - - -diff: _ScopeVisitor._excepthandler -Old:_ScopeVisitor._excepthandler - - -diff: _ComprehensionVisitor._comprehension -Old:_ComprehensionVisitor._comprehension - - -diff: _ClassVisitor._FunctionDef -Old:_ClassVisitor._FunctionDef - - -diff: _ClassInitVisitor._Tuple -Old:_ClassInitVisitor._Tuple - - - - -diff: rope/base/pyscopes.py -diff: Changed -diff: rope/base/pyscopes.py:HEAD -Old:rope/base/pyscopes.py:HEAD - - -diff: ComprehensionScope._visit_comprehension -Old:ComprehensionScope._visit_comprehension - - -diff: FunctionScope._visit_function -Old:FunctionScope._visit_function - - - - -diff: rope/contrib/codeassist.py -diff: Changed -diff: rope/contrib/codeassist.py:HEAD -Old:rope/contrib/codeassist.py:HEAD - - -diff: get_canonical_path -Old:get_canonical_path - - - - -diff: rope/contrib/finderrors.py -diff: Changed -diff: rope/contrib/finderrors.py:HEAD -Old:rope/contrib/finderrors.py:HEAD - - -diff: find_errors -Old:find_errors - - -diff: _BadAccessFinder._Attribute -Old:_BadAccessFinder._Attribute - - - - -diff: rope/contrib/generate.py -diff: Changed -diff: rope/contrib/generate.py:HEAD -Old:rope/contrib/generate.py:HEAD - - - - -diff: rope/refactor/extract.py -diff: Changed -diff: rope/refactor/extract.py:HEAD -Old:rope/refactor/extract.py:HEAD - - -diff: _ExtractMethodParts._create_info_collector -Old:_ExtractMethodParts._create_info_collector - - -diff: _ExtractMethodParts._get_globals_in_body -Old:_ExtractMethodParts._get_globals_in_body - - -diff: _FunctionInformationCollector._FunctionDef -Old:_FunctionInformationCollector._FunctionDef - - -diff: _FunctionInformationCollector._MatchAs -Old:_FunctionInformationCollector._MatchAs - - -diff: _FunctionInformationCollector._Assign -Old:_FunctionInformationCollector._Assign - - -diff: _FunctionInformationCollector._AugAssign -Old:_FunctionInformationCollector._AugAssign - - -diff: _FunctionInformationCollector._comp_exp -Old:_FunctionInformationCollector._comp_exp - - -diff: _FunctionInformationCollector._For -Old:_FunctionInformationCollector._For - - -diff: _FunctionInformationCollector._handle_conditional_node -Old:_FunctionInformationCollector._handle_conditional_node - - -diff: _VariableReadsAndWritesFinder._FunctionDef -Old:_VariableReadsAndWritesFinder._FunctionDef - - -diff: _VariableReadsAndWritesFinder.find_reads_and_writes -Old:_VariableReadsAndWritesFinder.find_reads_and_writes - - -diff: _VariableReadsAndWritesFinder.find_reads_for_one_liners -Old:_VariableReadsAndWritesFinder.find_reads_for_one_liners - - -diff: _BaseErrorFinder.has_errors -Old:_BaseErrorFinder.has_errors - - -diff: _UnmatchedBreakOrContinueFinder.loop_encountered -Old:_UnmatchedBreakOrContinueFinder.loop_encountered - - - - -diff: rope/refactor/importutils/module_imports.py -diff: Changed -diff: rope/refactor/importutils/module_imports.py:HEAD -Old:rope/refactor/importutils/module_imports.py:HEAD - - -diff: ModuleImports._get_unbound_names -Old:ModuleImports._get_unbound_names - - -diff: ModuleImports._get_all_star_list -Old:ModuleImports._get_all_star_list - - -diff: _UnboundNameFinder._visit_child_scope -Old:_UnboundNameFinder._visit_child_scope - - -diff: _UnboundNameFinder._Attribute -Old:_UnboundNameFinder._Attribute - - - - -diff: rope/refactor/patchedast.py -diff: Changed -diff: rope/refactor/patchedast.py:HEAD -Old:rope/refactor/patchedast.py:HEAD - - -diff: get_patched_ast -Old:get_patched_ast - - -diff: patch_ast -Old:patch_ast - - -diff: _PatchingASTWalker.__call__ -Old:_PatchingASTWalker.__call__ - - -diff: _PatchingASTWalker._handle (changed) -Old:_PatchingASTWalker._handle (changed) - - -diff: _Source.consume (changed) -Old:_Source.consume (changed) - - - - -diff: rope/refactor/restructure.py -diff: Changed -diff: rope/refactor/restructure.py:HEAD -Old:rope/refactor/restructure.py:HEAD - - -diff: _ChangeComputer._get_nearest_roots -Old:_ChangeComputer._get_nearest_roots - - - - -diff: rope/refactor/similarfinder.py -diff: Changed -diff: rope/refactor/similarfinder.py:HEAD -Old:rope/refactor/similarfinder.py:HEAD - - -diff: RawSimilarFinder.__init__ -Old:RawSimilarFinder.__init__ - - -diff: RawSimilarFinder._create_pattern -Old:RawSimilarFinder._create_pattern - - -diff: _ASTMatcher.find_matches -Old:_ASTMatcher.find_matches - - -diff: _ASTMatcher._check_statements -Old:_ASTMatcher._check_statements - - -diff: _ASTMatcher._get_children -Old:_ASTMatcher._get_children - - - - - -diff: rope/refactor/suites.py -diff: Changed -diff: rope/refactor/suites.py:HEAD -Old:rope/refactor/suites.py:HEAD - - -diff: Suite.get_children -Old:Suite.get_children - - - - -diff: rope/refactor/usefunction.py -diff: Changed -diff: rope/refactor/usefunction.py:HEAD -Old:rope/refactor/usefunction.py:HEAD - - -diff: _ReturnOrYieldFinder.start_walking -Old:_ReturnOrYieldFinder.start_walking - - - - -diff: rope/refactor/wildcards.py -diff: Changed -diff: rope/refactor/wildcards.py:HEAD -Old:rope/refactor/wildcards.py:HEAD - - - - -diff: ropetest/contrib/autoimport/utilstest.py -diff: Changed -diff: ropetest/contrib/autoimport/utilstest.py:HEAD -Old:ropetest/contrib/autoimport/utilstest.py:HEAD - - - - -diff: ropetest/pycoretest.py -diff: Changed -diff: ropetest/pycoretest.py:HEAD -Old:ropetest/pycoretest.py:HEAD - - - - - -=== PR xxx: ekr-clean-imports -diff master..HEAD (ekr-clean-pyflakes) -unused as e: -diff: rope/refactor/patchedast.py -diff: Changed -diff: _Source.consume (changed) -Old:_Source.consume (changed) - - - - - -Good changes -diff: rope/base/ast.py -diff: Changed -diff: rope/base/ast.py:HEAD -Old:rope/base/ast.py:HEAD - - - - -diff: rope/base/fscommands.py -diff: Changed -diff: rope/base/fscommands.py:HEAD -Old:rope/base/fscommands.py:HEAD - - - - -diff: rope/base/oi/soa.py -diff: Changed -diff: _analyze_node -Old:_analyze_node - - - - -diff: rope/base/oi/type_hinting/evaluate.py -diff: Changed -diff: rope/base/oi/type_hinting/evaluate.py:HEAD -Old:rope/base/oi/type_hinting/evaluate.py:HEAD - - -diff: eval_str2 -Old:eval_str2 - - -diff: ScopeNameFinder._is_defined_in_class_body -Old:ScopeNameFinder._is_defined_in_class_body - - -diff: ScopeNameFinder._is_function_name_in_function_header -Old:ScopeNameFinder._is_function_name_in_function_header - - -diff: ScopeNameFinder.get_primary_and_pyname_at -Old:ScopeNameFinder.get_primary_and_pyname_at - - -diff: ScopeNameFinder.get_enclosing_function -Old:ScopeNameFinder.get_enclosing_function - - - - -diff: rope/base/oi/type_hinting/providers/pep0484_type_comments.py -diff: Changed -diff: rope/base/oi/type_hinting/providers/pep0484_type_comments.py:HEAD -Old:rope/base/oi/type_hinting/providers/pep0484_type_comments.py:HEAD - - - - -diff: rope/base/oi/type_hinting/utils.py -diff: Changed -diff: rope/base/oi/type_hinting/utils.py:HEAD -Old:rope/base/oi/type_hinting/utils.py:HEAD - - - - -diff: rope/base/pycore.py -diff: Changed -diff: rope/base/pycore.py:HEAD -Old:rope/base/pycore.py:HEAD - - - - -diff: rope/base/pyobjectsdef.py -diff: Changed -diff: << imports: pyobjectsdef >> -Old:<< imports: pyobjectsdef >> - - -diff: _ScopeVisitor._For -Old:_ScopeVisitor._For - - - - -diff: rope/refactor/suites.py -diff: Changed -diff: rope/refactor/suites.py:HEAD -Old:rope/refactor/suites.py:HEAD - - - - - -Good and bad changes -diff: ropetest/advanced_oi_test.py -diff: Changed -diff: ropetest/advanced_oi_test.py:HEAD -Old:ropetest/advanced_oi_test.py:HEAD - - -diff: NewStaticOITest.test_validation_problems_for_changing_builtin_types -Old:NewStaticOITest.test_validation_problems_for_changing_builtin_types - - -diff: NewStaticOITest.test_set_comprehension -Old:NewStaticOITest.test_set_comprehension - - - - - -Bad changes -diff: rope/contrib/autoimport/__init__.py -diff: Changed -diff: rope/contrib/autoimport/__init__.py:HEAD -Old:rope/contrib/autoimport/__init__.py:HEAD - - - - -diff: rope/refactor/__init__.py -diff: Changed -diff: rope/refactor/__init__.py:HEAD -Old:rope/refactor/__init__.py:HEAD - - - - -diff: rope/refactor/inline.py -diff: Changed -diff: rope/refactor/inline.py:HEAD -Old:rope/refactor/inline.py:HEAD - - - - -diff: ropetest/builtinstest.py -diff: Changed -diff: BuiltinTypesTest.test_wrong_arguments_to_zip_function -Old:BuiltinTypesTest.test_wrong_arguments_to_zip_function - - - - -diff: ropetest/codeanalyzetest.py -diff: Changed -diff: WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line -Old:WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line - - -diff: ScopeNameFinderTest.test_relative_modules_after_from_statements2 -Old:ScopeNameFinderTest.test_relative_modules_after_from_statements2 - - - - - -Bad unittest changes -diff: ropetest/contrib/autoimport/utilstest.py -diff: Changed -diff: ropetest/contrib/autoimport/utilstest.py:HEAD -Old:ropetest/contrib/autoimport/utilstest.py:HEAD - - -diff: test_get_package_tuple_compiled -Old:test_get_package_tuple_compiled - - - - -diff: ropetest/contrib/codeassisttest.py -diff: Changed -diff: CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref -Old:CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref - - -diff: CodeAssistTest.test_commenting_errors_before_offset -Old:CodeAssistTest.test_commenting_errors_before_offset - - -diff: CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing -Old:CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing - - -diff: CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions -Old:CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions - - -diff: CodeAssistInProjectsTest.setUp -Old:CodeAssistInProjectsTest.setUp - - - - -diff: ropetest/contrib/fixmodnamestest.py -diff: Changed -diff: FixModuleNamesTest.test_handling_nested_modules -Old:FixModuleNamesTest.test_handling_nested_modules - - - - -diff: ropetest/historytest.py -diff: Changed -diff: SavingHistoryTest.test_writing_and_reading_history -Old:SavingHistoryTest.test_writing_and_reading_history - - -diff: SavingHistoryTest.test_writing_and_reading_history2 -Old:SavingHistoryTest.test_writing_and_reading_history2 - - - - -diff: ropetest/objectinfertest.py -diff: Changed -diff: ObjectInferTest.test_empty_tuples -Old:ObjectInferTest.test_empty_tuples - - - - -diff: ropetest/projecttest.py -diff: Changed -diff: ropetest/projecttest.py:HEAD -Old:ropetest/projecttest.py:HEAD - - -diff: ResourceObserverTest.test_revalidating_folders -Old:ResourceObserverTest.test_revalidating_folders - - -diff: ResourceObserverTest.test_changes_and_adding_resources -Old:ResourceObserverTest.test_changes_and_adding_resources - - -diff: ResourceObserverTest.test_validating_get_files_list -Old:ResourceObserverTest.test_validating_get_files_list - - -diff: RopeFolderTest.test_ignored_resources_and_get_files2 -Old:RopeFolderTest.test_ignored_resources_and_get_files2 - - -diff: RopeFolderTest.test_ignoring_syntax_errors -Old:RopeFolderTest.test_ignoring_syntax_errors - - - - -diff: ropetest/pycoretest.py -diff: Changed -diff: PyCoreTest.test_nested_modules -Old:PyCoreTest.test_nested_modules - - -diff: PyCoreTest.test_package -Old:PyCoreTest.test_package - - -diff: PyCoreTest.test_class_variables -Old:PyCoreTest.test_class_variables - - -diff: PyCoreTest.test_class_attributes_set_in_init -Old:PyCoreTest.test_class_attributes_set_in_init - - -diff: PyCoreTest.test_get_string_module_with_extra_spaces -Old:PyCoreTest.test_get_string_module_with_extra_spaces - - -diff: PyCoreTest.test_packaged_module_creation -Old:PyCoreTest.test_packaged_module_creation - - - - -diff: ropetest/pyscopestest.py -diff: Changed -diff: PyCoreScopesTest.test_classes_inside_function_scopes -Old:PyCoreScopesTest.test_classes_inside_function_scopes - - -diff: PyCoreScopesTest.test_getting_defined_names_for_classes -Old:PyCoreScopesTest.test_getting_defined_names_for_classes - - - - -diff: ropetest/refactor/__init__.py -diff: Changed -diff: ropetest/refactor/__init__.py:HEAD -Old:ropetest/refactor/__init__.py:HEAD - - - - -diff: ropetest/refactor/importutilstest.py -diff: Changed -diff: ImportUtilsTest.setUp -Old:ImportUtilsTest.setUp - - - - -diff: ropetest/refactor/movetest.py -diff: Changed -diff: MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable -Old:MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable - - - - -diff: ropetest/refactor/patchedasttest.py -diff: Changed -diff: PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name -Old:PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name - - - - -diff: ropetest/testutils.py -diff: Changed -diff: ropetest/testutils.py:HEAD -Old:ropetest/testutils.py:HEAD - - -diff: remove_recursively -Old:remove_recursively - - - - - -Weird change: diff: setup.py - -COPY: diff master..HEAD (ekr-clean-pyflakes) -unused as e: -diff: rope/refactor/patchedast.py -diff: Changed -diff: _Source.consume (changed) -Old:_Source.consume (changed) -_Source.consume (changed) - - - - -Good changes -diff: rope/base/ast.py -diff: Changed -diff: rope/base/ast.py:HEAD -Old:rope/base/ast.py:HEAD -@clean ast.py -parse -walk -get_child_nodes -call_for_nodes -get_children - - - - -diff: rope/base/fscommands.py -diff: Changed -diff: rope/base/fscommands.py:HEAD -Old:rope/base/fscommands.py:HEAD -@clean fscommands.py -create_fscommands -class FileSystemCommands -FileSystemCommands.create_file -FileSystemCommands.create_folder -FileSystemCommands.move -FileSystemCommands.remove -FileSystemCommands.write -FileSystemCommands.read - -class SubversionCommands -SubversionCommands.__init__ -SubversionCommands.create_file -SubversionCommands.create_folder -SubversionCommands.move -SubversionCommands.remove -SubversionCommands.write -SubversionCommands.read - -class MercurialCommands -MercurialCommands.__init__ -MercurialCommands._import_mercurial -MercurialCommands.create_file -MercurialCommands.create_folder -MercurialCommands.move -MercurialCommands.remove -MercurialCommands.write -MercurialCommands.read - -class GITCommands -GITCommands.__init__ -GITCommands.create_file -GITCommands.create_folder -GITCommands.move -GITCommands.remove -GITCommands.write -GITCommands.read -GITCommands._do -GITCommands._in_dir - -class DarcsCommands -DarcsCommands.__init__ -DarcsCommands.create_file -DarcsCommands.create_folder -DarcsCommands.move -DarcsCommands.remove -DarcsCommands.read -DarcsCommands.write -DarcsCommands._do - -_execute -unicode_to_file_data -file_data_to_unicode -_decode_data -read_str_coding -_find_coding - - - - -diff: rope/base/oi/soa.py -diff: Changed -diff: _analyze_node -Old:_analyze_node -_analyze_node - - - -diff: rope/base/oi/type_hinting/evaluate.py -diff: Changed -diff: rope/base/oi/type_hinting/evaluate.py:HEAD -Old:rope/base/oi/type_hinting/evaluate.py:HEAD -@clean evaluate.py -eval_location -eval_location2 -eval_node -eval_node2 -eval_str -eval_str2 -class ScopeNameFinder -ScopeNameFinder.__init__ -ScopeNameFinder._is_defined_in_class_body -ScopeNameFinder._is_function_name_in_function_header -ScopeNameFinder.get_pyname_at -ScopeNameFinder.get_primary_and_pyname_at -ScopeNameFinder.get_enclosing_function -ScopeNameFinder._find_module - -class StatementEvaluator -StatementEvaluator.__init__ -StatementEvaluator._Name -StatementEvaluator._Attribute -StatementEvaluator._Call -StatementEvaluator._Str -StatementEvaluator._Num -StatementEvaluator._Constant -StatementEvaluator._get_builtin_name -StatementEvaluator._BinOp -StatementEvaluator._BoolOp -StatementEvaluator._Repr -StatementEvaluator._UnaryOp -StatementEvaluator._Compare -StatementEvaluator._Dict -StatementEvaluator._List -StatementEvaluator._ListComp -StatementEvaluator._GeneratorExp -StatementEvaluator._what_does_comprehension_hold -StatementEvaluator._make_comprehension_scope -StatementEvaluator._Tuple -StatementEvaluator._get_object_for_node -StatementEvaluator._get_primary_and_object_for_node -StatementEvaluator._Subscript -StatementEvaluator._Slice -StatementEvaluator._call_function -StatementEvaluator._Lambda - -_get_evaluated_names - - -diff: eval_str2 -Old:eval_str2 - - -diff: ScopeNameFinder._is_defined_in_class_body -Old:ScopeNameFinder._is_defined_in_class_body - - -diff: ScopeNameFinder._is_function_name_in_function_header -Old:ScopeNameFinder._is_function_name_in_function_header - - -diff: ScopeNameFinder.get_primary_and_pyname_at -Old:ScopeNameFinder.get_primary_and_pyname_at - - -diff: ScopeNameFinder.get_enclosing_function -Old:ScopeNameFinder.get_enclosing_function - - - - -diff: rope/base/oi/type_hinting/providers/pep0484_type_comments.py -diff: Changed -diff: rope/base/oi/type_hinting/providers/pep0484_type_comments.py:HEAD -Old:rope/base/oi/type_hinting/providers/pep0484_type_comments.py:HEAD -@clean pep0484_type_comments.py -class AssignmentProvider -AssignmentProvider.__init__ -AssignmentProvider.PEP0484_TYPE_COMMENT_PATTERNS = (re.compile(r"type:/s*([^/n]+)"),) -AssignmentProvider.__call__ -AssignmentProvider._search_type_in_type_comment - - - - - -diff: rope/base/oi/type_hinting/utils.py -diff: Changed -diff: rope/base/oi/type_hinting/utils.py:HEAD -Old:rope/base/oi/type_hinting/utils.py:HEAD -@clean libutils.py -path_to_resource -path_relative_to_project_root -relative -report_change -analyze_module -analyze_modules -get_string_module -get_string_scope -is_python_file -modname - - - - -diff: rope/base/pycore.py -diff: Changed -diff: rope/base/pycore.py:HEAD -Old:rope/base/pycore.py:HEAD -@clean pycore.py -class PyCore -PyCore.__init__ -PyCore._init_python_files -PyCore._init_resource_observer -PyCore._init_automatic_soa -PyCore.automatic_soa -PyCore._file_changed_for_soa -PyCore.is_python_file -PyCore.get_module -PyCore._builtin_submodules -PyCore.builtin_module -PyCore.get_relative_module -PyCore.get_string_module -PyCore.get_string_scope -PyCore._invalidate_resource_cache -PyCore.get_python_path_folders -PyCore.find_module -PyCore.find_relative_module -PyCore.get_source_folders -PyCore.resource_to_pyobject (unique) -PyCore.get_python_files -PyCore._is_package -PyCore._find_source_folders -PyCore.run_module -PyCore.analyze_module -PyCore.get_classes -PyCore.__str__ -PyCore.modname -PyCore.extension_modules - -class _ModuleCache -_ModuleCache.__init__ -_ModuleCache._invalidate_resource -_ModuleCache.get_pymodule -_ModuleCache.forget_all_data -_ModuleCache.__str__ - -class _ExtensionCache -_ExtensionCache.__init__ -_ExtensionCache.get_pymodule - -perform_soa_on_changed_scopes -class _TextChangeDetector -_TextChangeDetector.__init__ -_TextChangeDetector._set_diffs -_TextChangeDetector.is_changed -_TextChangeDetector.consume_changes -_TextChangeDetector._get_changed - - - - - -diff: rope/base/pyobjectsdef.py -diff: Changed -diff: << imports: pyobjectsdef >> -Old:<< imports: pyobjectsdef >> -<< imports: pyobjectsdef >> - -diff: _ScopeVisitor._For -Old:_ScopeVisitor._For -_ScopeVisitor._For - - - -diff: rope/refactor/suites.py -diff: Changed -diff: rope/refactor/suites.py:HEAD -Old:rope/refactor/suites.py:HEAD -@clean suites.py -find_visible -find_visible_for_suite -valid - -ast_suite_tree -class Suite -Suite.__init__ -Suite.get_start -Suite.get_children -Suite.local_start -Suite.local_end -Suite.find_suite -Suite._get_level - -class _SuiteWalker -_SuiteWalker.__init__ -_SuiteWalker._If -_SuiteWalker._For -_SuiteWalker._While -_SuiteWalker._With -_SuiteWalker._AsyncWith -_SuiteWalker._Match -_SuiteWalker._TryFinally -_SuiteWalker._Try -_SuiteWalker._TryExcept -_SuiteWalker._add_if_like_node -_SuiteWalker._FunctionDef -_SuiteWalker._AsyncFunctionDef -_SuiteWalker._ClassDef - - - - - - -Good and bad changes -diff: ropetest/advanced_oi_test.py -diff: Changed -diff: ropetest/advanced_oi_test.py:HEAD -Old:ropetest/advanced_oi_test.py:HEAD -@clean advanced_oi_test.py -class DynamicOITest -DynamicOITest.setUp -DynamicOITest.tearDown -DynamicOITest.test_simple_dti -DynamicOITest.test_module_dti -DynamicOITest.test_class_from_another_module_dti -DynamicOITest.test_class_dti -DynamicOITest.test_instance_dti -DynamicOITest.test_method_dti -DynamicOITest.test_function_argument_dti -DynamicOITest.test_classes_with_the_same_name -DynamicOITest.test_nested_classes -DynamicOITest.test_function_argument_dti2 -DynamicOITest.test_dti_and_concluded_data_invalidation -DynamicOITest.test_list_objects_and_dynamicoi -DynamicOITest.test_for_loops_and_dynamicoi -DynamicOITest.test_dict_objects_and_dynamicoi -DynamicOITest.test_dict_keys_and_dynamicoi -DynamicOITest.test_dict_keys_and_dynamicoi2 -DynamicOITest.test_strs_and_dynamicoi -DynamicOITest.test_textual_transformations -DynamicOITest.test_arguments_with_keywords -DynamicOITest.test_a_function_with_different_returns -DynamicOITest.test_a_function_with_different_returns2 -DynamicOITest.test_ignoring_star_args -DynamicOITest.test_ignoring_double_star_args -DynamicOITest.test_invalidating_data_after_changing -DynamicOITest.test_invalidating_data_after_moving - -class NewStaticOITest -NewStaticOITest.setUp -NewStaticOITest.tearDown -NewStaticOITest.test_static_oi_for_simple_function_calls -NewStaticOITest.test_static_oi_not_failing_when_callin_callables -NewStaticOITest.test_static_oi_for_nested_calls -NewStaticOITest.test_static_oi_class_methods -NewStaticOITest.test_static_oi_preventing_soi_maximum_recursion_exceptions -NewStaticOITest.test_static_oi_for_infer_return_typs_from_funcs_based_on_params -NewStaticOITest.test_a_function_with_different_returns -NewStaticOITest.test_not_reporting_out_of_date_information -NewStaticOITest.test_invalidating_concluded_data_in_a_function -NewStaticOITest.test_handling_generator_functions_for_strs -NewStaticOITest.xxx_test_handl_generator_functions_when_unknown_type_is_yielded -NewStaticOITest.test_static_oi_for_lists_depending_on_append_function -NewStaticOITest.test_static_oi_for_lists_per_object_for_get_item -NewStaticOITest.test_static_oi_for_lists_per_object_for_fields -NewStaticOITest.test_static_oi_for_lists_per_object_for_set_item -NewStaticOITest.test_static_oi_for_lists_per_object_for_extending_lists -NewStaticOITest.test_static_oi_for_lists_per_object_for_iters -NewStaticOITest.test_static_oi_for_dicts_depending_on_append_function -NewStaticOITest.test_static_oi_for_dicts_depending_on_for_loops -NewStaticOITest.test_static_oi_for_dicts_depending_on_update -NewStaticOITest.test_static_oi_for_dicts_depending_on_update_on_seqs -NewStaticOITest.test_static_oi_for_sets_per_object_for_set_item -NewStaticOITest.test_properties_and_calling_get_property -NewStaticOITest.test_soi_on_constructors -NewStaticOITest.test_soi_on_literal_assignment -NewStaticOITest.test_soi_on_typed_assignment -NewStaticOITest.test_not_saving_unknown_function_returns -NewStaticOITest.test_using_the_best_callinfo -NewStaticOITest.test_call_function_and_parameters -NewStaticOITest.test_report_change_in_libutils -NewStaticOITest.test_report_libutils_and_analyze_all_modules -NewStaticOITest.test_validation_problems_for_objectdb_retrievals -NewStaticOITest.test_validation_problems_for_changing_builtin_types -NewStaticOITest.test_always_returning_containing_class_for_selfs -NewStaticOITest.test_following_function_calls_when_asked_to -NewStaticOITest.test_set_comprehension - - - -diff: NewStaticOITest.test_validation_problems_for_changing_builtin_types -Old:NewStaticOITest.test_validation_problems_for_changing_builtin_types - - -diff: NewStaticOITest.test_set_comprehension -Old:NewStaticOITest.test_set_comprehension - - - - - -Bad changes -diff: rope/contrib/autoimport/__init__.py -diff: Changed -diff: rope/contrib/autoimport/__init__.py:HEAD -Old:rope/contrib/autoimport/__init__.py:HEAD -@clean __init__.py - - - -diff: rope/refactor/__init__.py -diff: Changed -diff: rope/refactor/__init__.py:HEAD -Old:rope/refactor/__init__.py:HEAD - - - - -diff: rope/refactor/inline.py -diff: Changed -diff: rope/refactor/inline.py:HEAD -Old:rope/refactor/inline.py:HEAD -@clean inline.py -unique_prefix -create_inline -class _Inliner -_Inliner.__init__ -_Inliner.get_changes -_Inliner.get_kind - -class InlineMethod -InlineMethod.__init__ -InlineMethod._init_imports -InlineMethod._get_scope_range -InlineMethod.get_changes -InlineMethod._get_removed_range -InlineMethod._defining_file_changes -InlineMethod._get_method_replacement -InlineMethod._is_the_last_method_of_a_class -InlineMethod.get_kind - -class InlineVariable -InlineVariable.__init__ -InlineVariable._check_exceptional_conditions -InlineVariable.get_changes -InlineVariable._change_main_module -InlineVariable._init_imports -InlineVariable._change_module -InlineVariable.check_aim - -InlineVariable.get_kind - -class InlineParameter -InlineParameter.__init__ -InlineParameter._function_location -InlineParameter.get_changes -InlineParameter.get_kind - -_join_lines -class _DefinitionGenerator -_DefinitionGenerator.__init__ -_DefinitionGenerator._get_definition_info -_DefinitionGenerator._get_definition_params -_DefinitionGenerator.get_function_name -_DefinitionGenerator.get_definition -_DefinitionGenerator._calculate_header -_DefinitionGenerator._calculate_definition -_DefinitionGenerator._replace_returns_with -_DefinitionGenerator._check_nothing_after_return -_DefinitionGenerator._get_return_pattern -_DefinitionGenerator.named_pattern - - -class _InlineFunctionCallsForModuleHandle -_InlineFunctionCallsForModuleHandle.__init__ -_InlineFunctionCallsForModuleHandle.occurred_inside_skip -_InlineFunctionCallsForModuleHandle.occurred_outside_skip -_InlineFunctionCallsForModuleHandle._find_end_parens -_InlineFunctionCallsForModuleHandle.pymodule -_InlineFunctionCallsForModuleHandle.source -_InlineFunctionCallsForModuleHandle.lines - -_inline_variable -_getvardef -_assigned_lineno -_add_imports -_get_pyname -_remove_from - - - - -diff: ropetest/builtinstest.py -diff: Changed -diff: BuiltinTypesTest.test_wrong_arguments_to_zip_function -Old:BuiltinTypesTest.test_wrong_arguments_to_zip_function -BuiltinTypesTest.test_wrong_arguments_to_zip_function - - - -diff: ropetest/codeanalyzetest.py -diff: Changed -diff: WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line -Old:WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line -WordRangeFinderTest.test_getting_primary_and_strings_at_the_end_of_line - -diff: ScopeNameFinderTest.test_relative_modules_after_from_statements2 -Old:ScopeNameFinderTest.test_relative_modules_after_from_statements2 -ScopeNameFinderTest.test_relative_modules_after_from_statements2 - - - - -Bad unittest changes -diff: ropetest/contrib/autoimport/utilstest.py -diff: Changed -diff: ropetest/contrib/autoimport/utilstest.py:HEAD -Old:ropetest/contrib/autoimport/utilstest.py:HEAD -@clean utilstest.py -test_get_package_source -test_get_package_source_not_project -test_get_package_source_pytest -test_get_package_source_typing -test_get_modname_project_no_add -test_get_modname_single_file -test_get_modname_folder -test_get_package_tuple_sample -test_get_package_tuple_typing -test_get_package_tuple_compiled - - -diff: test_get_package_tuple_compiled -Old:test_get_package_tuple_compiled - - - - -diff: ropetest/contrib/codeassisttest.py -diff: Changed -diff: CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref -Old:CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref -CodeAssistTest.test_proposals_sorter_and_missing_type_in_typepref - -diff: CodeAssistTest.test_commenting_errors_before_offset -Old:CodeAssistTest.test_commenting_errors_before_offset -CodeAssistTest.test_commenting_errors_before_offset - -diff: CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing -Old:CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing -CodeAssistTest.test_and_normal_complete_blocks_and_single_fixing - -diff: CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions -Old:CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions -CodeAssistTest.test_proposing_function_keywords_when_calling_for_non_functions - -diff: CodeAssistInProjectsTest.setUp -Old:CodeAssistInProjectsTest.setUp -CodeAssistInProjectsTest.setUp - - - -diff: ropetest/contrib/fixmodnamestest.py -diff: Changed -diff: FixModuleNamesTest.test_handling_nested_modules -Old:FixModuleNamesTest.test_handling_nested_modules -FixModuleNamesTest.test_handling_nested_modules - - - -diff: ropetest/historytest.py -diff: Changed -diff: SavingHistoryTest.test_writing_and_reading_history -Old:SavingHistoryTest.test_writing_and_reading_history -SavingHistoryTest.test_writing_and_reading_history - -diff: SavingHistoryTest.test_writing_and_reading_history2 -Old:SavingHistoryTest.test_writing_and_reading_history2 -SavingHistoryTest.test_writing_and_reading_history2 - - - -diff: ropetest/objectinfertest.py -diff: Changed -diff: ObjectInferTest.test_empty_tuples -Old:ObjectInferTest.test_empty_tuples -ObjectInferTest.test_empty_tuples - - - -diff: ropetest/projecttest.py -diff: Changed -diff: ropetest/projecttest.py:HEAD -Old:ropetest/projecttest.py:HEAD -@clean projecttest.py -class ProjectTest -ProjectTest.setUp -ProjectTest._make_sample_project -ProjectTest.tearDown -ProjectTest.test_project_creation -ProjectTest.test_getting_project_file -ProjectTest.test_project_file_reading -ProjectTest.test_getting_not_existing_project_file -ProjectTest.test_writing_in_project_files -ProjectTest.test_creating_files -ProjectTest.test_creating_files_that_already_exist -ProjectTest.test_making_root_folder_if_it_does_not_exist -ProjectTest.test_failure_when_project_root_exists_and_is_a_file -ProjectTest.test_creating_folders -ProjectTest.test_making_folder_that_already_exists -ProjectTest.test_failing_if_creating_folder_while_file_already_exists -ProjectTest.test_creating_file_inside_folder -ProjectTest.test_failing_when_creating_file_inside_non_existent_folder -ProjectTest.test_nested_directories -ProjectTest.test_removing_files -ProjectTest.test_removing_files_invalidating_in_project_resource_pool -ProjectTest.test_removing_directories -ProjectTest.test_removing_non_existent_files -ProjectTest.test_removing_nested_files -ProjectTest.test_file_get_name -ProjectTest.test_folder_get_name -ProjectTest.test_file_get_path -ProjectTest.test_folder_get_path -ProjectTest.test_is_folder -ProjectTest.testget_children -ProjectTest.test_nonempty_get_children -ProjectTest.test_nonempty_get_children2 -ProjectTest.test_does_not_fail_for_permission_denied -ProjectTest.test_getting_files -ProjectTest.test_getting_folders -ProjectTest.test_nested_folder_get_files -ProjectTest.test_nested_folder_get_folders -ProjectTest.test_root_folder -ProjectTest.test_get_all_files -ProjectTest.test_get_all_files_after_changing -ProjectTest.test_multifile_get_all_files -ProjectTest.test_ignoring_dot_pyc_files_in_get_files -ProjectTest.test_folder_creating_files -ProjectTest.test_folder_creating_nested_files -ProjectTest.test_folder_creating_files2 -ProjectTest.test_folder_creating_nested_files2 -ProjectTest.test_folder_get_child -ProjectTest.test_folder_get_child_nested -ProjectTest.test_project_root_is_root_folder -ProjectTest.test_moving_files -ProjectTest.test_moving_folders -ProjectTest.test_moving_destination_folders -ProjectTest.test_moving_files_and_resource_objects -ProjectTest.test_file_encoding_reading -ProjectTest.test_file_encoding_writing -ProjectTest.test_using_utf8_when_writing_in_case_of_errors -ProjectTest.test_encoding_declaration_in_the_second_line -ProjectTest.test_not_an_encoding_declaration -ProjectTest.test_read_bytes -ProjectTest.test_file_with_unix_line_ending -ProjectTest.test_file_with_dos_line_ending -ProjectTest.test_file_with_mac_line_ending -ProjectTest.test_file_binary -ProjectTest.xxx_test_using_utf16 -ProjectTest.xxx_test_file_encoding_reading_for_notepad_styles -ProjectTest.test_using_project_get_file -ProjectTest.test_using_file_create -ProjectTest.test_using_folder_create -ProjectTest.test_exception_when_creating_twice -ProjectTest.test_exception_when_parent_does_not_exist -ProjectTest.test_simple_path_to_resource -ProjectTest.test_ignoring_symlinks_inside_project -ProjectTest.test_getting_empty_source_folders -ProjectTest.test_root_source_folder -ProjectTest.test_root_source_folder2 -ProjectTest.test_src_source_folder -ProjectTest.test_packages -ProjectTest.test_multi_source_folders -ProjectTest.test_multi_source_folders2 - -class ResourceObserverTest -ResourceObserverTest.setUp -ResourceObserverTest.tearDown -ResourceObserverTest.test_resource_change_observer -ResourceObserverTest.test_resource_change_observer_after_removal -ResourceObserverTest.test_resource_change_observer2 -ResourceObserverTest.test_resource_change_observer_for_folders -ResourceObserverTest.test_resource_change_observer_after_moving -ResourceObserverTest.test_revalidating_files -ResourceObserverTest.test_revalidating_files_and_no_changes2 -ResourceObserverTest.test_revalidating_folders -ResourceObserverTest.test_removing_and_adding_resources_to_filtered_observer -ResourceObserverTest.test_validation_and_changing_files -ResourceObserverTest.test_validation_and_changing_files2 -ResourceObserverTest.test_not_reporting_multiple_changes_to_folders -ResourceObserverTest._write_file -ResourceObserverTest.test_moving_and_being_interested_about_a_folder_and_a_child -ResourceObserverTest.test_contains_for_folders -ResourceObserverTest.test_validating_when_created -ResourceObserverTest.test_validating_twice_when_created -ResourceObserverTest.test_changes_and_adding_resources -ResourceObserverTest.test_validating_get_files_list -ResourceObserverTest.test_clear_observered_resources_for_filtered_observers - -class _MockChangeIndicator -_MockChangeIndicator.__init__ -_MockChangeIndicator.set_indicator -_MockChangeIndicator.get_indicator - -class _SampleObserver -_SampleObserver.__init__ -_SampleObserver.resource_changed -_SampleObserver.resource_moved -_SampleObserver.resource_created -_SampleObserver.resource_removed - -class OutOfProjectTest -OutOfProjectTest.setUp -OutOfProjectTest.tearDown -OutOfProjectTest.test_simple_out_of_project_file -OutOfProjectTest.test_simple_out_of_project_folder -OutOfProjectTest.test_using_absolute_path -OutOfProjectTest.test_folder_get_child -OutOfProjectTest.test_out_of_project_files_and_path_to_resource - -class _MockFSCommands -_MockFSCommands.__init__ -_MockFSCommands.create_file -_MockFSCommands.create_folder -_MockFSCommands.move -_MockFSCommands.remove -_MockFSCommands.read - -class _DeprecatedFSCommands -_DeprecatedFSCommands.__init__ -_DeprecatedFSCommands.create_file -_DeprecatedFSCommands.create_folder -_DeprecatedFSCommands.move -_DeprecatedFSCommands.remove - -class RopeFolderTest -RopeFolderTest.setUp -RopeFolderTest.tearDown -RopeFolderTest.test_none_project_rope_folder -RopeFolderTest.test_getting_project_rope_folder -RopeFolderTest.test_setting_ignored_resources -RopeFolderTest.test_ignored_folders -RopeFolderTest.test_ignored_resources_and_get_files -RopeFolderTest.test_ignored_resources_and_get_files2 -RopeFolderTest.test_setting_ignored_resources_patterns -RopeFolderTest.test_star_should_not_include_slashes -RopeFolderTest.test_normal_fscommands -RopeFolderTest.test_fscommands_and_ignored_resources -RopeFolderTest.test_deprecated_fscommands -RopeFolderTest.test_ignored_resources_and_prefixes -RopeFolderTest.test_loading_config_dot_py -RopeFolderTest.test_loading_pyproject -RopeFolderTest.test_loading_pyproject_empty_file -RopeFolderTest.test_loading_pyproject_no_tool_section -RopeFolderTest.test_loading_pyproject_no_tool_rope_section -RopeFolderTest.test_ignoring_syntax_errors -RopeFolderTest.test_compressed_history -RopeFolderTest.test_compressed_objectdb -RopeFolderTest.test_nested_dot_ropeproject_folder - - - -diff: ResourceObserverTest.test_revalidating_folders -Old:ResourceObserverTest.test_revalidating_folders - - -diff: ResourceObserverTest.test_changes_and_adding_resources -Old:ResourceObserverTest.test_changes_and_adding_resources - - -diff: ResourceObserverTest.test_validating_get_files_list -Old:ResourceObserverTest.test_validating_get_files_list - - -diff: RopeFolderTest.test_ignored_resources_and_get_files2 -Old:RopeFolderTest.test_ignored_resources_and_get_files2 - - -diff: RopeFolderTest.test_ignoring_syntax_errors -Old:RopeFolderTest.test_ignoring_syntax_errors - - - - -diff: ropetest/pycoretest.py -diff: Changed -diff: PyCoreTest.test_nested_modules -Old:PyCoreTest.test_nested_modules -PyCoreTest.test_nested_modules - -diff: PyCoreTest.test_package -Old:PyCoreTest.test_package -PyCoreTest.test_package - -diff: PyCoreTest.test_class_variables -Old:PyCoreTest.test_class_variables -PyCoreTest.test_class_variables - -diff: PyCoreTest.test_class_attributes_set_in_init -Old:PyCoreTest.test_class_attributes_set_in_init -PyCoreTest.test_class_attributes_set_in_init - -diff: PyCoreTest.test_get_string_module_with_extra_spaces -Old:PyCoreTest.test_get_string_module_with_extra_spaces -PyCoreTest.test_get_string_module_with_extra_spaces - -diff: PyCoreTest.test_packaged_module_creation -Old:PyCoreTest.test_packaged_module_creation -PyCoreTest.test_packaged_module_creation - - - -diff: ropetest/pyscopestest.py -diff: Changed -diff: PyCoreScopesTest.test_classes_inside_function_scopes -Old:PyCoreScopesTest.test_classes_inside_function_scopes -PyCoreScopesTest.test_classes_inside_function_scopes - -diff: PyCoreScopesTest.test_getting_defined_names_for_classes -Old:PyCoreScopesTest.test_getting_defined_names_for_classes -PyCoreScopesTest.test_getting_defined_names_for_classes - - - -diff: ropetest/refactor/__init__.py -diff: Changed -diff: ropetest/refactor/__init__.py:HEAD -Old:ropetest/refactor/__init__.py:HEAD - - - - -diff: ropetest/refactor/importutilstest.py -diff: Changed -diff: ImportUtilsTest.setUp -Old:ImportUtilsTest.setUp -ImportUtilsTest.setUp - - - -diff: ropetest/refactor/movetest.py -diff: Changed -diff: MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable -Old:MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable -MoveRefactoringTest.test_raising_an_exception_for_moving_non_global_variable - - - -diff: ropetest/refactor/patchedasttest.py -diff: Changed -diff: PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name -Old:PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name -PatchedASTTest.test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name - - - -diff: ropetest/testutils.py -diff: Changed -diff: ropetest/testutils.py:HEAD -Old:ropetest/testutils.py:HEAD -@clean testutils.py -sample_project -create_module = generate.create_module -remove_project -remove_recursively -_remove_recursively -parse_version -only_for -only_for_versions_lower -only_for_versions_higher -skipNotPOSIX -time_limit - - -diff: remove_recursively -Old:remove_recursively - - - - - -Weird change: diff: setup.py - -Found 6:ast_arg_type (same as ast.arg) - - - - - - - - -Found 23:pycompat - - - - - - - - - - - - - - - - - - - - - - - - - -'''Recursively import all python files in a directory and clean the result.''' -@tabwidth -4 # For a better match. -g.cls() -dir_ = r'C:\Repos\ekr-rope\rope\base\ast.py' -c.recursiveImport( - add_context=True, # Override setting only if True/False - add_file_context=False, # Override setting only if True/False - dir_=dir_, - kind = '@clean', # '@auto', '@clean', '@nosent','@file', - add_path = True, - recursive = True, - safe_at_file = False, - theTypes = ['.py'], - # ['.ts', '.js', '.json'] # ['.html', '.js', '.json', '.py', '.rs', '.svg', '.ts', '.tsx'] - verbose = False, -) -if 1: - last = c.lastTopLevel() - # for p in last.self_and_subtree(): - # p.expand() - # c.expandAllSubheads() - c.redraw(last) -print('Done') -@path C:/Repos/ekr-rope/docs/ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - -# -- Project information ----------------------------------------------------- -import rope - -project = "rope" -copyright = "2022, Rope Contributors" -author = "Rope Contributors" - -# The full version, including alpha/beta/rc tags -version = release = rope.VERSION - - -# -- General configuration --------------------------------------------------- - -pygments_style = "sphinx" -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.autosectionlabel", - "sphinx.ext.autosummary", - "sphinx_autodoc_typehints", - "pytoolconfig.documentation", - "sphinx_rtd_theme", -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = "sphinx_rtd_theme" - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - -# Make sure the target is unique -autosectionlabel_prefix_document = True -@language python -@tabwidth -4 - -def _new_list(self, args): - return _create_builtin(args, get_list) - - -@abstractmethod -def is_stopped(self) -> bool: - pass - - -@abstractmethod -def get_jobsets(self) -> Sequence[BaseJobSet]: - pass - - -def create_jobset( - self, name: str = "JobSet", count: Optional[int] = None -) -> BaseJobSet: - pass - - -def _inform_observers(self) -> None: - pass - - - -class TaskHandle(BaseTaskHandle): - @others - -def __init__(self, name="Task", interrupts=True): - """Construct a TaskHandle - - If `interrupts` is `False` the task won't be interrupted by - calling `TaskHandle.stop()`. - - """ - self.name = name - self.interrupts = interrupts - self.stopped = False - self.job_sets = [] - self.observers = [] - - -def stop(self): - """Interrupts the refactoring""" - if self.interrupts: - self.stopped = True - self._inform_observers() - - -def current_jobset(self): - """Return the current `JobSet`""" - if self.job_sets: - return self.job_sets[-1] - - -def add_observer(self, observer): - """Register an observer for this task handle - - The observer is notified whenever the task is stopped or - a job gets finished. - - """ - self.observers.append(observer) - - -def is_stopped(self): - return self.stopped - - -def _list_add(self, context): - if self.holding is not None: - return - holding = context.get_argument("value") - if holding is not None and holding != pyobjects.get_unknown(): - context.save_per_name(holding) - - -def get_jobsets(self): - return self.job_sets - - -def create_jobset(self, name="JobSet", count=None): - result = JobSet(self, name=name, count=count) - self.job_sets.append(result) - self._inform_observers() - return result - - -def _inform_observers(self): - for observer in list(self.observers): - observer() - - - -class JobSet(BaseJobSet): - @others - -def __init__(self, handle, name, count): - self.handle = handle - self.name = name - self.count = count - self.done = 0 - self.job_name = None - - -def started_job(self, name): - self.check_status() - self.job_name = name - self.handle._inform_observers() - - -def finished_job(self): - self.check_status() - self.done += 1 - self.handle._inform_observers() - self.job_name = None - - -def check_status(self): - if self.handle.is_stopped(): - raise exceptions.InterruptedTaskError() - - -@utils.deprecated("Just use JobSet.job_name attribute/property instead") -def get_active_job_name(self): - return self.job_name - - -def get_percent_done(self): - if self.count is not None and self.count > 0: - percent = self.done * 100 // self.count - return min(percent, 100) - - -def _self_set(self, context): - if self.holding is not None: - return - iterable = context.get_pyname("iterable") - holding = _infer_sequence_for_pyname(iterable) - if holding is not None and holding != pyobjects.get_unknown(): - context.save_per_name(holding) - - -@utils.deprecated("Just use JobSet.name attribute/property instead") -def get_name(self): - return self.name - - -def increment(self): - self.count += 1 - - - -class NullTaskHandle(BaseTaskHandle): - @others - -def __init__(self): - pass - - -def is_stopped(self): - return False - - -def stop(self): - pass - - -def create_jobset(self, *args, **kwds): - return NullJobSet() - - -def get_jobsets(self): - return [] - - -def add_observer(self, observer): - pass - - -def current_jobset(self) -> None: - """Return the current `JobSet`""" - return None - - - -def _list_get(self, context): - if self.holding is not None: - args = context.get_arguments(["self", "key"]) - if ( - len(args) > 1 - and args[1] is not None - and args[1].get_type() == builtins["slice"].get_object() - ): - return get_list(self.holding) - return self.holding - return context.get_per_name() - - -class NullJobSet(BaseJobSet): - @others - -def __init__(self, *args): - pass - - -def started_job(self, name): - pass - - -def finished_job(self): - pass - - -def check_status(self): - pass - - -@utils.deprecated("Just use JobSet.job_name attribute/property instead") -def get_active_job_name(self): - pass - - -def get_percent_done(self): - pass - - -@utils.deprecated("Just use JobSet.name attribute/property instead") -def get_name(self): - pass - - -def increment(self): - pass - -@path C:/Repos/ekr-rope/rope/base/ -import bisect -import keyword - -import rope.base.simplify - -MINIMAL_LEN_FOR_AS = 5 - - -@others -@language python -@tabwidth -4 - -def _iterator_get(self, context): - return get_iterator(self._list_get(context)) - - -def get_name_at(resource, offset): - source_code = resource.read() - word_finder = Worder(source_code) - return word_finder.get_word_at(offset) - - - -class Worder: - """A class for finding boundaries of words and expressions - - Note that in these methods, offset should be the index of the - character not the index of the character after it. - - Some of the methods here doesn't exactly do what their name might lead you - to think they do, these probably should be fixed. Refer to - ropetest/codeanalyzetest.py for what these methods returns. Note that - codeanalyzetest.py documents the current behavior, rather than what they - should've been. - """ - - @others - -def __init__(self, code, handle_ignores=False): - simplified = rope.base.simplify.real_code(code) - self.code_finder = _RealFinder(simplified, code) - self.handle_ignores = handle_ignores - self.code = code - - -def _init_ignores(self): - ignores = rope.base.simplify.ignored_regions(self.code) - self.dumb_finder = _RealFinder(self.code, self.code) - self.starts = [ignored[0] for ignored in ignores] - self.ends = [ignored[1] for ignored in ignores] - - -def _context_call(self, name, offset): - if self.handle_ignores: - if not hasattr(self, "starts"): - self._init_ignores() - start = bisect.bisect(self.starts, offset) - if start > 0 and offset < self.ends[start - 1]: - return getattr(self.dumb_finder, name)(offset) - return getattr(self.code_finder, name)(offset) - - -def get_primary_at(self, offset): - return self._context_call("get_primary_at", offset) - - -def get_word_at(self, offset): - return self._context_call("get_word_at", offset) - - -def get_primary_range(self, offset): - return self._context_call("get_primary_range", offset) - - -def get_splitted_primary_before(self, offset): - return self._context_call("get_splitted_primary_before", offset) - - -def get_word_range(self, offset): - return self._context_call("get_word_range", offset) - - -def _self_get(self, context): - return get_list(self._list_get(context)) - - - -def is_function_keyword_parameter(self, offset): - return self.code_finder.is_function_keyword_parameter(offset) - - -def is_a_class_or_function_name_in_header(self, offset): - return self.code_finder.is_a_class_or_function_name_in_header(offset) - - -def is_from_statement_module(self, offset): - return self.code_finder.is_from_statement_module(offset) - - -def is_from_aliased(self, offset): - return self.code_finder.is_from_aliased(offset) - - -def is_import_statement_aliased_module(self, offset): - return self.code_finder.is_import_statement_aliased_module(offset) - - -def find_parens_start_from_inside(self, offset): - return self.code_finder.find_parens_start_from_inside(offset) - - -def is_a_name_after_from_import(self, offset): - return self.code_finder.is_a_name_after_from_import(offset) - - -def is_from_statement(self, offset): - return self.code_finder.is_from_statement(offset) - - -def get_from_aliased(self, offset): - return self.code_finder.get_from_aliased(offset) - - -def is_import_statement(self, offset): - return self.code_finder.is_import_statement(offset) - - -get_list = _create_builtin_getter(List) -get_list_type = _create_builtin_type_getter(List) - - - -def is_assigned_here(self, offset): - return self.code_finder.is_assigned_here(offset) - - -def is_a_function_being_called(self, offset): - return self.code_finder.is_a_function_being_called(offset) - - -def get_word_parens_range(self, offset): - return self.code_finder.get_word_parens_range(offset) - - -def is_name_assigned_in_class_body(self, offset): - return self.code_finder.is_name_assigned_in_class_body(offset) - - -def is_on_function_call_keyword(self, offset): - return self.code_finder.is_on_function_call_keyword(offset) - - -def _find_parens_start(self, offset): - return self.code_finder._find_parens_start(offset) - - -def get_parameters(self, first, last): - return self.code_finder.get_parameters(first, last) - - -def get_from_module(self, offset): - return self.code_finder.get_from_module(offset) - - -def is_assigned_in_a_tuple_assignment(self, offset): - return self.code_finder.is_assigned_in_a_tuple_assignment(offset) - - -def get_assignment_type(self, offset): - return self.code_finder.get_assignment_type(offset) - - -class Dict(BuiltinClass): - @others - -def get_function_and_args_in_header(self, offset): - return self.code_finder.get_function_and_args_in_header(offset) - - -def get_lambda_and_args(self, offset): - return self.code_finder.get_lambda_and_args(offset) - - -def find_function_offset(self, offset): - return self.code_finder.find_function_offset(offset) - - - -class _RealFinder: - @others - -def __init__(self, code, raw): - self.code = code - self.raw = raw - - -def _find_word_start(self, offset): - current_offset = offset - while current_offset >= 0 and self._is_id_char(current_offset): - current_offset -= 1 - return current_offset + 1 - - -def _find_word_end(self, offset): - while offset + 1 < len(self.code) and self._is_id_char(offset + 1): - offset += 1 - return offset - - -def _find_last_non_space_char(self, offset): - while offset >= 0 and self.code[offset].isspace(): - if self.code[offset] == "\n": - return offset - offset -= 1 - return max(-1, offset) - - -def get_word_at(self, offset): - offset = self._get_fixed_offset(offset) - return self.raw[self._find_word_start(offset) : self._find_word_end(offset) + 1] - - -def _get_fixed_offset(self, offset): - if offset >= len(self.code): - return offset - 1 - if not self._is_id_char(offset): - if offset > 0 and self._is_id_char(offset - 1): - return offset - 1 - if offset < len(self.code) - 1 and self._is_id_char(offset + 1): - return offset + 1 - return offset - - -def __init__(self, keys=None, values=None): - self.keys = keys - self.values = values - collector = _AttributeCollector(dict) - collector("__new__", function=self._new_dict, parent=self) - collector("__setitem__", function=self._dict_add, parent=self) - collector("popitem", function=self._item_get, parent=self) - collector("pop", function=self._value_get, parent=self) - collector("get", function=self._key_get, parent=self) - collector("keys", function=self._key_list, parent=self) - collector("values", function=self._value_list, parent=self) - collector("items", function=self._item_list, parent=self) - collector("copy", function=self._self_get, parent=self) - collector("__getitem__", function=self._value_get, parent=self) - collector("__iter__", function=self._key_iter, parent=self) - collector("update", function=self._self_set, parent=self) - super().__init__(dict, collector.attributes) - - -def _is_id_char(self, offset): - return self.code[offset].isalnum() or self.code[offset] == "_" - - -def _find_string_start(self, offset): - kind = self.code[offset] - try: - return self.code.rindex(kind, 0, offset) - except ValueError: - return 0 - - -def _find_parens_start(self, offset): - offset = self._find_last_non_space_char(offset - 1) - while offset >= 0 and self.code[offset] not in "[({": - if self.code[offset] not in ":,": - offset = self._find_primary_start(offset) - offset = self._find_last_non_space_char(offset - 1) - return offset - - -def _find_atom_start(self, offset): - old_offset = offset - if self.code[offset] == "\n": - return offset + 1 - if self.code[offset].isspace(): - offset = self._find_last_non_space_char(offset) - if self.code[offset] in "'\"": - return self._find_string_start(offset) - if self.code[offset] in ")]}": - return self._find_parens_start(offset) - if self._is_id_char(offset): - return self._find_word_start(offset) - return old_offset - - -def _find_primary_without_dot_start(self, offset): - """It tries to find the undotted primary start - - It is different from `self._get_atom_start()` in that it - follows function calls, too; such as in ``f(x)``. - - """ - last_atom = offset - offset = self._find_last_non_space_char(last_atom) - while offset > 0 and self.code[offset] in ")]": - last_atom = self._find_parens_start(offset) - offset = self._find_last_non_space_char(last_atom - 1) - if offset >= 0 and (self.code[offset] in "\"'})]" or self._is_id_char(offset)): - atom_start = self._find_atom_start(offset) - if not keyword.iskeyword(self.code[atom_start : offset + 1]) or ( - offset + 1 < len(self.code) and self._is_id_char(offset + 1) - ): - return atom_start - return last_atom - - -def _find_primary_start(self, offset): - if offset >= len(self.code): - offset = len(self.code) - 1 - if self.code[offset] != ".": - offset = self._find_primary_without_dot_start(offset) - else: - offset = offset + 1 - while offset > 0: - prev = self._find_last_non_space_char(offset - 1) - if offset <= 0 or self.code[prev] != ".": - break - - # Check if relative import - # XXX: Looks like a hack... - prev_word_end = self._find_last_non_space_char(prev - 1) - if self.code[prev_word_end - 3 : prev_word_end + 1] == "from": - offset = prev - break - - offset = self._find_primary_without_dot_start(prev - 1) - if not self._is_id_char(offset): - break - - return offset - - -def get_primary_at(self, offset): - offset = self._get_fixed_offset(offset) - start, end = self.get_primary_range(offset) - return self.raw[start:end].strip() - - -def get_splitted_primary_before(self, offset): - """returns expression, starting, starting_offset - - This function is used in `rope.codeassist.assist` function. - """ - if offset == 0: - return ("", "", 0) - end = offset - 1 - word_start = self._find_atom_start(end) - real_start = self._find_primary_start(end) - if self.code[word_start:offset].strip() == "": - word_start = end - if self.code[end].isspace(): - word_start = end - if self.code[real_start:word_start].strip() == "": - real_start = word_start - if real_start == word_start == end and not self._is_id_char(end): - return ("", "", offset) - if real_start == word_start: - return ("", self.raw[word_start:offset], word_start) - else: - if self.code[end] == ".": - return (self.raw[real_start:end], "", offset) - last_dot_position = word_start - if self.code[word_start] != ".": - last_dot_position = self._find_last_non_space_char(word_start - 1) - last_char_position = self._find_last_non_space_char(last_dot_position - 1) - if self.code[word_start].isspace(): - word_start = offset - return ( - self.raw[real_start : last_char_position + 1], - self.raw[word_start:offset], - word_start, - ) - - -def _get_line_start(self, offset): - try: - return self.code.rindex("\n", 0, offset + 1) - except ValueError: - return 0 - - -def _get_line_end(self, offset): - try: - return self.code.index("\n", offset) - except ValueError: - return len(self.code) - - -def _new_dict(self, args): - def do_create(holding=None): - if holding is None: - return get_dict() - type = holding.get_type() - if isinstance(type, Tuple) and len(type.get_holding_objects()) == 2: - return get_dict(*type.get_holding_objects()) - - return _create_builtin(args, do_create) - - -def is_name_assigned_in_class_body(self, offset): - word_start = self._find_word_start(offset - 1) - word_end = self._find_word_end(offset) + 1 - if "." in self.code[word_start:word_end]: - return False - line_start = self._get_line_start(word_start) - line = self.code[line_start:word_start].strip() - return not line and self.get_assignment_type(offset) == "=" - - -def is_a_class_or_function_name_in_header(self, offset): - word_start = self._find_word_start(offset - 1) - line_start = self._get_line_start(word_start) - prev_word = self.code[line_start:word_start].strip() - return prev_word in ["def", "class"] - - -def _find_first_non_space_char(self, offset): - if offset >= len(self.code): - return len(self.code) - while offset < len(self.code) and self.code[offset].isspace(): - if self.code[offset] == "\n": - return offset - offset += 1 - return offset - - -def is_a_function_being_called(self, offset): - word_end = self._find_word_end(offset) + 1 - next_char = self._find_first_non_space_char(word_end) - return ( - next_char < len(self.code) - and self.code[next_char] == "(" - and not self.is_a_class_or_function_name_in_header(offset) - ) - - -def _find_import_end(self, start): - return self._get_line_end(start) - - -def is_import_statement(self, offset): - try: - last_import = self.code.rindex("import ", 0, offset) - except ValueError: - return False - line_start = self._get_line_start(last_import) - return ( - self._find_import_end(last_import + 7) >= offset - and self._find_word_start(line_start) == last_import - ) - - -def is_from_statement(self, offset): - try: - last_from = self.code.rindex("from ", 0, offset) - from_import = self.code.index(" import ", last_from) - from_names = from_import + 8 - except ValueError: - return False - from_names = self._find_first_non_space_char(from_names) - return self._find_import_end(from_names) >= offset - - -def is_from_statement_module(self, offset): - if offset >= len(self.code) - 1: - return False - stmt_start = self._find_primary_start(offset) - line_start = self._get_line_start(stmt_start) - prev_word = self.code[line_start:stmt_start].strip() - return prev_word == "from" - - -def is_import_statement_aliased_module(self, offset): - if not self.is_import_statement(offset): - return False - try: - line_start = self._get_line_start(offset) - import_idx = self.code.rindex("import", line_start, offset) - imported_names = import_idx + 7 - except ValueError: - return False - # Check if the offset is within the imported names - if ( - imported_names - 1 > offset - or self._find_import_end(imported_names) < offset - ): - return False - try: - end = self._find_import_main_part_end(offset) - if not self._has_enough_len_for_as(end): - return False - as_end = min(self._find_word_end(end + 1), len(self.code)) - as_start = self._find_word_start(as_end) - return self.code[as_start : as_end + 1] == "as" - except ValueError: - return False - - -def _has_enough_len_for_as(self, end): - return len(self.code) > end + MINIMAL_LEN_FOR_AS - - -@path C:/Repos/ekr-rope/docs/ -# The default ``config.py`` -# flake8: noqa - - -@others -@language python -@tabwidth -4 - -def _dict_add(self, context): - if self.keys is not None: - return - key, value = context.get_arguments(["self", "key", "value"])[1:] - if key is not None and key != pyobjects.get_unknown(): - context.save_per_name(get_tuple(key, value)) - - -def _find_import_main_part_end(self, offset): - end = self._find_word_end(offset) - while len(self.code) > end + 2 and self.code[end + 1] == ".": - end = self._find_word_end(end + 2) - return end - - -def is_a_name_after_from_import(self, offset): - try: - if len(self.code) > offset and self.code[offset] == "\n": - line_start = self._get_line_start(offset - 1) - else: - line_start = self._get_line_start(offset) - last_from = self.code.rindex("from ", line_start, offset) - from_import = self.code.index(" import ", last_from) - from_names = from_import + 8 - except ValueError: - return False - if from_names - 1 > offset: - return False - return self._find_import_end(from_names) >= offset - - -def get_from_module(self, offset): - try: - last_from = self.code.rindex("from ", 0, offset) - import_offset = self.code.index(" import ", last_from) - end = self._find_last_non_space_char(import_offset) - return self.get_primary_at(end) - except ValueError: - pass - - -def is_from_aliased(self, offset): - if not self.is_a_name_after_from_import(offset): - return False - try: - end = self._find_word_end(offset) - as_end = min(self._find_word_end(end + 1), len(self.code)) - as_start = self._find_word_start(as_end) - return self.code[as_start : as_end + 1] == "as" - except ValueError: - return False - - -def get_from_aliased(self, offset): - try: - end = self._find_word_end(offset) - as_ = self._find_word_end(end + 1) - alias = self._find_word_end(as_ + 1) - start = self._find_word_start(alias) - return self.raw[start : alias + 1] - except ValueError: - pass - - -def is_function_keyword_parameter(self, offset): - word_end = self._find_word_end(offset) - if word_end + 1 == len(self.code): - return False - next_char = self._find_first_non_space_char(word_end + 1) - equals = self.code[next_char : next_char + 2] - if equals == "==" or not equals.startswith("="): - return False - word_start = self._find_word_start(offset) - prev_char = self._find_last_non_space_char(word_start - 1) - return prev_char - 1 >= 0 and self.code[prev_char] in ",(" - - -def is_on_function_call_keyword(self, offset): - stop = self._get_line_start(offset) - if self._is_id_char(offset): - offset = self._find_word_start(offset) - 1 - offset = self._find_last_non_space_char(offset) - if offset <= stop or self.code[offset] not in "(,": - return False - parens_start = self.find_parens_start_from_inside(offset) - return stop < parens_start - - -def find_parens_start_from_inside(self, offset): - stop = self._get_line_start(offset) - while offset > stop: - if self.code[offset] == "(": - break - if self.code[offset] != ",": - offset = self._find_primary_start(offset) - offset -= 1 - return max(stop, offset) - - -def is_assigned_here(self, offset): - return self.get_assignment_type(offset) is not None - - -def get_assignment_type(self, offset): - # XXX: does not handle tuple assignments - word_end = self._find_word_end(offset) - next_char = self._find_first_non_space_char(word_end + 1) - single = self.code[next_char : next_char + 1] - double = self.code[next_char : next_char + 2] - triple = self.code[next_char : next_char + 3] - if double not in ("==", "<=", ">=", "!="): - for op in [single, double, triple]: - if op.endswith("="): - return op - - -def _item_get(self, context): - if self.keys is not None: - return get_tuple(self.keys, self.values) - item = context.get_per_name() - if item is None or not isinstance(item.get_type(), Tuple): - return get_tuple(self.keys, self.values) - return item - - -def get_primary_range(self, offset): - start = self._find_primary_start(offset) - end = self._find_word_end(offset) + 1 - return (start, end) - - -def get_word_range(self, offset): - offset = max(0, offset) - start = self._find_word_start(offset) - end = self._find_word_end(offset) + 1 - return (start, end) - - -def get_word_parens_range(self, offset, opening="(", closing=")"): - end = self._find_word_end(offset) - start_parens = self.code.index(opening, end) - index = start_parens - open_count = 0 - while index < len(self.code): - if self.code[index] == opening: - open_count += 1 - if self.code[index] == closing: - open_count -= 1 - if open_count == 0: - return (start_parens, index + 1) - index += 1 - return (start_parens, index) - - -def get_parameters(self, first, last): - keywords = [] - args = [] - current = self._find_last_non_space_char(last - 1) - while current > first: - primary_start = current - current = self._find_primary_start(current) - while current != first and ( - self.code[current] not in "=," or self.code[current - 1] in "=!<>" - ): - current = self._find_last_non_space_char(current - 1) - primary = self.raw[current + 1 : primary_start + 1].strip() - if self.code[current] == "=": - primary_start = current - 1 - current -= 1 - while current != first and self.code[current] not in ",": - current = self._find_last_non_space_char(current - 1) - param_name = self.raw[current + 1 : primary_start + 1].strip() - keywords.append((self.__strip_type_hint(param_name), primary)) - else: - args.append(self.__strip_type_hint(primary)) - current = self._find_last_non_space_char(current - 1) - args.reverse() - keywords.reverse() - return args, keywords - - -def __strip_type_hint(self, name): - return name.split(":", 1)[0] - - -def is_assigned_in_a_tuple_assignment(self, offset): - start = self._get_line_start(offset) - end = self._get_line_end(offset) - primary_start = self._find_primary_start(offset) - primary_end = self._find_word_end(offset) - - prev_char_offset = self._find_last_non_space_char(primary_start - 1) - next_char_offset = self._find_first_non_space_char(primary_end + 1) - next_char = prev_char = "" - if prev_char_offset >= start: - prev_char = self.code[prev_char_offset] - if next_char_offset < end: - next_char = self.code[next_char_offset] - try: - equals_offset = self.code.index("=", start, end) - except ValueError: - return False - if prev_char not in "(," and next_char not in ",)": - return False - parens_start = self.find_parens_start_from_inside(offset) - # XXX: only handling (x, y) = value - return offset < equals_offset and self.code[start:parens_start].strip() == "" - - -def get_function_and_args_in_header(self, offset): - offset = self.find_function_offset(offset) - lparens, rparens = self.get_word_parens_range(offset) - return self.raw[offset : rparens + 1] - - -def find_function_offset(self, offset, definition="def "): - while True: - offset = self.code.index(definition, offset) - if offset == 0 or not self._is_id_char(offset - 1): - break - offset += 1 - def_ = offset + 4 - return self._find_first_non_space_char(def_) - - -def get_lambda_and_args(self, offset): - offset = self.find_function_offset(offset, definition="lambda ") - lparens, rparens = self.get_word_parens_range(offset, opening=" ", closing=":") - return self.raw[offset : rparens + 1] - -@path C:/Repos/ekr-rope/rope/base/ -"""Base rope package - -This package contains rope core modules that are used by other modules -and packages. - -""" - -__all__ = ["project", "libutils", "exceptions"] -@language python -@tabwidth -4 - -def _value_get(self, context): - item = self._item_get(context).get_type() - return item.get_holding_objects()[1] - - - -@path C:/Repos/ekr-rope/rope/base/oi/ -import base64 -import hashlib -import hmac - -try: - import cPickle as pickle -except ImportError: - import pickle -import marshal -import os -import socket -import subprocess -import sys -import tempfile -import threading - - -@others -@language python -@tabwidth -4 - -def _compat_compare_digest(a, b): - """Implementation of hmac.compare_digest for python < 2.7.7. - - This function uses an approach designed to prevent timing analysis by - avoiding content-based short circuiting behaviour, making it appropriate - for cryptography. - """ - if len(a) != len(b): - return False - # Computes the bitwise difference of all characters in the two strings - # before returning whether or not they are equal. - difference = 0 - for (a_char, b_char) in zip(a, b): - difference |= ord(a_char) ^ ord(b_char) - return difference == 0 - - - -try: - from hmac import compare_digest -except ImportError: - compare_digest = _compat_compare_digest - - - -class PythonFileRunner: - """A class for running python project files""" - - @others - -def __init__( - self, pycore, file_, args=None, stdin=None, stdout=None, analyze_data=None -): - self.pycore = pycore - self.file = file_ - self.analyze_data = analyze_data - self.observers = [] - self.args = args - self.stdin = stdin - self.stdout = stdout - - -def run(self): - """Execute the process""" - env = dict(os.environ) - file_path = self.file.real_path - path_folders = ( - self.pycore.project.get_source_folders() - + self.pycore.project.get_python_path_folders() - ) - env["PYTHONPATH"] = os.pathsep.join(folder.real_path for folder in path_folders) - runmod_path = self.pycore.project.find_module("rope.base.oi.runmod").real_path - self.receiver = None - self._init_data_receiving() - send_info = "-" - if self.receiver: - send_info = self.receiver.get_send_info() - args = [ - sys.executable, - runmod_path, - send_info, - self.pycore.project.address, - self.file.real_path, - ] - if self.analyze_data is None: - del args[1:4] - if self.args is not None: - args.extend(self.args) - self.process = subprocess.Popen( - executable=sys.executable, - args=args, - env=env, - cwd=os.path.split(file_path)[0], - stdin=self.stdin, - stdout=self.stdout, - stderr=self.stdout, - close_fds=os.name != "nt", - ) - - -def _init_data_receiving(self): - if self.analyze_data is None: - return - # Disabling FIFO data transfer due to blocking when running - # unittests in the GUI. - # XXX: Handle FIFO data transfer for `rope.ui.testview` - if True or os.name == "nt": - self.receiver = _SocketReceiver() - else: - self.receiver = _FIFOReceiver() - self.receiving_thread = threading.Thread(target=self._receive_information) - self.receiving_thread.setDaemon(True) - self.receiving_thread.start() - - -def _receive_information(self): - # temp = open('/dev/shm/info', 'wb') - for data in self.receiver.receive_data(): - self.analyze_data(data) - # temp.write(str(data) + '\n') - # temp.close() - for observer in self.observers: - observer() - - -def wait_process(self): - """Wait for the process to finish""" - self.process.wait() - if self.analyze_data: - self.receiving_thread.join() - - -def _key_get(self, context): - item = self._item_get(context).get_type() - return item.get_holding_objects()[0] - - -def kill_process(self): - """Stop the process""" - if self.process.poll() is not None: - return - try: - if hasattr(self.process, "terminate"): - self.process.terminate() - elif os.name != "nt": - os.kill(self.process.pid, 9) - else: - import ctypes - - handle = int(self.process._handle) - ctypes.windll.kernel32.TerminateProcess(handle, -1) - except OSError: - pass - - -def add_finishing_observer(self, observer): - """Notify this observer when execution finishes""" - self.observers.append(observer) - - - -class _MessageReceiver: - def receive_data(self): - pass - - def get_send_info(self): - pass - - - -class _SocketReceiver(_MessageReceiver): - @others - -def __init__(self): - self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.data_port = 3037 - self.key = os.urandom(32) - - while self.data_port < 4000: - try: - self.server_socket.bind(("localhost", self.data_port)) - break - except OSError: - self.data_port += 1 - self.server_socket.listen(1) - - -def get_send_info(self): - return "%d:%s" % (self.data_port, base64.b64encode(self.key).decode("utf-8")) - - -def receive_data(self): - conn, addr = self.server_socket.accept() - self.server_socket.close() - my_file = conn.makefile("rb") - while True: - # Received messages must meet the following criteria: - # 1. Must be contained on a single line. - # 2. Must be prefixed with a base64 encoded sha256 message digest - # of the base64 encoded pickle data. - # 3. Message digest must be computed using the correct key. - # - # Any messages received that do not meet these criteria will never - # be unpickled and will be dropped silently. - try: - buf = my_file.readline() - if len(buf) == 0: - break - - try: - digest_end = buf.index(b":") - buf_digest = base64.b64decode(buf[:digest_end]) - buf_data = buf[digest_end + 1 : -1] - decoded_buf_data = base64.b64decode(buf_data) - except: - # Corrupted data; the payload cannot be trusted and just has - # to be dropped. See CVE-2014-3539. - continue - - digest = hmac.new(self.key, buf_data, hashlib.sha256).digest() - if not compare_digest(buf_digest, digest): - # Signature mismatch; the payload cannot be trusted and just - # has to be dropped. See CVE-2014-3539. - continue - - yield pickle.loads(decoded_buf_data) - except EOFError: - break - my_file.close() - conn.close() - - - -class _FIFOReceiver(_MessageReceiver): - @others - -def __init__(self): - # XXX: this is insecure and might cause race conditions - self.file_name = self._get_file_name() - os.mkfifo(self.file_name) - - -def _get_file_name(self): - prefix = tempfile.gettempdir() + "/__rope_" - i = 0 - while os.path.exists(prefix + str(i).rjust(4, "0")): - i += 1 - return prefix + str(i).rjust(4, "0") - - -def _value_list(self, context): - return get_list(self._value_get(context)) - - -def get_send_info(self): - return self.file_name - - -def receive_data(self): - my_file = open(self.file_name, "rb") - while True: - try: - yield marshal.load(my_file) - except EOFError: - break - my_file.close() - os.remove(self.file_name) - -@path C:/Repos/ekr-rope/rope/base/oi/ -from rope.base.oi import objectdb - - -@others -@language python -@tabwidth -4 - -class MemoryDB(objectdb.FileDict): - @others - -def __init__(self, project, persist=None): - self.project = project - self._persist = persist - self.files = self - self._load_files() - self.project.data_files.add_write_hook(self.write) - - -def _load_files(self): - self._files = {} - if self.persist: - result = self.project.data_files.read_data( - "objectdb", compress=self.compress, import_=True - ) - if result is not None: - self._files = result - - -def keys(self): - return self._files.keys() - - -def __iter__(self): - yield from self._files - - -def __len__(self): - return len(self._files) - - -def __setitem__(self): - raise NotImplementedError() - - -def _key_list(self, context): - return get_list(self._key_get(context)) - - -def __contains__(self, key): - return key in self._files - - -def __getitem__(self, key): - return FileInfo(self._files[key]) - - -def create(self, path): - self._files[path] = {} - - -def rename(self, file, newfile): - if file not in self._files: - return - self._files[newfile] = self._files[file] - del self[file] - - -def __delitem__(self, file): - del self._files[file] - - -def write(self): - if self.persist: - self.project.data_files.write_data("objectdb", self._files, self.compress) - - -@property -def compress(self): - return self.project.prefs.get("compress_objectdb", False) - - -@property -def persist(self): - if self._persist is not None: - return self._persist - else: - return self.project.prefs.get("save_objectdb", False) - - - -class FileInfo(objectdb.FileInfo): - @others - -def __init__(self, scopes): - self.scopes = scopes - - -def _item_list(self, context): - return get_list(self._item_get(context)) - - -def create_scope(self, key): - self.scopes[key] = ScopeInfo() - - -def keys(self): - return self.scopes.keys() - - -def __contains__(self, key): - return key in self.scopes - - -def __getitem__(self, key): - return self.scopes[key] - - -def __delitem__(self, key): - del self.scopes[key] - - -def __iter__(self): - yield from self.scopes - - -def __len__(self): - return len(self.scopes) - - -def __setitem__(self): - raise NotImplementedError() - - - -class ScopeInfo(objectdb.ScopeInfo): - @others - -def __init__(self): - self.call_info = {} - self.per_name = {} - - -def _value_iter(self, context): - return get_iterator(self._value_get(context)) - - -def get_per_name(self, name): - return self.per_name.get(name, None) - - -def save_per_name(self, name, value): - self.per_name[name] = value - - -def get_returned(self, parameters): - return self.call_info.get(parameters, None) - - -def get_call_infos(self): - for args, returned in self.call_info.items(): - yield objectdb.CallInfo(args, returned) - - -def add_call(self, parameters, returned): - self.call_info[parameters] = returned - - -def __getstate__(self): - return (self.call_info, self.per_name) - - -def __setstate__(self, data): - self.call_info, self.per_name = data - -@path C:/Repos/ekr-rope/rope/base/oi/ -@others -@language python -@tabwidth -4 - -class ObjectDB: - @others - -def __init__(self, db, validation): - self.db = db - self.validation = validation - self.observers = [] - self.files = db.files - - -def _key_iter(self, context): - return get_iterator(self._key_get(context)) - - -def validate_files(self): - for file in list(self.files): - if not self.validation.is_file_valid(file): - del self.files[file] - self._file_removed(file) - - -def validate_file(self, file): - if file not in self.files: - return - for key in list(self.files[file]): - if not self.validation.is_scope_valid(file, key): - del self.files[file][key] - - -def file_moved(self, file, newfile): - if file not in self.files: - return - self.files.rename(file, newfile) - self._file_removed(file) - self._file_added(newfile) - - -def get_files(self): - return self.files.keys() - - -def get_returned(self, path, key, args): - scope_info = self._get_scope_info(path, key, readonly=True) - result = scope_info.get_returned(args) - if self.validation.is_value_valid(result): - return result - - -def get_pername(self, path, key, name): - scope_info = self._get_scope_info(path, key, readonly=True) - result = scope_info.get_per_name(name) - if self.validation.is_value_valid(result): - return result - - -def get_callinfos(self, path, key): - scope_info = self._get_scope_info(path, key, readonly=True) - return scope_info.get_call_infos() - - -def add_callinfo(self, path, key, args, returned): - scope_info = self._get_scope_info(path, key, readonly=False) - old_returned = scope_info.get_returned(args) - if self.validation.is_more_valid(returned, old_returned): - scope_info.add_call(args, returned) - - -def add_pername(self, path, key, name, value): - scope_info = self._get_scope_info(path, key, readonly=False) - old_value = scope_info.get_per_name(name) - if self.validation.is_more_valid(value, old_value): - scope_info.save_per_name(name, value) - - -def add_file_list_observer(self, observer): - self.observers.append(observer) - - -def _item_iter(self, context): - return get_iterator(self._item_get(context)) - - -def write(self): - self.db.write() - - -def _get_scope_info(self, path, key, readonly=True): - if path not in self.files: - if readonly: - return _NullScopeInfo() - self.files.create(path) - self._file_added(path) - if key not in self.files[path]: - if readonly: - return _NullScopeInfo() - self.files[path].create_scope(key) - result = self.files[path][key] - if isinstance(result, dict): - print(self.files, self.files[path], self.files[path][key]) - return result - - -def _file_removed(self, path): - for observer in self.observers: - observer.removed(path) - - -def _file_added(self, path): - for observer in self.observers: - observer.added(path) - - -def __str__(self): - scope_count = 0 - for file_dict in self.files.values(): - scope_count += len(file_dict) - return "ObjectDB holds {} file and {} scope infos".format( - len(self.files), - scope_count, - ) - - - -class _NullScopeInfo: - @others - -def __init__(self, error_on_write=True): - self.error_on_write = error_on_write - - -def get_per_name(self, name): - pass - - -def save_per_name(self, name, value): - if self.error_on_write: - raise NotImplementedError() - - -def get_returned(self, parameters): - pass - - -def set_prefs(prefs): - """This function is called before opening the project""" - - # Specify which files and folders to ignore in the project. - # Changes to ignored resources are not added to the history and - # VCSs. Also they are not returned in `Project.get_files()`. - # Note that ``?`` and ``*`` match all characters but slashes. - # "*.pyc": matches "test.pyc" and "pkg/test.pyc" - # "mod*.pyc": matches "test/mod1.pyc" but not "mod/1.pyc" - # ".svn": matches "pkg/.svn" and all of its children - # "build/*.o": matches "build/lib.o" but not "build/sub/lib.o" - # "build//*.o": matches "build/lib.o" and "build/sub/lib.o" - # - # prefs["ignored_resources"] = [ - # "*.pyc", - # "*~", - # ".ropeproject", - # ".hg", - # ".svn", - # "_svn", - # ".git", - # ".tox", - # ".venv", - # "venv", - # ".mypy_cache", - # ".pytest_cache", - # ] - - # Specifies which files should be considered python files. It is - # useful when you have scripts inside your project. Only files - # ending with ``.py`` are considered to be python files by - # default. - # - # prefs["python_files"] = ["*.py"] - - # Custom source folders: By default rope searches the project - # for finding source folders (folders that should be searched - # for finding modules). You can add paths to that list. Note - # that rope guesses project source folders correctly most of the - # time; use this if you have any problems. - # The folders should be relative to project root and use "/" for - # separating folders regardless of the platform rope is running on. - # "src/my_source_folder" for instance. - # - # prefs.add("source_folders", "src") - - # You can extend python path for looking up modules - # - # prefs.add("python_path", "~/python/") - - # Should rope save object information or not. - # - # prefs["save_objectdb"] = True - # prefs["compress_objectdb"] = False - - # If `True`, rope analyzes each module when it is being saved. - # - # prefs["automatic_soa"] = True - # - # The depth of calls to follow in static object analysis - # - # prefs["soa_followed_calls"] = 0 - - # If `False` when running modules or unit tests "dynamic object - # analysis" is turned off. This makes them much faster. - # - # prefs["perform_doa"] = True - - # Rope can check the validity of its object DB when running. - # - # prefs["validate_objectdb"] = True - - # How many undos to hold? - # - # prefs["max_history_items"] = 32 - - # Shows whether to save history across sessions. - # - # prefs["save_history"] = True - # prefs["compress_history"] = False - - # Set the number spaces used for indenting. According to - # :PEP:`8`, it is best to use 4 spaces. Since most of rope's - # unit-tests use 4 spaces it is more reliable, too. - # - # prefs["indent_size"] = 4 - - # Builtin and c-extension modules that are allowed to be imported - # and inspected by rope. - # - # prefs["extension_modules"] = [] - - # Add all standard c-extensions to extension_modules list. - # - # prefs["import_dynload_stdmods"] = True - - # If `True` modules with syntax errors are considered to be empty. - # The default value is `False`; When `False` syntax errors raise - # `rope.base.exceptions.ModuleSyntaxError` exception. - # - # prefs["ignore_syntax_errors"] = False - - # If `True`, rope ignores unresolvable imports. Otherwise, they - # appear in the importing namespace. - # - # prefs["ignore_bad_imports"] = False - - # If `True`, rope will insert new module imports as - # `from <package> import <module>` by default. - # - # prefs["prefer_module_from_imports"] = False - - # If `True`, rope will transform a comma list of imports into - # multiple separate import statements when organizing - # imports. - # - # prefs["split_imports"] = False - - # If `True`, rope will remove all top-level import statements and - # reinsert them at the top of the module when making changes. - # - # prefs["pull_imports_to_top"] = True - - # If `True`, rope will sort imports alphabetically by module name instead - # of alphabetically by import statement, with from imports after normal - # imports. - # - # prefs["sort_imports_alphabetically"] = False - - # Location of implementation of - # rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general - # case, you don't have to change this value, unless you're an rope expert. - # Change this value to inject you own implementations of interfaces - # listed in module rope.base.oi.type_hinting.providers.interfaces - # For example, you can add you own providers for Django Models, or disable - # the search type-hinting in a class hierarchy, etc. - # - # prefs[ - # "type_hinting_factory" - # ] = "rope.base.oi.type_hinting.factory.default_type_hinting_factory" - - - -def _self_get(self, context): - item = self._item_get(context).get_type() - key, value = item.get_holding_objects()[:2] - return get_dict(key, value) - - -def get_call_infos(self): - return [] - - -def add_call(self, parameters, returned): - if self.error_on_write: - raise NotImplementedError() - - - -class FileInfo(dict): - def create_scope(self, key): - pass - - - -class FileDict(dict): - def create(self, key): - pass - - def rename(self, key, new_key): - pass - - - -class ScopeInfo: - @others - -def get_per_name(self, name): - pass - - -def save_per_name(self, name, value): - pass - - -def get_returned(self, parameters): - pass - - -def get_call_infos(self): - pass - - -def add_call(self, parameters, returned): - pass - - - -def _self_set(self, context): - if self.keys is not None: - return - new_dict = context.get_pynames(["self", "d"])[1] - if new_dict and isinstance(new_dict.get_object().get_type(), Dict): - args = arguments.ObjectArguments([new_dict]) - items = ( - new_dict.get_object()["popitem"].get_object().get_returned_object(args) - ) - context.save_per_name(items) - else: - holding = _infer_sequence_for_pyname(new_dict) - if holding is not None and isinstance(holding.get_type(), Tuple): - context.save_per_name(holding) - - - -class CallInfo: - @others - -def __init__(self, args, returned): - self.args = args - self.returned = returned - - -def get_parameters(self): - return self.args - - -def get_returned(self): - return self.returned - - - -class FileListObserver: - def added(self, path): - pass - - def removed(self, path): - pass - -@path C:/Repos/ekr-rope/rope/base/oi/ -import warnings - -from rope.base import exceptions, resourceobserver -from rope.base.oi import objectdb, memorydb, transform - - -@others -@language python -@tabwidth -4 - -class ObjectInfoManager: - """Stores object information - - It uses an instance of `objectdb.ObjectDB` for storing - information. - - """ - - @others - -def __init__(self, project): - self.project = project - self.to_textual = transform.PyObjectToTextual(project) - self.to_pyobject = transform.TextualToPyObject(project) - self.doi_to_pyobject = transform.DOITextualToPyObject(project) - self._init_objectdb() - if project.prefs.get("validate_objectdb", False): - self._init_validation() - - -def _init_objectdb(self): - dbtype = self.project.get_prefs().get("objectdb_type", None) - persist = None - if dbtype is not None: - warnings.warn( - '"objectdb_type" project config is deprecated;\n' - 'Use "save_objectdb" instead in your project ' - 'config file.\n(".ropeproject/config.py" by default)\n', - DeprecationWarning, - ) - if dbtype != "memory" and self.project.ropefolder is not None: - persist = True - self.validation = TextualValidation(self.to_pyobject) - db = memorydb.MemoryDB(self.project, persist=persist) - self.objectdb = objectdb.ObjectDB(db, self.validation) - - -def _init_validation(self): - self.objectdb.validate_files() - observer = resourceobserver.ResourceObserver( - changed=self._resource_changed, - moved=self._resource_moved, - removed=self._resource_moved, - ) - files = [] - for path in self.objectdb.get_files(): - resource = self.to_pyobject.path_to_resource(path) - if resource is not None and resource.project == self.project: - files.append(resource) - self.observer = resourceobserver.FilteredResourceObserver(observer, files) - self.objectdb.add_file_list_observer(_FileListObserver(self)) - self.project.add_observer(self.observer) - - -get_dict = _create_builtin_getter(Dict) -get_dict_type = _create_builtin_type_getter(Dict) - - - -def _resource_changed(self, resource): - try: - self.objectdb.validate_file(self.to_textual.resource_to_path(resource)) - except exceptions.ModuleSyntaxError: - pass - - -def _resource_moved(self, resource, new_resource=None): - self.observer.remove_resource(resource) - if new_resource is not None: - old = self.to_textual.resource_to_path(resource) - new = self.to_textual.resource_to_path(new_resource) - self.objectdb.file_moved(old, new) - self.observer.add_resource(new_resource) - - -def get_returned(self, pyobject, args): - result = self.get_exact_returned(pyobject, args) - if result is not None: - return result - path, key = self._get_scope(pyobject) - if path is None: - return None - for call_info in self.objectdb.get_callinfos(path, key): - returned = call_info.get_returned() - if returned and returned[0] not in ("unknown", "none"): - result = returned - break - if result is None: - result = returned - if result is not None: - return self.to_pyobject(result) - - -def get_exact_returned(self, pyobject, args): - path, key = self._get_scope(pyobject) - if path is not None: - returned = self.objectdb.get_returned( - path, key, self._args_to_textual(pyobject, args) - ) - if returned is not None: - return self.to_pyobject(returned) - - -def _args_to_textual(self, pyfunction, args): - parameters = list(pyfunction.get_param_names(special_args=False)) - arguments = args.get_arguments(parameters)[: len(parameters)] - textual_args = tuple(self.to_textual(arg) for arg in arguments) - return textual_args - - -def get_parameter_objects(self, pyobject): - path, key = self._get_scope(pyobject) - if path is None: - return None - arg_count = len(pyobject.get_param_names(special_args=False)) - unknowns = arg_count - parameters = [None] * arg_count - for call_info in self.objectdb.get_callinfos(path, key): - args = call_info.get_parameters() - for index, arg in enumerate(args[:arg_count]): - old = parameters[index] - if self.validation.is_more_valid(arg, old): - parameters[index] = arg - if self.validation.is_value_valid(arg): - unknowns -= 1 - if unknowns == 0: - break - if unknowns < arg_count: - return [self.to_pyobject(parameter) for parameter in parameters] - - -def get_passed_objects(self, pyfunction, parameter_index): - path, key = self._get_scope(pyfunction) - if path is None: - return [] - result = [] - for call_info in self.objectdb.get_callinfos(path, key): - args = call_info.get_parameters() - if len(args) > parameter_index: - parameter = self.to_pyobject(args[parameter_index]) - if parameter is not None: - result.append(parameter) - return result - - -def doa_data_received(self, data): - def doi_to_normal(textual): - pyobject = self.doi_to_pyobject(textual) - return self.to_textual(pyobject) - - function = doi_to_normal(data[0]) - args = tuple(doi_to_normal(textual) for textual in data[1]) - returned = doi_to_normal(data[2]) - if function[0] == "defined" and len(function) == 3: - self._save_data(function, args, returned) - - -def function_called(self, pyfunction, params, returned=None): - function_text = self.to_textual(pyfunction) - params_text = tuple(self.to_textual(param) for param in params) - returned_text = ("unknown",) - if returned is not None: - returned_text = self.to_textual(returned) - self._save_data(function_text, params_text, returned_text) - - -def save_per_name(self, scope, name, data): - path, key = self._get_scope(scope.pyobject) - if path is not None: - self.objectdb.add_pername(path, key, name, self.to_textual(data)) - - -class Tuple(BuiltinClass): - @others - -def get_per_name(self, scope, name): - path, key = self._get_scope(scope.pyobject) - if path is not None: - result = self.objectdb.get_pername(path, key, name) - if result is not None: - return self.to_pyobject(result) - - -def _save_data(self, function, args, returned=("unknown",)): - self.objectdb.add_callinfo(function[1], function[2], args, returned) - - -def _get_scope(self, pyobject): - resource = pyobject.get_module().get_resource() - if resource is None: - return None, None - textual = self.to_textual(pyobject) - if textual[0] == "defined": - path = textual[1] - if len(textual) == 3: - key = textual[2] - else: - key = "" - return path, key - return None, None - - -def sync(self): - self.objectdb.sync() - - -def __str__(self): - return str(self.objectdb) - - - -class TextualValidation: - @others - -def __init__(self, to_pyobject): - self.to_pyobject = to_pyobject - - -def is_value_valid(self, value): - # ???: Should none and unknown be considered valid? - if value is None or value[0] in ("none", "unknown"): - return False - return self.to_pyobject(value) is not None - - -def is_more_valid(self, new, old): - if old is None: - return True - return new[0] not in ("unknown", "none") - - -def is_file_valid(self, path): - return self.to_pyobject.path_to_resource(path) is not None - - -def __init__(self, *objects): - self.objects = objects - first = None - if objects: - first = objects[0] - attributes = { - "__getitem__": BuiltinName( - BuiltinFunction(first) - ), # TODO: add slice support - "__getslice__": BuiltinName(BuiltinFunction(pyobjects.PyObject(self))), - "__new__": BuiltinName(BuiltinFunction(function=self._new_tuple)), - "__iter__": BuiltinName(BuiltinFunction(get_iterator(first))), - } - super().__init__(tuple, attributes) - - -def is_scope_valid(self, path, key): - if key == "": - textual = ("defined", path) - else: - textual = ("defined", path, key) - return self.to_pyobject(textual) is not None - - - -class _FileListObserver: - @others - -def __init__(self, object_info): - self.object_info = object_info - self.observer = self.object_info.observer - self.to_pyobject = self.object_info.to_pyobject - - -def removed(self, path): - resource = self.to_pyobject.path_to_resource(path) - if resource is not None: - self.observer.remove_resource(resource) - - -def added(self, path): - resource = self.to_pyobject.path_to_resource(path) - if resource is not None: - self.observer.add_resource(resource) - -@path C:/Repos/ekr-rope/rope/base/oi/ -@others -if __name__ == "__main__": - __rope_start_everything() -@language python -@tabwidth -4 - -def __rope_start_everything(): - import os - import sys - import socket - - try: - import cPickle as pickle - except ImportError: - import pickle - import marshal - import inspect - import types - import threading - import base64 - import hashlib - import hmac - - @others - send_info = sys.argv[1] - project_root = sys.argv[2] - file_to_run = sys.argv[3] - run_globals = globals() - run_globals.update( - {"__name__": "__main__", "__builtins__": __builtins__, "__file__": file_to_run} - ) - - if send_info != "-": - data_sender = _FunctionCallDataSender(send_info, project_root) - del sys.argv[1:4] - with open(file_to_run) as f: - code = compile(f.read(), file_to_run, 'exec') - exec(code, run_globals) - if send_info != "-": - data_sender.close() - -class _MessageSender: - def send_data(self, data): - pass - - -class _SocketSender(_MessageSender): - def __init__(self, port, key): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect(("127.0.0.1", port)) - self.my_file = s.makefile("wb") - self.key = base64.b64decode(key) - - def send_data(self, data): - if not self.my_file.closed: - pickled_data = base64.b64encode( - pickle.dumps(data, pickle.HIGHEST_PROTOCOL) - ) - dgst = hmac.new(self.key, pickled_data, hashlib.sha256).digest() - self.my_file.write(base64.b64encode(dgst) + b":" + pickled_data + b"\n") - - def close(self): - self.my_file.close() - - -class _FileSender(_MessageSender): - def __init__(self, file_name): - self.my_file = open(file_name, "wb") - - def send_data(self, data): - if not self.my_file.closed: - marshal.dump(data, self.my_file) - - def close(self): - self.my_file.close() - - -def get_holding_objects(self): - return self.objects - - -def _cached(func): - cache = {} - - def newfunc(self, arg): - if arg in cache: - return cache[arg] - result = func(self, arg) - cache[arg] = result - return result - - return newfunc - - -class _FunctionCallDataSender: - def __init__(self, send_info, project_root): - self.project_root = project_root - if send_info[0].isdigit(): - port, key = send_info.split(":", 1) - self.sender = _SocketSender(int(port), key) - else: - self.sender = _FileSender(send_info) - - @others - sys.settrace(global_trace) - threading.settrace(global_trace) - - def on_function_call(self, frame, event, arg): - if event != "return": - return - args = [] - returned = ("unknown",) - code = frame.f_code - for argname in code.co_varnames[: code.co_argcount]: - try: - argvalue = self._object_to_persisted_form(frame.f_locals[argname]) - args.append(argvalue) - except (TypeError, AttributeError): - args.append(("unknown",)) - try: - returned = self._object_to_persisted_form(arg) - except (TypeError, AttributeError): - pass - try: - data = ( - self._object_to_persisted_form(frame.f_code), - tuple(args), - returned, - ) - self.sender.send_data(data) - except (TypeError): - pass - return self.on_function_call - - def _is_an_interesting_call(self, frame): - # if frame.f_code.co_name in ['?', '<module>']: - # return False - # return not frame.f_back or - # not self._is_code_inside_project(frame.f_back.f_code) - if not self._is_code_inside_project(frame.f_code) and ( - not frame.f_back - or not self._is_code_inside_project(frame.f_back.f_code) - ): - return False - return True - - def _is_code_inside_project(self, code): - source = self._path(code.co_filename) - return ( - source is not None - and os.path.exists(source) - and _realpath(source).startswith(self.project_root) - ) - - @_cached - def _get_persisted_code(self, object_): - source = self._path(object_.co_filename) - if not os.path.exists(source): - raise TypeError("no source") - return ("defined", _realpath(source), str(object_.co_firstlineno)) - - @_cached - def _get_persisted_class(self, object_): - try: - return ( - "defined", - _realpath(inspect.getsourcefile(object_)), - object_.__name__, - ) - except (TypeError, AttributeError): - return ("unknown",) - - def _get_persisted_builtin(self, object_): - if isinstance(object_, str): - return ("builtin", "str") - if isinstance(object_, list): - holding = None - if len(object_) > 0: - holding = object_[0] - return ("builtin", "list", self._object_to_persisted_form(holding)) - if isinstance(object_, dict): - keys = None - values = None - if len(object_) > 0: - # @todo - fix it properly, why is __locals__ being - # duplicated ? - keys = [key for key in object_.keys() if key != "__locals__"][0] - values = object_[keys] - return ( - "builtin", - "dict", - self._object_to_persisted_form(keys), - self._object_to_persisted_form(values), - ) - if isinstance(object_, tuple): - objects = [] - if len(object_) < 3: - for holding in object_: - objects.append(self._object_to_persisted_form(holding)) - else: - objects.append(self._object_to_persisted_form(object_[0])) - return tuple(["builtin", "tuple"] + objects) - if isinstance(object_, set): - holding = None - if len(object_) > 0: - for o in object_: - holding = o - break - return ("builtin", "set", self._object_to_persisted_form(holding)) - return ("unknown",) - - def _object_to_persisted_form(self, object_): - if object_ is None: - return ("none",) - if isinstance(object_, types.CodeType): - return self._get_persisted_code(object_) - if isinstance(object_, types.FunctionType): - return self._get_persisted_code(object_.__code__) - if isinstance(object_, types.MethodType): - return self._get_persisted_code(object_.__func__.__code__) - if isinstance(object_, types.ModuleType): - return self._get_persisted_module(object_) - if isinstance(object_, (str, list, dict, tuple, set)): - return self._get_persisted_builtin(object_) - if isinstance(object_, type): - return self._get_persisted_class(object_) - return ("instance", self._get_persisted_class(type(object_))) - - @_cached - def _get_persisted_module(self, object_): - path = self._path(object_.__file__) - if path and os.path.exists(path): - return ("defined", _realpath(path)) - return ("unknown",) - - def _path(self, path): - if path.endswith(".pyc"): - path = path[:-1] - if path.endswith(".py"): - return path - - def close(self): - self.sender.close() - sys.settrace(None) - - -def global_trace(frame, event, arg): - # HACK: Ignoring out->in calls - # This might lose some information - if self._is_an_interesting_call(frame): - return self.on_function_call - - -def _realpath(path): - return os.path.realpath(os.path.abspath(os.path.expanduser(path))) - - -@path C:/Repos/ekr-rope/rope/base/oi/ -import rope.base.ast -import rope.base.oi.soi -import rope.base.pynames -from rope.base import pyobjects, evaluate, astutils, arguments - - -@others -@language python -@tabwidth -4 - -def analyze_module(pycore, pymodule, should_analyze, search_subscopes, followed_calls): - """Analyze `pymodule` for static object inference - - Analyzes scopes for collecting object information. The analysis - starts from inner scopes. - - """ - _analyze_node(pycore, pymodule, should_analyze, search_subscopes, followed_calls) - - - -def _analyze_node(pycore, pydefined, should_analyze, search_subscopes, followed_calls): - if search_subscopes(pydefined): - for scope in pydefined.get_scope().get_scopes(): - _analyze_node( - pycore, scope.pyobject, should_analyze, search_subscopes, followed_calls - ) - if should_analyze(pydefined): - new_followed_calls = max(0, followed_calls - 1) - return_true = lambda pydefined: True - return_false = lambda pydefined: False - - def _follow(pyfunction): - _analyze_node( - pycore, pyfunction, return_true, return_false, new_followed_calls - ) - - if not followed_calls: - _follow = None - visitor = SOAVisitor(pycore, pydefined, _follow) - for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): - rope.base.ast.walk(child, visitor) - - - -class SOAVisitor: - @others - -def __init__(self, pycore, pydefined, follow_callback=None): - self.pycore = pycore - self.pymodule = pydefined.get_module() - self.scope = pydefined.get_scope() - self.follow = follow_callback - - -def _FunctionDef(self, node): - pass - - -def _new_tuple(self, args): - return _create_builtin(args, get_tuple) - - - -def _ClassDef(self, node): - pass - - -def _Call(self, node): - for child in rope.base.ast.get_child_nodes(node): - rope.base.ast.walk(child, self) - primary, pyname = evaluate.eval_node2(self.scope, node.func) - if pyname is None: - return - pyfunction = pyname.get_object() - if isinstance(pyfunction, pyobjects.AbstractFunction): - args = arguments.create_arguments(primary, pyfunction, node, self.scope) - elif isinstance(pyfunction, pyobjects.PyClass): - pyclass = pyfunction - if "__init__" in pyfunction: - pyfunction = pyfunction["__init__"].get_object() - pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass)) - args = self._args_with_self(primary, pyname, pyfunction, node) - elif "__call__" in pyfunction: - pyfunction = pyfunction["__call__"].get_object() - args = self._args_with_self(primary, pyname, pyfunction, node) - else: - return - self._call(pyfunction, args) - - -def _args_with_self(self, primary, self_pyname, pyfunction, node): - base_args = arguments.create_arguments(primary, pyfunction, node, self.scope) - return arguments.MixedArguments(self_pyname, base_args, self.scope) - - -def _call(self, pyfunction, args): - if isinstance(pyfunction, pyobjects.PyFunction): - if self.follow is not None: - before = self._parameter_objects(pyfunction) - self.pycore.object_info.function_called( - pyfunction, args.get_arguments(pyfunction.get_param_names()) - ) - pyfunction._set_parameter_pyobjects(None) - if self.follow is not None: - after = self._parameter_objects(pyfunction) - if after != before: - self.follow(pyfunction) - # XXX: Maybe we should not call every builtin function - if isinstance(pyfunction, rope.base.builtins.BuiltinFunction): - pyfunction.get_returned_object(args) - - -def _parameter_objects(self, pyfunction): - return [ - pyfunction.get_parameter(i) - for i in range(len(pyfunction.get_param_names(False))) - ] - - -def _AnnAssign(self, node): - for child in rope.base.ast.get_child_nodes(node): - rope.base.ast.walk(child, self) - visitor = _SOAAssignVisitor() - nodes = [] - - rope.base.ast.walk(node.target, visitor) - nodes.extend(visitor.nodes) - - self._evaluate_assign_value(node, nodes, type_hint=node.annotation) - - -def _Assign(self, node): - for child in rope.base.ast.get_child_nodes(node): - rope.base.ast.walk(child, self) - visitor = _SOAAssignVisitor() - nodes = [] - for child in node.targets: - rope.base.ast.walk(child, visitor) - nodes.extend(visitor.nodes) - self._evaluate_assign_value(node, nodes) - - -def _evaluate_assign_value(self, node, nodes, type_hint=False): - for subscript, levels in nodes: - instance = evaluate.eval_node(self.scope, subscript.value) - args_pynames = [evaluate.eval_node(self.scope, subscript.slice)] - value = rope.base.oi.soi._infer_assignment( - rope.base.pynames.AssignmentValue( - node.value, levels, type_hint=type_hint - ), - self.pymodule, - ) - args_pynames.append(rope.base.pynames.UnboundName(value)) - if instance is not None and value is not None: - pyobject = instance.get_object() - if "__setitem__" in pyobject: - pyfunction = pyobject["__setitem__"].get_object() - args = arguments.ObjectArguments([instance] + args_pynames) - self._call(pyfunction, args) - # IDEA: handle `__setslice__`, too - - - -class _SOAAssignVisitor(astutils._NodeNameCollector): - @others - -def __init__(self): - super().__init__() - self.nodes = [] - - -get_tuple = _create_builtin_getter(Tuple) -get_tuple_type = _create_builtin_type_getter(Tuple) - - - -def _added(self, node, levels): - if isinstance(node, rope.base.ast.Subscript) and isinstance( - node.slice, (rope.base.ast.Index, rope.base.ast.expr) - ): - self.nodes.append((node, levels)) - -@path C:/Repos/ekr-rope/rope/base/oi/ -"""A module for inferring objects - -For more information see the documentation in `rope.base.oi` -package. - -""" -import rope.base.builtins -import rope.base.pynames -import rope.base.pyobjects -from rope.base import evaluate, utils, arguments -from rope.base.oi.type_hinting.factory import get_type_hinting_factory - - -_ignore_inferred = utils.ignore_exception(rope.base.pyobjects.IsBeingInferredError) - - -@others -@language python -@tabwidth -4 - -@_ignore_inferred -def infer_returned_object(pyfunction, args): - """Infer the `PyObject` this `PyFunction` returns after calling""" - object_info = pyfunction.pycore.object_info - result = object_info.get_exact_returned(pyfunction, args) - if result is not None: - return result - result = _infer_returned(pyfunction, args) - if result is not None: - if args and pyfunction.get_module().get_resource() is not None: - params = args.get_arguments(pyfunction.get_param_names(special_args=False)) - object_info.function_called(pyfunction, params, result) - return result - result = object_info.get_returned(pyfunction, args) - if result is not None: - return result - hint_return = get_type_hinting_factory( - pyfunction.pycore.project - ).make_return_provider() - type_ = hint_return(pyfunction) - if type_ is not None: - return rope.base.pyobjects.PyObject(type_) - - - -@_ignore_inferred -def infer_parameter_objects(pyfunction): - """Infer the `PyObject` of parameters of this `PyFunction`""" - object_info = pyfunction.pycore.object_info - result = object_info.get_parameter_objects(pyfunction) - if result is None: - result = _parameter_objects(pyfunction) - _handle_first_parameter(pyfunction, result) - return result - - - -def _handle_first_parameter(pyobject, parameters): - kind = pyobject.get_kind() - if parameters is None or kind not in ["method", "classmethod"]: - pass - if not parameters: - if not pyobject.get_param_names(special_args=False): - return - parameters.append(rope.base.pyobjects.get_unknown()) - if kind == "method": - parameters[0] = rope.base.pyobjects.PyObject(pyobject.parent) - if kind == "classmethod": - parameters[0] = pyobject.parent - - - -@_ignore_inferred -def infer_assigned_object(pyname): - if not pyname.assignments: - return - for assignment in reversed(pyname.assignments): - result = _infer_assignment(assignment, pyname.module) - if ( - isinstance(result, rope.base.builtins.BuiltinUnknown) - and result.get_name() == "NotImplementedType" - ): - break - elif result == rope.base.pyobjects.get_unknown(): - break - elif result is not None: - return result - - hint_assignment = get_type_hinting_factory( - pyname.module.pycore.project - ).make_assignment_provider() - hinting_result = hint_assignment(pyname) - if hinting_result is not None: - return rope.base.pyobjects.PyObject(hinting_result) - return result - - - -def get_passed_objects(pyfunction, parameter_index): - object_info = pyfunction.pycore.object_info - result = object_info.get_passed_objects(pyfunction, parameter_index) - if not result: - statically_inferred = _parameter_objects(pyfunction) - if len(statically_inferred) > parameter_index: - result.append(statically_inferred[parameter_index]) - return result - - - -def _infer_returned(pyobject, args): - if args: - # HACK: Setting parameter objects manually - # This is not thread safe and might cause problems if `args` - # does not come from a good call site - pyobject.get_scope().invalidate_data() - pyobject._set_parameter_pyobjects( - args.get_arguments(pyobject.get_param_names(special_args=False)) - ) - scope = pyobject.get_scope() - if not scope._get_returned_asts(): - return - maxtries = 3 - for returned_node in reversed(scope._get_returned_asts()[-maxtries:]): - try: - resulting_pyname = evaluate.eval_node(scope, returned_node) - if resulting_pyname is None: - continue - pyobject = resulting_pyname.get_object() - if pyobject == rope.base.pyobjects.get_unknown(): - continue - if not scope._is_generator(): - return pyobject - else: - return rope.base.builtins.get_generator(pyobject) - except rope.base.pyobjects.IsBeingInferredError: - pass - - - -def _parameter_objects(pyobject): - result = [] - params = pyobject.get_param_names(special_args=False) - hint_param = get_type_hinting_factory(pyobject.pycore.project).make_param_provider() - for name in params: - type_ = hint_param(pyobject, name) - if type_ is not None: - result.append(rope.base.pyobjects.PyObject(type_)) - else: - result.append(rope.base.pyobjects.get_unknown()) - return result - - - -class Set(BuiltinClass): - @others - -# handling `rope.base.pynames.AssignmentValue` - - -@_ignore_inferred -def _infer_assignment(assignment, pymodule): - result = _follow_pyname(assignment, pymodule) - if result is None: - return None - pyname, pyobject = result - pyobject = _follow_evaluations(assignment, pyname, pyobject) - if pyobject is None: - return None - return _follow_levels(assignment, pyobject) - - - -def _follow_levels(assignment, pyobject): - for index in assignment.levels: - if isinstance(pyobject.get_type(), rope.base.builtins.Tuple): - holdings = pyobject.get_type().get_holding_objects() - if holdings: - pyobject = holdings[min(len(holdings) - 1, index)] - else: - pyobject = None - elif isinstance(pyobject.get_type(), rope.base.builtins.List): - pyobject = pyobject.get_type().holding - else: - pyobject = None - if pyobject is None: - break - return pyobject - - - -@_ignore_inferred -def _follow_pyname(assignment, pymodule, lineno=None): - assign_node = assignment.type_hint or assignment.ast_node - if lineno is None: - lineno = _get_lineno_for_node(assign_node) - holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - pyname = evaluate.eval_node(holding_scope, assign_node) - if pyname is not None: - result = pyname.get_object() - if ( - isinstance(result.get_type(), rope.base.builtins.Property) - and holding_scope.get_kind() == "Class" - ): - arg = rope.base.pynames.UnboundName( - rope.base.pyobjects.PyObject(holding_scope.pyobject) - ) - return pyname, result.get_type().get_property_object( - arguments.ObjectArguments([arg]) - ) - return pyname, result - - - -@_ignore_inferred -def _follow_evaluations(assignment, pyname, pyobject): - new_pyname = pyname - tokens = assignment.evaluation.split(".") - for token in tokens: - call = token.endswith("()") - if call: - token = token[:-2] - if token: - pyname = new_pyname - new_pyname = _get_attribute(pyobject, token) - if new_pyname is not None: - pyobject = new_pyname.get_object() - if pyobject is not None and call: - if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): - args = arguments.ObjectArguments([pyname]) - pyobject = pyobject.get_returned_object(args) - else: - pyobject = None - if pyobject is None: - break - if pyobject is not None and assignment.assign_type: - return rope.base.pyobjects.PyObject(pyobject) - return pyobject - - - -def _get_lineno_for_node(assign_node): - if hasattr(assign_node, "lineno") and assign_node.lineno is not None: - return assign_node.lineno - return 1 - - - -def _get_attribute(pyobject, name): - if pyobject is not None and name in pyobject: - return pyobject[name] - -@path C:/Repos/ekr-rope/rope/base/oi/ -"""Provides classes for persisting `PyObject`""" -import os -import re - -import rope.base.builtins -from rope.base import exceptions - - -@others -@language python -@tabwidth -4 - -class PyObjectToTextual: - """For transforming `PyObject` to textual form - - This can be used for storing `PyObjects` in files. Use - `TextualToPyObject` for converting back. - - """ - - @others - -def __init__(self, project): - self.project = project - - -def transform(self, pyobject): - """Transform a `PyObject` to textual form""" - if pyobject is None: - return ("none",) - object_type = type(pyobject) - try: - method = getattr(self, object_type.__name__ + "_to_textual") - return method(pyobject) - except AttributeError: - return ("unknown",) - - -def __init__(self, holding=None): - self.holding = holding - collector = _AttributeCollector(set) - collector("__new__", function=self._new_set) - - self_methods = [ - "copy", - "difference", - "intersection", - "symmetric_difference", - "union", - ] - for method in self_methods: - collector(method, function=self._self_get, parent=self) - collector("add", function=self._set_add, parent=self) - collector("update", function=self._self_set, parent=self) - collector("update", function=self._self_set, parent=self) - collector("symmetric_difference_update", function=self._self_set, parent=self) - collector("difference_update", function=self._self_set, parent=self) - - collector("pop", function=self._set_get, parent=self) - collector("__iter__", function=self._iterator_get, parent=self) - super().__init__(set, collector.attributes) - - -def __call__(self, pyobject): - return self.transform(pyobject) - - -def PyObject_to_textual(self, pyobject): - if isinstance(pyobject.get_type(), rope.base.pyobjects.AbstractClass): - result = self.transform(pyobject.get_type()) - if result[0] == "defined": - return ("instance", result) - return result - return ("unknown",) - - -def PyFunction_to_textual(self, pyobject): - return self._defined_to_textual(pyobject) - - -def PyClass_to_textual(self, pyobject): - return self._defined_to_textual(pyobject) - - -def _defined_to_textual(self, pyobject): - address = [] - while pyobject.parent is not None: - address.insert(0, pyobject.get_name()) - pyobject = pyobject.parent - return ( - "defined", - self._get_pymodule_path(pyobject.get_module()), - ".".join(address), - ) - - -def PyModule_to_textual(self, pyobject): - return ("defined", self._get_pymodule_path(pyobject)) - - -def PyPackage_to_textual(self, pyobject): - return ("defined", self._get_pymodule_path(pyobject)) - - -def List_to_textual(self, pyobject): - return ("builtin", "list", self.transform(pyobject.holding)) - - -def Dict_to_textual(self, pyobject): - return ( - "builtin", - "dict", - self.transform(pyobject.keys), - self.transform(pyobject.values), - ) - - -def Tuple_to_textual(self, pyobject): - objects = [ - self.transform(holding) for holding in pyobject.get_holding_objects() - ] - return tuple(["builtin", "tuple"] + objects) - - -def project_opened(project): - """This function is called after opening the project""" - # Do whatever you like here! - -def _new_set(self, args): - return _create_builtin(args, get_set) - - -def Set_to_textual(self, pyobject): - return ("builtin", "set", self.transform(pyobject.holding)) - - -def Iterator_to_textual(self, pyobject): - return ("builtin", "iter", self.transform(pyobject.holding)) - - -def Generator_to_textual(self, pyobject): - return ("builtin", "generator", self.transform(pyobject.holding)) - - -def Str_to_textual(self, pyobject): - return ("builtin", "str") - - -def File_to_textual(self, pyobject): - return ("builtin", "file") - - -def BuiltinFunction_to_textual(self, pyobject): - return ("builtin", "function", pyobject.get_name()) - - -def _get_pymodule_path(self, pymodule): - return self.resource_to_path(pymodule.get_resource()) - - -def resource_to_path(self, resource): - if resource.project == self.project: - return resource.path - else: - return resource.real_path - - - -class TextualToPyObject: - """For transforming textual form to `PyObject`""" - - @others - -def __init__(self, project, allow_in_project_absolutes=False): - self.project = project - - -def _set_add(self, context): - if self.holding is not None: - return - holding = context.get_arguments(["self", "value"])[1] - if holding is not None and holding != pyobjects.get_unknown(): - context.save_per_name(holding) - - -def __call__(self, textual): - return self.transform(textual) - - -def transform(self, textual): - """Transform an object from textual form to `PyObject`""" - if textual is None: - return None - type = textual[0] - try: - method = getattr(self, type + "_to_pyobject") - return method(textual) - except AttributeError: - return None - - -def builtin_to_pyobject(self, textual): - method = getattr(self, "builtin_%s_to_pyobject" % textual[1], None) - if method is not None: - return method(textual) - - -def builtin_str_to_pyobject(self, textual): - return rope.base.builtins.get_str() - - -def builtin_list_to_pyobject(self, textual): - holding = self.transform(textual[2]) - return rope.base.builtins.get_list(holding) - - -def builtin_dict_to_pyobject(self, textual): - keys = self.transform(textual[2]) - values = self.transform(textual[3]) - return rope.base.builtins.get_dict(keys, values) - - -def builtin_tuple_to_pyobject(self, textual): - objects = [self.transform(holding) for holding in textual[2:]] - return rope.base.builtins.get_tuple(*objects) - - -def builtin_set_to_pyobject(self, textual): - holding = self.transform(textual[2]) - return rope.base.builtins.get_set(holding) - - -def builtin_iter_to_pyobject(self, textual): - holding = self.transform(textual[2]) - return rope.base.builtins.get_iterator(holding) - - -def builtin_generator_to_pyobject(self, textual): - holding = self.transform(textual[2]) - return rope.base.builtins.get_generator(holding) - - -def _self_set(self, context): - if self.holding is not None: - return - iterable = context.get_pyname("iterable") - holding = _infer_sequence_for_pyname(iterable) - if holding is not None and holding != pyobjects.get_unknown(): - context.save_per_name(holding) - - -def builtin_file_to_pyobject(self, textual): - return rope.base.builtins.get_file() - - -def builtin_function_to_pyobject(self, textual): - if textual[2] in rope.base.builtins.builtins: - return rope.base.builtins.builtins[textual[2]].get_object() - - -def unknown_to_pyobject(self, textual): - return None - - -def none_to_pyobject(self, textual): - return None - - -def _module_to_pyobject(self, textual): - path = textual[1] - return self._get_pymodule(path) - - -def _hierarchical_defined_to_pyobject(self, textual): - path = textual[1] - names = textual[2].split(".") - pymodule = self._get_pymodule(path) - pyobject = pymodule - for name in names: - if pyobject is None: - return None - if isinstance(pyobject, rope.base.pyobjects.PyDefinedObject): - try: - pyobject = pyobject.get_scope()[name].get_object() - except exceptions.NameNotFoundError: - return None - else: - return None - return pyobject - - -def defined_to_pyobject(self, textual): - if len(textual) == 2 or textual[2] == "": - return self._module_to_pyobject(textual) - else: - return self._hierarchical_defined_to_pyobject(textual) - - -def instance_to_pyobject(self, textual): - type = self.transform(textual[1]) - if type is not None: - return rope.base.pyobjects.PyObject(type) - - -def _get_pymodule(self, path): - resource = self.path_to_resource(path) - if resource is not None: - return self.project.get_pymodule(resource) - - -def path_to_resource(self, path): - try: - root = self.project.address - if not os.path.isabs(path): - return self.project.get_resource(path) - if path == root or path.startswith(root + os.sep): - # INFO: This is a project file; should not be absolute - return None - import rope.base.project - - return rope.base.project.get_no_project().get_resource(path) - except exceptions.ResourceNotFoundError: - return None - - - -def _set_get(self, context): - if self.holding is not None: - return self.holding - return context.get_per_name() - - -class DOITextualToPyObject(TextualToPyObject): - """For transforming textual form to `PyObject` - - The textual form DOI uses is different from rope's standard - textual form. The reason is that we cannot find the needed - information by analyzing live objects. This class can be - used to transform DOI textual form to `PyObject` and later - we can convert it to standard textual form using - `TextualToPyObject` class. - - """ - - @others - -def _function_to_pyobject(self, textual): - path = textual[1] - lineno = int(textual[2]) - pymodule = self._get_pymodule(path) - if pymodule is not None: - scope = pymodule.get_scope() - inner_scope = scope.get_inner_scope_for_line(lineno) - return inner_scope.pyobject - - -def _class_to_pyobject(self, textual): - path, name = textual[1:] - pymodule = self._get_pymodule(path) - if pymodule is None: - return None - module_scope = pymodule.get_scope() - suspected = None - if name in module_scope.get_names(): - suspected = module_scope[name].get_object() - if suspected is not None and isinstance(suspected, rope.base.pyobjects.PyClass): - return suspected - else: - lineno = self._find_occurrence(name, pymodule.get_resource().read()) - if lineno is not None: - inner_scope = module_scope.get_inner_scope_for_line(lineno) - return inner_scope.pyobject - - -def defined_to_pyobject(self, textual): - if len(textual) == 2: - return self._module_to_pyobject(textual) - else: - if textual[2].isdigit(): - result = self._function_to_pyobject(textual) - else: - result = self._class_to_pyobject(textual) - if not isinstance(result, rope.base.pyobjects.PyModule): - return result - - -def _find_occurrence(self, name, source): - pattern = re.compile(r"^\s*class\s*" + name + r"\b") - lines = source.split("\n") - for i in range(len(lines)): - if pattern.match(lines[i]): - return i + 1 - - -def path_to_resource(self, path): - import rope.base.libutils - - relpath = rope.base.libutils.path_relative_to_project_root(self.project, path) - if relpath is not None: - path = relpath - return super().path_to_resource(path) - -@path C:/Repos/ekr-rope/rope/base/oi/ -<< docstring: oi/__init__ >> -@language python -@tabwidth -4 - - -@path C:/Repos/ekr-rope/rope/base/ -@nopyflakes -# Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm -# and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py -import re -from rope.base.oi.type_hinting import utils -from rope.base import utils as base_utils - - -@others -evaluate = Evaluator() -@language python -@tabwidth -4 - -class SymbolBase: - - name = None # node/token type name - - @others - -def _iterator_get(self, context): - return get_iterator(self._set_get(context)) - - -def __init__(self): - self.value = None # used by name and literals - self.first = None - self.second = None - self.third = None # used by tree nodes - - -def nud(self, parser): - raise SyntaxError("Syntax error (%r)." % self.name) - - -def led(self, left, parser): - raise SyntaxError("Unknown operator (%r)." % self.name) - - -def evaluate(self, pyobject): - raise NotImplementedError(self.name, self) - - -def __repr__(self): - if self.name == "(name)": - return "({} {})".format(self.name[1:-1], self.value) - out = [repr(self.name), self.first, self.second, self.third] - out = [str(i) for i in out if i] - return "(" + " ".join(out) + ")" - - - -class SymbolTable: - @others - multi = staticmethod(multi) # Just for code checker - - - -def multi(func): - def _inner(self, names, *a, **kw): - for name in names.split(): - func(self, name, *a, **kw) - - return _inner - - -def __init__(self): - self.symbol_table = {} - - -def get(self, name, default=None): - return self.symbol_table.get(name, default) - - -def __getitem__(self, name): - return self.symbol_table[name] - - -def _self_get(self, context): - return get_list(self._set_get(context)) - - - -def __iter__(self): - return iter(self.symbol_table) - - -def symbol(self, name, bp=0): - try: - s = self.symbol_table[name] - except KeyError: - - @others - s = S - s.__name__ = "symbol-" + name # for debugging - s.name = name - s.lbp = bp - self.symbol_table[name] = s - else: - s.lbp = max(bp, s.lbp) - return s - - -class S(SymbolBase): - pass - - -@multi -def infix(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def led(self, left, parser): - self.first = left - self.second = parser.expression(bp) - return self - - -@multi -def infix_r(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def led(self, left, parser): - self.first = left - self.second = parser.expression(bp - 0.1) - return self - - -def ternary(self, name, name2, bp): - symbol = self.symbol(name, bp) - symbol2 = self.symbol(name2) - - @method(symbol) - def led(self, left, parser): - self.first = left - self.second = parser.expression(symbol2.lbp) - parser.advance(symbol2.name) - self.third = parser.expression(symbol2.lbp + 0.1) - return self - - -@multi -def prefix(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def nud(self, parser): - self.first = parser.expression(bp) - return self - - -@multi -def postfix(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def led(self, left, parser): - self.first = left - return self - - -symbol_table = SymbolTable() - - - -class Lexer: - - _token_pattern = re.compile( - r""" - \s* - (?: - ( - [,()\[\]|] - | -> - | (?<=\s)(?:or)\b - ) # operator - | ([a-zA-Z](?:\w|\.)*) # name - ) - """, - re.U | re.S | re.X, - ) - - @others - -get_set = _create_builtin_getter(Set) -get_set_type = _create_builtin_type_getter(Set) - - - -def __init__(self, symbol_table): - self.symbol_table = symbol_table - - -def tokenize(self, program): - for name, value in self._tokenize_expr(program): - symbol = symbol_table.get(value) - if symbol: - s = symbol() - elif name == "(name)": - symbol = symbol_table[name] - s = symbol() - s.value = value - else: - raise SyntaxError( - "Unknown operator ({}). Possible operators are {!r}".format( - value, list(self.symbol_table) - ) - ) - - yield s - - -def _tokenize_expr(self, program): - if isinstance(program, bytes): - program = program.decode("utf-8") - # import pprint; pprint.pprint(self._token_pattern.findall(program)) - for operator, name in self._token_pattern.findall(program): - if operator: - yield "(operator)", operator - elif name: - yield "(name)", name - else: - raise SyntaxError - yield "(end)", "(end)" - - - -class Parser: - - token = None - next = None - - @others - -def __init__(self, lexer): - self.lexer = lexer - - -def parse(self, program): - generator = self.lexer.tokenize(program) - self.next = generator.__next__ - self.token = self.next() - return self.expression() - - -def expression(self, rbp=0): - t = self.token - self.token = self.next() - left = t.nud(self) - while rbp < self.token.lbp: - t = self.token - self.token = self.next() - left = t.led(left, self) - return left - - -def advance(self, name=None): - if name and self.token.name != name: - raise SyntaxError(f"Expected {name!r} but found {self.token.name!r}") - self.token = self.next() - - - -def method(s): - assert issubclass(s, SymbolBase) - - @others - return bind - - - -def bind(fn): - setattr(s, fn.__name__, fn) - return fn - - -class Str(BuiltinClass): - @others - -symbol, infix, infix_r, prefix, postfix, ternary = ( - symbol_table.symbol, - symbol_table.infix, - symbol_table.infix_r, - symbol_table.prefix, - symbol_table.postfix, - symbol_table.ternary, -) - -symbol("(", 270) -symbol(")") -symbol("[", 250) # Parameters -symbol("]") -symbol("->", 230) -infix("|", 170) -infix("or", 170) -symbol(",") - -symbol("(name)") -symbol("(end)") - - - -@method(symbol("(name)")) -def nud(self, parser): - return self - - - -@method(symbol("(name)")) -def evaluate(self, pyobject): - return utils.resolve_type(self.value, pyobject) - - - -# Parametrized objects -@method(symbol("[")) -def led(self, left, parser): - self.first = left - self.second = [] - if parser.token.name != "]": - while 1: - if parser.token.name == "]": - break - self.second.append(parser.expression()) - if parser.token.name != ",": - break - parser.advance(",") - parser.advance("]") - return self - - - -@method(symbol("[")) -def evaluate(self, pyobject): - return utils.parametrize_type( - self.first.evaluate(pyobject), *[i.evaluate(pyobject) for i in self.second] - ) - - - -# Anonymous Function Calls -@method(symbol("(")) -def nud(self, parser): - self.second = [] - if parser.token.name != ")": - while 1: - self.second.append(parser.expression()) - if parser.token.name != ",": - break - parser.advance(",") - parser.advance(")") - parser.advance("->") - self.third = parser.expression(symbol("->").lbp + 0.1) - return self - - - -# Function Calls -@method(symbol("(")) -def led(self, left, parser): - self.first = left - self.second = [] - if parser.token.name != ")": - while 1: - self.second.append(parser.expression()) - if parser.token.name != ",": - break - parser.advance(",") - parser.advance(")") - parser.advance("->") - self.third = parser.expression(symbol("->").lbp + 0.1) - return self - - - -@method(symbol("(")) -def evaluate(self, pyobject): - # TODO: Implement me - raise NotImplementedError - - - -@method(symbol("or")) -@method(symbol("|")) -def evaluate(self, pyobject): - # TODO: Implement me - raise NotImplementedError - - - -class Compiler: - - parser_factory = Parser - lexer_factory = Lexer - symbol_table = symbol_table - - @others - -def __init__(self): - self_object = pyobjects.PyObject(self) - collector = _AttributeCollector(str) - collector("__iter__", get_iterator(self_object), check_existence=False) - - self_methods = [ - "__getitem__", - "capitalize", - "center", - "encode", - "expandtabs", - "join", - "ljust", - "lower", - "lstrip", - "replace", - "rjust", - "rstrip", - "strip", - "swapcase", - "title", - "translate", - "upper", - "zfill", - ] - for method in self_methods: - collector(method, self_object, parent=self) - - py2_self_methods = ["__getslice__", "decode"] - for method in py2_self_methods: - try: - collector(method, self_object) - except AttributeError: - pass - - for method in ["rsplit", "split", "splitlines"]: - collector(method, get_list(self_object), parent=self) - - super().__init__(str, collector.attributes) - - -def _make_parser(self): - return self.parser_factory(self.lexer_factory(self.symbol_table)) - - -@base_utils.cached(500) -def __call__(self, program): - """ - :type program: str - :rtype: rope.base.oi.type_hinting.evaluate.SymbolBase - """ - return self._make_parser().parse(program) - - - -compile = Compiler() - - - -class Evaluator: - - compile = compile - - @others - -def __call__(self, program, pyobject): - """Evaluates the program string or AST - - :type program: str or rope.base.oi.type_hinting.evaluate.SymbolBase - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - ast = self.compile(program) if isinstance(program, str) else program - return ast.evaluate(pyobject) - - - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/ -from rope.base.oi.type_hinting import interfaces -from rope.base.oi.type_hinting.providers import ( - composite, - inheritance, - docstrings, - numpydocstrings, - pep0484_type_comments, -) -from rope.base.oi.type_hinting.resolvers import composite as composite_resolvers, types -from rope.base import utils - - -@others -get_type_hinting_factory = TypeHintingFactoryAccessor() -@language python -@tabwidth -4 - -class TypeHintingFactory(interfaces.ITypeHintingFactory): - @others - -@utils.saveit -def make_param_provider(self): - providers = [ - docstrings.ParamProvider( - docstrings.DocstringParamParser(), self.make_resolver() - ), - docstrings.ParamProvider( - numpydocstrings.NumPyDocstringParamParser(), self.make_resolver() - ), - ] - return inheritance.ParamProvider(composite.ParamProvider(*providers)) - - -@utils.saveit -def make_return_provider(self): - providers = [ - docstrings.ReturnProvider( - docstrings.DocstringReturnParser(), self.make_resolver() - ), - ] - return inheritance.ReturnProvider(composite.ReturnProvider(*providers)) - - -@utils.saveit -def make_assignment_provider(self): - providers = [ - pep0484_type_comments.AssignmentProvider(self.make_resolver()), - docstrings.AssignmentProvider( - docstrings.DocstringParamParser(), self.make_resolver() - ), - docstrings.AssignmentProvider( - numpydocstrings.NumPyDocstringParamParser(), self.make_resolver() - ), - ] - return inheritance.AssignmentProvider(composite.AssignmentProvider(*providers)) - - -def get_doc(self): - return str.__doc__ - - - -@utils.saveit -def make_resolver(self): - """ - :rtype: rope.base.oi.type_hinting.resolvers.interfaces.IResolver - """ - resolvers = [ - types.Resolver(), - ] - return composite_resolvers.Resolver(*resolvers) - - - -default_type_hinting_factory = TypeHintingFactory() - - - -class TypeHintingFactoryAccessor: - @others - -def __call__(self, project): - """ - :type project: rope.base.project.Project - :rtype: rope.base.oi.type_hinting.interfaces.ITypeHintingFactory - """ - factory_location = project.get_prefs().get( - "type_hinting_factory", - "rope.base.oi.type_hinting.factory.default_type_hinting_factory", - ) - return self._get_factory(factory_location) - - -@utils.cached(10) -def _get_factory(self, factory_location): - """ - :type factory_location: str - :rtype: rope.base.oi.type_hinting.interfaces.ITypeHintingFactory - """ - return utils.resolve(factory_location) - - - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/ -@others -@language python -@tabwidth -4 - -class ITypeHintingFactory: - @others - -def make_param_provider(self): - """ - :rtype: rope.base.oi.type_hinting.providers.interfaces.IParamProvider - """ - raise NotImplementedError - - -def make_return_provider(self): - """ - :rtype: rope.base.oi.type_hinting.providers.interfaces.IReturnProvider - """ - raise NotImplementedError - - -def make_assignment_provider(self): - """ - :rtype: rope.base.oi.type_hinting.providers.interfaces.IAssignmentProvider - """ - raise NotImplementedError - - -get_str = _create_builtin_getter(Str) -get_str_type = _create_builtin_type_getter(Str) - - - -def make_resolver(self): - """ - :rtype: rope.base.oi.type_hinting.resolvers.interfaces.IResolver - """ - raise NotImplementedError - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/ -import logging - -try: - from typing import Union, Optional -except ImportError: - pass -import rope.base.utils as base_utils -from rope.base import evaluate -from rope.base.exceptions import AttributeNotFoundError -from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject - - -@others -parametrize_type = ParametrizeType() -@language python -@tabwidth -4 - -def get_super_func(pyfunc): - - if not isinstance(pyfunc.parent, PyClass): - return - - for cls in get_mro(pyfunc.parent)[1:]: - try: - superfunc = cls.get_attribute(pyfunc.get_name()).get_object() - except AttributeNotFoundError: - pass - else: - if isinstance(superfunc, PyFunction): - return superfunc - - - -def get_super_assignment(pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :type: rope.base.pynamesdef.AssignedName - """ - try: - pyclass, attr_name = get_class_with_attr_name(pyname) - except TypeError: - return - else: - for super_pyclass in get_mro(pyclass)[1:]: - if attr_name in super_pyclass: - return super_pyclass[attr_name] - - - -def get_class_with_attr_name(pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :return: rope.base.pyobjectsdef.PyClass, str - :rtype: tuple - """ - lineno = get_lineno_for_node(pyname.assignments[0].ast_node) - holding_scope = pyname.module.get_scope().get_inner_scope_for_line(lineno) - pyobject = holding_scope.pyobject - if isinstance(pyobject, PyClass): - pyclass = pyobject - elif isinstance(pyobject, PyFunction) and isinstance(pyobject.parent, PyClass): - pyclass = pyobject.parent - else: - return - for name, attr in pyclass.get_attributes().items(): - if attr is pyname: - return (pyclass, name) - - - -def get_lineno_for_node(assign_node): - if hasattr(assign_node, "lineno") and assign_node.lineno is not None: - return assign_node.lineno - return 1 - - - -def get_mro(pyclass): - # FIXME: to use real mro() result - class_list = [pyclass] - for cls in class_list: - for super_cls in cls.get_superclasses(): - if isinstance(super_cls, PyClass) and super_cls not in class_list: - class_list.append(super_cls) - return class_list - - - -def resolve_type(type_name, pyobject): - # type: (str, Union[PyDefinedObject, PyObject]) -> Optional[PyDefinedObject, PyObject] - """ - Find proper type object from its name. - """ - deprecated_aliases = {"collections": "collections.abc"} - ret_type = None - logging.debug("Looking for %s", type_name) - if "." not in type_name: - try: - ret_type = ( - pyobject.get_module().get_scope().get_name(type_name).get_object() - ) - except AttributeNotFoundError: - logging.exception("Cannot resolve type %s", type_name) - else: - mod_name, attr_name = type_name.rsplit(".", 1) - try: - mod_finder = evaluate.ScopeNameFinder(pyobject.get_module()) - mod = mod_finder._find_module(mod_name).get_object() - ret_type = mod.get_attribute(attr_name).get_object() - except AttributeNotFoundError: - if mod_name in deprecated_aliases: - try: - logging.debug( - "Looking for %s in %s", attr_name, deprecated_aliases[mod_name] - ) - mod = mod_finder._find_module( - deprecated_aliases[mod_name] - ).get_object() - ret_type = mod.get_attribute(attr_name).get_object() - except AttributeNotFoundError: - logging.exception( - "Cannot resolve type %s in %s", attr_name, dir(mod) - ) - logging.debug("ret_type = %s", ret_type) - return ret_type - - - -class ParametrizeType: - - _supported_mapping = { - "builtins.list": "rope.base.builtins.get_list", - "builtins.tuple": "rope.base.builtins.get_tuple", - "builtins.set": "rope.base.builtins.get_set", - "builtins.dict": "rope.base.builtins.get_dict", - "_collections_abc.Iterable": "rope.base.builtins.get_iterator", - "_collections_abc.Iterator": "rope.base.builtins.get_iterator", - "collections.abc.Iterable": "rope.base.builtins.get_iterator", # Python3.3 - "collections.abc.Iterator": "rope.base.builtins.get_iterator", # Python3.3 - } - - @others - -def __call__(self, pyobject, *args, **kwargs): - """ - :type pyobject: rope.base.pyobjects.PyObject - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - type_factory = self._get_type_factory(pyobject) - if type_factory: - parametrized_type = type_factory(*args, **kwargs) - if parametrized_type: - return parametrized_type - return pyobject - - -class BuiltinName(pynames.PyName): - @others - -def _get_type_factory(self, pyobject): - type_str = "{}.{}".format( - pyobject.get_module().get_name(), - pyobject.get_name(), - ) - if type_str in self._supported_mapping: - return base_utils.resolve(self._supported_mapping[type_str]) - - - - - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ -from rope.base.oi.type_hinting.providers import interfaces - - -@others -@language python -@tabwidth -4 - -class ParamProvider(interfaces.IParamProvider): - @others - -def __init__(self, *delegates): - """ - :type delegates: list[rope.base.oi.type_hinting.providers.interfaces.IParamProvider] - """ - self._delegates = delegates - - -def __call__(self, pyfunc, param_name): - """ - :type pyfunc: rope.base.pyobjectsdef.PyFunction - :type param_name: str - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - for delegate in self._delegates: - result = delegate(pyfunc, param_name) - if result: - return result - - - -class ReturnProvider(interfaces.IReturnProvider): - @others - -def __init__(self, *delegates): - """ - :type delegates: list[rope.base.oi.type_hinting.providers.interfaces.IReturnProvider] - """ - self._delegates = delegates - - -def __call__(self, pyfunc): - """ - :type pyfunc: rope.base.pyobjectsdef.PyFunction - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - for delegate in self._delegates: - result = delegate(pyfunc) - if result: - return result - - - -def __init__(self, pyobject): - self.pyobject = pyobject - - -class AssignmentProvider(interfaces.IAssignmentProvider): - @others - -def __init__(self, *delegates): - """ - :type delegates: list[rope.base.oi.type_hinting.providers.interfaces.IAssignmentProvider] - """ - self._delegates = delegates - - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - for delegate in self._delegates: - result = delegate(pyname) - if result: - return result - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ -""" -Hinting the type using docstring of class/function. - -It's an irreplaceable thing if you are using Dependency Injection with passive class: -http://www.martinfowler.com/articles/injection.html - -Some code extracted (or based on code) from: -https://github.com/davidhalter/jedi/blob/b489019f5bd5750051122b94cc767df47751ecb7/jedi/evaluate/docstrings.py -Thanks to @davidhalter for this utils under MIT License. - -Similar solutions: - - - https://www.jetbrains.com/pycharm/help/type-hinting-in-pycharm.html - - https://www.python.org/dev/peps/pep-0484/#type-comments - - http://www.pydev.org/manual_adv_type_hints.html - - https://jedi.readthedocs.org/en/latest/docs/features.html#type-hinting - -Discussions: - - - https://groups.google.com/d/topic/rope-dev/JlAzmZ83K1M/discussion - - https://groups.google.com/d/topic/rope-dev/LCFNN98vckI/discussion - -""" -import re - -from rope.base.oi.type_hinting import utils -from rope.base.oi.type_hinting.providers import interfaces - - -@others -@language python -@tabwidth -4 - -class ParamProvider(interfaces.IParamProvider): - @others - -def __init__(self, docstring_parser, resolver): - """ - :type docstring_parser: rope.base.oi.type_hinting.providers.docstrings.IParamParser - :type resolver: rope.base.oi.type_hinting.resolvers.interfaces.IResolver - """ - self._parse_docstring = docstring_parser - self._resolve = resolver - - -def __call__(self, pyfunc, param_name): - """ - :type pyfunc: rope.base.pyobjectsdef.PyFunction - :type param_name: str - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - type_strs = self._parse_docstring(pyfunc.get_doc(), param_name) - if type_strs: - return self._resolve(type_strs[0], pyfunc) - - - -class ReturnProvider(interfaces.IReturnProvider): - @others - -def __init__(self, docstring_parser, resolver): - """ - :type docstring_parser: rope.base.oi.type_hinting.providers.docstrings.IReturnParser - :type resolver: rope.base.oi.type_hinting.resolvers.interfaces.IResolver - """ - self._parse_docstring = docstring_parser - self._resolve = resolver - - -def __call__(self, pyfunc): - """ - :type pyfunc: rope.base.pyobjectsdef.PyFunction - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - type_strs = self._parse_docstring(pyfunc.get_doc()) - if type_strs: - return self._resolve(type_strs[0], pyfunc) - - - -def get_object(self): - return self.pyobject - - -class AssignmentProvider(interfaces.IAssignmentProvider): - @others - -def __init__(self, docstring_parser, resolver): - """ - :type docstring_parser: rope.base.oi.type_hinting.providers.docstrings.IParamParser - :type resolver: rope.base.oi.type_hinting.resolvers.interfaces.IResolver - """ - self._parse_docstring = docstring_parser - self._resolve = resolver - - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - try: - pyclass, attr_name = utils.get_class_with_attr_name(pyname) - except TypeError: - return - else: - type_strs = self._parse_docstring(pyclass.get_doc(), attr_name) - if type_strs: - return self._resolve(type_strs[0], pyclass) - - - -class IParamParser: - def __call__(self, docstring, param_name): - """ - :type docstring: str - :type param_name: str - """ - - - -class IReturnParser: - def __call__(self, docstring): - """ - :type docstring: str - """ - - - -class DocstringParamParser(IParamParser): - - DOCSTRING_PARAM_PATTERNS = [ - r"\s*:type\s+%s:\s*([^\n]+)", # Sphinx - r"\s*:param\s+(\w+)\s+%s:[^\n]+", # Sphinx param with type - r"\s*@type\s+%s:\s*([^\n]+)", # Epydoc - ] - - @others - -def __init__(self): - self._strip_rst_role = RSTRoleStrip() - - -def __call__(self, docstring, param_name): - """Search `docstring` for type(-s) of `param_name`. - - >>> DocstringParamParser()(':type param: int', 'param') - ['int'] - >>> DocstringParamParser()('@type param: int', 'param') - ['int'] - >>> DocstringParamParser()(':type param: :class:`threading.Thread`', 'param') - ['threading.Thread'] - >>> bool(DocstringParamParser()('no document', 'param')) - False - >>> DocstringParamParser()(':param int param: some description', 'param') - ['int'] - """ - if not docstring: - return [] - patterns = [ - re.compile(p % re.escape(param_name)) for p in self.DOCSTRING_PARAM_PATTERNS - ] - for pattern in patterns: - match = pattern.search(docstring) - if match: - return [self._strip_rst_role(match.group(1))] - - return [] - - - -class DocstringReturnParser(IReturnParser): - - DOCSTRING_RETURN_PATTERNS = [ - re.compile(r"\s*:rtype:\s*([^\n]+)", re.M), # Sphinx - re.compile(r"\s*@rtype:\s*([^\n]+)", re.M), # Epydoc - ] - - @others - -def __init__(self): - self._strip_rst_role = RSTRoleStrip() - - -def get_definition_location(self): - return (None, None) - - - -def __call__(self, docstring): - if not docstring: - return [] - for p in self.DOCSTRING_RETURN_PATTERNS: - match = p.search(docstring) - if match: - return [self._strip_rst_role(match.group(1))] - return [] - - - -class RSTRoleStrip: - - RST_ROLE_PATTERN = re.compile(r":[^`]+:`([^`]+)`") - - @others - -def __call__(self, type_str): - """ - Strip off the part looks like a ReST role in `type_str`. - - >>> RSTRoleStrip()(':class:`ClassName`') # strip off :class: - 'ClassName' - >>> RSTRoleStrip()(':py:obj:`module.Object`') # works with domain - 'module.Object' - >>> RSTRoleStrip()('ClassName') # do nothing when not ReST role - 'ClassName' - - See also: - http://sphinx-doc.org/domains.html#cross-referencing-python-objects - - """ - match = self.RST_ROLE_PATTERN.match(type_str) - if match: - return match.group(1) - else: - return type_str - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ -from rope.base.oi.type_hinting import utils -from rope.base.oi.type_hinting.providers import interfaces - - -@others -@language python -@tabwidth -4 - -class ParamProvider(interfaces.IParamProvider): - @others - -def __init__(self, delegate): - """ - :type delegate: rope.base.oi.type_hinting.providers.interfaces.IParamProvider - """ - self._delegate = delegate - - -def __call__(self, pyfunc, param_name): - """ - :type pyfunc: rope.base.pyobjectsdef.PyFunction - :type param_name: str - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - superfunc = pyfunc - while superfunc: - result = self._delegate(superfunc, param_name) - if result: - return result - superfunc = utils.get_super_func(superfunc) - - - -class ReturnProvider(interfaces.IReturnProvider): - @others - -def __init__(self, delegate): - """ - :type delegate: rope.base.oi.type_hinting.providers.interfaces.IReturnProvider - """ - self._delegate = delegate - - -def __call__(self, pyfunc): - """ - :type pyfunc: rope.base.pyobjectsdef.PyFunction - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - superfunc = pyfunc - while superfunc: - result = self._delegate(superfunc) - if result: - return result - superfunc = utils.get_super_func(superfunc) - - - -class Iterator(pyobjects.AbstractClass): - @others - -class AssignmentProvider(interfaces.IAssignmentProvider): - @others - -def __init__(self, delegate): - """ - :type delegate: rope.base.oi.type_hinting.providers.interfaces.IAssignmentProvider - """ - self._delegate = delegate - - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - super_pyname = pyname - while super_pyname: - result = self._delegate(super_pyname) - if result: - return result - super_pyname = utils.get_super_assignment(super_pyname) - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ -@others -@language python -@tabwidth -4 - -class IParamProvider: - @others - -def __call__(self, pyfunc, param_name): - """ - :type pyfunc: rope.base.pyobjectsdef.PyFunction - :type param_name: str - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - raise NotImplementedError - - - -class IReturnProvider: - """ - :type resolve: rope.base.oi.type_hinting.resolvers.interfaces.IResolver - """ - - resolve = None - - @others - -def __call__(self, pyfunc): - """ - :type pyfunc: rope.base.pyobjectsdef.PyFunction - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - raise NotImplementedError - - - -class IAssignmentProvider: - """ - :type resolve: rope.base.oi.type_hinting.resolvers.interfaces.IResolver - """ - - resolve = None - - @others - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - raise NotImplementedError - -def __init__(self, holding=None): - super().__init__() - self.holding = holding - self.attributes = { - "next": BuiltinName(BuiltinFunction(self.holding)), - "__iter__": BuiltinName(BuiltinFunction(self)), - } - - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ -@nopyflakes -""" -Some code extracted (or based on code) from: -https://github.com/davidhalter/jedi/blob/b489019f5bd5750051122b94cc767df47751ecb7/jedi/evaluate/docstrings.py -Thanks to @davidhalter for this utils under MIT License. -""" -import re -from ast import literal_eval -from rope.base.oi.type_hinting.providers import docstrings - -try: - from numpydoc.docscrape import NumpyDocString -except ImportError: - NumpyDocString = None - - -@others -if not NumpyDocString: - NumPyDocstringParamParser = _DummyParamParser -@language python -@tabwidth -4 - -class NumPyDocstringParamParser(docstrings.IParamParser): - @others - -def __call__(self, docstring, param_name): - """Search `docstring` (in numpydoc format) for type(-s) of `param_name`.""" - if not docstring: - return [] - params = NumpyDocString(docstring)._parsed_data["Parameters"] - for p_name, p_type, p_descr in params: - if p_name == param_name: - m = re.match("([^,]+(,[^,]+)*?)(,[ ]*optional)?$", p_type) - if m: - p_type = m.group(1) - - if p_type.startswith("{"): - types = {type(x).__name__ for x in literal_eval(p_type)} - return list(types) - else: - return [p_type] - return [] - - - -class _DummyParamParser(docstrings.IParamParser): - def __call__(self, docstring, param_name): - return [] - - - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ -import re -from rope.base.oi.type_hinting import utils -from rope.base.oi.type_hinting.providers import interfaces - - -@others -@language python -@tabwidth -4 - -class AssignmentProvider(interfaces.IAssignmentProvider): - @others - -def __init__(self, resolver): - """ - :type resolver: rope.base.oi.type_hinting.resolvers.interfaces.IResolver - """ - self._resolve = resolver - - -PEP0484_TYPE_COMMENT_PATTERNS = (re.compile(r"type:\s*([^\n]+)"),) - - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - from rope.base.oi.soi import _get_lineno_for_node - - lineno = _get_lineno_for_node(pyname.assignments[0].ast_node) - holding_scope = pyname.module.get_scope().get_inner_scope_for_line(lineno) - line = holding_scope._get_global_scope()._scope_finder.lines.get_line(lineno) - if "#" in line: - type_strs = self._search_type_in_type_comment(line.split("#", 1)[1]) - if type_strs: - return self._resolve(type_strs[0], holding_scope.pyobject) - - -def _search_type_in_type_comment(self, code): - """For more info see: - https://www.python.org/dev/peps/pep-0484/#type-comments - - >>> AssignmentProvider()._search_type_in_type_comment('type: int') - ['int'] - """ - for p in self.PEP0484_TYPE_COMMENT_PATTERNS: - match = p.search(code) - if match: - return [match.group(1)] - -def get_attributes(self): - return self.attributes - - - - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/resolvers/ -from rope.base.oi.type_hinting.resolvers import interfaces - - -@others -@language python -@tabwidth -4 - -class Resolver(interfaces.IResolver): - @others - -def __init__(self, *delegates): - """ - :type delegates: list[rope.base.oi.type_hinting.resolvers.interfaces.IResolver] - """ - self._delegates = delegates - - -def __call__(self, hint, pyobject): - """ - :param hint: For example "List[int]" or "(Foo, Bar) -> Baz" or simple "Foo" - :type hint: str - :type pyobject: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - for delegate in self._delegates: - result = delegate(hint, pyobject) - if result: - return result - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/resolvers/ -class IResolver: - def __call__(self, hint, pyobject): - """ - :param hint: For example "List[int]" or "(Foo, Bar) -> Baz" or simple "Foo" - :type hint: str - :type pyobject: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - raise NotImplementedError -@language python -@tabwidth -4 - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/resolvers/ -from rope.base.oi.type_hinting import evaluate -from rope.base.oi.type_hinting.resolvers import interfaces - - -@others -@language python -@tabwidth -4 - -class Resolver(interfaces.IResolver): - @others - -def __call__(self, hint, pyobject): - """ - :param hint: For example "List[int]" or "(Foo, Bar) -> Baz" or simple "Foo" - :type hint: str - :type pyobject: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - try: - return evaluate.evaluate(hint, pyobject) - except (Exception): - pass - -def get_returned_object(self, args): - return self.holding - - - - - -@path C:/Repos/ekr-rope/rope/base/utils/ -# this snippet was taken from this link -# http://code.activestate.com/recipes/576694/ - -try: - from collections.abc import MutableSet -except ImportError: - from collections import MutableSet - - -@others -@language python -@tabwidth -4 - -class OrderedSet(MutableSet): - @others - -def __init__(self, iterable=None): - self.end = end = [] - end += [None, end, end] # sentinel - # node for doubly linked list - self.map = {} # key --> [key, prev, next] - if iterable is not None: - self |= iterable - - -def __len__(self): - return len(self.map) - - -def __contains__(self, key): - return key in self.map - - -def add(self, key): - if key not in self.map: - end = self.end - curr = end[1] - curr[2] = end[1] = self.map[key] = [key, curr, end] - - -def intersection(self, set_b): - return OrderedSet([item for item in self if item in set_b]) - - -def discard(self, key): - if key in self.map: - key, prev, next = self.map.pop(key) - prev[2] = next - next[1] = prev - - -get_iterator = _create_builtin_getter(Iterator) - - - -def __iter__(self): - end = self.end - curr = end[2] - while curr is not end: - yield curr[0] - curr = curr[2] - - -def __reversed__(self): - end = self.end - curr = end[1] - while curr is not end: - yield curr[0] - curr = curr[1] - - -def pop(self, last=True): - if not self: - raise KeyError("set is empty") - key = self.end[1][0] if last else self.end[2][0] - self.discard(key) - return key - - -def __repr__(self): - if not self: - return "{}()".format(self.__class__.__name__) - return "{}({!r})".format(self.__class__.__name__, list(self)) - - -def __eq__(self, other): - if isinstance(other, OrderedSet): - return len(self) == len(other) and list(self) == list(other) - return set(self) == set(other) - -@path C:/Repos/ekr-rope/rope/base/utils/ -import sys -import warnings - - -@others -@language python -@tabwidth -4 - - -class Generator(pyobjects.AbstractClass): - @others - -def saveit(func): - """A decorator that caches the return value of a function""" - - name = "_" + func.__name__ - - @others - return _wrapper - - - -def _wrapper(self, *args, **kwds): - if not hasattr(self, name): - setattr(self, name, func(self, *args, **kwds)) - return getattr(self, name) - - -cacheit = saveit - - - -def prevent_recursion(default): - """A decorator that returns the return value of `default` in recursions""" - - @others - return decorator - - - -def decorator(func): - name = "_calling_%s_" % func.__name__ - - def newfunc(self, *args, **kwds): - if getattr(self, name, False): - return default() - setattr(self, name, True) - try: - return func(self, *args, **kwds) - finally: - setattr(self, name, False) - - return newfunc - - -def ignore_exception(exception_class): - """A decorator that ignores `exception_class` exceptions""" - - @others - return _decorator - - - -def _decorator(func): - def newfunc(*args, **kwds): - try: - return func(*args, **kwds) - except exception_class: - pass - - return newfunc - - -def deprecated(message=None): - """A decorator for deprecated functions""" - - @others - return _decorator - - - -def _decorator(func, message=message): - if message is None: - message = "%s is deprecated" % func.__name__ - - def newfunc(*args, **kwds): - warnings.warn(message, DeprecationWarning, stacklevel=2) - return func(*args, **kwds) - - return newfunc - - -def cached(size): - """A caching decorator based on parameter objects""" - - @others - return decorator - - - -def __init__(self, holding=None): - super().__init__() - self.holding = holding - self.attributes = { - "next": BuiltinName(BuiltinFunction(self.holding)), - "__iter__": BuiltinName(BuiltinFunction(get_iterator(self.holding))), - "close": BuiltinName(BuiltinFunction()), - "send": BuiltinName(BuiltinFunction()), - "throw": BuiltinName(BuiltinFunction()), - } - - -def decorator(func): - cached_func = _Cached(func, size) - return lambda *a, **kw: cached_func(*a, **kw) - - -class _Cached: - @others - -def __init__(self, func, count): - self.func = func - self.cache = [] - self.count = count - - -def __call__(self, *args, **kwds): - key = (args, kwds) - for cached_key, cached_result in self.cache: - if cached_key == key: - return cached_result - result = self.func(*args, **kwds) - self.cache.append((key, result)) - if len(self.cache) > self.count: - del self.cache[0] - return result - - - -def resolve(str_or_obj): - """Returns object from string""" - if not isinstance(str_or_obj, str): - return str_or_obj - if "." not in str_or_obj: - str_or_obj += "." - mod_name, obj_name = str_or_obj.rsplit(".", 1) - __import__(mod_name) - mod = sys.modules[mod_name] - return getattr(mod, obj_name) if obj_name else mod - - - -def guess_def_lineno(module, node): - """Find the line number for a function or class definition. - - `node` may be either an ast.FunctionDef, ast.AsyncFunctionDef, or ast.ClassDef - - Python 3.8 simply provides this to us, but in earlier versions the ast - node.lineno points to the first decorator rather than the actual - definition, so we try our best to find where the definitions are. - - This is to workaround bpo-33211 (https://bugs.python.org/issue33211) - """ - - @others - if sys.version_info >= (3, 8) or not hasattr(node, "body"): - return node.lineno - - possible_def_line = ( - node.body[0].lineno if is_inline_body() else node.body[0].lineno - 1 - ) - return module.logical_lines.logical_line_in(possible_def_line)[0] - -def is_inline_body(): - # class Foo(object): - # def inline_body(): pass - # ^ ^--- body_col_offset - # `--- indent_col_offset - # def not_inline_body(): - # pass - # ^--- body_col_offset == indent_col_offset - line = module.lines.get_line(node.body[0].lineno) - indent_col_offset = len(line) - len(line.lstrip()) - body_col_offset = node.body[0].col_offset - return indent_col_offset < body_col_offset - - - -@path C:/Repos/ekr-rope/rope/contrib/ -"""For performing many refactorings as a single command - -`changestack` module can be used to perform many refactorings on top -of each other as one bigger command. It can be used like:: - - stack = ChangeStack(project, 'my big command') - - #.. - stack.push(refactoring1.get_changes()) - #.. - stack.push(refactoring2.get_changes()) - #.. - stack.push(refactoringX.get_changes()) - - stack.pop_all() - changes = stack.merged() - -Now `changes` can be previewed or performed as before. -""" - -from rope.base import change - - -@others -@language python -@tabwidth -4 - -class ChangeStack: - @others - -def get_attributes(self): - return self.attributes - - -def __init__(self, project, description="merged changes"): - self.project = project - self.description = description - self.stack = [] - - -def push(self, changes): - self.stack.append(changes) - self.project.do(changes) - - -def pop_all(self): - for i in range(len(self.stack)): - self.project.history.undo(drop=True) - - -def merged(self): - result = change.ChangeSet(self.description) - for changes in self.stack: - for c in self._basic_changes(changes): - result.add_change(c) - return result - - -def _basic_changes(self, changes): - if isinstance(changes, change.ChangeSet): - for child in changes.changes: - yield from self._basic_changes(child) - else: - yield changes - -@path C:/Repos/ekr-rope/rope/contrib/ -import keyword -import sys -import warnings - -import rope.base.codeanalyze -import rope.base.evaluate -from rope.base import builtins -from rope.base import exceptions -from rope.base import libutils -from rope.base import pynames -from rope.base import pynamesdef -from rope.base import pyobjects -from rope.base import pyobjectsdef -from rope.base import pyscopes -from rope.base import worder -from rope.contrib import fixsyntax -from rope.refactor import functionutils - - -@others -@language python -@tabwidth -4 - -def code_assist( - project, - source_code, - offset, - resource=None, - templates=None, - maxfixes=1, - later_locals=True, -): - """Return python code completions as a list of `CodeAssistProposal` - - `resource` is a `rope.base.resources.Resource` object. If - provided, relative imports are handled. - - `maxfixes` is the maximum number of errors to fix if the code has - errors in it. - - If `later_locals` is `False` names defined in this scope and after - this line is ignored. - - """ - if templates is not None: - warnings.warn( - "Codeassist no longer supports templates", DeprecationWarning, stacklevel=2 - ) - assist = _PythonCodeAssist( - project, - source_code, - offset, - resource=resource, - maxfixes=maxfixes, - later_locals=later_locals, - ) - return assist() - - - -def starting_offset(source_code, offset): - """Return the offset in which the completion should be inserted - - Usually code assist proposals should be inserted like:: - - completion = proposal.name - result = (source_code[:starting_offset] + - completion + source_code[offset:]) - - Where starting_offset is the offset returned by this function. - - """ - word_finder = worder.Worder(source_code, True) - expression, starting, starting_offset = word_finder.get_splitted_primary_before( - offset - ) - return starting_offset - - - -def get_doc(project, source_code, offset, resource=None, maxfixes=1): - """Get the pydoc""" - fixer = fixsyntax.FixSyntax(project, source_code, resource, maxfixes) - pyname = fixer.pyname_at(offset) - if pyname is None: - return None - pyobject = pyname.get_object() - return PyDocExtractor().get_doc(pyobject) - - - -def get_calltip( - project, - source_code, - offset, - resource=None, - maxfixes=1, - ignore_unknown=False, - remove_self=False, -): - """Get the calltip of a function - - The format of the returned string is - ``module_name.holding_scope_names.function_name(arguments)``. For - classes `__init__()` and for normal objects `__call__()` function - is used. - - Note that the offset is on the function itself *not* after the its - open parenthesis. (Actually it used to be the other way but it - was easily confused when string literals were involved. So I - decided it is better for it not to try to be too clever when it - cannot be clever enough). You can use a simple search like:: - - offset = source_code.rindex('(', 0, offset) - 1 - - to handle simple situations. - - If `ignore_unknown` is `True`, `None` is returned for functions - without source-code like builtins and extensions. - - If `remove_self` is `True`, the first parameter whose name is self - will be removed for methods. - """ - fixer = fixsyntax.FixSyntax(project, source_code, resource, maxfixes) - pyname = fixer.pyname_at(offset) - if pyname is None: - return None - pyobject = pyname.get_object() - return PyDocExtractor().get_calltip(pyobject, ignore_unknown, remove_self) - - - -def get_returned_object(self, args): - return self.holding - - - -def get_definition_location(project, source_code, offset, resource=None, maxfixes=1): - """Return the definition location of the python name at `offset` - - Return a (`rope.base.resources.Resource`, lineno) tuple. If no - `resource` is given and the definition is inside the same module, - the first element of the returned tuple would be `None`. If the - location cannot be determined ``(None, None)`` is returned. - - """ - fixer = fixsyntax.FixSyntax(project, source_code, resource, maxfixes) - pyname = fixer.pyname_at(offset) - if pyname is not None: - module, lineno = pyname.get_definition_location() - if module is not None: - return module.get_module().get_resource(), lineno - return (None, None) - - - -def find_occurrences(*args, **kwds): - import rope.contrib.findit - - warnings.warn( - "Use `rope.contrib.findit.find_occurrences()` instead", - DeprecationWarning, - stacklevel=2, - ) - return rope.contrib.findit.find_occurrences(*args, **kwds) - - - -def get_canonical_path(project, resource, offset): - """Get the canonical path to an object. - - Given the offset of the object, this returns a list of - (name, name_type) tuples representing the canonical path to the - object. For example, the 'x' in the following code: - - class Foo(object): - def bar(self): - class Qux(object): - def mux(self, x): - pass - - we will return: - - [('Foo', 'CLASS'), ('bar', 'FUNCTION'), ('Qux', 'CLASS'), - ('mux', 'FUNCTION'), ('x', 'PARAMETER')] - - `resource` is a `rope.base.resources.Resource` object. - - `offset` is the offset of the pyname you want the path to. - - """ - # Retrieve the PyName. - pymod = project.get_pymodule(resource) - pyname = rope.base.evaluate.eval_location(pymod, offset) - - # Now get the location of the definition and its containing scope. - defmod, lineno = pyname.get_definition_location() - if not defmod: - return None - scope = defmod.get_scope().get_inner_scope_for_line(lineno) - - # Start with the name of the object we're interested in. - names = [] - if isinstance(pyname, pynamesdef.ParameterName): - names = [(worder.get_name_at(pymod.get_resource(), offset), "PARAMETER")] - elif isinstance(pyname, pynamesdef.AssignedName): - names = [(worder.get_name_at(pymod.get_resource(), offset), "VARIABLE")] - - # Collect scope names. - while scope.parent: - if isinstance(scope, pyscopes.FunctionScope): - scope_type = "FUNCTION" - elif isinstance(scope, pyscopes.ClassScope): - scope_type = "CLASS" - else: - scope_type = None - names.append((scope.pyobject.get_name(), scope_type)) - scope = scope.parent - - names.append((defmod.get_resource().real_path, "MODULE")) - names.reverse() - return names - - - -class CompletionProposal: - """A completion proposal - - The `scope` instance variable shows where proposed name came from - and can be 'global', 'local', 'builtin', 'attribute', 'keyword', - 'imported', 'parameter_keyword'. - - The `type` instance variable shows the approximate type of the - proposed object and can be 'instance', 'class', 'function', 'module', - and `None`. - - All possible relations between proposal's `scope` and `type` are shown - in the table below (different scopes in rows and types in columns): - - | instance | class | function | module | None - local | + | + | + | + | - global | + | + | + | + | - builtin | + | + | + | | - attribute | + | + | + | + | - imported | + | + | + | + | - keyword | | | | | + - parameter_keyword | | | | | + - - """ - - @others - -def __init__(self, name, scope, pyname=None): - self.name = name - self.pyname = pyname - self.scope = self._get_scope(scope) - - -def __str__(self): - return "{} ({}, {})".format(self.name, self.scope, self.type) - - -def __repr__(self): - return str(self) - - -@property -def parameters(self): - """The names of the parameters the function takes. - - Returns None if this completion is not a function. - """ - pyname = self.pyname - if isinstance(pyname, pynames.ImportedName): - pyname = pyname._get_imported_pyname() - if isinstance(pyname, pynames.DefinedName): - pyobject = pyname.get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - return pyobject.get_param_names() - - -@property -def type(self): - pyname = self.pyname - if isinstance(pyname, builtins.BuiltinName): - pyobject = pyname.get_object() - if isinstance(pyobject, builtins.BuiltinFunction): - return "function" - elif isinstance(pyobject, builtins.BuiltinClass): - return "class" - elif isinstance(pyobject, builtins.BuiltinObject) or isinstance( - pyobject, builtins.BuiltinName - ): - return "instance" - elif isinstance(pyname, pynames.ImportedModule): - return "module" - elif isinstance(pyname, pynames.ImportedName) or isinstance( - pyname, pynames.DefinedName - ): - pyobject = pyname.get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - return "function" - if isinstance(pyobject, pyobjects.AbstractClass): - return "class" - return "instance" - - -def _get_scope(self, scope): - if isinstance(self.pyname, builtins.BuiltinName): - return "builtin" - if isinstance(self.pyname, pynames.ImportedModule) or isinstance( - self.pyname, pynames.ImportedName - ): - return "imported" - return scope - - -get_generator = _create_builtin_getter(Generator) - - - -def get_doc(self): - """Get the proposed object's docstring. - - Returns None if it can not be get. - """ - if not self.pyname: - return None - pyobject = self.pyname.get_object() - if not hasattr(pyobject, "get_doc"): - return None - return self.pyname.get_object().get_doc() - - -@property -def kind(self): - warnings.warn( - "the proposal's `kind` property is deprecated, " "use `scope` instead" - ) - return self.scope - - - -# leaved for backward compatibility -CodeAssistProposal = CompletionProposal - - - -class NamedParamProposal(CompletionProposal): - """A parameter keyword completion proposal - - Holds reference to ``_function`` -- the function which - parameter ``name`` belongs to. This allows to determine - default value for this parameter. - """ - - @others - -def __init__(self, name, function): - self.argname = name - name = "%s=" % name - super().__init__(name, "parameter_keyword") - self._function = function - - -def get_default(self): - """Get a string representation of a param's default value. - - Returns None if there is no default value for this param. - """ - definfo = functionutils.DefinitionInfo.read(self._function) - for arg, default in definfo.args_with_defaults: - if self.argname == arg: - return default - return None - - - -def sorted_proposals(proposals, scopepref=None, typepref=None): - """Sort a list of proposals - - Return a sorted list of the given `CodeAssistProposal`. - - `scopepref` can be a list of proposal scopes. Defaults to - ``['parameter_keyword', 'local', 'global', 'imported', - 'attribute', 'builtin', 'keyword']``. - - `typepref` can be a list of proposal types. Defaults to - ``['class', 'function', 'instance', 'module', None]``. - (`None` stands for completions with no type like keywords.) - """ - sorter = _ProposalSorter(proposals, scopepref, typepref) - return sorter.get_sorted_proposal_list() - - - -def starting_expression(source_code, offset): - """Return the expression to complete""" - word_finder = worder.Worder(source_code, True) - expression, starting, starting_offset = word_finder.get_splitted_primary_before( - offset - ) - if expression: - return expression + "." + starting - return starting - - - -def default_templates(): - warnings.warn( - "default_templates() is deprecated.", DeprecationWarning, stacklevel=2 - ) - return {} - - - -class _PythonCodeAssist: - @others - -class File(BuiltinClass): - @others - -def __init__( - self, project, source_code, offset, resource=None, maxfixes=1, later_locals=True -): - self.project = project - self.code = source_code - self.resource = resource - self.maxfixes = maxfixes - self.later_locals = later_locals - self.word_finder = worder.Worder(source_code, True) - ( - self.expression, - self.starting, - self.offset, - ) = self.word_finder.get_splitted_primary_before(offset) - - -keywords = keyword.kwlist - - -def _find_starting_offset(self, source_code, offset): - current_offset = offset - 1 - while current_offset >= 0 and ( - source_code[current_offset].isalnum() or source_code[current_offset] in "_" - ): - current_offset -= 1 - return current_offset + 1 - - -def _matching_keywords(self, starting): - return [ - CompletionProposal(kw, "keyword") - for kw in self.keywords - if kw.startswith(starting) - ] - - -def __call__(self): - if self.offset > len(self.code): - return [] - completions = list(self._code_completions().values()) - if self.expression.strip() == "" and self.starting.strip() != "": - completions.extend(self._matching_keywords(self.starting)) - return completions - - -def _dotted_completions(self, module_scope, holding_scope): - result = {} - found_pyname = rope.base.evaluate.eval_str(holding_scope, self.expression) - if found_pyname is not None: - element = found_pyname.get_object() - compl_scope = "attribute" - if isinstance(element, (pyobjectsdef.PyModule, pyobjectsdef.PyPackage)): - compl_scope = "imported" - for name, pyname in element.get_attributes().items(): - if name.startswith(self.starting): - result[name] = CompletionProposal(name, compl_scope, pyname) - return result - - -def _undotted_completions(self, scope, result, lineno=None): - if scope.parent is not None: - self._undotted_completions(scope.parent, result) - if lineno is None: - names = scope.get_propagated_names() - else: - names = scope.get_names() - for name, pyname in names.items(): - if name.startswith(self.starting): - compl_scope = "local" - if scope.get_kind() == "Module": - compl_scope = "global" - if ( - lineno is None - or self.later_locals - or not self._is_defined_after(scope, pyname, lineno) - ): - result[name] = CompletionProposal(name, compl_scope, pyname) - - -def _from_import_completions(self, pymodule): - module_name = self.word_finder.get_from_module(self.offset) - if module_name is None: - return {} - pymodule = self._find_module(pymodule, module_name) - result = {} - for name in pymodule: - if name.startswith(self.starting): - result[name] = CompletionProposal( - name, scope="global", pyname=pymodule[name] - ) - return result - - -def _find_module(self, pymodule, module_name): - dots = 0 - while module_name[dots] == ".": - dots += 1 - pyname = pynames.ImportedModule(pymodule, module_name[dots:], dots) - return pyname.get_object() - - -def _is_defined_after(self, scope, pyname, lineno): - location = pyname.get_definition_location() - if location is not None and location[1] is not None: - if ( - location[0] == scope.pyobject.get_module() - and lineno <= location[1] <= scope.get_end() - ): - return True - - -def __init__(self, filename=None, mode="r", *args): - self.filename = filename - self.mode = mode - self.args = args - str_object = get_str() - str_list = get_list(get_str()) - attributes = {} - - def add(name, returned=None, function=None): - builtin = getattr(io.TextIOBase, name, None) - attributes[name] = BuiltinName( - BuiltinFunction(returned=returned, function=function, builtin=builtin) - ) - - add("__iter__", get_iterator(str_object)) - add("__enter__", returned=pyobjects.PyObject(self)) - for method in ["next", "read", "readline", "readlines"]: - add(method, str_list) - for method in [ - "close", - "flush", - "lineno", - "isatty", - "seek", - "tell", - "truncate", - "write", - "writelines", - ]: - add(method) - super().__init__(open, attributes) - - - -def _code_completions(self): - lineno = self.code.count("\n", 0, self.offset) + 1 - fixer = fixsyntax.FixSyntax( - self.project, self.code, self.resource, self.maxfixes - ) - pymodule = fixer.get_pymodule() - module_scope = pymodule.get_scope() - code = pymodule.source_code - lines = code.split("\n") - result = {} - start = fixsyntax._logical_start(lines, lineno) - indents = fixsyntax._get_line_indents(lines[start - 1]) - inner_scope = module_scope.get_inner_scope_for_line(start, indents) - if self.word_finder.is_a_name_after_from_import(self.offset): - return self._from_import_completions(pymodule) - if self.expression.strip() != "": - result.update(self._dotted_completions(module_scope, inner_scope)) - else: - result.update(self._keyword_parameters(module_scope.pyobject, inner_scope)) - self._undotted_completions(inner_scope, result, lineno=lineno) - return result - - -def _keyword_parameters(self, pymodule, scope): - offset = self.offset - if offset == 0: - return {} - word_finder = worder.Worder(self.code, True) - if word_finder.is_on_function_call_keyword(offset - 1): - function_parens = word_finder.find_parens_start_from_inside(offset - 1) - primary = word_finder.get_primary_at(function_parens - 1) - try: - function_pyname = rope.base.evaluate.eval_str(scope, primary) - except exceptions.BadIdentifierError: - return {} - if function_pyname is not None: - pyobject = function_pyname.get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - pass - elif ( - isinstance(pyobject, pyobjects.AbstractClass) - and "__init__" in pyobject - ): - pyobject = pyobject["__init__"].get_object() - elif "__call__" in pyobject: - pyobject = pyobject["__call__"].get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - param_names = [] - param_names.extend(pyobject.get_param_names(special_args=False)) - result = {} - for name in param_names: - if name.startswith(self.starting): - result[name + "="] = NamedParamProposal(name, pyobject) - return result - return {} - - - -class _ProposalSorter: - """Sort a list of code assist proposals""" - - @others - -def __init__(self, code_assist_proposals, scopepref=None, typepref=None): - self.proposals = code_assist_proposals - if scopepref is None: - scopepref = [ - "parameter_keyword", - "local", - "global", - "imported", - "attribute", - "builtin", - "keyword", - ] - self.scopepref = scopepref - if typepref is None: - typepref = ["class", "function", "instance", "module", None] - self.typerank = {type: index for index, type in enumerate(typepref)} - - -def get_sorted_proposal_list(self): - """Return a list of `CodeAssistProposal`""" - proposals = {} - for proposal in self.proposals: - proposals.setdefault(proposal.scope, []).append(proposal) - result = [] - for scope in self.scopepref: - scope_proposals = proposals.get(scope, []) - scope_proposals = [ - proposal - for proposal in scope_proposals - if proposal.type in self.typerank - ] - scope_proposals.sort(key=self._proposal_key) - result.extend(scope_proposals) - return result - - -def _proposal_key(self, proposal1): - def _underline_count(name): - return sum(1 for c in name if c == "_") - - return ( - self.typerank.get(proposal1.type, 100), - _underline_count(proposal1.name), - proposal1.name, - ) - # if proposal1.type != proposal2.type: - # return cmp(self.typerank.get(proposal1.type, 100), - # self.typerank.get(proposal2.type, 100)) - # return self._compare_underlined_names(proposal1.name, - # proposal2.name) - - - -class PyDocExtractor: - @others - -def get_doc(self, pyobject): - if isinstance(pyobject, pyobjects.AbstractFunction): - return self._get_function_docstring(pyobject) - elif isinstance(pyobject, pyobjects.AbstractClass): - return self._get_class_docstring(pyobject) - elif isinstance(pyobject, pyobjects.AbstractModule): - return self._trim_docstring(pyobject.get_doc()) - return None - - -def get_calltip(self, pyobject, ignore_unknown=False, remove_self=False): - try: - if isinstance(pyobject, pyobjects.AbstractClass): - pyobject = pyobject["__init__"].get_object() - if not isinstance(pyobject, pyobjects.AbstractFunction): - pyobject = pyobject["__call__"].get_object() - except exceptions.AttributeNotFoundError: - return None - if ignore_unknown and not isinstance(pyobject, pyobjects.PyFunction): - return - if isinstance(pyobject, pyobjects.AbstractFunction): - result = self._get_function_signature(pyobject, add_module=True) - if remove_self and self._is_method(pyobject): - return result.replace("(self)", "()").replace("(self, ", "(") - return result - - -def _get_class_docstring(self, pyclass): - contents = self._trim_docstring(pyclass.get_doc(), 2) - supers = [super.get_name() for super in pyclass.get_superclasses()] - doc = ( - "class {}({}):\n\n".format(pyclass.get_name(), ", ".join(supers)) + contents - ) - - if "__init__" in pyclass: - init = pyclass["__init__"].get_object() - if isinstance(init, pyobjects.AbstractFunction): - doc += "\n\n" + self._get_single_function_docstring(init) - return doc - - -get_file = _create_builtin_getter(File) -get_file_type = _create_builtin_type_getter(File) - - - -def _get_function_docstring(self, pyfunction): - functions = [pyfunction] - if self._is_method(pyfunction): - functions.extend( - self._get_super_methods(pyfunction.parent, pyfunction.get_name()) - ) - return "\n\n".join( - [self._get_single_function_docstring(function) for function in functions] - ) - - -def _is_method(self, pyfunction): - return isinstance(pyfunction, pyobjects.PyFunction) and isinstance( - pyfunction.parent, pyobjects.PyClass - ) - - -def _get_single_function_docstring(self, pyfunction): - signature = self._get_function_signature(pyfunction) - docs = self._trim_docstring(pyfunction.get_doc(), indents=2) - return signature + ":\n\n" + docs - - -def _get_super_methods(self, pyclass, name): - result = [] - for super_class in pyclass.get_superclasses(): - if name in super_class: - function = super_class[name].get_object() - if isinstance(function, pyobjects.AbstractFunction): - result.append(function) - result.extend(self._get_super_methods(super_class, name)) - return result - - -def _get_function_signature(self, pyfunction, add_module=False): - location = self._location(pyfunction, add_module) - if isinstance(pyfunction, pyobjects.PyFunction): - info = functionutils.DefinitionInfo.read(pyfunction) - return location + info.to_string() - else: - return "{}({})".format( - location + pyfunction.get_name(), - ", ".join(pyfunction.get_param_names()), - ) - - -def _location(self, pyobject, add_module=False): - location = [] - parent = pyobject.parent - while parent and not isinstance(parent, pyobjects.AbstractModule): - location.append(parent.get_name()) - location.append(".") - parent = parent.parent - if add_module: - if isinstance(pyobject, pyobjects.PyFunction): - location.insert(0, self._get_module(pyobject)) - if isinstance(parent, builtins.BuiltinModule): - location.insert(0, parent.get_name() + ".") - return "".join(location) - - -def _get_module(self, pyfunction): - module = pyfunction.get_module() - if module is not None: - resource = module.get_resource() - if resource is not None: - return libutils.modname(resource) + "." - return "" - - -def _trim_docstring(self, docstring, indents=0): - """The sample code from :PEP:`257`""" - if not docstring: - return "" - # Convert tabs to spaces (following normal Python rules) - # and split into a list of lines: - lines = docstring.expandtabs().splitlines() - # Determine minimum indentation (first line doesn't count): - indent = sys.maxsize - for line in lines[1:]: - stripped = line.lstrip() - if stripped: - indent = min(indent, len(line) - len(stripped)) - # Remove indentation (first line is special): - trimmed = [lines[0].strip()] - if indent < sys.maxsize: - for line in lines[1:]: - trimmed.append(line[indent:].rstrip()) - # Strip off trailing and leading blank lines: - while trimmed and not trimmed[-1]: - trimmed.pop() - while trimmed and not trimmed[0]: - trimmed.pop(0) - # Return a single string: - return "\n".join(" " * indents + line for line in trimmed) - - - -# Deprecated classes - - - -class TemplateProposal(CodeAssistProposal): - def __init__(self, name, template): - warnings.warn( - "TemplateProposal is deprecated.", DeprecationWarning, stacklevel=2 - ) - super().__init__(name, "template") - self.template = template - - - -class Property(BuiltinClass): - @others - -class Template: - @others - -def __init__(self, template): - self.template = template - warnings.warn("Template is deprecated.", DeprecationWarning, stacklevel=2) - - -def variables(self): - return [] - - -def substitute(self, mapping): - return self.template - - -def get_cursor_location(self, mapping): - return len(self.template) - -@path C:/Repos/ekr-rope/rope/contrib/ -"""Finding bad name and attribute accesses - -`find_errors` function can be used to find possible bad name and -attribute accesses. As an example:: - - errors = find_errors(project, project.get_resource('mod.py')) - for error in errors: - print('%s: %s' % (error.lineno, error.error)) - -prints possible errors for ``mod.py`` file. - -TODO: - -* use task handles -* reporting names at most once -* attributes of extension modules that don't appear in - extension_modules project config can be ignored -* not calling `PyScope.get_inner_scope_for_line()` if it is a - bottleneck; needs profiling -* not reporting occurrences where rope cannot infer the object -* rope saves multiple objects for some of the names in its objectdb - use all of them not to give false positives -* ... ;-) - -""" -from rope.base import ast, evaluate, pyobjects - - -@others -@language python -@tabwidth -4 - -def find_errors(project, resource): - """Find possible bad name and attribute accesses - - It returns a list of `Error`. - """ - pymodule = project.get_pymodule(resource) - finder = _BadAccessFinder(pymodule) - ast.walk(pymodule.get_ast(), finder) - return finder.errors - - - -class _BadAccessFinder: - @others - -def __init__(self, pymodule): - self.pymodule = pymodule - self.scope = pymodule.get_scope() - self.errors = [] - - -def _Name(self, node): - if isinstance(node.ctx, (ast.Store, ast.Param)): - return - scope = self.scope.get_inner_scope_for_line(node.lineno) - pyname = scope.lookup(node.id) - if pyname is None: - self._add_error(node, "Unresolved variable") - elif self._is_defined_after(scope, pyname, node.lineno): - self._add_error(node, "Defined later") - - -def __init__(self, fget=None, fset=None, fdel=None, fdoc=None): - self._fget = fget - self._fdoc = fdoc - attributes = { - "fget": BuiltinName(BuiltinFunction()), - "fset": BuiltinName(pynames.UnboundName()), - "fdel": BuiltinName(pynames.UnboundName()), - "__new__": BuiltinName(BuiltinFunction(function=_property_function)), - } - super().__init__(property, attributes) - - -def _Attribute(self, node): - if not isinstance(node.ctx, ast.Store): - scope = self.scope.get_inner_scope_for_line(node.lineno) - pyname = evaluate.eval_node(scope, node.value) - if pyname is not None and pyname.get_object() != pyobjects.get_unknown(): - if node.attr not in pyname.get_object(): - self._add_error(node, "Unresolved attribute") - ast.walk(node.value, self) - - -def _add_error(self, node, msg): - if isinstance(node, ast.Attribute): - name = node.attr - else: - name = node.id - if name != "None": - error = Error(node.lineno, msg + " " + name) - self.errors.append(error) - - -def _is_defined_after(self, scope, pyname, lineno): - location = pyname.get_definition_location() - if location is not None and location[1] is not None: - if ( - location[0] == self.pymodule - and lineno <= location[1] <= scope.get_end() - ): - return True - - - -class Error: - def __init__(self, lineno, error): - self.lineno = lineno - self.error = error - - def __str__(self): - return "{}: {}".format(self.lineno, self.error) - -@path C:/Repos/ekr-rope/rope/contrib/ -import rope.base.codeanalyze -import rope.base.evaluate -import rope.base.pyobjects -from rope.base import taskhandle, exceptions, worder -from rope.contrib import fixsyntax -from rope.refactor import occurrences - - -@others -@language python -@tabwidth -4 - -def find_occurrences( - project, - resource, - offset, - unsure=False, - resources=None, - in_hierarchy=False, - task_handle=taskhandle.NullTaskHandle(), -): - """Return a list of `Location` - - If `unsure` is `True`, possible matches are returned, too. You - can use `Location.unsure` to see which are unsure occurrences. - `resources` can be a list of `rope.base.resource.File` that - should be searched for occurrences; if `None` all python files - in the project are searched. - - """ - name = worder.get_name_at(resource, offset) - this_pymodule = project.get_pymodule(resource) - primary, pyname = rope.base.evaluate.eval_location2(this_pymodule, offset) - - @others - finder = occurrences.create_finder( - project, - name, - pyname, - unsure=is_match, - in_hierarchy=in_hierarchy, - instance=primary, - ) - if resources is None: - resources = project.get_python_files() - job_set = task_handle.create_jobset("Finding Occurrences", count=len(resources)) - return _find_locations(finder, resources, job_set) - - - -def is_match(occurrence): - return unsure - - -def find_implementations( - project, resource, offset, resources=None, task_handle=taskhandle.NullTaskHandle() -): - """Find the places a given method is overridden. - - Finds the places a method is implemented. Returns a list of - `Location`. - """ - name = worder.get_name_at(resource, offset) - this_pymodule = project.get_pymodule(resource) - pyname = rope.base.evaluate.eval_location(this_pymodule, offset) - if pyname is not None: - pyobject = pyname.get_object() - if ( - not isinstance(pyobject, rope.base.pyobjects.PyFunction) - or pyobject.get_kind() != "method" - ): - raise exceptions.BadIdentifierError("Not a method!") - else: - raise exceptions.BadIdentifierError("Cannot resolve the identifier!") - - @others - filters = [is_defined, not_self, occurrences.InHierarchyFilter(pyname, True)] - finder = occurrences.Finder(project, name, filters=filters) - if resources is None: - resources = project.get_python_files() - job_set = task_handle.create_jobset("Finding Implementations", count=len(resources)) - return _find_locations(finder, resources, job_set) - - - -def is_defined(occurrence): - if not occurrence.is_defined(): - return False - - -def not_self(occurrence): - if occurrence.get_pyname().get_object() == pyname.get_object(): - return False - - -@path C:/Repos/ekr-rope/rope/ -"""rope, a python refactoring library""" - -from pkg_resources import get_distribution, DistributionNotFound - -try: - VERSION = get_distribution("rope").version -except DistributionNotFound: - - def get_fallback_version(): - import re - import pathlib - - pyproject = ( - pathlib.Path(__file__).resolve().parent.parent / "pyproject.toml" - ).read_text() - version = re.search("version.*=.*'(.*)'", pyproject) - return version.group(1) if version else None - - VERSION = get_fallback_version() - - -INFO = __doc__ -COPYRIGHT = """\ -Copyright (C) 2021-2022 Lie Ryan -Copyright (C) 2019-2021 Matej Cepl -Copyright (C) 2015-2018 Nicholas Smith -Copyright (C) 2014-2015 Matej Cepl -Copyright (C) 2006-2012 Ali Gholami Rudi -Copyright (C) 2009-2012 Anton Gritsay - -This program is free software: you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation, either -version 3 of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this program. If not, see -<https://www.gnu.org/licenses/>.""" -@language python -@tabwidth -4 - -def get_property_object(self, args): - if isinstance(self._fget, pyobjects.AbstractFunction): - return self._fget.get_returned_object(args) - - - -def find_definition(project, code, offset, resource=None, maxfixes=1): - """Return the definition location of the python name at `offset` - - A `Location` object is returned if the definition location can be - determined, otherwise ``None`` is returned. - """ - fixer = fixsyntax.FixSyntax(project, code, resource, maxfixes) - pyname = fixer.pyname_at(offset) - if pyname is not None: - module, lineno = pyname.get_definition_location() - name = rope.base.worder.Worder(code).get_word_at(offset) - if lineno is not None: - start = module.lines.get_line_start(lineno) - - def check_offset(occurrence): - if occurrence.offset < start: - return False - - pyname_filter = occurrences.PyNameFilter(pyname) - finder = occurrences.Finder(project, name, [check_offset, pyname_filter]) - for occurrence in finder.find_occurrences(pymodule=module): - return Location(occurrence) - - - -class Location: - def __init__(self, occurrence): - self.resource = occurrence.resource - self.region = occurrence.get_word_range() - self.offset = self.region[0] - self.unsure = occurrence.is_unsure() - self.lineno = occurrence.lineno - - - -def _find_locations(finder, resources, job_set): - result = [] - for resource in resources: - job_set.started_job(resource.path) - for occurrence in finder.find_occurrences(resource): - result.append(Location(occurrence)) - job_set.finished_job() - return result - -@path C:/Repos/ekr-rope/rope/contrib/ -"""Fix the name of modules - -This module is useful when you want to rename many of the modules in -your project. That can happen specially when you want to change their -naming style. - -For instance:: - - fixer = FixModuleNames(project) - changes = fixer.get_changes(fixer=str.lower) - project.do(changes) - -Here it renames all modules and packages to use lower-cased chars. -You can tell it to use any other style by using the ``fixer`` -argument. - -""" -from rope.base import taskhandle -from rope.contrib import changestack -from rope.refactor import rename - - -@others -@language python -@tabwidth -4 - -class FixModuleNames: - @others - -def __init__(self, project): - self.project = project - - -def get_changes(self, fixer=str.lower, task_handle=taskhandle.NullTaskHandle()): - """Fix module names - - `fixer` is a function that takes and returns a `str`. Given - the name of a module, it should return the fixed name. - - """ - stack = changestack.ChangeStack(self.project, "Fixing module names") - jobset = task_handle.create_jobset( - "Fixing module names", self._count_fixes(fixer) + 1 - ) - try: - while True: - for resource in self._tobe_fixed(fixer): - jobset.started_job(resource.path) - renamer = rename.Rename(self.project, resource) - changes = renamer.get_changes(fixer(self._name(resource))) - stack.push(changes) - jobset.finished_job() - break - else: - break - finally: - jobset.started_job("Reverting to original state") - stack.pop_all() - jobset.finished_job() - return stack.merged() - - -def _count_fixes(self, fixer): - return len(list(self._tobe_fixed(fixer))) - - -def _tobe_fixed(self, fixer): - for resource in self.project.get_python_files(): - modname = self._name(resource) - if modname != fixer(modname): - yield resource - - -def _name(self, resource): - modname = resource.name.rsplit(".", 1)[0] - if modname == "__init__": - modname = resource.parent.name - return modname - -def _property_function(args): - parameters = args.get_arguments(["fget", "fset", "fdel", "fdoc"]) - return pyobjects.PyObject(Property(parameters[0])) - - - -@path C:/Repos/ekr-rope/rope/contrib/ -import rope.base.codeanalyze -import rope.base.evaluate -from rope.base import exceptions -from rope.base import libutils -from rope.base import utils -from rope.base import worder -from rope.base.codeanalyze import ArrayLinesAdapter, LogicalLineFinder - - -@others -@language python -@tabwidth -4 - -class Lambda(pyobjects.AbstractFunction): - @others - -def __init__(self, node, scope): - super().__init__() - self.node = node - self.arguments = node.args - self.scope = scope - - -def get_returned_object(self, args): - result = rope.base.evaluate.eval_node(self.scope, self.node.body) - if result is not None: - return result.get_object() - else: - return pyobjects.get_unknown() - - -def get_module(self): - return self.parent.get_module() - - -def get_scope(self): - return self.scope - - -def get_kind(self): - return "lambda" - - -def get_ast(self): - return self.node - - -def get_attributes(self): - return {} - - - -def get_name(self): - return "lambda" - - -def get_param_names(self, special_args=True): - result = [ - node.arg for node in self.arguments.args if isinstance(node, ast.arg) - ] - if self.arguments.vararg: - result.append("*" + self.arguments.vararg.arg) - if self.arguments.kwarg: - result.append("**" + self.arguments.kwarg.arg) - return result - - -@property -def parent(self): - return self.scope.pyobject - - - -class BuiltinObject(BuiltinClass): - def __init__(self): - super().__init__(object, {}) - - - -class BuiltinType(BuiltinClass): - def __init__(self): - super().__init__(type, {}) - - - -def _infer_sequence_for_pyname(pyname): - if pyname is None: - return None - seq = pyname.get_object() - args = arguments.ObjectArguments([pyname]) - if "__iter__" in seq: - obj = seq["__iter__"].get_object() - if not isinstance(obj, pyobjects.AbstractFunction): - return None - iter = obj.get_returned_object(args) - if iter is not None and "next" in iter: - holding = iter["next"].get_object().get_returned_object(args) - return holding - - - -def _create_builtin(args, creator): - passed = args.get_pynames(["sequence"])[0] - if passed is None: - holding = None - else: - holding = _infer_sequence_for_pyname(passed) - if holding is not None: - return creator(holding) - else: - return creator() - - - -def _open_function(args): - return _create_builtin(args, get_file) - - - -def _range_function(args): - return get_list() - - - -def _reversed_function(args): - return _create_builtin(args, get_iterator) - - - -@path C:/Repos/ekr-rope/rope/base/ -import rope.base.evaluate -from rope.base import ast - - -@others -@language python -@tabwidth -4 - -def _sorted_function(args): - return _create_builtin(args, get_list) - - - -def _super_function(args): - passed_class, passed_self = args.get_arguments(["type", "self"]) - if passed_self is None: - return passed_class - else: - # pyclass = passed_self.get_type() - pyclass = passed_class - if isinstance(pyclass, pyobjects.AbstractClass): - supers = pyclass.get_superclasses() - if supers: - return pyobjects.PyObject(supers[0]) - return passed_self - - - -def _zip_function(args): - args = args.get_pynames(["sequence"]) - objects = [] - for seq in args: - if seq is None: - holding = None - else: - holding = _infer_sequence_for_pyname(seq) - objects.append(holding) - tuple = get_tuple(*objects) - return get_list(tuple) - - - -def _enumerate_function(args): - passed = args.get_pynames(["sequence"])[0] - if passed is None: - holding = None - else: - holding = _infer_sequence_for_pyname(passed) - tuple = get_tuple(None, holding) - return get_iterator(tuple) - - - -def _iter_function(args): - passed = args.get_pynames(["sequence"])[0] - if passed is None: - holding = None - else: - holding = _infer_sequence_for_pyname(passed) - return get_iterator(holding) - - - -def _input_function(args): - return get_str() - - - -@path C:/Repos/ekr-rope/rope/base/ -import datetime -import difflib -import os -import time -from typing import Union - -import rope.base.fscommands -from rope.base import exceptions, taskhandle, utils -from rope.base.fscommands import FileContent - - -@others -@language python -@tabwidth -4 - -class Change: - """The base class for changes - - Rope refactorings return `Change` objects. They can be previewed, - committed or undone. - """ - - @others - -def do(self, job_set=None): - """Perform the change - - .. note:: Do use this directly. Use `Project.do()` instead. - """ - - -def undo(self, job_set=None): - """Perform the change - - .. note:: Do use this directly. Use `History.undo()` instead. - """ - - -class Arguments: - """A class for evaluating parameters passed to a function - - You can use the `create_arguments` factory. It handles implicit - first arguments. - - """ - - @others - -def get_description(self): - """Return the description of this change - - This can be used for previewing the changes. - """ - return str(self) - - -def get_changed_resources(self): - """Return the list of resources that will be changed""" - return [] - - -@property -@utils.saveit -def _operations(self): - return _ResourceOperations(self.resource.project) - - - -class ChangeSet(Change): - """A collection of `Change` objects - - This class holds a collection of changes. This class provides - these fields: - - * `changes`: the list of changes - * `description`: the goal of these changes - """ - - @others - -def __init__(self, description, timestamp=None): - self.changes = [] - self.description = description - self.time = timestamp - - -def do(self, job_set=taskhandle.NullJobSet()): - try: - done = [] - for change in self.changes: - change.do(job_set) - done.append(change) - self.time = time.time() - except Exception: - for change in done: - change.undo() - raise - - -def undo(self, job_set=taskhandle.NullJobSet()): - try: - done = [] - for change in reversed(self.changes): - change.undo(job_set) - done.append(change) - except Exception: - for change in done: - change.do() - raise - - -def add_change(self, change): - self.changes.append(change) - - -def get_description(self): - result = [str(self) + ":\n\n\n"] - for change in self.changes: - result.append(change.get_description()) - result.append("\n") - return "".join(result) - - -def __str__(self): - if self.time is not None: - date = datetime.datetime.fromtimestamp(self.time) - if date.date() == datetime.date.today(): - string_date = "today" - elif date.date() == (datetime.date.today() - datetime.timedelta(1)): - string_date = "yesterday" - elif date.year == datetime.date.today().year: - string_date = date.strftime("%b %d") - else: - string_date = date.strftime("%d %b, %Y") - string_time = date.strftime("%H:%M:%S") - string_time = "{} {} ".format(string_date, string_time) - return self.description + " - " + string_time - return self.description - - -def __init__(self, args, scope): - self.args = args - self.scope = scope - self.instance = None - - -def get_changed_resources(self): - result = set() - for change in self.changes: - result.update(change.get_changed_resources()) - return result - - - -def _handle_job_set(function): - """A decorator for handling `taskhandle.JobSet` - - A decorator for handling `taskhandle.JobSet` for `do` and `undo` - methods of `Change`. - """ - - @others - return call - - - -def call(self, job_set=taskhandle.NullJobSet()): - job_set.started_job(str(self)) - function(self) - job_set.finished_job() - - -class ChangeContents(Change): - """A class to change the contents of a file - - Fields: - - * `resource`: The `rope.base.resources.File` to change - * `new_contents`: What to write in the file - """ - - @others - -def __init__(self, resource, new_contents, old_contents=None): - self.resource = resource - # IDEA: Only saving diffs; possible problems when undo/redoing - self.new_contents = new_contents - self.old_contents = old_contents - - -@_handle_job_set -def do(self): - if self.old_contents is None: - self.old_contents = self.resource.read() - self._operations.write_file(self.resource, self.new_contents) - - -@_handle_job_set -def undo(self): - if self.old_contents is None: - raise exceptions.HistoryError("Undoing a change that is not performed yet!") - self._operations.write_file(self.resource, self.old_contents) - - -def __str__(self): - return "Change <%s>" % self.resource.path - - -def get_description(self): - new = self.new_contents - old = self.old_contents - if old is None: - if self.resource.exists(): - old = self.resource.read() - else: - old = "" - result = difflib.unified_diff( - old.splitlines(True), - new.splitlines(True), - "a/" + self.resource.path, - "b/" + self.resource.path, - ) - return "".join(list(result)) - - -def get_changed_resources(self): - return [self.resource] - - - -def get_arguments(self, parameters): - result = [] - for pyname in self.get_pynames(parameters): - if pyname is None: - result.append(None) - else: - result.append(pyname.get_object()) - return result - - -class MoveResource(Change): - """Move a resource to a new location - - Fields: - - * `resource`: The `rope.base.resources.Resource` to move - * `new_resource`: The destination for move; It is the moved - resource not the folder containing that resource. - """ - - @others - -def __init__(self, resource, new_location, exact=False): - self.project = resource.project - self.resource = resource - if not exact: - new_location = _get_destination_for_move(resource, new_location) - if resource.is_folder(): - self.new_resource = self.project.get_folder(new_location) - else: - self.new_resource = self.project.get_file(new_location) - - -@_handle_job_set -def do(self): - self._operations.move(self.resource, self.new_resource) - - -@_handle_job_set -def undo(self): - self._operations.move(self.new_resource, self.resource) - - -def __str__(self): - return "Move <%s>" % self.resource.path - - -def get_description(self): - return "rename from {}\nrename to {}".format( - self.resource.path, - self.new_resource.path, - ) - - -def get_changed_resources(self): - return [self.resource, self.new_resource] - - - -class CreateResource(Change): - """A class to create a resource - - Fields: - - * `resource`: The resource to create - """ - - @others - -def __init__(self, resource): - self.resource = resource - - -@_handle_job_set -def do(self): - self._operations.create(self.resource) - - -def get_pynames(self, parameters): - result = [None] * max(len(parameters), len(self.args)) - for index, arg in enumerate(self.args): - if isinstance(arg, ast.keyword) and arg.arg in parameters: - result[parameters.index(arg.arg)] = self._evaluate(arg.value) - else: - result[index] = self._evaluate(arg) - return result - - -@_handle_job_set -def undo(self): - self._operations.remove(self.resource) - - -def __str__(self): - return "Create Resource <%s>" % (self.resource.path) - - -def get_description(self): - return "new file %s" % (self.resource.path) - - -def get_changed_resources(self): - return [self.resource] - - -def _get_child_path(self, parent, name): - if parent.path == "": - return name - else: - return parent.path + "/" + name - - - -class CreateFolder(CreateResource): - """A class to create a folder - - See docs for `CreateResource`. - """ - - @others - -def __init__(self, parent, name): - resource = parent.project.get_folder(self._get_child_path(parent, name)) - super().__init__(resource) - - - -class CreateFile(CreateResource): - """A class to create a file - - See docs for `CreateResource`. - """ - - @others - -def __init__(self, parent, name): - resource = parent.project.get_file(self._get_child_path(parent, name)) - super().__init__(resource) - - - -class RemoveResource(Change): - """A class to remove a resource - - Fields: - - * `resource`: The resource to be removed - """ - - @others - -def get_instance_pyname(self): - if self.args: - return self._evaluate(self.args[0]) - - -def __init__(self, resource): - self.resource = resource - - -@_handle_job_set -def do(self): - self._operations.remove(self.resource) - - -# TODO: Undoing remove operations -@_handle_job_set -def undo(self): - raise NotImplementedError("Undoing `RemoveResource` is not implemented yet.") - - -def __str__(self): - return "Remove <%s>" % (self.resource.path) - - -def get_changed_resources(self): - return [self.resource] - - - -def count_changes(change): - """Counts the number of basic changes a `Change` will make""" - if isinstance(change, ChangeSet): - result = 0 - for child in change.changes: - result += count_changes(child) - return result - return 1 - - - -def create_job_set(task_handle, change): - return task_handle.create_jobset(str(change), count_changes(change)) - - - -class _ResourceOperations: - @others - -def __init__(self, project): - self.project = project - self.fscommands = project.fscommands - self.direct_commands = rope.base.fscommands.FileSystemCommands() - - -def _get_fscommands(self, resource): - if self.project.is_ignored(resource): - return self.direct_commands - return self.fscommands - - -def _evaluate(self, ast_node): - return rope.base.evaluate.eval_node(self.scope, ast_node) - - - -def write_file(self, resource, contents: Union[str, FileContent]): - data: FileContent - if not isinstance(contents, bytes): - data = rope.base.fscommands.unicode_to_file_data( - contents, - newlines=resource.newlines, - ) - else: - data = contents - fscommands = self._get_fscommands(resource) - fscommands.write(resource.real_path, data) - for observer in list(self.project.observers): - observer.resource_changed(resource) - - -def move(self, resource, new_resource): - fscommands = self._get_fscommands(resource) - fscommands.move(resource.real_path, new_resource.real_path) - for observer in list(self.project.observers): - observer.resource_moved(resource, new_resource) - - -def create(self, resource): - if resource.is_folder(): - self._create_resource(resource.path, kind="folder") - else: - self._create_resource(resource.path) - for observer in list(self.project.observers): - observer.resource_created(resource) - - -def remove(self, resource): - fscommands = self._get_fscommands(resource) - fscommands.remove(resource.real_path) - for observer in list(self.project.observers): - observer.resource_removed(resource) - - -def _create_resource(self, file_name, kind="file"): - resource_path = self.project._get_resource_path(file_name) - if os.path.exists(resource_path): - raise exceptions.RopeError("Resource <%s> already exists" % resource_path) - resource = self.project.get_file(file_name) - if not resource.parent.exists(): - raise exceptions.ResourceNotFoundError( - "Parent folder of <%s> does not exist" % resource.path - ) - fscommands = self._get_fscommands(resource) - try: - if kind == "file": - fscommands.create_file(resource_path) - else: - fscommands.create_folder(resource_path) - except OSError as e: - raise exceptions.RopeError(e) - - - -def _get_destination_for_move(resource, destination): - dest_path = resource.project._get_resource_path(destination) - if os.path.isdir(dest_path): - if destination != "": - return destination + "/" + resource.name - else: - return resource.name - return destination - - - -class ChangeToData: - @others - -def convertChangeSet(self, change): - description = change.description - changes = [self(child) for child in change.changes] - return (description, changes, change.time) - - -def convertChangeContents(self, change): - return (change.resource.path, change.new_contents, change.old_contents) - - -def convertMoveResource(self, change): - return (change.resource.path, change.new_resource.path) - - -def create_arguments(primary, pyfunction, call_node, scope): - """A factory for creating `Arguments`""" - args = list(call_node.args) - args.extend(call_node.keywords) - called = call_node.func - # XXX: Handle constructors - if _is_method_call(primary, pyfunction) and isinstance(called, ast.Attribute): - args.insert(0, called.value) - return Arguments(args, scope) - - - -def convertCreateResource(self, change): - return (change.resource.path, change.resource.is_folder()) - - -def convertRemoveResource(self, change): - return (change.resource.path, change.resource.is_folder()) - - -def __call__(self, change): - change_type = type(change) - if change_type in (CreateFolder, CreateFile): - change_type = CreateResource - method = getattr(self, "convert" + change_type.__name__) - return (change_type.__name__, method(change)) - - - -class DataToChange: - @others - -def __init__(self, project): - self.project = project - - -def makeChangeSet(self, description, changes, time=None): - result = ChangeSet(description, time) - for child in changes: - result.add_change(self(child)) - return result - - -def makeChangeContents(self, path, new_contents, old_contents): - resource = self.project.get_file(path) - return ChangeContents(resource, new_contents, old_contents) - - -def makeMoveResource(self, old_path, new_path): - resource = self.project.get_file(old_path) - return MoveResource(resource, new_path, exact=True) - - -def makeCreateResource(self, path, is_folder): - if is_folder: - resource = self.project.get_folder(path) - else: - resource = self.project.get_file(path) - return CreateResource(resource) - - -def makeRemoveResource(self, path, is_folder): - if is_folder: - resource = self.project.get_folder(path) - else: - resource = self.project.get_file(path) - return RemoveResource(resource) - - -class ObjectArguments: - @others - -def __call__(self, data): - method = getattr(self, "make" + data[0]) - return method(*data[1]) - -@path C:/Repos/ekr-rope/rope/base/ -import bisect -import re -import token -import tokenize - - -@others -@language python -@tabwidth -4 - -class ChangeCollector: - @others - -def __init__(self, text): - self.text = text - self.changes = [] - - -def add_change(self, start, end, new_text=None): - if new_text is None: - new_text = self.text[start:end] - self.changes.append((start, end, new_text)) - - -def get_changed(self): - if not self.changes: - return None - - self.changes.sort(key=lambda x: x[:2]) - pieces = [] - last_changed = 0 - for change in self.changes: - start, end, text = change - pieces.append(self.text[last_changed:start] + text) - last_changed = end - if last_changed < len(self.text): - pieces.append(self.text[last_changed:]) - result = "".join(pieces) - if result != self.text: - return result - - - -class SourceLinesAdapter: - """Adapts source to Lines interface - - Note: The creation of this class is expensive. - """ - - @others - -def __init__(self, source_code): - self.code = source_code - self.starts = None - self._initialize_line_starts() - - -def _initialize_line_starts(self): - self.starts = [] - self.starts.append(0) - try: - i = 0 - while True: - i = self.code.index("\n", i) + 1 - self.starts.append(i) - except ValueError: - pass - self.starts.append(len(self.code) + 1) - - -def get_line(self, lineno): - return self.code[self.starts[lineno - 1] : self.starts[lineno] - 1] - - -def __init__(self, pynames): - self.pynames = pynames - - -def length(self): - return len(self.starts) - 1 - - -def get_line_number(self, offset): - return bisect.bisect(self.starts, offset) - - -def get_line_start(self, lineno): - return self.starts[lineno - 1] - - -def get_line_end(self, lineno): - return self.starts[lineno] - 1 - - - -class ArrayLinesAdapter: - @others - -def __init__(self, lines): - self.lines = lines - - -def get_line(self, line_number): - return self.lines[line_number - 1] - - -def length(self): - return len(self.lines) - - - -class LinesToReadline: - @others - -def __init__(self, lines, start): - self.lines = lines - self.current = start - - -def get_arguments(self, parameters): - result = [] - for pyname in self.pynames: - if pyname is None: - result.append(None) - else: - result.append(pyname.get_object()) - return result - - -def readline(self): - if self.current <= self.lines.length(): - self.current += 1 - return self.lines.get_line(self.current - 1) + "\n" - return "" - - -def __call__(self): - return self.readline() - - - -class _CustomGenerator: - @others - -def __init__(self, lines): - self.lines = lines - self.in_string = "" - self.open_count = 0 - self.continuation = False - - -def __call__(self): - size = self.lines.length() - result = [] - i = 1 - while i <= size: - while i <= size and not self.lines.get_line(i).strip(): - i += 1 - if i <= size: - start = i - while True: - line = self.lines.get_line(i) - self._analyze_line(line) - if ( - not (self.continuation or self.open_count or self.in_string) - or i == size - ): - break - i += 1 - result.append((start, i)) - i += 1 - return result - - -# Matches all backslashes before the token, to detect escaped quotes -_main_tokens = re.compile(r'(\\*)((\'\'\'|"""|\'|")|#|\[|\]|\{|\}|\(|\))') - - -def _analyze_line(self, line): - token = None - for match in self._main_tokens.finditer(line): - prefix = match.group(1) - token = match.group(2) - # Skip any tokens which are escaped - if len(prefix) % 2 == 1: - continue - if token in ["'''", '"""', "'", '"']: - if not self.in_string: - self.in_string = token - elif self.in_string == token or ( - self.in_string in ['"', "'"] and token == 3 * self.in_string - ): - self.in_string = "" - if self.in_string: - continue - if token == "#": - break - if token in "([{": - self.open_count += 1 - elif token in ")]}": - self.open_count -= 1 - if line and token != "#" and line.endswith("\\"): - self.continuation = True - else: - self.continuation = False - - - -def custom_generator(lines): - return _CustomGenerator(lines)() - - - -class LogicalLineFinder: - @others - -def __init__(self, lines): - self.lines = lines - - -def get_pynames(self, parameters): - return self.pynames - - -def logical_line_in(self, line_number): - indents = count_line_indents(self.lines.get_line(line_number)) - tries = 0 - while True: - block_start = get_block_start(self.lines, line_number, indents) - try: - return self._block_logical_line(block_start, line_number) - except IndentationError as e: - tries += 1 - if tries == 5: - raise e - lineno = e.lineno + block_start - 1 - indents = count_line_indents(self.lines.get_line(lineno)) - - -def generate_starts(self, start_line=1, end_line=None): - for start, end in self.generate_regions(start_line, end_line): - yield start - - -def generate_regions(self, start_line=1, end_line=None): - # XXX: `block_start` should be at a better position! - block_start = 1 - readline = LinesToReadline(self.lines, block_start) - try: - for start, end in self._logical_lines(readline): - real_start = start + block_start - 1 - real_start = self._first_non_blank(real_start) - if end_line is not None and real_start >= end_line: - break - real_end = end + block_start - 1 - if real_start >= start_line: - yield (real_start, real_end) - except tokenize.TokenError: - pass - - -def _block_logical_line(self, block_start, line_number): - readline = LinesToReadline(self.lines, block_start) - shifted = line_number - block_start + 1 - region = self._calculate_logical(readline, shifted) - start = self._first_non_blank(region[0] + block_start - 1) - if region[1] is None: - end = self.lines.length() - else: - end = region[1] + block_start - 1 - return start, end - - -def _calculate_logical(self, readline, line_number): - last_end = 1 - try: - for start, end in self._logical_lines(readline): - if line_number <= end: - return (start, end) - last_end = end + 1 - except tokenize.TokenError as e: - current = e.args[1][0] - return (last_end, max(last_end, current - 1)) - return (last_end, None) - - -def _logical_lines(self, readline): - last_end = 1 - for current_token in tokenize.generate_tokens(readline): - current = current_token[2][0] - if current_token[0] == token.NEWLINE: - yield (last_end, current) - last_end = current + 1 - - -def _first_non_blank(self, line_number): - current = line_number - while current < self.lines.length(): - line = self.lines.get_line(current).strip() - if line and not line.startswith("#"): - return current - current += 1 - return current - - - -def tokenizer_generator(lines): - return LogicalLineFinder(lines).generate_regions() - - - -class CachingLogicalLineFinder: - @others - -def __init__(self, lines, generate=custom_generator): - self.lines = lines - self._generate = generate - - -def get_instance_pyname(self): - return self.pynames[0] - - - -_starts = None - - -@property -def starts(self): - if self._starts is None: - self._init_logicals() - return self._starts - - -_ends = None - - -@property -def ends(self): - if self._ends is None: - self._init_logicals() - return self._ends - - -def _init_logicals(self): - """Should initialize _starts and _ends attributes""" - size = self.lines.length() + 1 - self._starts = [None] * size - self._ends = [None] * size - for start, end in self._generate(self.lines): - self._starts[start] = True - self._ends[end] = True - - -def logical_line_in(self, line_number): - start = line_number - while start > 0 and not self.starts[start]: - start -= 1 - if start == 0: - try: - start = self.starts.index(True, line_number) - except ValueError: - return (line_number, line_number) - return (start, self.ends.index(True, start)) - - -def generate_starts(self, start_line=1, end_line=None): - if end_line is None: - end_line = self.lines.length() - for index in range(start_line, end_line): - if self.starts[index]: - yield index - - - -def get_block_start(lines, lineno, maximum_indents=80): - """Approximate block start""" - pattern = get_block_start_patterns() - for i in range(lineno, 0, -1): - match = pattern.search(lines.get_line(i)) - if ( - match is not None - and count_line_indents(lines.get_line(i)) <= maximum_indents - ): - striped = match.string.lstrip() - # Maybe we're in a list comprehension or generator expression - if i > 1 and striped.startswith("if") or striped.startswith("for"): - bracs = 0 - for j in range(i, min(i + 5, lines.length() + 1)): - for c in lines.get_line(j): - if c == "#": - break - if c in "[(": - bracs += 1 - if c in ")]": - bracs -= 1 - if bracs < 0: - break - if bracs < 0: - break - if bracs < 0: - continue - return i - return 1 - - - -_block_start_pattern = None - - - -def get_block_start_patterns(): - global _block_start_pattern - if not _block_start_pattern: - pattern = ( - "^\\s*(((def|class|if|elif|except|for|while|with)\\s)|" - "((try|else|finally|except)\\s*:))" - ) - _block_start_pattern = re.compile(pattern, re.M) - return _block_start_pattern - - - -class MixedArguments: - @others - -def count_line_indents(line): - indents = 0 - for char in line: - if char == " ": - indents += 1 - elif char == "\t": - indents += 8 - else: - return indents - return 0 - - - -def get_string_pattern_with_prefix(prefix, prefix_group_name=None): - longstr = r'"""(\\.|"(?!"")|\\\n|[^"\\])*"""' - shortstr = r'"(\\.|\\\n|[^"\\\n])*"' - if prefix_group_name is not None: - pattern = "(?P<%s>%%s)(%%s)" % prefix_group_name - else: - pattern = "%s(%s)" - return pattern % ( - prefix, - "|".join( - [ - longstr, - longstr.replace('"', "'"), - shortstr, - shortstr.replace('"', "'"), - ] - ), - ) - - - -def get_string_pattern(): - prefix = r"(?<![fF])(\b[uUbB]?[rR]?)?" - return get_string_pattern_with_prefix(prefix) - - - -def get_formatted_string_pattern(): - prefix = r"(\b[rR]?[fF]|[fF][rR]?)" - return get_string_pattern_with_prefix(prefix) - - - -def get_any_string_pattern(): - prefix = r"[bBfFrRuU]{,4}" - return get_string_pattern_with_prefix( - prefix, - prefix_group_name="prefix", - ) - - - -def get_comment_pattern(): - return r"#[^\n]*" - -@path C:/Repos/ekr-rope/rope/base/ -from operator import itemgetter -from typing import Optional, Tuple - -import rope.base.builtins -import rope.base.pynames -import rope.base.pyobjects -from rope.base import ( - ast, - astutils, - exceptions, - pyobjects, - pyobjectsdef, - arguments, - worder, -) - - -BadIdentifierError = exceptions.BadIdentifierError - - -@others -@language python -@tabwidth -4 - -def eval_location(pymodule, offset): - """Find the pyname at the offset""" - return eval_location2(pymodule, offset)[1] - - - -def eval_location2(pymodule, offset): - """Find the primary and pyname at offset""" - pyname_finder = ScopeNameFinder(pymodule) - return pyname_finder.get_primary_and_pyname_at(offset) - - - -def eval_node(scope, node): - """Evaluate a `ast.AST` node and return a PyName - - Return `None` if the expression cannot be evaluated. - """ - return eval_node2(scope, node)[1] - - - -def __init__(self, pyname, arguments, scope): - """`argumens` is an instance of `Arguments`""" - self.pyname = pyname - self.args = arguments - - -def eval_node2(scope, node): - evaluator = StatementEvaluator(scope) - ast.walk(node, evaluator) - return evaluator.old_result, evaluator.result - - - -def eval_str(holding_scope, name): - return eval_str2(holding_scope, name)[1] - - - -def eval_str2(holding_scope, name): - try: - # parenthesizing for handling cases like 'a_var.\nattr' - node = ast.parse("(%s)" % name) - except SyntaxError: - raise BadIdentifierError("Not a resolvable python identifier selected.") - return eval_node2(holding_scope, node) - - - -class ScopeNameFinder: - @others - -def __init__(self, pymodule): - self.module_scope = pymodule.get_scope() - self.lines = pymodule.lines - self.worder = worder.Worder(pymodule.source_code, True) - - -def _is_defined_in_class_body(self, holding_scope, offset, lineno): - if ( - lineno == holding_scope.get_start() - and holding_scope.parent is not None - and holding_scope.parent.get_kind() == "Class" - and self.worder.is_a_class_or_function_name_in_header(offset) - ): - return True - if ( - lineno != holding_scope.get_start() - and holding_scope.get_kind() == "Class" - and self.worder.is_name_assigned_in_class_body(offset) - ): - return True - return False - - -def _is_function_name_in_function_header(self, scope, offset, lineno): - return ( - scope.get_start() <= lineno <= scope.get_body_start() - and scope.get_kind() == "Function" - and self.worder.is_a_class_or_function_name_in_header(offset) - ) - - -def get_pyname_at(self, offset): - return self.get_primary_and_pyname_at(offset)[1] - - -def get_primary_and_pyname_at( - self, - offset: int, -) -> Tuple[Optional[rope.base.pynames.PyName], Optional[rope.base.pynames.PyName]]: - lineno = self.lines.get_line_number(offset) - holding_scope = self.module_scope.get_inner_scope_for_offset(offset) - # function keyword parameter - if self.worder.is_function_keyword_parameter(offset): - keyword_name = self.worder.get_word_at(offset) - pyobject = self.get_enclosing_function(offset) - if isinstance(pyobject, pyobjectsdef.PyFunction): - parameter_name = pyobject.get_parameters().get(keyword_name, None) - return (None, parameter_name) - elif isinstance(pyobject, pyobjects.AbstractFunction): - parameter_name = rope.base.pynames.ParameterName() - return (None, parameter_name) - # class body - if self._is_defined_in_class_body(holding_scope, offset, lineno): - class_scope = holding_scope - if lineno == holding_scope.get_start(): - class_scope = holding_scope.parent - name = self.worder.get_primary_at(offset).strip() - try: - return (None, class_scope.pyobject[name]) - except rope.base.exceptions.AttributeNotFoundError: - return (None, None) - # function header - if self._is_function_name_in_function_header(holding_scope, offset, lineno): - name = self.worder.get_primary_at(offset).strip() - return (None, holding_scope.parent[name]) - # module in a from statement or an imported name that is aliased - if self.worder.is_from_statement_module( - offset - ) or self.worder.is_import_statement_aliased_module(offset): - module = self.worder.get_primary_at(offset) - module_pyname = self._find_module(module) - return (None, module_pyname) - if self.worder.is_from_aliased(offset): - name = self.worder.get_from_aliased(offset) - else: - name = self.worder.get_primary_at(offset) - return eval_str2(holding_scope, name) - - -def get_enclosing_function(self, offset): - function_parens = self.worder.find_parens_start_from_inside(offset) - try: - function_pyname = self.get_pyname_at(function_parens - 1) - except BadIdentifierError: - function_pyname = None - if function_pyname is not None: - pyobject = function_pyname.get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - return pyobject - elif ( - isinstance(pyobject, pyobjects.AbstractClass) and "__init__" in pyobject - ): - return pyobject["__init__"].get_object() - elif "__call__" in pyobject: - return pyobject["__call__"].get_object() - return None - - -def get_pynames(self, parameters): - return [self.pyname] + self.args.get_pynames(parameters[1:]) - - -def _find_module(self, module_name): - dots = 0 - while module_name[dots] == ".": - dots += 1 - return rope.base.pynames.ImportedModule( - self.module_scope.pyobject, module_name[dots:], dots - ) - - - -class StatementEvaluator: - @others - -def __init__(self, scope): - self.scope = scope - self.result = None - self.old_result = None - - -def _Name(self, node): - self.result = self.scope.lookup(node.id) - - -def _Attribute(self, node): - pyname = eval_node(self.scope, node.value) - if pyname is None: - pyname = rope.base.pynames.UnboundName() - self.old_result = pyname - if pyname.get_object() != rope.base.pyobjects.get_unknown(): - try: - self.result = pyname.get_object()[node.attr] - except exceptions.AttributeNotFoundError: - self.result = None - - -def _Call(self, node): - primary, pyobject = self._get_primary_and_object_for_node(node.func) - if pyobject is None: - return - - def _get_returned(pyobject): - args = arguments.create_arguments(primary, pyobject, node, self.scope) - return pyobject.get_returned_object(args) - - if isinstance(pyobject, rope.base.pyobjects.AbstractClass): - result = None - if "__new__" in pyobject: - new_function = pyobject["__new__"].get_object() - result = _get_returned(new_function) - if result is None or result == rope.base.pyobjects.get_unknown(): - result = rope.base.pyobjects.PyObject(pyobject) - self.result = rope.base.pynames.UnboundName(pyobject=result) - return - - pyfunction = None - if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): - pyfunction = pyobject - elif "__call__" in pyobject: - pyfunction = pyobject["__call__"].get_object() - if pyfunction is not None: - self.result = rope.base.pynames.UnboundName( - pyobject=_get_returned(pyfunction) - ) - - -def _Str(self, node): - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_str() - ) - - -def _Num(self, node): - type_name = type(node.n).__name__ - self.result = self._get_builtin_name(type_name) - - -def _Constant(self, node): - type_name = type(node.n).__name__ - try: - self.result = self._get_builtin_name(type_name) - except exceptions.AttributeNotFoundError: - # XXX: Right way to fix this is to add missing NoneType to builtins? - pass - - -def _get_builtin_name(self, type_name): - pytype = rope.base.builtins.builtins[type_name].get_object() - return rope.base.pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) - - -def get_arguments(self, parameters): - result = [] - for pyname in self.get_pynames(parameters): - if pyname is None: - result.append(None) - else: - result.append(pyname.get_object()) - return result - - -def _BinOp(self, node): - self.result = rope.base.pynames.UnboundName( - self._get_object_for_node(node.left) - ) - - -def _BoolOp(self, node): - pyobject = self._get_object_for_node(node.values[0]) - if pyobject is None: - pyobject = self._get_object_for_node(node.values[1]) - self.result = rope.base.pynames.UnboundName(pyobject) - - -def _Repr(self, node): - self.result = self._get_builtin_name("str") - - -def _UnaryOp(self, node): - self.result = rope.base.pynames.UnboundName( - self._get_object_for_node(node.operand) - ) - - -def _Compare(self, node): - self.result = self._get_builtin_name("bool") - - -def _Dict(self, node): - keys = None - values = None - if node.keys and node.keys[0]: - keys, values = next( - iter(filter(itemgetter(0), zip(node.keys, node.values))), (None, None) - ) - if keys: - keys = self._get_object_for_node(keys) - if values: - values = self._get_object_for_node(values) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_dict(keys, values) - ) - - -def _List(self, node): - holding = None - if node.elts: - holding = self._get_object_for_node(node.elts[0]) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_list(holding) - ) - - -def _ListComp(self, node): - pyobject = self._what_does_comprehension_hold(node) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_list(pyobject) - ) - - -def _GeneratorExp(self, node): - pyobject = self._what_does_comprehension_hold(node) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_iterator(pyobject) - ) - - -def _what_does_comprehension_hold(self, node): - scope = self._make_comprehension_scope(node) - pyname = eval_node(scope, node.elt) - return pyname.get_object() if pyname is not None else None - - -def get_instance_pyname(self): - return self.pyname - - - -def _make_comprehension_scope(self, node): - scope = self.scope - module = scope.pyobject.get_module() - names = {} - for comp in node.generators: - new_names = _get_evaluated_names( - comp.target, comp.iter, module, ".__iter__().next()", node.lineno - ) - names.update(new_names) - return rope.base.pyscopes.TemporaryScope(scope.pycore, scope, names) - - -def _Tuple(self, node): - objects = [] - if len(node.elts) < 4: - for stmt in node.elts: - pyobject = self._get_object_for_node(stmt) - objects.append(pyobject) - else: - objects.append(self._get_object_for_node(node.elts[0])) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_tuple(*objects) - ) - - -def _get_object_for_node(self, stmt): - pyname = eval_node(self.scope, stmt) - pyobject = None - if pyname is not None: - pyobject = pyname.get_object() - return pyobject - - -def _get_primary_and_object_for_node(self, stmt): - primary, pyname = eval_node2(self.scope, stmt) - pyobject = None - if pyname is not None: - pyobject = pyname.get_object() - return primary, pyobject - - -def _Subscript(self, node): - if isinstance(node.slice, ast.Index): - self._call_function(node.value, "__getitem__", [node.slice.value]) - elif isinstance(node.slice, ast.Slice): - self._call_function(node.value, "__getitem__", [node.slice]) - elif isinstance(node.slice, ast.expr): - self._call_function(node.value, "__getitem__", [node.value]) - - -def _Slice(self, node): - self.result = self._get_builtin_name("slice") - - -def _call_function(self, node, function_name, other_args=None): - pyname = eval_node(self.scope, node) - if pyname is not None: - pyobject = pyname.get_object() - else: - return - if function_name in pyobject: - called = pyobject[function_name].get_object() - if not called or not isinstance(called, pyobjects.AbstractFunction): - return - args = [node] - if other_args: - args += other_args - arguments_ = arguments.Arguments(args, self.scope) - self.result = rope.base.pynames.UnboundName( - pyobject=called.get_returned_object(arguments_) - ) - - -def _Lambda(self, node): - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.Lambda(node, self.scope) - ) - - - -def _get_evaluated_names(targets, assigned, module, evaluation, lineno): - result = {} - for name, levels in astutils.get_name_levels(targets): - assignment = rope.base.pynames.AssignmentValue(assigned, levels, evaluation) - # XXX: this module should not access `rope.base.pynamesdef`! - pyname = rope.base.pynamesdef.AssignedName(lineno, module) - pyname.assignments.append(assignment) - result[name] = pyname - return result - -@path C:/Repos/ekr-rope/rope/base/ -@others -@language python -@tabwidth -4 - -def _is_method_call(primary, pyfunction): - if primary is None: - return False - pyobject = primary.get_object() - if ( - isinstance(pyobject.get_type(), rope.base.pyobjects.PyClass) - and isinstance(pyfunction, rope.base.pyobjects.PyFunction) - and isinstance(pyfunction.parent, rope.base.pyobjects.PyClass) - ): - return True - if isinstance( - pyobject.get_type(), rope.base.pyobjects.AbstractClass - ) and isinstance(pyfunction, rope.base.builtins.BuiltinFunction): - return True - return False - -class RopeError(Exception): - """Base exception for rope""" - - - -class ResourceNotFoundError(RopeError): - """Resource not found exception""" - - - -class RefactoringError(RopeError): - """Errors for performing a refactoring""" - - - -class InterruptedTaskError(RopeError): - """The task has been interrupted""" - - - -class HistoryError(RopeError): - """Errors for history undo/redo operations""" - - - -class ModuleNotFoundError(RopeError): - """Module not found exception""" - - - -class AttributeNotFoundError(RopeError): - """Attribute not found exception""" - - - -class NameNotFoundError(RopeError): - """Name not found exception""" - - - -class BadIdentifierError(RopeError): - """The name cannot be resolved""" - - - -class ModuleSyntaxError(RopeError): - """Module has syntax errors - - The `filename` and `lineno` fields indicate where the error has - occurred. - - """ - - @others - -def __init__(self, filename, lineno, message): - self.filename = filename - self.lineno = lineno - self.message_ = message - super().__init__( - "Syntax error in file <{}> line <{}>: {}".format(filename, lineno, message) - ) - - - -class ModuleDecodeError(RopeError): - """Cannot decode module""" - - def __init__(self, filename, message): - self.filename = filename - self.message_ = message - super().__init__("Cannot decode file <{}>: {}".format(filename, message)) - -@path C:/Repos/ekr-rope/rope/base/ -"""Project file system commands. - -This modules implements file system operations used by rope. Different -version control systems can be supported by implementing the interface -provided by `FileSystemCommands` class. See `SubversionCommands` and -`MercurialCommands` for example. - -""" -import re -import os -import shutil -import subprocess -import typing - - -FileContent = typing.NewType("FileContent", bytes) - - -@others -@language python -@tabwidth -4 - -def create_fscommands(root): - dirlist = os.listdir(root) - commands = { - ".hg": MercurialCommands, - ".svn": SubversionCommands, - ".git": GITCommands, - "_svn": SubversionCommands, - "_darcs": DarcsCommands, - } - for key in commands: - if key in dirlist: - try: - return commands[key](root) - except (ImportError, OSError): - pass - return FileSystemCommands() - - - -class FileSystemCommands: - @others - -def create_file(self, path): - open(path, "w").close() - - -def create_folder(self, path): - os.mkdir(path) - - -def move(self, path, new_location): - shutil.move(path, new_location) - - -def remove(self, path): - if os.path.isfile(path): - os.remove(path) - else: - shutil.rmtree(path) - - -def write(self, path, data): - file_ = open(path, "wb") - try: - file_.write(data) - finally: - file_.close() - - -def read(self, path): - with open(path, "rb") as handle: - return handle.read() - - - -class SubversionCommands: - @others - -def __init__(self, *args): - self.normal_actions = FileSystemCommands() - import pysvn - - self.client = pysvn.Client() - - -def create_file(self, path): - self.normal_actions.create_file(path) - self.client.add(path, force=True) - - -def create_folder(self, path): - self.normal_actions.create_folder(path) - self.client.add(path, force=True) - - -def move(self, path, new_location): - self.client.move(path, new_location, force=True) - - -def remove(self, path): - self.client.remove(path, force=True) - - -def write(self, path, data): - self.normal_actions.write(path, data) - - -def read(self, path): - return self.normal_actions.read(path) - - - -class MercurialCommands: - @others - -def __init__(self, root): - self.hg = self._import_mercurial() - self.normal_actions = FileSystemCommands() - try: - self.ui = self.hg.ui.ui( - verbose=False, - debug=False, - quiet=True, - interactive=False, - traceback=False, - report_untrusted=False, - ) - except: - self.ui = self.hg.ui.ui() - self.ui.setconfig("ui", "interactive", "no") - self.ui.setconfig("ui", "debug", "no") - self.ui.setconfig("ui", "traceback", "no") - self.ui.setconfig("ui", "verbose", "no") - self.ui.setconfig("ui", "report_untrusted", "no") - self.ui.setconfig("ui", "quiet", "yes") - - self.repo = self.hg.hg.repository(self.ui, root) - - -def _import_mercurial(self): - import mercurial.commands - import mercurial.hg - import mercurial.ui - - return mercurial - - -def create_file(self, path): - self.normal_actions.create_file(path) - self.hg.commands.add(self.ui, self.repo, path) - - -def create_folder(self, path): - self.normal_actions.create_folder(path) - - -def move(self, path, new_location): - self.hg.commands.rename(self.ui, self.repo, path, new_location, after=False) - - -def remove(self, path): - self.hg.commands.remove(self.ui, self.repo, path) - - -def write(self, path, data): - self.normal_actions.write(path, data) - - -def read(self, path): - return self.normal_actions.read(path) - - - -class GITCommands: - @others - -def __init__(self, root): - self.root = root - self._do(["version"]) - self.normal_actions = FileSystemCommands() - - - -def create_file(self, path): - self.normal_actions.create_file(path) - self._do(["add", self._in_dir(path)]) - - -def create_folder(self, path): - self.normal_actions.create_folder(path) - - -def move(self, path, new_location): - self._do(["mv", self._in_dir(path), self._in_dir(new_location)]) - - -def remove(self, path): - self._do(["rm", self._in_dir(path)]) - - -def write(self, path, data): - # XXX: should we use ``git add``? - self.normal_actions.write(path, data) - - -def read(self, path): - return self.normal_actions.read(path) - - -def _do(self, args): - _execute(["git"] + args, cwd=self.root) - - -def _in_dir(self, path): - if path.startswith(self.root): - return path[len(self.root) + 1 :] - return self.root - - - -class DarcsCommands: - @others - -def __init__(self, root): - self.root = root - self.normal_actions = FileSystemCommands() - - -def create_file(self, path): - self.normal_actions.create_file(path) - self._do(["add", path]) - - -def create_folder(self, path): - self.normal_actions.create_folder(path) - self._do(["add", path]) - - -def move(self, path, new_location): - self._do(["mv", path, new_location]) - - -def remove(self, path): - self.normal_actions.remove(path) - - -def read(self, path): - return self.normal_actions.read(path) - - -def write(self, path, data): - self.normal_actions.write(path, data) - - -def _do(self, args): - _execute(["darcs"] + args, cwd=self.root) - - - -def _execute(args, cwd=None): - process = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE) - process.wait() - return process.returncode - - - -def unicode_to_file_data(contents: str, encoding=None, newlines=None) -> FileContent: - assert isinstance(contents, str) - if newlines and newlines != "\n": - contents = contents.replace("\n", newlines) - if encoding is None: - encoding = read_str_coding(contents) - if encoding is not None: - return FileContent(contents.encode(encoding)) - try: - return FileContent(contents.encode()) - except UnicodeEncodeError: - return FileContent(contents.encode("utf-8")) - - - -def file_data_to_unicode(data, encoding=None): - result = _decode_data(data, encoding) - newline = "\n" - if "\r\n" in result: - result = result.replace("\r\n", "\n") - newline = "\r\n" - if "\r" in result: - result = result.replace("\r", "\n") - newline = "\r" - return result, newline - - - -def _decode_data(data, encoding): - if isinstance(data, str): - return data - if encoding is None: - encoding = read_str_coding(data) - if encoding is None: - # there is no encoding tip, we need to guess. - # PEP263 says that "encoding not explicitly defined" means it is ascii, - # but we will use utf8 instead since utf8 fully covers ascii and btw is - # the only non-latin sane encoding. - encoding = "utf-8" - try: - return data.decode(encoding) - except (UnicodeError, LookupError): - # fallback to latin1: it should never fail - return data.decode("latin1") - - - -def read_str_coding(source): - # as defined by PEP-263 (https://www.python.org/dev/peps/pep-0263/) - CODING_LINE_PATTERN = b"^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)" - - if type(source) == bytes: - newline = b"\n" - CODING_LINE_PATTERN = re.compile(CODING_LINE_PATTERN) - else: - newline = "\n" - CODING_LINE_PATTERN = re.compile(CODING_LINE_PATTERN.decode("ascii")) - for line in source.split(newline, 2)[:2]: - if re.match(CODING_LINE_PATTERN, line): - return _find_coding(line) - else: - return - - - -def _find_coding(text): - if isinstance(text, str): - text = text.encode("utf-8") - coding = b"coding" - to_chr = chr - try: - start = text.index(coding) + len(coding) - if text[start] not in b"=:": - return - start += 1 - while start < len(text) and to_chr(text[start]).isspace(): - start += 1 - end = start - while end < len(text): - c = text[end] - if not to_chr(c).isalnum() and c not in b"-_": - break - end += 1 - result = text[start:end] - if isinstance(result, bytes): - result = result.decode("utf-8") - return result - except ValueError: - pass - -@path C:/Repos/ekr-rope/rope/base/ -@nopyflakes -from rope.base import exceptions, change, taskhandle - - -@others -@language python -@tabwidth -4 - -class History: - """A class that holds project history""" - - @others - -def __init__(self, project, maxundos=None): - self.project = project - self._undo_list = [] - self._redo_list = [] - self._maxundos = maxundos - self._load_history() - self.project.data_files.add_write_hook(self.write) - self.current_change = None - - -def _load_history(self): - if self.save: - result = self.project.data_files.read_data( - "history", compress=self.compress, import_=True - ) - if result is not None: - to_change = change.DataToChange(self.project) - for data in result[0]: - self._undo_list.append(to_change(data)) - for data in result[1]: - self._redo_list.append(to_change(data)) - - -def do(self, changes, task_handle=taskhandle.NullTaskHandle()): - """Perform the change and add it to the `self.undo_list` - - Note that uninteresting changes (changes to ignored files) - will not be appended to `self.undo_list`. - - """ - try: - self.current_change = changes - changes.do(change.create_job_set(task_handle, changes)) - finally: - self.current_change = None - if self._is_change_interesting(changes): - self.undo_list.append(changes) - self._remove_extra_items() - del self.redo_list[:] - - -def _remove_extra_items(self): - if len(self.undo_list) > self.max_undos: - del self.undo_list[0 : len(self.undo_list) - self.max_undos] - - -def _is_change_interesting(self, changes): - for resource in changes.get_changed_resources(): - if not self.project.is_ignored(resource): - return True - return False - - -def undo(self, change=None, drop=False, task_handle=taskhandle.NullTaskHandle()): - """Redo done changes from the history - - When `change` is `None`, the last done change will be undone. - If change is not `None` it should be an item from - `self.undo_list`; this change and all changes that depend on - it will be undone. In both cases the list of undone changes - will be returned. - - If `drop` is `True`, the undone change will not be appended to - the redo list. - - """ - if not self._undo_list: - raise exceptions.HistoryError("Undo list is empty") - if change is None: - change = self.undo_list[-1] - dependencies = self._find_dependencies(self.undo_list, change) - self._move_front(self.undo_list, dependencies) - self._perform_undos(len(dependencies), task_handle) - result = self.redo_list[-len(dependencies) :] - if drop: - del self.redo_list[-len(dependencies) :] - return result - - -def redo(self, change=None, task_handle=taskhandle.NullTaskHandle()): - """Redo undone changes from the history - - When `change` is `None`, the last undone change will be - redone. If change is not `None` it should be an item from - `self.redo_list`; this change and all changes that depend on - it will be redone. In both cases the list of redone changes - will be returned. - - """ - if not self.redo_list: - raise exceptions.HistoryError("Redo list is empty") - if change is None: - change = self.redo_list[-1] - dependencies = self._find_dependencies(self.redo_list, change) - self._move_front(self.redo_list, dependencies) - self._perform_redos(len(dependencies), task_handle) - return self.undo_list[-len(dependencies) :] - - -def _move_front(self, change_list, changes): - for change in changes: - change_list.remove(change) - change_list.append(change) - - -def _find_dependencies(self, change_list, change): - index = change_list.index(change) - return _FindChangeDependencies(change_list[index:])() - - -def _perform_undos(self, count, task_handle): - for i in range(count): - self.current_change = self.undo_list[-1] - try: - job_set = change.create_job_set(task_handle, self.current_change) - self.current_change.undo(job_set) - finally: - self.current_change = None - self.redo_list.append(self.undo_list.pop()) - - -def _perform_redos(self, count, task_handle): - for i in range(count): - self.current_change = self.redo_list[-1] - try: - job_set = change.create_job_set(task_handle, self.current_change) - self.current_change.do(job_set) - finally: - self.current_change = None - self.undo_list.append(self.redo_list.pop()) - - -def contents_before_current_change(self, file): - if self.current_change is None: - return None - result = self._search_for_change_contents([self.current_change], file) - if result is not None: - return result - if file.exists() and not file.is_folder(): - return file.read() - else: - return None - - -def _search_for_change_contents(self, change_list, file): - for change_ in reversed(change_list): - if isinstance(change_, change.ChangeSet): - result = self._search_for_change_contents(change_.changes, file) - if result is not None: - return result - if isinstance(change_, change.ChangeContents) and change_.resource == file: - return change_.old_contents - - -def write(self): - if self.save: - data = [] - to_data = change.ChangeToData() - self._remove_extra_items() - data.append([to_data(change_) for change_ in self.undo_list]) - data.append([to_data(change_) for change_ in self.redo_list]) - self.project.data_files.write_data("history", data, compress=self.compress) - - -def get_file_undo_list(self, resource): - return [ - change - for change in self.undo_list - if resource in change.get_changed_resources() - ] - - -def __str__(self): - return "History holds %s changes in memory" % ( - len(self.undo_list) + len(self.redo_list) - ) - - -undo_list = property(lambda self: self._undo_list) -redo_list = property(lambda self: self._redo_list) - - -@property -def tobe_undone(self): - """The last done change if available, `None` otherwise""" - if self.undo_list: - return self.undo_list[-1] - - -@property -def tobe_redone(self): - """The last undone change if available, `None` otherwise""" - if self.redo_list: - return self.redo_list[-1] - - -@property -def max_undos(self): - if self._maxundos is None: - return self.project.prefs.get("max_history_items", 100) - else: - return self._maxundos - - -@property -def save(self): - return self.project.prefs.get("save_history", False) - - -@property -def compress(self): - return self.project.prefs.get("compress_history", False) - - -def clear(self): - """Forget all undo and redo information""" - del self.undo_list[:] - del self.redo_list[:] - - - -class _FindChangeDependencies: - @others - -def __init__(self, change_list): - self.change = change_list[0] - self.change_list = change_list - self.changed_resources = set(self.change.get_changed_resources()) - - -def __call__(self): - result = [self.change] - for change in self.change_list[1:]: - if self._depends_on(change, result): - result.append(change) - self.changed_resources.update(change.get_changed_resources()) - return result - - -def _depends_on(self, changes, result): - for resource in changes.get_changed_resources(): - if resource is None: - continue - if resource in self.changed_resources: - return True - for changed in self.changed_resources: - if resource.is_folder() and resource.contains(changed): - return True - if changed.is_folder() and changed.contains(resource): - return True - return False - -@path C:/Repos/ekr-rope/rope/base/ -"""A few useful functions for using rope as a library""" -import os.path - -import rope.base.project -import rope.base.pycore -from rope.base import pyobjectsdef -from rope.base import utils -from rope.base import taskhandle - - -@others -@language python -@tabwidth -4 - -def path_to_resource(project, path, type=None): - """Get the resource at path - - You only need to specify `type` if `path` does not exist. It can - be either 'file' or 'folder'. If the type is `None` it is assumed - that the resource already exists. - - Note that this function uses `Project.get_resource()`, - `Project.get_file()`, and `Project.get_folder()` methods. - - """ - project_path = path_relative_to_project_root(project, path) - if project_path is None: - project_path = rope.base.project._realpath(path) - project = rope.base.project.get_no_project() - if type is None: - return project.get_resource(project_path) - if type == "file": - return project.get_file(project_path) - if type == "folder": - return project.get_folder(project_path) - return None - - - -def path_relative_to_project_root(project, path): - return relative(project.address, path) - - - -@utils.deprecated() -def relative(root, path): - root = rope.base.project._realpath(root).replace(os.path.sep, "/") - path = rope.base.project._realpath(path).replace(os.path.sep, "/") - if path == root: - return "" - if path.startswith(root + "/"): - return path[len(root) + 1 :] - - - -def report_change(project, path, old_content): - """Report that the contents of file at `path` was changed - - The new contents of file is retrieved by reading the file. - - """ - resource = path_to_resource(project, path) - if resource is None: - return - for observer in list(project.observers): - observer.resource_changed(resource) - if project.pycore.automatic_soa: - rope.base.pycore.perform_soa_on_changed_scopes(project, resource, old_content) - - - -def analyze_module(project, resource): - """Perform static object analysis on a python file in the project - - Note that this might be really time consuming. - """ - project.pycore.analyze_module(resource) - - - -def analyze_modules(project, task_handle=taskhandle.NullTaskHandle()): - """Perform static object analysis on all python files in the project - - Note that this might be really time consuming. - """ - resources = project.get_python_files() - job_set = task_handle.create_jobset("Analyzing Modules", len(resources)) - for resource in resources: - job_set.started_job(resource.path) - analyze_module(project, resource) - job_set.finished_job() - - - -def get_string_module(project, code, resource=None, force_errors=False): - """Returns a `PyObject` object for the given code - - If `force_errors` is `True`, `exceptions.ModuleSyntaxError` is - raised if module has syntax errors. This overrides - ``ignore_syntax_errors`` project config. - - """ - return pyobjectsdef.PyModule( - project.pycore, code, resource, force_errors=force_errors - ) - - - -def get_string_scope(project, code, resource=None): - """Returns a `Scope` object for the given code""" - return get_string_module(project, code, resource).get_scope() - - - -def is_python_file(project, resource): - return project.pycore.is_python_file(resource) - - - -def modname(resource): - if resource.is_folder(): - module_name = resource.name - source_folder = resource.parent - elif resource.name == "__init__.py": - module_name = resource.parent.name - source_folder = resource.parent.parent - else: - module_name = resource.name[:-3] - source_folder = resource.parent - - while source_folder != source_folder.parent and source_folder.has_child( - "__init__.py" - ): - module_name = source_folder.name + "." + module_name - source_folder = source_folder.parent - - return module_name - -@path C:/Repos/ekr-rope/rope/base/ -"""Rope preferences.""" -from dataclasses import asdict, dataclass -from textwrap import dedent -from typing import Any, Callable, Dict, List, Optional, Tuple - -from packaging.requirements import Requirement -from pytoolconfig import PyToolConfig, UniversalKey, field -from pytoolconfig.sources import Source -from rope.base.resources import Folder - - -@others -@language python -@tabwidth -4 - -@dataclass -class Prefs: - """Class to store rope preferences.""" - - ignored_resources: List[str] = field( - default_factory=lambda: [ - "*.pyc", - "*~", - ".ropeproject", - ".hg", - ".svn", - "_svn", - ".git", - ".tox", - ".venv", - "venv", - ".mypy_cache", - ".pytest_cache", - ], - description=dedent(""" - Specify which files and folders to ignore in the project. - Changes to ignored resources are not added to the history and - VCSs. Also they are not returned in `Project.get_files()`. - Note that ``?`` and ``*`` match all characters but slashes. - '*.pyc': matches 'test.pyc' and 'pkg/test.pyc' - 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc' - '.svn': matches 'pkg/.svn' and all of its children - 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o' - 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o' - """), - ) - python_files: List[str] = field( - default_factory=lambda: ["*.py"], - description=dedent(""" - Specifies which files should be considered python files. It is - useful when you have scripts inside your project. Only files - ending with ``.py`` are considered to be python files by - default. - """), - ) - source_folders: List[str] = field( - description=dedent(""" - Custom source folders: By default rope searches the project - for finding source folders (folders that should be searched - for finding modules). You can add paths to that list. Note - that rope guesses project source folders correctly most of the - time; use this if you have any problems. - The folders should be relative to project root and use '/' for - separating folders regardless of the platform rope is running on. - 'src/my_source_folder' for instance. - """), - default_factory=lambda: [], - ) - python_path: List[str] = field( - default_factory=lambda: [], - description="You can extend python path for looking up modules.", - ) - save_objectdb: bool = field( - default=False, description="Should rope save object information or not." - ) - compress_objectdb: bool = False - automatic_soa: bool = field( - True, "If `True`, rope analyzes each module when it is being saved." - ) - soa_followed_calls: int = field( - default=0, description="The depth of calls to follow in static object analysis" - ) - perform_doa: bool = field( - default=True, - description=dedent(""" - If `False` when running modules or unit tests 'dynamic object analysis' is turned off. - This makes them much faster. - """), - ) - validate_objectdb: bool = field( - default=False, - description="Rope can check the validity of its object DB when running.", - ) - - max_history_items: int = field(default=32, description="How many undos to hold?") - save_history: bool = field( - default=True, description="Shows whether to save history across sessions." - ) - compress_history: bool = False - - indent_size: int = field( - default=4, - description=dedent(""" - Set the number spaces used for indenting. According to - :PEP:`8`, it is best to use 4 spaces. Since most of rope's - unit-tests use 4 spaces it is more reliable, too. - """), - ) - - extension_modules: List[str] = field( - default_factory=list, - description=""" -Builtin and c-extension modules that are allowed to be imported and inspected by rope. - """, - ) - - import_dynload_stdmods: bool = field( - default=True, - description="Add all standard c-extensions to extension_modules list.", - ) - ignore_syntax_errors: bool = field( - default=False, - description=dedent(""" - If `True` modules with syntax errors are considered to be empty. - The default value is `False`; When `False` syntax errors raise - `rope.base.exceptions.ModuleSyntaxError` exception. - """), - ) - - ignore_bad_imports: bool = field( - default=False, - description=dedent(""" - If `True`, rope ignores unresolvable imports. Otherwise, they - appear in the importing namespace. - """), - ) - - prefer_module_from_imports: bool = field( - default=False, - description=dedent(""" - If `True`, rope will insert new module imports as `from <package> import <module>`by default. - """), - ) - - split_imports: bool = field( - default=False, - description=dedent(""" - If `True`, rope will transform a comma list of imports into - multiple separate import statements when organizing - imports. - """), - ) - - pull_imports_to_top: bool = field( - default=True, - description=dedent(""" - If `True`, rope will remove all top-level import statements and - reinsert them at the top of the module when making changes. - """), - ) - - sort_imports_alphabetically: bool = field( - default=False, - description=dedent(""" - If `True`, rope will sort imports alphabetically by module name instead - of alphabetically by import statement, with from imports after normal - imports. - """), - ) - type_hinting_factory: str = field( - "rope.base.oi.type_hinting.factory.default_type_hinting_factory", - description=dedent(""" - Location of implementation of - rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general - case, you don't have to change this value, unless you're an rope expert. - Change this value to inject you own implementations of interfaces - listed in module rope.base.oi.type_hinting.providers.interfaces - For example, you can add you own providers for Django Models, or disable - the search type-hinting in a class hierarchy, etc. - """), - ) - project_opened: Optional[Callable] = field( - None, - description=dedent(""" - This function is called after opening the project. - Can only be set in config.py. - """), - ) - py_version: Optional[Tuple[int, int]] = field( - default=None, - description="Minimum python version to target", - universal_config=UniversalKey.min_py_version, - ) - dependencies: Optional[List[Requirement]] = field( - default=None, universal_config=UniversalKey.dependencies - ) - callbacks: Dict[str, Callable[[Any], None]] = field( - default_factory=lambda: {}, - description=dedent(""" - Callbacks run when configuration values are changed. - Can only be set in config.py. - """), - ) - - @others - -def set(self, key: str, value: Any): - """Set the value of `key` preference to `value`.""" - if key in self.callbacks: - self.callbacks[key](value) - else: - setattr(self, key, value) - - -def add(self, key: str, value: Any): - """Add an entry to a list preference - - Add `value` to the list of entries for the `key` preference. - - """ - if getattr(self, key) is None: - self[key] = [] - getattr(self, key).append(value) - - -def get(self, key: str, default: Any = None): - """Get the value of the key preference""" - return getattr(self, key, default) - - -def add_callback(self, key: str, callback: Callable): - """Add `key` preference with `callback` function - - Whenever `key` is set the callback is called with the - given `value` as parameter. - - """ - self.callbacks[key] = callback - - -def __setitem__(self, key: str, value: Any): - self.set(key, value) - - -def __getitem__(self, key: str): - return self.get(key) - - - -class _RopeConfigSource(Source): - """Custom source for rope config.py files.""" - - name: str = "config.py" - run_globals: Dict - - @others - -def __init__(self, ropefolder: Folder): - self.ropefolder = ropefolder - self.run_globals = {} - - -def _read(self) -> bool: - if self.ropefolder is None or not self.ropefolder.has_child("config.py"): - return False - config = self.ropefolder.get_child("config.py") - self.run_globals.update( - { - "__name__": "__main__", - "__builtins__": __builtins__, - "__file__": config.real_path, - } - ) - with open(config.real_path) as f: - code = compile(f.read(),config.real_path, 'exec') - exec(code, self.run_globals) - return True - - -def parse(self) -> Optional[Dict]: - prefs = Prefs() - if not self._read(): - return None - if "set_prefs" in self.run_globals: - self.run_globals["set_prefs"](prefs) - if "project_opened" in self.run_globals: - prefs["project_opened"] = self.run_globals["project_opened"] - return asdict(prefs) - - - -def get_config(root: Folder, ropefolder: Folder) -> PyToolConfig: - custom_sources = [_RopeConfigSource(ropefolder)] - config = PyToolConfig( - "rope", - root.pathlib, - Prefs, - custom_sources=custom_sources, - bases=[".ropefolder"], - recursive=False, - global_config=True, - ) - return config - -@path C:/Repos/ekr-rope/rope/base/ -import os -import shutil -import sys -import warnings - -import rope.base.fscommands -import rope.base.resourceobserver as resourceobserver -from rope.base import exceptions, history, pycore, taskhandle, utils -from rope.base.exceptions import ModuleNotFoundError -from rope.base.prefs import Prefs, get_config -from rope.base.resources import File, Folder, _ResourceMatcher - -try: - import cPickle as pickle -except ImportError: - import pickle - - -@others -@language python -@tabwidth -4 - -class _Project: - prefs: Prefs - - @others - ropefolder = None - - - -def __init__(self, fscommands): - self.observers = [] - self.fscommands = fscommands - self.prefs = Prefs() - self.data_files = _DataFiles(self) - self._custom_source_folders = [] - - -def get_resource(self, resource_name): - """Get a resource in a project. - - `resource_name` is the path of a resource in a project. It is - the path of a resource relative to project root. Project root - folder address is an empty string. If the resource does not - exist a `exceptions.ResourceNotFound` exception would be - raised. Use `get_file()` and `get_folder()` when you need to - get nonexistent `Resource`. - - """ - path = self._get_resource_path(resource_name) - if not os.path.exists(path): - raise exceptions.ResourceNotFoundError( - "Resource <%s> does not exist" % resource_name - ) - elif os.path.isfile(path): - return File(self, resource_name) - elif os.path.isdir(path): - return Folder(self, resource_name) - else: - raise exceptions.ResourceNotFoundError("Unknown resource " + resource_name) - - -def get_module(self, name, folder=None): - """Returns a `PyObject` if the module was found.""" - # check if this is a builtin module - pymod = self.pycore.builtin_module(name) - if pymod is not None: - return pymod - module = self.find_module(name, folder) - if module is None: - raise ModuleNotFoundError("Module %s not found" % name) - return self.pycore.resource_to_pyobject(module) - - -def get_python_path_folders(self): - result = [] - for src in self.prefs.get("python_path", []) + sys.path: - try: - src_folder = get_no_project().get_resource(src) - result.append(src_folder) - except exceptions.ResourceNotFoundError: - pass - return result - - -# INFO: It was decided not to cache source folders, since: -# - Does not take much time when the root folder contains -# packages, that is most of the time -# - We need a separate resource observer; `self.observer` -# does not get notified about module and folder creations -def get_source_folders(self): - """Returns project source folders""" - if self.root is None: - return [] - result = list(self._custom_source_folders) - result.extend(self.pycore._find_source_folders(self.root)) - return result - - -def validate(self, folder): - """Validate files and folders contained in this folder - - It validates all of the files and folders contained in this - folder if some observers are interested in them. - - """ - for observer in list(self.observers): - observer.validate(folder) - - -def add_observer(self, observer): - """Register a `ResourceObserver` - - See `FilteredResourceObserver`. - """ - self.observers.append(observer) - - -def remove_observer(self, observer): - """Remove a registered `ResourceObserver`""" - if observer in self.observers: - self.observers.remove(observer) - - -def do(self, changes, task_handle=taskhandle.NullTaskHandle()): - """Apply the changes in a `ChangeSet` - - Most of the time you call this function for committing the - changes for a refactoring. - """ - self.history.do(changes, task_handle=task_handle) - - -def get_pymodule(self, resource, force_errors=False): - return self.pycore.resource_to_pyobject(resource, force_errors) - - -def get_pycore(self): - return self.pycore - - -def get_file(self, path): - """Get the file with `path` (it may not exist)""" - return File(self, path) - - -def get_folder(self, path): - """Get the folder with `path` (it may not exist)""" - return Folder(self, path) - - -def get_prefs(self): - return self.prefs - - -def get_relative_module(self, name, folder, level): - module = self.find_relative_module(name, folder, level) - if module is None: - raise ModuleNotFoundError("Module %s not found" % name) - return self.pycore.resource_to_pyobject(module) - - -def find_module(self, modname, folder=None): - """Returns a resource corresponding to the given module - - returns None if it can not be found - """ - for src in self.get_source_folders(): - module = _find_module_in_folder(src, modname) - if module is not None: - return module - for src in self.get_python_path_folders(): - module = _find_module_in_folder(src, modname) - if module is not None: - return module - if folder is not None: - module = _find_module_in_folder(folder, modname) - if module is not None: - return module - return None - - -def find_relative_module(self, modname, folder, level): - for i in range(level - 1): - folder = folder.parent - if modname == "": - return folder - else: - return _find_module_in_folder(folder, modname) - - -def is_ignored(self, resource): - return False - - -def _get_resource_path(self, name): - pass - - -@property -@utils.saveit -def history(self): - return history.History(self) - - -@property -@utils.saveit -def pycore(self): - return pycore.PyCore(self) - - -def close(self): - warnings.warn("Cannot close a NoProject", DeprecationWarning, stacklevel=2) - - -@path C:/Repos/ekr-rope/bin/ -#!/usr/bin/env python - -import re -import subprocess -from datetime import datetime - -import toml - - -pyproject = toml.load("pyproject.toml") -version = pyproject["project"]["version"] - - -@others -message = get_changelog(version) -proc = subprocess.Popen(["git", "tag", "-s", version, "-m", message]) -proc.wait() - -subprocess.check_call(["git", "show", version]) - -print() -if input("Push [yn]? ") in "yY": - subprocess.check_output(["git", "push", "origin", version]) -@language python -@tabwidth -4 - -class Project(_Project): - """A Project containing files and folders""" - - @others - root = property(lambda self: self.get_resource("")) - address = property(lambda self: self._address) - - - -def __init__( - self, projectroot, fscommands=None, ropefolder=".ropeproject", **prefs -): - """A rope project - - :parameters: - - `projectroot`: The address of the root folder of the project - - `fscommands`: Implements the file system operations used - by rope; have a look at `rope.base.fscommands` - - `ropefolder`: The name of the folder in which rope stores - project configurations and data. Pass `None` for not using - such a folder at all. - - `prefs`: Specify project preferences. These values - overwrite config file preferences. - - """ - if projectroot != "/": - projectroot = _realpath(projectroot).rstrip("/\\") - self._address = projectroot - self._ropefolder_name = ropefolder - if not os.path.exists(self._address): - os.mkdir(self._address) - elif not os.path.isdir(self._address): - raise exceptions.RopeError("Project root exists and" " is not a directory") - if fscommands is None: - fscommands = rope.base.fscommands.create_fscommands(self._address) - super().__init__(fscommands) - self.ignored = _ResourceMatcher() - self.file_list = _FileListCacher(self) - self._init_prefs(prefs) - if ropefolder is not None: - self.prefs.add("ignored_resources", ropefolder) - self._init_source_folders() - - -def __repr__(self): - return '<{}.{} "{}">'.format( - self.__class__.__module__, - self.__class__.__name__, - self.address, - ) - - -@utils.deprecated("Delete once deprecated functions are gone") -def _init_source_folders(self): - for path in self.prefs.get("source_folders", []): - folder = self.get_resource(path) - self._custom_source_folders.append(folder) - - -def get_files(self): - return self.file_list.get_files() - - -def get_python_files(self): - """Returns all python files available in the project""" - return [ - resource - for resource in self.get_files() - if self.pycore.is_python_file(resource) - ] - - -def _get_resource_path(self, name): - return os.path.join(self._address, *name.split("/")) - - -def _init_ropefolder(self): - if self.ropefolder is not None: - if not self.ropefolder.exists(): - self._create_recursively(self.ropefolder) - - -def _create_recursively(self, folder): - if folder.parent != self.root and not folder.parent.exists(): - self._create_recursively(folder.parent) - folder.create() - - -def _init_prefs(self, prefs): - config = get_config(self.root, self.ropefolder).parse() - self.prefs = config - self.prefs.add_callback("ignored_resources", self.ignored.set_patterns) - self.ignored.set_patterns(self.prefs.ignored_resources) - for key, value in prefs.items(): - self.prefs.set(key, value) - self._init_other_parts() - self._init_ropefolder() - if config.project_opened: - config.project_opened(self) - - -def _init_other_parts(self): - # Forcing the creation of `self.pycore` to register observers - self.pycore - - -def is_ignored(self, resource): - return self.ignored.does_match(resource) - - -def sync(self): - """Closes project open resources""" - self.close() - - -def close(self): - """Closes project open resources""" - self.data_files.write() - - -def set(self, key, value): - """Set the `key` preference to `value`""" - self.prefs.set(key, value) - - -@property -def ropefolder(self): - if self._ropefolder_name is not None: - return self.get_folder(self._ropefolder_name) - - -def validate(self, folder=None): - if folder is None: - folder = self.root - super().validate(folder) - - -class NoProject(_Project): - """A null object for holding out of project files. - - This class is singleton use `get_no_project` global function - """ - - @others - _no_project = None - - - -def __init__(self): - fscommands = rope.base.fscommands.FileSystemCommands() - super().__init__(fscommands) - - -def _get_resource_path(self, name): - real_name = name.replace("/", os.path.sep) - return _realpath(real_name) - - -def get_resource(self, name): - universal_name = _realpath(name).replace(os.path.sep, "/") - return super().get_resource(universal_name) - - -def get_files(self): - return [] - - -def get_python_files(self): - return [] - - -def get_no_project(): - if NoProject._no_project is None: - NoProject._no_project = NoProject() - return NoProject._no_project - - - -class _FileListCacher: - @others - -def __init__(self, project): - self.project = project - self.files = None - rawobserver = resourceobserver.ResourceObserver( - self._changed, self._invalid, self._invalid, self._invalid, self._invalid - ) - self.project.add_observer(rawobserver) - - -def get_files(self): - if self.files is None: - self.files = set() - self._add_files(self.project.root) - return self.files - - -def _add_files(self, folder): - for child in folder.get_children(): - if child.is_folder(): - self._add_files(child) - elif not self.project.is_ignored(child): - self.files.add(child) - - -def _changed(self, resource): - if resource.is_folder(): - self.files = None - - -def _invalid(self, resource, new_resource=None): - self.files = None - - - -class _DataFiles: - @others - -def __init__(self, project): - self.project = project - self.hooks = [] - - -def read_data(self, name, compress=False, import_=False): - if self.project.ropefolder is None: - return None - compress = compress and self._can_compress() - opener = self._get_opener(compress) - file = self._get_file(name, compress) - if not compress and import_: - self._import_old_files(name) - if file.exists(): - input = opener(file.real_path, "rb") - try: - result = [] - try: - while True: - result.append(pickle.load(input)) - except EOFError: - pass - if len(result) == 1: - return result[0] - if len(result) > 1: - return result - finally: - input.close() - - -def write_data(self, name, data, compress=False): - if self.project.ropefolder is not None: - compress = compress and self._can_compress() - file = self._get_file(name, compress) - opener = self._get_opener(compress) - output = opener(file.real_path, "wb") - try: - pickle.dump(data, output, 2) - finally: - output.close() - - -def add_write_hook(self, hook): - self.hooks.append(hook) - - -def write(self): - for hook in self.hooks: - hook() - - -def _can_compress(self): - try: - import gzip # noqa - - return True - except ImportError: - return False - - -def _import_old_files(self, name): - old = self._get_file(name + ".pickle", False) - new = self._get_file(name, False) - if old.exists() and not new.exists(): - shutil.move(old.real_path, new.real_path) - - -def _get_opener(self, compress): - if compress: - try: - import gzip - - return gzip.open - except ImportError: - pass - return open - - -def _get_file(self, name, compress): - path = self.project.ropefolder.path + "/" + name - if compress: - path += ".gz" - return self.project.get_file(path) - - - -def _realpath(path): - """Return the real path of `path` - - Is equivalent to ``realpath(abspath(expanduser(path)))``. - - Of the particular notice is the hack dealing with the unfortunate - situation of running native-Windows python (os.name == 'nt') inside - of Cygwin (abspath starts with '/'), which apparently normal - os.path.realpath completely messes up. - - """ - # there is a bug in cygwin for os.path.abspath() for abs paths - if sys.platform == "cygwin": - if path[1:3] == ":\\": - return path - elif path[1:3] == ":/": - path = "/cygdrive/" + path[0] + path[2:] - return os.path.abspath(os.path.expanduser(path)) - return os.path.realpath(os.path.abspath(os.path.expanduser(path))) - - - -def _find_module_in_folder(folder, modname): - module = folder - packages = modname.split(".") - for pkg in packages[:-1]: - if module.is_folder() and module.has_child(pkg): - module = module.get_child(pkg) - else: - return None - if module.is_folder(): - if ( - module.has_child(packages[-1]) - and module.get_child(packages[-1]).is_folder() - ): - return module.get_child(packages[-1]) - elif ( - module.has_child(packages[-1] + ".py") - and not module.get_child(packages[-1] + ".py").is_folder() - ): - return module.get_child(packages[-1] + ".py") - -@path C:/Repos/ekr-rope/rope/base/ -import bisect -import difflib -import sys -import warnings - -import rope.base.libutils -import rope.base.resourceobserver -import rope.base.resources -import rope.base.oi.doa -import rope.base.oi.objectinfo -import rope.base.oi.soa -from rope.base import builtins -from rope.base import exceptions -from rope.base import pyobjectsdef -from rope.base import stdmods -from rope.base import taskhandle -from rope.base import utils -from rope.base.exceptions import ModuleNotFoundError - - -@others -@language python -@tabwidth -4 - -class PyCore: - @others - -def __init__(self, project): - self.project = project - self._init_resource_observer() - self.cache_observers = [] - self.module_cache = _ModuleCache(self) - self.extension_cache = _ExtensionCache(self) - self.object_info = rope.base.oi.objectinfo.ObjectInfoManager(project) - self._init_python_files() - self._init_automatic_soa() - - -def _init_python_files(self): - self.python_matcher = None - patterns = self.project.prefs.get("python_files", None) - if patterns is not None: - self.python_matcher = rope.base.resources._ResourceMatcher() - self.python_matcher.set_patterns(patterns) - - -def _init_resource_observer(self): - callback = self._invalidate_resource_cache - observer = rope.base.resourceobserver.ResourceObserver( - changed=callback, moved=callback, removed=callback - ) - self.observer = rope.base.resourceobserver.FilteredResourceObserver(observer) - self.project.add_observer(self.observer) - - -def _init_automatic_soa(self): - if not self.automatic_soa: - return - callback = self._file_changed_for_soa - observer = rope.base.resourceobserver.ResourceObserver( - changed=callback, moved=callback, removed=callback - ) - self.project.add_observer(observer) - - -@property -def automatic_soa(self): - auto_soa = self.project.prefs.get("automatic_soi", None) - return self.project.prefs.get("automatic_soa", auto_soa) - - -def _file_changed_for_soa(self, resource, new_resource=None): - old_contents = self.project.history.contents_before_current_change(resource) - if old_contents is not None: - perform_soa_on_changed_scopes(self.project, resource, old_contents) - - -@path C:/Repos/ekr-rope/rope/base/ -"""This module tries to support builtin types and functions.""" -import ast -import inspect -import io - -try: - raw_input -except NameError: - raw_input = input - -import rope.base.evaluate -from rope.base import pynames, pyobjects, arguments, utils - - -@others -_initial_builtins = { - "list": BuiltinName(get_list_type()), - "dict": BuiltinName(get_dict_type()), - "tuple": BuiltinName(get_tuple_type()), - "set": BuiltinName(get_set_type()), - "str": BuiltinName(get_str_type()), - "file": BuiltinName(get_file_type()), - "open": BuiltinName(BuiltinFunction(function=_open_function, builtin=open)), - "unicode": BuiltinName(get_str_type()), - "range": BuiltinName(BuiltinFunction(function=_range_function, builtin=range)), - "reversed": BuiltinName( - BuiltinFunction(function=_reversed_function, builtin=reversed) - ), - "sorted": BuiltinName(BuiltinFunction(function=_sorted_function, builtin=sorted)), - "super": BuiltinName(BuiltinFunction(function=_super_function, builtin=super)), - "property": BuiltinName( - BuiltinFunction(function=_property_function, builtin=property) - ), - "zip": BuiltinName(BuiltinFunction(function=_zip_function, builtin=zip)), - "enumerate": BuiltinName( - BuiltinFunction(function=_enumerate_function, builtin=enumerate) - ), - "object": BuiltinName(BuiltinObject()), - "type": BuiltinName(BuiltinType()), - "iter": BuiltinName(BuiltinFunction(function=_iter_function, builtin=iter)), - "raw_input": BuiltinName( - BuiltinFunction(function=_input_function, builtin=raw_input) - ), -} - -builtins = BuiltinModule('builtins', initial=_initial_builtins) -@language python -@tabwidth -4 - -def is_python_file(self, resource): - if resource.is_folder(): - return False - if self.python_matcher is None: - return resource.name.endswith(".py") - return self.python_matcher.does_match(resource) - - -@utils.deprecated("Use `project.get_module` instead") -def get_module(self, name, folder=None): - """Returns a `PyObject` if the module was found.""" - return self.project.get_module(name, folder) - - -def _builtin_submodules(self, modname): - result = {} - for extension in self.extension_modules: - if extension.startswith(modname + "."): - name = extension[len(modname) + 1 :] - if "." not in name: - result[name] = self.builtin_module(extension) - return result - - -def builtin_module(self, name): - return self.extension_cache.get_pymodule(name) - - -@utils.deprecated("Use `project.get_relative_module` instead") -def get_relative_module(self, name, folder, level): - return self.project.get_relative_module(name, folder, level) - - -@utils.deprecated("Use `libutils.get_string_module` instead") -def get_string_module(self, code, resource=None, force_errors=False): - """Returns a `PyObject` object for the given code - - If `force_errors` is `True`, `exceptions.ModuleSyntaxError` is - raised if module has syntax errors. This overrides - ``ignore_syntax_errors`` project config. - - """ - return pyobjectsdef.PyModule(self, code, resource, force_errors=force_errors) - - -@utils.deprecated("Use `libutils.get_string_scope` instead") -def get_string_scope(self, code, resource=None): - """Returns a `Scope` object for the given code""" - return rope.base.libutils.get_string_scope(code, resource) - - -def _invalidate_resource_cache(self, resource, new_resource=None): - for observer in self.cache_observers: - observer(resource) - - -@utils.deprecated("Use `project.get_python_path_folders` instead") -def get_python_path_folders(self): - return self.project.get_python_path_folders() - - -@utils.deprecated("Use `project.find_module` instead") -def find_module(self, modname, folder=None): - """Returns a resource corresponding to the given module - - returns None if it can not be found - """ - return self.project.find_module(modname, folder) - - -class BuiltinModule(pyobjects.AbstractModule): - @others - -@utils.deprecated("Use `project.find_relative_module` instead") -def find_relative_module(self, modname, folder, level): - return self.project.find_relative_module(modname, folder, level) - - -# INFO: It was decided not to cache source folders, since: -# - Does not take much time when the root folder contains -# packages, that is most of the time -# - We need a separate resource observer; `self.observer` -# does not get notified about module and folder creations -@utils.deprecated("Use `project.get_source_folders` instead") -def get_source_folders(self): - """Returns project source folders""" - return self.project.get_source_folders() - - -def resource_to_pyobject(self, resource, force_errors=False): - return self.module_cache.get_pymodule(resource, force_errors) - - -@utils.deprecated("Use `project.get_python_files` instead") -def get_python_files(self): - """Returns all python files available in the project""" - return self.project.get_python_files() - - -def _is_package(self, folder): - return ( - folder.has_child("__init__.py") - and not folder.get_child("__init__.py").is_folder() - ) - - -def _find_source_folders(self, folder): - for resource in folder.get_folders(): - if self._is_package(resource): - return [folder] - result = [] - for resource in folder.get_files(): - if resource.name.endswith(".py"): - result.append(folder) - break - for resource in folder.get_folders(): - result.extend(self._find_source_folders(resource)) - return result - - -def run_module(self, resource, args=None, stdin=None, stdout=None): - """Run `resource` module - - Returns a `rope.base.oi.doa.PythonFileRunner` object for - controlling the process. - - """ - perform_doa = self.project.prefs.get("perform_doi", True) - perform_doa = self.project.prefs.get("perform_doa", perform_doa) - receiver = self.object_info.doa_data_received - if not perform_doa: - receiver = None - runner = rope.base.oi.doa.PythonFileRunner( - self, resource, args, stdin, stdout, receiver - ) - runner.add_finishing_observer(self.module_cache.forget_all_data) - runner.run() - return runner - - -def analyze_module( - self, - resource, - should_analyze=lambda py: True, - search_subscopes=lambda py: True, - followed_calls=None, -): - """Analyze `resource` module for static object inference - - This function forces rope to analyze this module to collect - information about function calls. `should_analyze` is a - function that is called with a `PyDefinedObject` argument. If - it returns `True` the element is analyzed. If it is `None` or - returns `False` the element is not analyzed. - - `search_subscopes` is like `should_analyze`; The difference is - that if it returns `False` the sub-scopes are all ignored. - That is it is assumed that `should_analyze` returns `False` - for all of its subscopes. - - `followed_calls` override the value of ``soa_followed_calls`` - project config. - """ - if followed_calls is None: - followed_calls = self.project.prefs.get("soa_followed_calls", 0) - pymodule = self.resource_to_pyobject(resource) - self.module_cache.forget_all_data() - rope.base.oi.soa.analyze_module( - self, pymodule, should_analyze, search_subscopes, followed_calls - ) - - -def get_classes(self, task_handle=taskhandle.NullTaskHandle()): - warnings.warn( - "`PyCore.get_classes()` is deprecated", DeprecationWarning, stacklevel=2 - ) - return [] - - -def __str__(self): - return str(self.module_cache) + str(self.object_info) - - -def __init__(self, name, pycore=None, initial={}): - super().__init__() - self.name = name - self.pycore = pycore - self.initial = initial - - -@utils.deprecated("Use `libutils.modname` instead") -def modname(self, resource): - return rope.base.libutils.modname(resource) - - -@property -@utils.cacheit -def extension_modules(self): - result = set(self.project.prefs.get("extension_modules", [])) - if self.project.prefs.get("import_dynload_stdmods", False): - result.update(stdmods.dynload_modules()) - return result - - - -class _ModuleCache: - @others - -def __init__(self, pycore): - self.pycore = pycore - self.module_map = {} - self.pycore.cache_observers.append(self._invalidate_resource) - self.observer = self.pycore.observer - - -def _invalidate_resource(self, resource): - if resource in self.module_map: - self.forget_all_data() - self.observer.remove_resource(resource) - del self.module_map[resource] - - -def get_pymodule(self, resource, force_errors=False): - if resource in self.module_map: - return self.module_map[resource] - if resource.is_folder(): - result = pyobjectsdef.PyPackage( - self.pycore, - resource, - force_errors=force_errors, - ) - else: - result = pyobjectsdef.PyModule( - self.pycore, - resource=resource, - force_errors=force_errors, - ) - if result.has_errors: - return result - self.module_map[resource] = result - self.observer.add_resource(resource) - return result - - -def forget_all_data(self): - for pymodule in self.module_map.values(): - pymodule._forget_concluded_data() - - -def __str__(self): - return "PyCore caches %d PyModules\n" % len(self.module_map) - - - -class _ExtensionCache: - @others - -def __init__(self, pycore): - self.pycore = pycore - self.extensions = {} - - -parent = None - - -def get_pymodule(self, name): - if name == "__builtin__": - return builtins.builtins - allowed = self.pycore.extension_modules - if name not in self.extensions and name in allowed: - self.extensions[name] = builtins.BuiltinModule(name, self.pycore) - return self.extensions.get(name) - - - -def perform_soa_on_changed_scopes(project, resource, old_contents): - pycore = project.pycore - if resource.exists() and pycore.is_python_file(resource): - try: - new_contents = resource.read() - # detecting changes in new_contents relative to old_contents - detector = _TextChangeDetector(new_contents, old_contents) - - def search_subscopes(pydefined): - scope = pydefined.get_scope() - return detector.is_changed(scope.get_start(), scope.get_end()) - - def should_analyze(pydefined): - scope = pydefined.get_scope() - start = scope.get_start() - end = scope.get_end() - return detector.consume_changes(start, end) - - pycore.analyze_module(resource, should_analyze, search_subscopes) - except exceptions.ModuleSyntaxError: - pass - - - -class _TextChangeDetector: - @others - -def __init__(self, old, new): - self.old = old - self.new = new - self._set_diffs() - - -def _set_diffs(self): - differ = difflib.Differ() - self.lines = [] - lineno = 0 - for line in differ.compare( - self.old.splitlines(True), self.new.splitlines(True) - ): - if line.startswith(" "): - lineno += 1 - elif line.startswith("-"): - lineno += 1 - self.lines.append(lineno) - - -def is_changed(self, start, end): - """Tell whether any of start till end lines have changed - - The end points are inclusive and indices start from 1. - """ - left, right = self._get_changed(start, end) - return left < right - - -def consume_changes(self, start, end): - """Clear the changed status of lines from start till end""" - left, right = self._get_changed(start, end) - if left < right: - del self.lines[left:right] - return left < right - - -def _get_changed(self, start, end): - left = bisect.bisect_left(self.lines, start) - right = bisect.bisect_right(self.lines, end) - return left, right - -@path C:/Repos/ekr-rope/rope/base/ -import rope.base.pyobjects -from rope.base import exceptions, utils - - -@others -@language python -@tabwidth -4 - -class PyName: - """References to `PyObject` inside python programs""" - - @others - -def get_attributes(self): - return self.attributes - - -def get_object(self): - """Return the `PyObject` object referenced by this `PyName`""" - - -def get_definition_location(self): - """Return a (module, lineno) tuple""" - - - -class DefinedName(PyName): - @others - -def __init__(self, pyobject): - self.pyobject = pyobject - - -def get_object(self): - return self.pyobject - - -def get_definition_location(self): - lineno = utils.guess_def_lineno( - self.pyobject.get_module(), self.pyobject.get_ast() - ) - return (self.pyobject.get_module(), lineno) - - - -class UnboundName(PyName): - @others - -def __init__(self, pyobject=None): - self.pyobject = pyobject - if self.pyobject is None: - self.pyobject = rope.base.pyobjects.get_unknown() - - -def get_object(self): - return self.pyobject - - -def get_changelog(version): - s = open("CHANGELOG.md").read() - search_heading = f"# Release {version}" - curdate = datetime.today().date().isoformat() - - headings = re.findall(r"# Release \d+\.\d+\.\d+", s) - version_heading_index = headings.index(search_heading) - version_changelog = s[ - s.index(headings[version_heading_index]) : s.index( - headings[version_heading_index + 1] - ) - ].strip() - - version_changelog = insert_date(version_changelog, curdate, after=search_heading) - version_changelog = remove_headings(version_changelog) - - return version_changelog - - - -def get_doc(self): - if self.module: - return self.module.__doc__ - - -def get_definition_location(self): - return (None, None) - - - -class AssignmentValue: - """An assigned expression""" - - @others - -def __init__( - self, ast_node, levels=None, evaluation="", assign_type=False, type_hint=None -): - """The `level` is `None` for simple assignments and is - a list of numbers for tuple assignments for example in:: - - a, (b, c) = x - - The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for - `c` is ``[1, 1]``. - - """ - self.ast_node = ast_node - if levels is None: - self.levels = [] - else: - self.levels = levels - self.evaluation = evaluation - self.assign_type = assign_type - self.type_hint = type_hint - - -def get_lineno(self): - return self.ast_node.lineno - - - -class EvaluatedName(PyName): - """A name whose object will be evaluated later""" - - @others - -def __init__(self, callback, module=None, lineno=None): - self.module = module - self.lineno = lineno - self.callback = callback - self.pyobject = _Inferred(callback, _get_concluded_data(module)) - - -def get_object(self): - return self.pyobject.get() - - -def get_definition_location(self): - return (self.module, self.lineno) - - -def invalidate(self): - """Forget the `PyObject` this `PyName` holds""" - self.pyobject.set(None) - - - -def get_name(self): - return self.name.split(".")[-1] - - -class ImportedModule(PyName): - @others - -def __init__(self, importing_module, module_name=None, level=0, resource=None): - self.importing_module = importing_module - self.module_name = module_name - self.level = level - self.resource = resource - self.pymodule = _get_concluded_data(self.importing_module) - - -def _current_folder(self): - resource = self.importing_module.get_module().get_resource() - if resource is None: - return None - return resource.parent - - -def _get_pymodule(self): - if self.pymodule.get() is None: - pycore = self.importing_module.pycore - if self.resource is not None: - self.pymodule.set(pycore.project.get_pymodule(self.resource)) - elif self.module_name is not None: - try: - if self.level == 0: - pymodule = pycore.project.get_module( - self.module_name, self._current_folder() - ) - else: - pymodule = pycore.project.get_relative_module( - self.module_name, self._current_folder(), self.level - ) - self.pymodule.set(pymodule) - except exceptions.ModuleNotFoundError: - pass - return self.pymodule.get() - - -def get_object(self): - if self._get_pymodule() is None: - return rope.base.pyobjects.get_unknown() - return self._get_pymodule() - - -def get_definition_location(self): - pymodule = self._get_pymodule() - if not isinstance(pymodule, rope.base.pyobjects.PyDefinedObject): - return (None, None) - return (pymodule.get_module(), 1) - - - -class ImportedName(PyName): - @others - -def __init__(self, imported_module, imported_name): - self.imported_module = imported_module - self.imported_name = imported_name - - -def _get_imported_pyname(self): - try: - result = self.imported_module.get_object()[self.imported_name] - if result != self: - return result - except exceptions.AttributeNotFoundError: - pass - return UnboundName() - - -@utils.prevent_recursion(rope.base.pyobjects.get_unknown) -def get_object(self): - return self._get_imported_pyname().get_object() - - -@property -@utils.saveit -def attributes(self): - result = _object_attributes(self.module, self) - result.update(self.initial) - if self.pycore is not None: - submodules = self.pycore._builtin_submodules(self.name) - for name, module in submodules.items(): - result[name] = rope.base.builtins.BuiltinName(module) - return result - - -@utils.prevent_recursion(lambda: (None, None)) -def get_definition_location(self): - return self._get_imported_pyname().get_definition_location() - - - -def _get_concluded_data(module): - if module is None: - return rope.base.pyobjects._ConcludedData() - return module._get_concluded_data() - - - -def _circular_inference(): - raise rope.base.pyobjects.IsBeingInferredError("Circular Object Inference") - - - -class _Inferred: - @others - -def __init__(self, get_inferred, concluded=None): - self.get_inferred = get_inferred - self.concluded = concluded - if self.concluded is None: - self.temp = None - - -@utils.prevent_recursion(_circular_inference) -def get(self, *args, **kwds): - if self.concluded is None or self.concluded.get() is None: - self.set(self.get_inferred(*args, **kwds)) - if self._get() is None: - self.set(rope.base.pyobjects.get_unknown()) - return self._get() - - -def set(self, pyobject): - if self.concluded is not None: - self.concluded.set(pyobject) - self.temp = pyobject - - -def _get(self): - if self.concluded is not None: - return self.concluded.get() - return self.temp - -class AssignedName(PyName): - @others - -@property -@utils.saveit -def module(self): - try: - result = __import__(self.name) - for token in self.name.split(".")[1:]: - result = getattr(result, token, None) - return result - except ImportError: - return - - - -"""Only a placeholder""" - - - - - - - -class ParameterName(PyName): - @others - -"""Only a placeholder""" - - - - - - -class _BuiltinElement: - @others - -@path C:/Repos/ekr-rope/rope/base/ -from typing import Optional - -from rope.base import ast, exceptions, utils - - -@others -@language python -@tabwidth -4 - -class PyObject: - @others - -def __init__(self, type_): - if type_ is None: - type_ = self - self.type = type_ - - -def get_attributes(self): - if self.type is self: - return {} - return self.type.get_attributes() - - -def get_attribute(self, name): - if name not in self.get_attributes(): - raise exceptions.AttributeNotFoundError("Attribute %s not found" % name) - return self.get_attributes()[name] - - -def get_type(self): - return self.type - - -def __getitem__(self, key): - """The same as ``get_attribute(key)``""" - return self.get_attribute(key) - - -def __contains__(self, key): - """The same as ``key in self.get_attributes()``""" - return key in self.get_attributes() - - -def __eq__(self, obj): - """Check the equality of two `PyObject` - - Currently it is assumed that instances (the direct instances - of `PyObject`, not the instances of its subclasses) are equal - if their types are equal. For every other object like - defineds or builtins rope assumes objects are reference - objects and their identities should match. - - """ - if self.__class__ != obj.__class__: - return False - if type(self) == PyObject: - if self is not self.type: - return self.type == obj.type - else: - return self.type is obj.type - return self is obj - - -def __ne__(self, obj): - return not self.__eq__(obj) - - -def __init__(self, builtin, parent=None): - self.builtin = builtin - self._parent = parent - - -def __hash__(self): - """See docs for `__eq__()` method""" - if type(self) == PyObject and self != self.type: - return hash(self.type) + 1 - else: - return super().__hash__() - - -def __iter__(self): - """The same as ``iter(self.get_attributes())``""" - return iter(self.get_attributes()) - - -_types = None -_unknown = None - - -@staticmethod -def _get_base_type(name): - if PyObject._types is None: - PyObject._types = {} - base_type = PyObject(None) - PyObject._types["Type"] = base_type - PyObject._types["Module"] = PyObject(base_type) - PyObject._types["Function"] = PyObject(base_type) - PyObject._types["Unknown"] = PyObject(base_type) - return PyObject._types[name] - - - -def get_base_type(name): - """Return the base type with name `name`. - - The base types are 'Type', 'Function', 'Module' and 'Unknown'. It - was used to check the type of a `PyObject` but currently its use - is discouraged. Use classes defined in this module instead. - For example instead of - ``pyobject.get_type() == get_base_type('Function')`` use - ``isinstance(pyobject, AbstractFunction)``. - - You can use `AbstractClass` for classes, `AbstractFunction` for - functions, and `AbstractModule` for modules. You can also use - `PyFunction` and `PyClass` for testing if an object is - defined somewhere and rope can access its source. These classes - provide more methods. - - """ - return PyObject._get_base_type(name) - - - -def get_unknown(): - """Return a pyobject whose type is unknown - - Note that two unknown objects are equal. So for example you can - write:: - - if pyname.get_object() == get_unknown(): - print('cannot determine what this pyname holds') - - Rope could have used `None` for indicating unknown objects but - we had to check that in many places. So actually this method - returns a null object. - - """ - if PyObject._unknown is None: - PyObject._unknown = PyObject(get_base_type("Unknown")) - return PyObject._unknown - - - -class AbstractClass(PyObject): - @others - -def __init__(self): - super().__init__(get_base_type("Type")) - - -def get_name(self): - pass - - -def get_doc(self): - pass - - -def get_doc(self): - if self.builtin: - return getattr(self.builtin, "__doc__", None) - - -def get_superclasses(self): - return [] - - - -class AbstractFunction(PyObject): - @others - -def __init__(self): - super().__init__(get_base_type("Function")) - - -def get_name(self): - pass - - -def get_doc(self): - pass - - -def get_param_names(self, special_args=True): - return [] - - -def get_returned_object(self, args): - return get_unknown() - - - -class AbstractModule(PyObject): - @others - -def __init__(self, doc=None): - super().__init__(get_base_type("Module")) - - -def get_doc(self): - pass - - -def get_name(self): - if self.builtin: - return getattr(self.builtin, "__name__", None) - - -def get_resource(self): - pass - - - -class PyDefinedObject: - """Python defined names that rope can access their sources""" - - @others - -def __init__(self, pycore, ast_node, parent): - self.pycore = pycore - self.ast_node = ast_node - self.scope = None - self.parent = parent - self.structural_attributes = None - self.concluded_attributes = self.get_module()._get_concluded_data() - self.attributes = self.get_module()._get_concluded_data() - self.defineds = None - - -def __repr__(self): - return '<{}.{} "{}" at {}>'.format( - self.__class__.__module__, - self.__class__.__name__, - self.absolute_name, - hex(id(self)), - ) - - -@property -def absolute_name(self): - obj_name = self.get_name() - return self.get_module().get_name() + ("::" + obj_name if obj_name else "") - - -visitor_class = None - - -@utils.prevent_recursion(lambda: {}) -def _get_structural_attributes(self): - if self.structural_attributes is None: - self.structural_attributes = self._create_structural_attributes() - return self.structural_attributes - - -@utils.prevent_recursion(lambda: {}) -def _get_concluded_attributes(self): - if self.concluded_attributes.get() is None: - self._get_structural_attributes() - self.concluded_attributes.set(self._create_concluded_attributes()) - return self.concluded_attributes.get() - - -def get_attributes(self): - if self.attributes.get() is None: - result = dict(self._get_concluded_attributes()) - result.update(self._get_structural_attributes()) - self.attributes.set(result) - return self.attributes.get() - - -def get_attribute(self, name): - if name in self._get_structural_attributes(): - return self._get_structural_attributes()[name] - if name in self._get_concluded_attributes(): - return self._get_concluded_attributes()[name] - raise exceptions.AttributeNotFoundError("Attribute %s not found" % name) - - -@property -def parent(self): - if self._parent is None: - return builtins - return self._parent - - - -def get_scope(self): - if self.scope is None: - self.scope = self._create_scope() - return self.scope - - -def get_module(self): - current_object = self - while current_object.parent is not None: - current_object = current_object.parent - return current_object - - -def get_doc(self) -> Optional[str]: - if len(self.get_ast().body) > 0: - expr = self.get_ast().body[0] - if isinstance(expr, ast.Expr) and isinstance(expr.value, ast.Str): - docstring = expr.value.s - assert isinstance(docstring, str) - return docstring - return None - - -def _get_defined_objects(self): - if self.defineds is None: - self._get_structural_attributes() - return self.defineds - - -def _create_structural_attributes(self): - if self.visitor_class is None: - return {} - new_visitor = self.visitor_class(self.pycore, self) - for child in ast.get_child_nodes(self.ast_node): - ast.walk(child, new_visitor) - self.defineds = new_visitor.defineds - return new_visitor.names - - -def _create_concluded_attributes(self): - return {} - - -def get_ast(self): - return self.ast_node - - -def _create_scope(self): - pass - - - -class PyFunction(PyDefinedObject, AbstractFunction): - """Only a placeholder""" - - - -class PyComprehension(PyDefinedObject, PyObject): - """Only a placeholder""" - - def get_name(self): - return "<comprehension>" - - - -class BuiltinClass(_BuiltinElement, pyobjects.AbstractClass): - @others - -class PyClass(PyDefinedObject, AbstractClass): - """Only a placeholder""" - - - -class _ConcludedData: - @others - -def __init__(self): - self.data_ = None - - -def set(self, data): - self.data_ = data - - -def get(self): - return self.data_ - - -data = property(get, set) - - -def _invalidate(self): - self.data = None - - -def __str__(self): - return "<" + str(self.data) + ">" - - - -class _PyModule(PyDefinedObject, AbstractModule): - @others - -def __init__(self, pycore, ast_node, resource): - self.resource = resource - self.concluded_data = [] - AbstractModule.__init__(self) - PyDefinedObject.__init__(self, pycore, ast_node, None) - - -def remove_headings(version_changelog): - # Remove Markdown-style headings as it matches Git comment syntax - version_changelog = re.sub(r"^#+\s+", "", version_changelog, flags=re.MULTILINE) - return version_changelog - - - -def __init__(self, builtin, attributes, parent=None): - _BuiltinElement.__init__(self, builtin, parent) - pyobjects.AbstractClass.__init__(self) - self.initial = attributes - - -@property -def absolute_name(self) -> str: - return self.get_name() - - -def _get_concluded_data(self): - new_data = _ConcludedData() - self.concluded_data.append(new_data) - return new_data - - -def _forget_concluded_data(self): - for data in self.concluded_data: - data._invalidate() - - -def get_resource(self): - return self.resource - - - -class PyModule(_PyModule): - """Only a placeholder""" - - - -class PyPackage(_PyModule): - """Only a placeholder""" - - - -class IsBeingInferredError(exceptions.RopeError): - pass - -@path C:/Repos/ekr-rope/rope/base/ -<< imports: pyobjectsdef >> -@others -@language python -@tabwidth -4 - -class PyFunction(pyobjects.PyFunction): - @others - -def __init__(self, pycore, ast_node, parent): - rope.base.pyobjects.AbstractFunction.__init__(self) - rope.base.pyobjects.PyDefinedObject.__init__(self, pycore, ast_node, parent) - self.arguments = self.ast_node.args - self.parameter_pyobjects = pynames._Inferred( - self._infer_parameters, self.get_module()._get_concluded_data() - ) - self.returned = pynames._Inferred(self._infer_returned) - self.parameter_pynames = None - - -@utils.saveit -def get_attributes(self): - result = _object_attributes(self.builtin, self) - result.update(self.initial) - return result - - -def _create_structural_attributes(self): - return {} - - -def _create_concluded_attributes(self): - return {} - - -def _create_scope(self): - return rope.base.pyscopes.FunctionScope(self.pycore, self, _FunctionVisitor) - - -def _infer_parameters(self): - pyobjects = rope.base.oi.soi.infer_parameter_objects(self) - self._handle_special_args(pyobjects) - return pyobjects - - -def _infer_returned(self, args=None): - return rope.base.oi.soi.infer_returned_object(self, args) - - -def _handle_special_args(self, pyobjects): - if len(pyobjects) == len(self.arguments.args): - if self.arguments.vararg: - pyobjects.append(rope.base.builtins.get_list()) - if self.arguments.kwarg: - pyobjects.append(rope.base.builtins.get_dict()) - - -def _set_parameter_pyobjects(self, pyobjects): - if pyobjects is not None: - self._handle_special_args(pyobjects) - self.parameter_pyobjects.set(pyobjects) - - -def get_parameters(self): - if self.parameter_pynames is None: - result = {} - for index, name in enumerate(self.get_param_names()): - # TODO: handle tuple parameters - result[name] = pynames.ParameterName(self, index) - self.parameter_pynames = result - return self.parameter_pynames - - -def get_parameter(self, index): - if index < len(self.parameter_pyobjects.get()): - return self.parameter_pyobjects.get()[index] - - -def get_returned_object(self, args): - return self.returned.get(args) - - -def get_module(self): - return builtins - - - -def get_name(self): - return self.get_ast().name - - -def get_param_names(self, special_args=True): - # TODO: handle tuple parameters - result = [ - node.arg for node in self.arguments.args if isinstance(node, ast.arg) - ] - if special_args: - if self.arguments.vararg: - result.append(self.arguments.vararg.arg) - if self.arguments.kwarg: - result.append(self.arguments.kwarg.arg) - return result - - -def get_kind(self): - """Get function type - - It returns one of 'function', 'method', 'staticmethod' or - 'classmethod' strs. - - """ - scope = self.parent.get_scope() - if isinstance(self.parent, PyClass): - for decorator in self.decorators: - pyname = rope.base.evaluate.eval_node(scope, decorator) - if pyname == rope.base.builtins.builtins["staticmethod"]: - return "staticmethod" - if pyname == rope.base.builtins.builtins["classmethod"]: - return "classmethod" - return "method" - return "function" - - -@property -def decorators(self): - try: - return getattr(self.ast_node, "decorator_list") - except AttributeError: - return getattr(self.ast_node, "decorators", None) - - - -class PyComprehension(pyobjects.PyComprehension): - @others - -def __init__(self, pycore, ast_node, parent): - self.visitor_class = _ComprehensionVisitor - rope.base.pyobjects.PyObject.__init__(self, type_="Comp") - rope.base.pyobjects.PyDefinedObject.__init__(self, pycore, ast_node, parent) - - -def _create_scope(self): - return rope.base.pyscopes.ComprehensionScope( - self.pycore, self, _ComprehensionVisitor - ) - - -def get_kind(self): - return "Comprehension" - - - -class PyClass(pyobjects.PyClass): - @others - -def __init__(self, pycore, ast_node, parent): - self.visitor_class = _ClassVisitor - rope.base.pyobjects.AbstractClass.__init__(self) - rope.base.pyobjects.PyDefinedObject.__init__(self, pycore, ast_node, parent) - self.parent = parent - self._superclasses = self.get_module()._get_concluded_data() - - -class BuiltinFunction(_BuiltinElement, pyobjects.AbstractFunction): - @others - -def get_superclasses(self): - if self._superclasses.get() is None: - self._superclasses.set(self._get_bases()) - return self._superclasses.get() - - -def get_name(self): - return self.get_ast().name - - -def _create_concluded_attributes(self): - result = {} - for base in reversed(self.get_superclasses()): - result.update(base.get_attributes()) - return result - - -def _get_bases(self): - result = [] - for base_name in self.ast_node.bases: - base = rope.base.evaluate.eval_node(self.parent.get_scope(), base_name) - if ( - base is not None - and base.get_object().get_type() - == rope.base.pyobjects.get_base_type("Type") - ): - result.append(base.get_object()) - return result - - -def _create_scope(self): - return rope.base.pyscopes.ClassScope(self.pycore, self) - - - -class PyModule(pyobjects.PyModule): - @others - -def __init__(self, pycore, source=None, resource=None, force_errors=False): - ignore = pycore.project.prefs.get("ignore_syntax_errors", False) - syntax_errors = force_errors or not ignore - self.has_errors = False - try: - source, node = self._init_source(pycore, source, resource) - except exceptions.ModuleSyntaxError: - self.has_errors = True - if syntax_errors: - raise - else: - source = "\n" - node = ast.parse("\n") - self.source_code = source - self.star_imports = [] - self.visitor_class = _GlobalVisitor - self.coding = fscommands.read_str_coding(self.source_code) - super().__init__(pycore, node, resource) - - -def _init_source(self, pycore, source_code, resource): - filename = "string" - if resource: - filename = resource.path - try: - if source_code is None: - source_bytes = resource.read_bytes() - source_code, _ = fscommands.file_data_to_unicode(source_bytes) - else: - if isinstance(source_code, str): - source_bytes = fscommands.unicode_to_file_data(source_code) - else: - source_bytes = source_code - ast_node = ast.parse(source_bytes, filename=filename) - except SyntaxError as e: - raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg) - except UnicodeDecodeError as e: - raise exceptions.ModuleSyntaxError(filename, 1, "%s" % (e.reason)) - return source_code, ast_node - - -@utils.prevent_recursion(lambda: {}) -def _create_concluded_attributes(self): - result = {} - for star_import in self.star_imports: - result.update(star_import.get_names()) - return result - - -def _create_scope(self): - return rope.base.pyscopes.GlobalScope(self.pycore, self) - - -def __init__( - self, returned=None, function=None, builtin=None, argnames=[], parent=None -): - _BuiltinElement.__init__(self, builtin, parent) - pyobjects.AbstractFunction.__init__(self) - self.argnames = argnames - self.returned = returned - self.function = function - - -@property -@utils.saveit -def lines(self): - """A `SourceLinesAdapter`""" - return rope.base.codeanalyze.SourceLinesAdapter(self.source_code) - - -@property -@utils.saveit -def logical_lines(self): - """A `LogicalLinesFinder`""" - return rope.base.codeanalyze.CachingLogicalLineFinder(self.lines) - - -def get_name(self): - return rope.base.libutils.modname(self.resource) if self.resource else "" - - - -class PyPackage(pyobjects.PyPackage): - @others - -def __init__(self, pycore, resource=None, force_errors=False): - self.resource = resource - init_dot_py = self._get_init_dot_py() - if init_dot_py is not None: - ast_node = pycore.project.get_pymodule( - init_dot_py, force_errors=force_errors - ).get_ast() - else: - ast_node = ast.parse("\n") - super().__init__(pycore, ast_node, resource) - - -def _create_structural_attributes(self): - result = {} - modname = rope.base.libutils.modname(self.resource) - extension_submodules = self.pycore._builtin_submodules(modname) - for name, module in extension_submodules.items(): - result[name] = rope.base.builtins.BuiltinName(module) - if self.resource is None: - return result - for name, resource in self._get_child_resources().items(): - result[name] = pynames.ImportedModule(self, resource=resource) - return result - - -def _create_concluded_attributes(self): - result = {} - init_dot_py = self._get_init_dot_py() - if init_dot_py: - init_object = self.pycore.project.get_pymodule(init_dot_py) - result.update(init_object.get_attributes()) - return result - - -def _get_child_resources(self): - result = {} - for child in self.resource.get_children(): - if child.is_folder(): - result[child.name] = child - elif child.name.endswith(".py") and child.name != "__init__.py": - name = child.name[:-3] - result[name] = child - return result - - -def _get_init_dot_py(self): - if self.resource is not None and self.resource.has_child("__init__.py"): - return self.resource.get_child("__init__.py") - else: - return None - - -def _create_scope(self): - return self.get_module().get_scope() - - -def get_returned_object(self, args): - if self.function is not None: - return self.function(_CallContext(self.argnames, args)) - else: - return self.returned - - -def get_module(self): - init_dot_py = self._get_init_dot_py() - if init_dot_py: - return self.pycore.project.get_pymodule(init_dot_py) - return self - - -def get_name(self): - return rope.base.libutils.modname(self.resource) if self.resource else "" - - - -class _AnnAssignVisitor: - @others - -def __init__(self, scope_visitor): - self.scope_visitor = scope_visitor - self.assigned_ast = None - self.type_hint = None - - -def _AnnAssign(self, node): - self.assigned_ast = node.value - self.type_hint = node.annotation - - ast.walk(node.target, self) - - -def _assigned(self, name, assignment=None): - self.scope_visitor._assigned(name, assignment) - - -def _Name(self, node): - assignment = pynames.AssignmentValue( - self.assigned_ast, assign_type=True, type_hint=self.type_hint - ) - self._assigned(node.id, assignment) - - -def _Tuple(self, node): - names = astutils.get_name_levels(node) - for name, levels in names: - assignment = None - if self.assigned_ast is not None: - assignment = pynames.AssignmentValue(self.assigned_ast, levels) - self._assigned(name, assignment) - - -def _Annotation(self, node): - pass - - -def _Attribute(self, node): - pass - - -def get_param_names(self, special_args=True): - return self.argnames - - - -def _Subscript(self, node): - pass - - -def _Slice(self, node): - pass - - - -class _ExpressionVisitor: - @others - -def __init__(self, scope_visitor): - self.scope_visitor = scope_visitor - - -def _assigned(self, name, assignment=None): - self.scope_visitor._assigned(name, assignment) - - -def _GeneratorExp(self, node): - list_comp = PyComprehension( - self.scope_visitor.pycore, node, self.scope_visitor.owner_object - ) - self.scope_visitor.defineds.append(list_comp) - - -def _SetComp(self, node): - self._GeneratorExp(node) - - -def _ListComp(self, node): - self._GeneratorExp(node) - - -def _DictComp(self, node): - self._GeneratorExp(node) - - -def _NamedExpr(self, node): - ast.walk(node.target, _AssignVisitor(self)) - ast.walk(node.value, self) - - - -class BuiltinUnknown(_BuiltinElement, pyobjects.PyObject): - @others - -class _AssignVisitor: - @others - -def __init__(self, scope_visitor): - self.scope_visitor = scope_visitor - self.assigned_ast = None - - -def _Assign(self, node): - self.assigned_ast = node.value - for child_node in node.targets: - ast.walk(child_node, self) - ast.walk(node.value, _ExpressionVisitor(self.scope_visitor)) - - -def _assigned(self, name, assignment=None): - self.scope_visitor._assigned(name, assignment) - - -def _Name(self, node): - assignment = None - if self.assigned_ast is not None: - assignment = pynames.AssignmentValue(self.assigned_ast) - self._assigned(node.id, assignment) - - -def _Tuple(self, node): - names = astutils.get_name_levels(node) - for name, levels in names: - assignment = None - if self.assigned_ast is not None: - assignment = pynames.AssignmentValue(self.assigned_ast, levels) - self._assigned(name, assignment) - - -def _Attribute(self, node): - pass - - -def _Subscript(self, node): - pass - - -def _Slice(self, node): - pass - - - -class _ScopeVisitor(_ExpressionVisitor): - @others - -def __init__(self, builtin): - super().__init__(pyobjects.get_unknown()) - self.builtin = builtin - self.type = pyobjects.get_unknown() - - -def __init__(self, pycore, owner_object): - _ExpressionVisitor.__init__(self, scope_visitor=self) - self.pycore = pycore - self.owner_object = owner_object - self.names = {} - self.defineds = [] - - -def get_module(self): - if self.owner_object is not None: - return self.owner_object.get_module() - else: - return None - - -def _ClassDef(self, node): - pyclass = PyClass(self.pycore, node, self.owner_object) - self.names[node.name] = pynames.DefinedName(pyclass) - self.defineds.append(pyclass) - - -def _FunctionDef(self, node): - pyfunction = PyFunction(self.pycore, node, self.owner_object) - for decorator in pyfunction.decorators: - if isinstance(decorator, ast.Name) and decorator.id == "property": - if isinstance(self, _ClassVisitor): - type_ = rope.base.builtins.Property(pyfunction) - arg = pynames.UnboundName( - rope.base.pyobjects.PyObject(self.owner_object) - ) - - def _eval(type_=type_, arg=arg): - return type_.get_property_object( - arguments.ObjectArguments([arg]) - ) - - lineno = utils.guess_def_lineno(self.get_module(), node) - - self.names[node.name] = pynames.EvaluatedName( - _eval, module=self.get_module(), lineno=lineno - ) - break - else: - self.names[node.name] = pynames.DefinedName(pyfunction) - self.defineds.append(pyfunction) - - -def _AsyncFunctionDef(self, node): - return self._FunctionDef(node) - - -def _Assign(self, node): - ast.walk(node, _AssignVisitor(self)) - - -def _AnnAssign(self, node): - ast.walk(node, _AnnAssignVisitor(self)) - - -def _AugAssign(self, node): - pass - - -def _For(self, node): - self._update_evaluated( - node.target, node.iter, ".__iter__().next()" # noqa - ) - for child in node.body + node.orelse: - ast.walk(child, self) - - -def _AsyncFor(self, node): - return self._For(node) - - -def get_name(self): - return getattr(type(self.builtin), "__name__", None) - - -def _assigned(self, name, assignment): - pyname = self.names.get(name, None) - if pyname is None: - pyname = pynames.AssignedName(module=self.get_module()) - if isinstance(pyname, pynames.AssignedName): - if assignment is not None: - pyname.assignments.append(assignment) - self.names[name] = pyname - - -def _update_evaluated( - self, targets, assigned, evaluation="", eval_type=False, type_hint=None -): - result = {} - if isinstance(targets, str): - assignment = pynames.AssignmentValue(assigned, [], evaluation, eval_type) - self._assigned(targets, assignment) - else: - names = astutils.get_name_levels(targets) - for name, levels in names: - assignment = pynames.AssignmentValue( - assigned, levels, evaluation, eval_type - ) - self._assigned(name, assignment) - return result - - -def _With(self, node): - for item in node.items: - if item.optional_vars: - self._update_evaluated( - item.optional_vars, item.context_expr, ".__enter__()" - ) - for child in node.body: - ast.walk(child, self) - - -def _AsyncWith(self, node): - return self._With(node) - - -def _excepthandler(self, node): - node_name_type = str - if node.name is not None and isinstance(node.name, node_name_type): - type_node = node.type - if isinstance(node.type, ast.Tuple) and type_node.elts: - type_node = type_node.elts[0] - self._update_evaluated(node.name, type_node, eval_type=True) - - for child in node.body: - ast.walk(child, self) - - -def _ExceptHandler(self, node): - self._excepthandler(node) - - -def _Import(self, node): - for import_pair in node.names: - module_name = import_pair.name - alias = import_pair.asname - first_package = module_name.split(".")[0] - if alias is not None: - imported = pynames.ImportedModule(self.get_module(), module_name) - if not self._is_ignored_import(imported): - self.names[alias] = imported - else: - imported = pynames.ImportedModule(self.get_module(), first_package) - if not self._is_ignored_import(imported): - self.names[first_package] = imported - - -def _ImportFrom(self, node): - level = 0 - if node.level: - level = node.level - imported_module = pynames.ImportedModule(self.get_module(), node.module, level) - if self._is_ignored_import(imported_module): - return - if len(node.names) == 1 and node.names[0].name == "*": - if isinstance(self.owner_object, PyModule): - self.owner_object.star_imports.append(StarImport(imported_module)) - else: - for imported_name in node.names: - imported = imported_name.name - alias = imported_name.asname - if alias is not None: - imported = alias - self.names[imported] = pynames.ImportedName( - imported_module, imported_name.name - ) - - -def _is_ignored_import(self, imported_module): - if not self.pycore.project.prefs.get("ignore_bad_imports", False): - return False - return not isinstance( - imported_module.get_object(), rope.base.pyobjects.AbstractModule - ) - - -def _Global(self, node): - module = self.get_module() - for name in node.names: - if module is not None: - try: - pyname = module[name] - except exceptions.AttributeNotFoundError: - pyname = pynames.AssignedName(node.lineno) - self.names[name] = pyname - - - -def insert_date(version_changelog, curdate, after): - # Add a date section, if it doesn't already exist in the changelog section - if "Date:" not in version_changelog: - version_changelog = version_changelog.replace( - after, f"{after}\n\nDate: {curdate}", 1 - ) - return version_changelog - - - -@utils.saveit -def get_attributes(self): - return _object_attributes(self.builtin, self) - - - -class _ComprehensionVisitor(_ScopeVisitor): - @others - -def _comprehension(self, node): - ast.walk(node.target, self) - ast.walk(node.iter, self) - - -def _Name(self, node): - if isinstance(node.ctx, ast.Store): - self.names[node.id] = self._get_pyobject(node) - - -def _get_pyobject(self, node): - return pynames.AssignedName(lineno=node.lineno, module=self.get_module()) - - - -class _GlobalVisitor(_ScopeVisitor): - def __init__(self, pycore, owner_object): - super().__init__(pycore, owner_object) - - - -class _ClassVisitor(_ScopeVisitor): - @others - -def __init__(self, pycore, owner_object): - super().__init__(pycore, owner_object) - - -def _FunctionDef(self, node): - _ScopeVisitor._FunctionDef(self, node) - if len(node.args.args) > 0: - first = node.args.args[0] - new_visitor = None - if isinstance(first, ast.arg): - new_visitor = _ClassInitVisitor(self, first.arg) - if new_visitor is not None: - for child in ast.get_child_nodes(node): - ast.walk(child, new_visitor) - - - -class _FunctionVisitor(_ScopeVisitor): - @others - -def __init__(self, pycore, owner_object): - super().__init__(pycore, owner_object) - self.returned_asts = [] - self.generator = False - - -def _object_attributes(obj, parent): - attributes = {} - for name in dir(obj): - if name == "None": - continue - try: - child = getattr(obj, name) - except AttributeError: - # descriptors are allowed to raise AttributeError - # even if they are in dir() - continue - pyobject = None - if inspect.isclass(child): - pyobject = BuiltinClass(child, {}, parent=parent) - elif inspect.isroutine(child): - pyobject = BuiltinFunction(builtin=child, parent=parent) - else: - pyobject = BuiltinUnknown(builtin=child) - attributes[name] = BuiltinName(pyobject) - return attributes - - - -def _Return(self, node): - if node.value is not None: - self.returned_asts.append(node.value) - - -def _Yield(self, node): - if node.value is not None: - self.returned_asts.append(node.value) - self.generator = True - - - -class _ClassInitVisitor(_AssignVisitor): - @others - -def __init__(self, scope_visitor, self_name): - super().__init__(scope_visitor) - self.self_name = self_name - - -def _Attribute(self, node): - if not isinstance(node.ctx, ast.Store): - return - if isinstance(node.value, ast.Name) and node.value.id == self.self_name: - if node.attr not in self.scope_visitor.names: - self.scope_visitor.names[node.attr] = pynames.AssignedName( - lineno=node.lineno, module=self.scope_visitor.get_module() - ) - if self.assigned_ast is not None: - pyname = self.scope_visitor.names[node.attr] - if isinstance(pyname, pynames.AssignedName): - pyname.assignments.append( - pynames.AssignmentValue(self.assigned_ast) - ) - - -def _Tuple(self, node): - if not isinstance(node.ctx, ast.Store): - return - for child in ast.get_child_nodes(node): - ast.walk(child, self) - - -def _Name(self, node): - pass - - -def _FunctionDef(self, node): - pass - - -def _ClassDef(self, node): - pass - - -def _For(self, node): - pass - - -def _create_builtin_type_getter(cls): - @others - return _get_builtin - - - -def _With(self, node): - pass - - - -class StarImport: - @others - -def __init__(self, imported_module): - self.imported_module = imported_module - - -def get_names(self): - result = {} - imported = self.imported_module.get_object() - for name in imported: - if not name.startswith("_"): - result[name] = pynames.ImportedName(self.imported_module, name) - return result - -@path C:/Repos/ekr-rope/rope/base/ -import rope.base.builtins -import rope.base.codeanalyze -import rope.base.pynames -from rope.base import ast, exceptions, utils -from rope.refactor import patchedast - - -@others -@language python -@tabwidth -4 - -class Scope: - @others - -def __init__(self, pycore, pyobject, parent_scope): - self.pycore = pycore - self.pyobject = pyobject - self.parent = parent_scope - - -def get_names(self): - """Return the names defined or imported in this scope""" - return self.pyobject.get_attributes() - - -def get_defined_names(self): - """Return the names defined in this scope""" - return self.pyobject._get_structural_attributes() - - -def get_name(self, name): - """Return name `PyName` defined in this scope""" - if name not in self.get_names(): - raise exceptions.NameNotFoundError("name %s not found" % name) - return self.get_names()[name] - - -def _get_builtin(*args): - if not hasattr(cls, "_generated"): - cls._generated = {} - if args not in cls._generated: - cls._generated[args] = cls(*args) - return cls._generated[args] - - -def __getitem__(self, key): - """The same as ``get_name(key)``""" - return self.get_name(key) - - -def __contains__(self, key): - """The same as ``key in self.get_names()``""" - return key in self.get_names() - - -@utils.saveit -def get_scopes(self): - """Return the subscopes of this scope - - The returned scopes should be sorted by the order they appear. - """ - return self._create_scopes() - - -def lookup(self, name): - if name in self.get_names(): - return self.get_names()[name] - if self.parent is not None: - return self.parent._propagated_lookup(name) - return None - - -def get_propagated_names(self): - """Return the visible names of this scope - - Return the names defined in this scope that are visible from - scopes containing this scope. This method returns the same - dictionary returned by `get_names()` except for `ClassScope` - which returns an empty dict. - """ - return self.get_names() - - -def _propagated_lookup(self, name): - if name in self.get_propagated_names(): - return self.get_propagated_names()[name] - if self.parent is not None: - return self.parent._propagated_lookup(name) - return None - - -def _create_scopes(self): - return [ - pydefined.get_scope() for pydefined in self.pyobject._get_defined_objects() - ] - - -def _get_global_scope(self): - current = self - while current.parent is not None: - current = current.parent - return current - - -def get_start(self): - return self.pyobject.get_ast().lineno - - -def get_body_start(self): - body = self.pyobject.get_ast().body - if body: - return body[0].lineno - return self.get_start() - - -def _create_builtin_getter(cls): - type_getter = _create_builtin_type_getter(cls) - - def _get_builtin(*args): - return pyobjects.PyObject(type_getter(*args)) - - return _get_builtin - - - -def get_end(self): - pymodule = self._get_global_scope().pyobject - return pymodule.logical_lines.logical_line_in(self.logical_end)[1] - - -@utils.saveit -def get_logical_end(self): - global_scope = self._get_global_scope() - return global_scope._scope_finder.find_scope_end(self) - - -start = property(get_start) -end = property(get_end) -logical_end = property(get_logical_end) - - -def get_kind(self): - pass - - -def get_region(self): - self._calculate_scope_regions_for_module() - node = self.pyobject.get_ast() - region = patchedast.node_region(node) - return region - - -def _calculate_scope_regions_for_module(self): - self._get_global_scope()._calculate_scope_regions() - - -def in_region(self, offset): - """Checks if offset is in scope region""" - - region = self.get_region() - return region[0] < offset < region[1] - - - -class GlobalScope(Scope): - @others - -def __init__(self, pycore, module): - super().__init__(pycore, module, None) - self.names = module._get_concluded_data() - - -def get_start(self): - return 1 - - -class _CallContext: - @others - -def get_kind(self): - return "Module" - - -def get_name(self, name): - try: - return self.pyobject[name] - except exceptions.AttributeNotFoundError: - if name in self.builtin_names: - return self.builtin_names[name] - raise exceptions.NameNotFoundError("name %s not found" % name) - - -@utils.saveit -def _calculate_scope_regions(self): - source = self._get_source() - patchedast.patch_ast(self.pyobject.get_ast(), source) - - -def _get_source(self): - return self.pyobject.source_code - - -def get_names(self): - if self.names.get() is None: - result = dict(self.builtin_names) - result.update(super().get_names()) - self.names.set(result) - return self.names.get() - - -def get_inner_scope_for_line(self, lineno, indents=None): - return self._scope_finder.get_holding_scope(self, lineno, indents) - - -def get_inner_scope_for_offset(self, offset): - return self._scope_finder.get_holding_scope_for_offset(self, offset) - - -@property -@utils.saveit -def _scope_finder(self): - return _HoldingScopeFinder(self.pyobject) - - -@property -def builtin_names(self): - return rope.base.builtins.builtins.get_attributes() - - - -class ComprehensionScope(Scope): - @others - -def __init__(self, argnames, args): - self.argnames = argnames - self.args = args - - -def __init__(self, pycore, pyobject, visitor): - super().__init__(pycore, pyobject, pyobject.parent.get_scope()) - self.names = None - self.returned_asts = None - self.defineds = None - self.visitor = visitor - - -def _get_names(self): - if self.names is None: - self._visit_comprehension() - return self.names - - -def get_names(self): - return self._get_names() - - -def _visit_comprehension(self): - if self.names is None: - new_visitor = self.visitor(self.pycore, self.pyobject) - for node in ast.get_child_nodes(self.pyobject.get_ast()): - ast.walk(node, new_visitor) - self.names = dict(self.parent.get_names()) - self.names.update(new_visitor.names) - self.defineds = new_visitor.defineds - - -def get_logical_end(self): - return self.get_start() - - -logical_end = property(get_logical_end) - - -def get_body_start(self): - return self.get_start() - - - -class FunctionScope(Scope): - @others - -def __init__(self, pycore, pyobject, visitor): - super().__init__(pycore, pyobject, pyobject.parent.get_scope()) - self.names = None - self.returned_asts = None - self.is_generator = None - self.defineds = None - self.visitor = visitor - - -def _get_names(self): - if self.names is None: - self._visit_function() - return self.names - - -def _get_scope_and_pyname(self, pyname): - if pyname is not None and isinstance(pyname, pynames.AssignedName): - pymodule, lineno = pyname.get_definition_location() - if pymodule is None: - return None, None - if lineno is None: - lineno = 1 - scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - name = None - while name is None and scope is not None: - for current in scope.get_names(): - if scope[current] is pyname: - name = current - break - else: - scope = scope.parent - return scope, name - return None, None - - -def _visit_function(self): - if self.names is None: - new_visitor = self.visitor(self.pycore, self.pyobject) - for n in ast.get_child_nodes(self.pyobject.get_ast()): - ast.walk(n, new_visitor) - self.names = new_visitor.names - self.names.update(self.pyobject.get_parameters()) - self.returned_asts = new_visitor.returned_asts - self.is_generator = new_visitor.generator - self.defineds = new_visitor.defineds - - -def _get_returned_asts(self): - if self.names is None: - self._visit_function() - return self.returned_asts - - -def _is_generator(self): - if self.is_generator is None: - self._get_returned_asts() - return self.is_generator - - -def get_names(self): - return self._get_names() - - -def _create_scopes(self): - if self.defineds is None: - self._visit_function() - return [pydefined.get_scope() for pydefined in self.defineds] - - -def get_kind(self): - return "Function" - - -def invalidate_data(self): - for pyname in self.get_names().values(): - if isinstance( - pyname, - (rope.base.pynames.AssignedName, rope.base.pynames.EvaluatedName), - ): - pyname.invalidate() - - - -class ClassScope(Scope): - @others - -def __init__(self, pycore, pyobject): - super().__init__(pycore, pyobject, pyobject.parent.get_scope()) - - -def get_kind(self): - return "Class" - - -def get_argument(self, name): - if self.args: - args = self.args.get_arguments(self.argnames) - return args[self.argnames.index(name)] - - -def get_propagated_names(self): - return {} - - - -class _HoldingScopeFinder: - @others - -def __init__(self, pymodule): - self.pymodule = pymodule - - -def get_indents(self, lineno): - return rope.base.codeanalyze.count_line_indents(self.lines.get_line(lineno)) - - -def _get_scope_indents(self, scope): - return self.get_indents(scope.get_start()) - - -def get_holding_scope(self, module_scope, lineno, line_indents=None): - if line_indents is None: - line_indents = self.get_indents(lineno) - current_scope = module_scope - new_scope = current_scope - while new_scope is not None and ( - new_scope.get_kind() == "Module" - or self._get_scope_indents(new_scope) <= line_indents - ): - current_scope = new_scope - if ( - current_scope.get_start() == lineno - and current_scope.get_kind() != "Module" - ): - return current_scope - new_scope = None - for scope in current_scope.get_scopes(): - if scope.get_start() <= lineno: - if lineno <= scope.get_end(): - new_scope = scope - break - else: - break - return current_scope - - -def _is_empty_line(self, lineno): - line = self.lines.get_line(lineno) - return line.strip() == "" or line.lstrip().startswith("#") - - -def _get_body_indents(self, scope): - return self.get_indents(scope.get_body_start()) - - -@staticmethod -def get_holding_scope_for_offset(scope, offset): - for inner_scope in scope.get_scopes(): - if inner_scope.in_region(offset): - return _HoldingScopeFinder.get_holding_scope_for_offset( - inner_scope, offset - ) - return scope - - -def find_scope_end(self, scope): - if not scope.parent: - return self.lines.length() - end = scope.pyobject.get_ast().body[-1].lineno - scope_start = self.pymodule.logical_lines.logical_line_in(scope.start) - if scope_start[1] >= end: - # handling one-liners - body_indents = self._get_scope_indents(scope) + 4 - else: - body_indents = self._get_body_indents(scope) - for l in self.logical_lines.generate_starts( - min(end + 1, self.lines.length()), self.lines.length() + 1 - ): - if not self._is_empty_line(l): - if self.get_indents(l) < body_indents: - return end - else: - end = l - return end - - -def get_pyname(self, name): - if self.args: - args = self.args.get_pynames(self.argnames) - if name in self.argnames: - return args[self.argnames.index(name)] - - -@property -def lines(self): - return self.pymodule.lines - - -@property -def code(self): - return self.pymodule.source_code - - -@property -def logical_lines(self): - return self.pymodule.logical_lines - - - -class TemporaryScope(Scope): - """Currently used for list comprehensions and generator expressions - - These scopes do not appear in the `get_scopes()` method of their - parent scopes. - """ - - @others - -def __init__(self, pycore, parent_scope, names): - super().__init__(pycore, parent_scope.pyobject, parent_scope) - self.names = names - - -def get_names(self): - return self.names - - -def get_defined_names(self): - return self.names - - -def _create_scopes(self): - return [] - - -def get_kind(self): - return "Temporary" - -@path C:/Repos/ekr-rope/rope/base/ -import os - - -@others -@language python -@tabwidth -4 - - -def get_arguments(self, argnames): - if self.args: - return self.args.get_arguments(argnames) - - -class ResourceObserver: - """Provides the interface for observing resources - - `ResourceObserver` can be registered using `Project. - add_observer()`. But most of the time `FilteredResourceObserver` - should be used. `ResourceObserver` report all changes passed - to them and they don't report changes to all resources. For - example if a folder is removed, it only calls `removed()` for that - folder and not its contents. You can use - `FilteredResourceObserver` if you are interested in changes only - to a list of resources. And you want changes to be reported on - individual resources. - - """ - - @others - -def __init__( - self, changed=None, moved=None, created=None, removed=None, validate=None -): - self.changed = changed - self.moved = moved - self.created = created - self.removed = removed - self._validate = validate - - -def resource_changed(self, resource): - """It is called when the resource changes""" - if self.changed is not None: - self.changed(resource) - - -def resource_moved(self, resource, new_resource): - """It is called when a resource is moved""" - if self.moved is not None: - self.moved(resource, new_resource) - - -def resource_created(self, resource): - """Is called when a new resource is created""" - if self.created is not None: - self.created(resource) - - -def resource_removed(self, resource): - """Is called when a new resource is removed""" - if self.removed is not None: - self.removed(resource) - - -def validate(self, resource): - """Validate the existence of this resource and its children. - - This function is called when rope need to update its resource - cache about the files that might have been changed or removed - by other processes. - - """ - if self._validate is not None: - self._validate(resource) - - - -class FilteredResourceObserver: - """A useful decorator for `ResourceObserver` - - Most resource observers have a list of resources and are - interested only in changes to those files. This class satisfies - this need. It dispatches resource changed and removed messages. - It performs these tasks: - - * Changes to files and folders are analyzed to check whether any - of the interesting resources are changed or not. If they are, - it reports these changes to `resource_observer` passed to the - constructor. - * When a resource is removed it checks whether any of the - interesting resources are contained in that folder and reports - them to `resource_observer`. - * When validating a folder it validates all of the interesting - files in that folder. - - Since most resource observers are interested in a list of - resources that change over time, `add_resource` and - `remove_resource` might be useful. - - """ - - @others - -def __init__(self, resource_observer, initial_resources=None, timekeeper=None): - self.observer = resource_observer - self.resources = {} - if timekeeper is not None: - self.timekeeper = timekeeper - else: - self.timekeeper = ChangeIndicator() - if initial_resources is not None: - for resource in initial_resources: - self.add_resource(resource) - - -def add_resource(self, resource): - """Add a resource to the list of interesting resources""" - if resource.exists(): - self.resources[resource] = self.timekeeper.get_indicator(resource) - else: - self.resources[resource] = None - - -def get_pynames(self, argnames): - if self.args: - return self.args.get_pynames(argnames) - - -def remove_resource(self, resource): - """Add a resource to the list of interesting resources""" - if resource in self.resources: - del self.resources[resource] - - -def clear_resources(self): - """Removes all registered resources""" - self.resources.clear() - - -def resource_changed(self, resource): - changes = _Changes() - self._update_changes_caused_by_changed(changes, resource) - self._perform_changes(changes) - - -def _update_changes_caused_by_changed(self, changes, changed): - if changed in self.resources: - changes.add_changed(changed) - if self._is_parent_changed(changed): - changes.add_changed(changed.parent) - - -def _update_changes_caused_by_moved(self, changes, resource, new_resource=None): - if resource in self.resources: - changes.add_removed(resource, new_resource) - if new_resource in self.resources: - changes.add_created(new_resource) - if resource.is_folder(): - for file in list(self.resources): - if resource.contains(file): - new_file = self._calculate_new_resource( - resource, new_resource, file - ) - changes.add_removed(file, new_file) - if self._is_parent_changed(resource): - changes.add_changed(resource.parent) - if new_resource is not None: - if self._is_parent_changed(new_resource): - changes.add_changed(new_resource.parent) - - -def _is_parent_changed(self, child): - return child.parent in self.resources - - -def resource_moved(self, resource, new_resource): - changes = _Changes() - self._update_changes_caused_by_moved(changes, resource, new_resource) - self._perform_changes(changes) - - -def resource_created(self, resource): - changes = _Changes() - self._update_changes_caused_by_created(changes, resource) - self._perform_changes(changes) - - -def _update_changes_caused_by_created(self, changes, resource): - if resource in self.resources: - changes.add_created(resource) - if self._is_parent_changed(resource): - changes.add_changed(resource.parent) - - -def resource_removed(self, resource): - changes = _Changes() - self._update_changes_caused_by_moved(changes, resource) - self._perform_changes(changes) - - -def get_per_name(self): - if self.args is None: - return None - pyname = self.args.get_instance_pyname() - scope, name = self._get_scope_and_pyname(pyname) - if name is not None: - pymodule = pyname.get_definition_location()[0] - return pymodule.pycore.object_info.get_per_name(scope, name) - return None - - -def _perform_changes(self, changes): - for resource in changes.changes: - self.observer.resource_changed(resource) - self.resources[resource] = self.timekeeper.get_indicator(resource) - for resource, new_resource in changes.moves.items(): - self.resources[resource] = None - if new_resource is not None: - self.observer.resource_moved(resource, new_resource) - else: - self.observer.resource_removed(resource) - for resource in changes.creations: - self.observer.resource_created(resource) - self.resources[resource] = self.timekeeper.get_indicator(resource) - - -def validate(self, resource): - changes = _Changes() - for file in self._search_resource_moves(resource): - if file in self.resources: - self._update_changes_caused_by_moved(changes, file) - for file in self._search_resource_changes(resource): - if file in self.resources: - self._update_changes_caused_by_changed(changes, file) - for file in self._search_resource_creations(resource): - if file in self.resources: - changes.add_created(file) - self._perform_changes(changes) - - -def _search_resource_creations(self, resource): - creations = set() - if ( - resource in self.resources - and resource.exists() - and self.resources[resource] is None - ): - creations.add(resource) - if resource.is_folder(): - for file in self.resources: - if ( - file.exists() - and resource.contains(file) - and self.resources[file] is None - ): - creations.add(file) - return creations - - -def _search_resource_moves(self, resource): - all_moved = set() - if resource in self.resources and not resource.exists(): - all_moved.add(resource) - if resource.is_folder(): - for file in self.resources: - if resource.contains(file): - if not file.exists(): - all_moved.add(file) - moved = set(all_moved) - for folder in [file for file in all_moved if file.is_folder()]: - if folder in moved: - for file in list(moved): - if folder.contains(file): - moved.remove(file) - return moved - - -def _search_resource_changes(self, resource): - changed = set() - if resource in self.resources and self._is_changed(resource): - changed.add(resource) - if resource.is_folder(): - for file in self.resources: - if file.exists() and resource.contains(file): - if self._is_changed(file): - changed.add(file) - return changed - - -def _is_changed(self, resource): - if self.resources[resource] is None: - return False - return self.resources[resource] != self.timekeeper.get_indicator(resource) - - -def _calculate_new_resource(self, main, new_main, resource): - if new_main is None: - return None - diff = resource.path[len(main.path) :] - return resource.project.get_resource(new_main.path + diff) - - - -class ChangeIndicator: - @others - -def get_indicator(self, resource): - """Return the modification time and size of a `Resource`.""" - path = resource.real_path - # on dos, mtime does not change for a folder when files are added - if os.name != "posix" and os.path.isdir(path): - return ( - os.path.getmtime(path), - len(os.listdir(path)), - os.path.getsize(path), - ) - return (os.path.getmtime(path), os.path.getsize(path)) - - - -class _Changes: - @others - -def save_per_name(self, value): - if self.args is None: - return None - pyname = self.args.get_instance_pyname() - scope, name = self._get_scope_and_pyname(pyname) - if name is not None: - pymodule = pyname.get_definition_location()[0] - pymodule.pycore.object_info.save_per_name(scope, name, value) - - - -def __init__(self): - self.changes = set() - self.creations = set() - self.moves = {} - - -def add_changed(self, resource): - self.changes.add(resource) - - -def add_removed(self, resource, new_resource=None): - self.moves[resource] = new_resource - - -def add_created(self, resource): - self.creations.add(resource) - -@path C:/Repos/ekr-rope/rope/base/ -"""Files and folders in a project are represented as resource objects. - -Files and folders are access through `Resource` objects. `Resource` has -two subclasses: `File` and `Folder`. What we care about is that -refactorings and `rope.base.change.Change`s use resources. - -There are two options to create a `Resource` for a path in a project. -Note that in these examples `path` is the path to a file or folder -relative to the project's root. A project's root folder is represented -by an empty string. - - 1) Use the `rope.base.Project.get_resource()` method. E.g.: - - myresource = myproject.get_resource(path) - - - 2) Use the `rope.base.libutils` module. `libutils` has a function - named `path_to_resource()`. It takes a project and a path: - - from rope.base import libutils - - myresource = libutils.path_to_resource(myproject, path) - -Once we have a `Resource`, we can retrieve information from it, like -getting the path relative to the project's root (via `path`), reading -from and writing to the resource, moving the resource, etc. -""" - -import os -import re -import warnings - -from rope.base import change -from rope.base import exceptions -from rope.base import fscommands -from pathlib import Path - - -@others -@language python -@tabwidth -4 - -class Resource: - """Represents files and folders in a project""" - - @others - -def __init__(self, project, path): - self.project = project - self._path = path - - -def __repr__(self): - return '<{}.{} "{}" at {}>'.format( - self.__class__.__module__, - self.__class__.__name__, - self.path, - hex(id(self)), - ) - - -def move(self, new_location): - """Move resource to `new_location`""" - self._perform_change( - change.MoveResource(self, new_location), - "Moving <{}> to <{}>".format(self.path, new_location), - ) - - -def remove(self): - """Remove resource from the project""" - self._perform_change(change.RemoveResource(self), "Removing <%s>" % self.path) - - -class _AttributeCollector: - @others - -def is_folder(self): - """Return true if the resource is a folder""" - - -def create(self): - """Create this resource""" - - -def exists(self): - return os.path.exists(self.real_path) - - -@property -def parent(self): - parent = "/".join(self.path.split("/")[0:-1]) - return self.project.get_folder(parent) - - -@property -def path(self): - """Return the path of this resource relative to the project root - - The path is the list of parent directories separated by '/' followed - by the resource name. - """ - return self._path - - -@property -def name(self): - """Return the name of this resource""" - return self.path.split("/")[-1] - - -@property -def real_path(self): - """Return the file system path of this resource""" - return self.project._get_resource_path(self.path) - - -@property -def pathlib(self): - """Return the file as a pathlib path.""" - return Path(self.real_path) - - -def __eq__(self, obj): - return self.__class__ == obj.__class__ and self.path == obj.path - - -def __ne__(self, obj): - return not self.__eq__(obj) - - -def __init__(self, type): - self.attributes = {} - self.type = type - - -def __hash__(self): - return hash(self.path) - - -def _perform_change(self, change_, description): - changes = change.ChangeSet(description) - changes.add_change(change_) - self.project.do(changes) - - - -class File(Resource): - """Represents a file""" - - @others - -def __init__(self, project, name): - self.newlines = None - super().__init__(project, name) - - -def read(self): - data = self.read_bytes() - try: - content, self.newlines = fscommands.file_data_to_unicode(data) - return content - except UnicodeDecodeError as e: - raise exceptions.ModuleDecodeError(self.path, e.reason) - - -def read_bytes(self): - if not hasattr(self.project.fscommands, "read"): - warnings.warn( - "FileSystemCommands should implement read() method", - DeprecationWarning, - stacklevel=2, - ) - with open(self.real_path, "rb") as handle: - return handle.read() - return self.project.fscommands.read(self.real_path) - - -def write(self, contents): - try: - if contents == self.read(): - return - except OSError: - pass - self._perform_change( - change.ChangeContents(self, contents), "Writing file <%s>" % self.path - ) - - -def is_folder(self): - return False - - -def create(self): - self.parent.create_file(self.name) - - - -class Folder(Resource): - """Represents a folder""" - - @others - -def __call__( - self, - name, - returned=None, - function=None, - argnames=["self"], - check_existence=True, - parent=None, -): - try: - builtin = getattr(self.type, name) - except AttributeError: - if check_existence: - raise - builtin = None - self.attributes[name] = BuiltinName( - BuiltinFunction( - returned=returned, - function=function, - argnames=argnames, - builtin=builtin, - parent=parent, - ) - ) - - -def __init__(self, project, name): - super().__init__(project, name) - - -def is_folder(self): - return True - - -def get_children(self): - """Return the children of this folder""" - try: - children = os.listdir(self.real_path) - except OSError: - return [] - result = [] - for name in children: - try: - child = self.get_child(name) - except exceptions.ResourceNotFoundError: - continue - if not self.project.is_ignored(child): - result.append(self.get_child(name)) - return result - - -def create_file(self, file_name): - self._perform_change( - change.CreateFile(self, file_name), - "Creating file <%s>" % self._get_child_path(file_name), - ) - return self.get_child(file_name) - - -def create_folder(self, folder_name): - self._perform_change( - change.CreateFolder(self, folder_name), - "Creating folder <%s>" % self._get_child_path(folder_name), - ) - return self.get_child(folder_name) - - -def _get_child_path(self, name): - if self.path: - return self.path + "/" + name - else: - return name - - -def get_child(self, name): - return self.project.get_resource(self._get_child_path(name)) - - -def has_child(self, name): - try: - self.get_child(name) - return True - except exceptions.ResourceNotFoundError: - return False - - -def get_files(self): - return [ - resource for resource in self.get_children() if not resource.is_folder() - ] - - -def get_folders(self): - return [resource for resource in self.get_children() if resource.is_folder()] - - -def __setitem__(self, name, value): - self.attributes[name] = value - - - -def contains(self, resource): - if self == resource: - return False - return self.path == "" or resource.path.startswith(self.path + "/") - - -def create(self): - self.parent.create_folder(self.name) - - - -class _ResourceMatcher: - @others - -def __init__(self): - self.patterns = [] - self._compiled_patterns = [] - - -def set_patterns(self, patterns): - """Specify which resources to match - - `patterns` is a `list` of `str` that can contain ``*`` and - ``?`` signs for matching resource names. - - """ - self._compiled_patterns = None - self.patterns = patterns - - -def _add_pattern(self, pattern): - re_pattern = ( - pattern.replace(".", "\\.") - .replace("*", "[^/]*") - .replace("?", "[^/]") - .replace("//", "/(.*/)?") - ) - re_pattern = "^(.*/)?" + re_pattern + "(/.*)?$" - self.compiled_patterns.append(re.compile(re_pattern)) - - -def does_match(self, resource): - for pattern in self.compiled_patterns: - if pattern.match(resource.path): - return True - path = os.path.join(resource.project.address, *resource.path.split("/")) - return os.path.islink(path) - - -@property -def compiled_patterns(self): - if self._compiled_patterns is None: - self._compiled_patterns = [] - for pattern in self.patterns: - self._add_pattern(pattern) - return self._compiled_patterns - -@path C:/Repos/ekr-rope/rope/base/ -"""A module to ease code analysis - -This module is here to help source code analysis. -""" -import re - -from rope.base import codeanalyze, utils - - -@others -_str = re.compile( - "|".join( - [ - codeanalyze.get_comment_pattern(), - codeanalyze.get_any_string_pattern(), - ] - ) -) -_parens = re.compile(r"[\({\[\]}\)\n]") -@language python -@tabwidth -4 - -@utils.cached(7) -def real_code(source): - """Simplify `source` for analysis - - It replaces: - - * comments with spaces - * strs with a new str filled with spaces - * implicit and explicit continuations with spaces - * tabs and semicolons with spaces - - The resulting code is a lot easier to analyze if we are interested - only in offsets. - """ - collector = codeanalyze.ChangeCollector(source) - for start, end, matchgroups in ignored_regions(source): - if source[start] == "#": - replacement = " " * (end - start) - elif "f" in matchgroups.get("prefix", "").lower(): - replacement = None - else: - replacement = '"%s"' % (" " * (end - start - 2)) - if replacement is not None: - collector.add_change(start, end, replacement) - source = collector.get_changed() or source - collector = codeanalyze.ChangeCollector(source) - parens = 0 - for match in _parens.finditer(source): - i = match.start() - c = match.group() - if c in "({[": - parens += 1 - if c in ")}]": - parens -= 1 - if c == "\n" and parens > 0: - collector.add_change(i, i + 1, " ") - source = collector.get_changed() or source - return source.replace("\\\n", " ").replace("\t", " ").replace(";", "\n") - - - -class List(BuiltinClass): - @others - -@utils.cached(7) -def ignored_regions(source): - """Return ignored regions like strings and comments in `source`""" - return [ - (match.start(), match.end(), match.groupdict()) - for match in _str.finditer(source) - ] - - - -@path C:/Repos/ekr-rope/rope/base/ -import inspect -import os -import sys - -from rope.base import utils - - -@others -@language python -@tabwidth -4 - -def _stdlib_path(): - - return os.path.dirname(inspect.getsourcefile(inspect)) - - - -@utils.cached(1) -def standard_modules(): - return python_modules() | dynload_modules() - - - -@utils.cached(1) -def python_modules(): - result = set() - lib_path = _stdlib_path() - if os.path.exists(lib_path): - for name in os.listdir(lib_path): - path = os.path.join(lib_path, name) - if os.path.isdir(path): - if "-" not in name: - result.add(name) - else: - if name.endswith(".py"): - result.add(name[:-3]) - return result - - - -def normalize_so_name(name): - """ - Handle different types of python installations - """ - if "cpython" in name: - return os.path.splitext(os.path.splitext(name)[0])[0] - # XXX: Special handling for Fedora python2 distribution - # See: https://github.com/python-rope/rope/issues/211 - if name == "timemodule.so": - return "time" - return os.path.splitext(name)[0] - - - -@utils.cached(1) -def dynload_modules(): - result = set(sys.builtin_module_names) - dynload_path = os.path.join(_stdlib_path(), "lib-dynload") - if os.path.exists(dynload_path): - for name in os.listdir(dynload_path): - path = os.path.join(dynload_path, name) - if os.path.isfile(path): - if name.endswith(".dll"): - result.add(normalize_so_name(name)) - if name.endswith(".so"): - result.add(normalize_so_name(name)) - return result - -@path C:/Repos/ekr-rope/rope/base/ -from abc import ABC, abstractmethod -from typing import Optional, Sequence - -from rope.base import utils, exceptions - - -@others -@language python -@tabwidth -4 - -class BaseJobSet(ABC): - name: str = "" - job_name: str = "" - - @others - -@abstractmethod -def started_job(self, name: str) -> None: - pass - - -def __init__(self, holding=None): - self.holding = holding - collector = _AttributeCollector(list) - - collector("__iter__", function=self._iterator_get, parent=self) - collector("__new__", function=self._new_list, parent=self) - - # Adding methods - collector( - "append", function=self._list_add, argnames=["self", "value"], parent=self - ) - collector( - "__setitem__", - function=self._list_add, - argnames=["self", "index", "value"], - parent=self, - ) - collector( - "insert", - function=self._list_add, - argnames=["self", "index", "value"], - parent=self, - ) - collector( - "extend", - function=self._self_set, - argnames=["self", "iterable"], - parent=self, - ) - - # Getting methods - collector("__getitem__", function=self._list_get, parent=self) - collector("pop", function=self._list_get, parent=self) - try: - collector("__getslice__", function=self._list_get) - except AttributeError: - pass - - super().__init__(list, collector.attributes) - - -@abstractmethod -def finished_job(self) -> None: - pass - - -@abstractmethod -def check_status(self) -> None: - pass - - -@utils.deprecated("Just use JobSet.job_name attribute/property instead") -def get_active_job_name(self) -> str: - pass - - -@abstractmethod -def get_percent_done(self) -> Optional[float]: - pass - - -@utils.deprecated("Just use JobSet.name attribute/property instead") -def get_name(self) -> str: - pass - - -@abstractmethod -def increment(self) -> None: - """ - Increment the number of tasks to complete. - - This is used if the number is not known ahead of time. - """ - pass - - - -class BaseTaskHandle(ABC): - @others - -@abstractmethod -def stop(self) -> None: - pass - - -@abstractmethod -def current_jobset(self) -> Optional[BaseJobSet]: - pass - - -@abstractmethod -def add_observer(self) -> None: - pass - - -class FixSyntax: - @others - -def _last_non_blank(self, start): - while start > 0 and self.lines[start].strip() == "": - start -= 1 - return start - - -def get_type_object(imported_object) -> NameType: - """Determine the type of an object.""" - if inspect.isclass(imported_object): - return NameType.Class - if inspect.isfunction(imported_object) or inspect.isbuiltin(imported_object): - return NameType.Function - return NameType.Variable - - - -import_info = property(_get_import_info, _set_import_info) - - -def get_import_statement(self): - if self._is_changed or self.main_statement is None: - return self.import_info.get_import_statement() - else: - return self.main_statement - - -def empty_import(self): - self.import_info = ImportInfo.get_empty_import() - - -def move(self, lineno, blank_lines=0): - self.new_start = lineno - self.blank_lines = blank_lines - - -def get_old_location(self): - return self.start_line, self.end_line - - -def get_new_start(self): - return self.new_start - - -def is_changed(self): - return self._is_changed or ( - self.new_start is not None or self.new_start != self.start_line - ) - - -def accept(self, visitor): - return visitor.dispatch(self) - - - -class ImportInfo: - @others - -def get_imported_primaries(self, context): - pass - - -def get_names(module: ModuleInfo, package: Package) -> List[Name]: - """Get all names from a module and package.""" - if isinstance(module, ModuleCompiled): - return list( - get_names_from_compiled(package.name, package.source, module.underlined) - ) - if isinstance(module, ModuleFile): - return [ - combine(package, module, partial_name) - for partial_name in get_names_from_file( - module.filepath, - package.name, - underlined=module.underlined, - process_imports=module.process_imports, - ) - ] - return [] - - - -def get_imported_names(self, context): - return [ - primary.split(".")[0] for primary in self.get_imported_primaries(context) - ] - - -def get_import_statement(self): - pass - - -def is_empty(self): - pass - - -def __hash__(self): - return hash(self.get_import_statement()) - - -def _are_name_and_alias_lists_equal(self, list1, list2): - if len(list1) != len(list2): - return False - for pair1, pair2 in zip(list1, list2): - if pair1 != pair2: - return False - return True - - -def __eq__(self, obj): - return ( - isinstance(obj, self.__class__) - and self.get_import_statement() == obj.get_import_statement() - ) - - -def __ne__(self, obj): - return not self.__eq__(obj) - - -@staticmethod -def get_empty_import(): - return EmptyImport() - - - -class NormalImport(ImportInfo): - @others - -def __init__(self, names_and_aliases): - self.names_and_aliases = names_and_aliases - - -def get_names_from_compiled( - package: str, - source: Source, - underlined: bool = False, -) -> Generator[Name, None, None]: - """ - Get the names from a compiled module. - - Instead of using ast, it imports the module. - Parameters - ---------- - package : str - package to import. Must be in sys.path - underlined : bool - include underlined names - """ - # builtins is banned because you never have to import it - # python_crun is banned because it crashes python - banned = ["builtins", "python_crun"] - if package in banned or (package.startswith("_") and not underlined): - return # Builtins is redundant since you don't have to import it. - if source not in (Source.BUILTIN, Source.STANDARD): - return - try: - module = import_module(str(package)) - except ImportError: - logger.error(f"{package} could not be imported for autoimport analysis") - return - else: - for name, value in inspect.getmembers(module): - if underlined or not name.startswith("_"): - if ( - inspect.isclass(value) - or inspect.isfunction(value) - or inspect.isbuiltin(value) - ): - yield Name( - str(name), package, package, source, get_type_object(value) - ) - - - -def get_imported_primaries(self, context): - result = [] - for name, alias in self.names_and_aliases: - if alias: - result.append(alias) - else: - result.append(name) - return result - - -def get_import_statement(self): - result = "import " - for name, alias in self.names_and_aliases: - result += name - if alias: - result += " as " + alias - result += ", " - return result[:-2] - - -def is_empty(self): - return len(self.names_and_aliases) == 0 - - - -class FromImport(ImportInfo): - @others - -def __init__(self, module_name, level, names_and_aliases): - self.module_name = module_name - self.level = level - self.names_and_aliases = names_and_aliases - - -def get_imported_primaries(self, context): - if self.names_and_aliases[0][0] == "*": - module = self.get_imported_module(context) - return [name for name in module if not name.startswith("_")] - result = [] - for name, alias in self.names_and_aliases: - if alias: - result.append(alias) - else: - result.append(name) - return result - - -def get_imported_resource(self, context): - """Get the imported resource - - Returns `None` if module was not found. - """ - if self.level == 0: - return context.project.find_module(self.module_name, folder=context.folder) - else: - return context.project.find_relative_module( - self.module_name, context.folder, self.level - ) - - -def get_imported_module(self, context): - """Get the imported `PyModule` - - Raises `rope.base.exceptions.ModuleNotFoundError` if module - could not be found. - """ - if self.level == 0: - return context.project.get_module(self.module_name, context.folder) - else: - return context.project.get_relative_module( - self.module_name, context.folder, self.level - ) - - -def get_import_statement(self): - result = "from " + "." * self.level + self.module_name + " import " - for name, alias in self.names_and_aliases: - result += name - if alias: - result += " as " + alias - result += ", " - return result[:-2] - - -def is_empty(self): - return len(self.names_and_aliases) == 0 - - -def combine(package: Package, module: ModuleFile, name: PartialName) -> Name: - """Combine information to form a full name.""" - return Name(name.name, module.modname, package.name, package.source, name.name_type) - -def is_star_import(self): - return len(self.names_and_aliases) > 0 and self.names_and_aliases[0][0] == "*" - - - -class EmptyImport(ImportInfo): - - names_and_aliases = [] - - @others - -def is_empty(self): - return True - - -def get_imported_primaries(self, context): - return [] - - - -class ImportContext: - def __init__(self, project, folder): - self.project = project - self.folder = folder - -@path C:/Repos/ekr-rope/rope/refactor/importutils/ -from typing import Union, List - -from rope.base import ast, exceptions, pynames, pynamesdef, utils -from rope.refactor.importutils import actions, importinfo - - -@others -@language python -@tabwidth -4 - -class ModuleImports: - @others - -def __init__(self, project, pymodule, import_filter=None): - self.project = project - self.pymodule = pymodule - self.separating_lines = 0 - self.filter = import_filter - self.sorted = False - - -@property -@utils.saveit -def imports(self): - finder = _GlobalImportFinder(self.pymodule) - result = finder.find_import_statements() - self.separating_lines = finder.get_separating_line_count() - if self.filter is not None: - for import_stmt in result: - if not self.filter(import_stmt): - import_stmt.readonly = True - return result - - -def _get_unbound_names(self, defined_pyobject): - visitor = _GlobalUnboundNameFinder(self.pymodule, defined_pyobject) - ast.walk(self.pymodule.get_ast(), visitor) - return visitor.unbound - - -@path C:/Repos/ekr-rope/rope/contrib/autoimport/ -""" -IMPORTANT: This is a deprecated implementation of autoimport using pickle-based -storage. - -This pickle-based autoimport is provided only for backwards compatibility -purpose and will be removed and the sqlite backend will be the new default -implementation in the future. - -If you are still using this module, you should migrate to the new and improved -sqlite-based storage backend (rope.contrib.autoimport.sqlite.AutoImport). -""" - -import re - -from rope.base import builtins -from rope.base import exceptions -from rope.base import libutils -from rope.base import pynames -from rope.base import pyobjects -from rope.base import resources -from rope.base import resourceobserver -from rope.base import taskhandle -from rope.refactor import importutils - - -@others -@language python -@tabwidth -4 - -def _get_all_star_list(self, pymodule): - def _resolve_name( - name: Union[pynamesdef.AssignedName, pynames.ImportedName] - ) -> List: - while isinstance(name, pynames.ImportedName): - try: - name = name.imported_module.get_object().get_attribute( - name.imported_name, - ) - except exceptions.AttributeNotFoundError: - return [] - assert isinstance(name, pynamesdef.AssignedName) - return name.assignments - - result = set() - try: - all_star_list = pymodule.get_attribute("__all__") - except exceptions.AttributeNotFoundError: - return result - - assignments = [ - assignment.ast_node for assignment in _resolve_name(all_star_list) - ] - - # FIXME: Need a better way to recursively infer possible values. - # Currently pyobjects can recursively infer type, but not values. - # Do a very basic 1-level value inference - - while assignments: - assignment = assignments.pop() - if isinstance(assignment, ast.List): - stack = list(assignment.elts) - while stack: - el = stack.pop() - if isinstance(el, ast.IfExp): - stack.append(el.body) - stack.append(el.orelse) - elif isinstance(el, ast.Starred): - assignments.append(el.value) - else: - if isinstance(el, ast.Str): - result.add(el.s) - elif isinstance(el, ast.Name): - try: - name = pymodule.get_attribute(el.id) - except exceptions.AttributeNotFoundError: - continue - else: - for av in _resolve_name(name): - if isinstance(av.ast_node, ast.Str): - result.add(av.ast_node.s) - elif isinstance(assignment, ast.Name): - try: - name = pymodule.get_attribute(assignment.id) - except exceptions.AttributeNotFoundError: - continue - else: - assignments.extend( - assignment.ast_node for assignment in _resolve_name(name) - ) - elif isinstance(assignment, ast.BinOp): - assignments.append(assignment.left) - assignments.append(assignment.right) - return result - - -def remove_unused_imports(self): - can_select = _OneTimeSelector( - self._get_unbound_names(self.pymodule) - | self._get_all_star_list(self.pymodule) - | {"__all__"} - ) - visitor = actions.RemovingVisitor( - self.project, self._current_folder(), can_select - ) - for import_statement in self.imports: - import_statement.accept(visitor) - - -def get_used_imports(self, defined_pyobject): - result = [] - can_select = _OneTimeSelector(self._get_unbound_names(defined_pyobject)) - visitor = actions.FilteringVisitor( - self.project, self._current_folder(), can_select - ) - for import_statement in self.imports: - new_import = import_statement.accept(visitor) - if new_import is not None and not new_import.is_empty(): - result.append(new_import) - return result - - -def get_changed_source(self): - if not self.project.prefs.get("pull_imports_to_top") and not self.sorted: - return "".join(self._rewrite_imports(self.imports)) - - # Make sure we forward a removed import's preceding blank - # lines count to the following import statement. - prev_stmt = None - for stmt in self.imports: - if prev_stmt is not None and prev_stmt.import_info.is_empty(): - stmt.blank_lines = max(prev_stmt.blank_lines, stmt.blank_lines) - prev_stmt = stmt - # The new list of imports. - imports = [stmt for stmt in self.imports if not stmt.import_info.is_empty()] - - after_removing = self._remove_imports(self.imports) - first_non_blank = self._first_non_blank_line(after_removing, 0) - first_import = self._first_import_line() - 1 - result = [] - # Writing module docs - result.extend(after_removing[first_non_blank:first_import]) - # Writing imports - sorted_imports = sorted(imports, key=self._get_location) - for stmt in sorted_imports: - if stmt != sorted_imports[0]: - result.append("\n" * stmt.blank_lines) - result.append(stmt.get_import_statement() + "\n") - if sorted_imports and first_non_blank < len(after_removing): - result.append("\n" * self.separating_lines) - - # Writing the body - first_after_imports = self._first_non_blank_line(after_removing, first_import) - result.extend(after_removing[first_after_imports:]) - return "".join(result) - - -def _get_import_location(self, stmt): - start = stmt.get_new_start() - if start is None: - start = stmt.get_old_location()[0] - return start - - -def _get_location(self, stmt): - if stmt.get_new_start() is not None: - return stmt.get_new_start() - else: - return stmt.get_old_location()[0] - - -def _remove_imports(self, imports): - lines = self.pymodule.source_code.splitlines(True) - after_removing = [] - first_import_line = self._first_import_line() - last_index = 0 - for stmt in imports: - start, end = stmt.get_old_location() - blank_lines = 0 - if start != first_import_line: - blank_lines = _count_blank_lines( - lines.__getitem__, start - 2, last_index - 1, -1 - ) - after_removing.extend(lines[last_index : start - 1 - blank_lines]) - last_index = end - 1 - after_removing.extend(lines[last_index:]) - return after_removing - - -def _rewrite_imports(self, imports): - lines = self.pymodule.source_code.splitlines(True) - after_rewriting = [] - last_index = 0 - for stmt in imports: - start, end = stmt.get_old_location() - after_rewriting.extend(lines[last_index : start - 1]) - if not stmt.import_info.is_empty(): - after_rewriting.append(stmt.get_import_statement() + "\n") - last_index = end - 1 - after_rewriting.extend(lines[last_index:]) - return after_rewriting - - -def _first_non_blank_line(self, lines, lineno): - return lineno + _count_blank_lines(lines.__getitem__, lineno, len(lines)) - - -def add_import(self, import_info): - visitor = actions.AddingVisitor(self.project, [import_info]) - for import_statement in self.imports: - if import_statement.accept(visitor): - break - else: - lineno = self._get_new_import_lineno() - blanks = self._get_new_import_blanks() - self.imports.append( - importinfo.ImportStatement( - import_info, lineno, lineno, blank_lines=blanks - ) - ) - - -class AutoImport: - """A class for finding the module that provides a name - - This class maintains a cache of global names in python modules. - Note that this cache is not accurate and might be out of date. - - """ - - @others - -def _get_new_import_blanks(self): - return 0 - - -def _get_new_import_lineno(self): - if self.imports: - return self.imports[-1].end_line - return 1 - - -def filter_names(self, can_select): - visitor = actions.RemovingVisitor( - self.project, self._current_folder(), can_select - ) - for import_statement in self.imports: - import_statement.accept(visitor) - - -def expand_stars(self): - can_select = _OneTimeSelector(self._get_unbound_names(self.pymodule)) - visitor = actions.ExpandStarsVisitor( - self.project, self._current_folder(), can_select - ) - for import_statement in self.imports: - import_statement.accept(visitor) - - -def remove_duplicates(self): - added_imports = [] - for import_stmt in self.imports: - visitor = actions.AddingVisitor(self.project, [import_stmt.import_info]) - for added_import in added_imports: - if added_import.accept(visitor): - import_stmt.empty_import() - else: - added_imports.append(import_stmt) - - -def force_single_imports(self): - """force a single import per statement""" - for import_stmt in self.imports[:]: - import_info = import_stmt.import_info - if import_info.is_empty() or import_stmt.readonly: - continue - if len(import_info.names_and_aliases) > 1: - for name_and_alias in import_info.names_and_aliases: - if hasattr(import_info, "module_name"): - new_import = importinfo.FromImport( - import_info.module_name, import_info.level, [name_and_alias] - ) - else: - new_import = importinfo.NormalImport([name_and_alias]) - self.add_import(new_import) - import_stmt.empty_import() - - -def get_relative_to_absolute_list(self): - visitor = actions.RelativeToAbsoluteVisitor( - self.project, self._current_folder() - ) - for import_stmt in self.imports: - if not import_stmt.readonly: - import_stmt.accept(visitor) - return visitor.to_be_absolute - - -def get_self_import_fix_and_rename_list(self): - visitor = actions.SelfImportVisitor( - self.project, self._current_folder(), self.pymodule.get_resource() - ) - for import_stmt in self.imports: - if not import_stmt.readonly: - import_stmt.accept(visitor) - return visitor.to_be_fixed, visitor.to_be_renamed - - -def _current_folder(self): - return self.pymodule.get_resource().parent - - -def sort_imports(self): - if self.project.prefs.get("sort_imports_alphabetically"): - sort_kwargs = dict(key=self._get_import_name) - else: - sort_kwargs = dict(key=self._key_imports) - - # IDEA: Sort from import list - visitor = actions.SortingVisitor(self.project, self._current_folder()) - for import_statement in self.imports: - import_statement.accept(visitor) - in_projects = sorted(visitor.in_project, **sort_kwargs) - third_party = sorted(visitor.third_party, **sort_kwargs) - standards = sorted(visitor.standard, **sort_kwargs) - future = sorted(visitor.future, **sort_kwargs) - last_index = self._first_import_line() - last_index = self._move_imports(future, last_index, 0) - last_index = self._move_imports(standards, last_index, 1) - last_index = self._move_imports(third_party, last_index, 1) - last_index = self._move_imports(in_projects, last_index, 1) - self.separating_lines = 2 - self.sorted = True - - -def __init__(self, project, observe=True, underlined=False): - """Construct an AutoImport object - - If `observe` is `True`, listen for project changes and update - the cache. - - If `underlined` is `True`, underlined names are cached, too. - """ - self.project = project - self.underlined = underlined - self.names = project.data_files.read_data("globalnames") - if self.names is None: - self.names = {} - project.data_files.add_write_hook(self._write) - # XXX: using a filtered observer - observer = resourceobserver.ResourceObserver( - changed=self._changed, moved=self._moved, removed=self._removed - ) - if observe: - project.add_observer(observer) - - -def _first_import_line(self): - nodes = self.pymodule.get_ast().body - lineno = 0 - if self.pymodule.get_doc() is not None: - lineno = 1 - if len(nodes) > lineno: - if isinstance(nodes[lineno], ast.Import) or isinstance( - nodes[lineno], ast.ImportFrom - ): - return nodes[lineno].lineno - first_line = get_first_decorator_or_function_start_line(nodes[lineno]) - lineno = self.pymodule.logical_lines.logical_line_in(first_line)[0] - else: - lineno = self.pymodule.lines.length() - - return lineno - _count_blank_lines( - self.pymodule.lines.get_line, lineno - 1, 1, -1 - ) - - -def _get_import_name(self, import_stmt): - import_info = import_stmt.import_info - if hasattr(import_info, "module_name"): - return "{}.{}".format( - import_info.module_name, - import_info.names_and_aliases[0][0], - ) - else: - return import_info.names_and_aliases[0][0] - - -def _key_imports(self, stm1): - str1 = stm1.get_import_statement() - return str1.startswith("from "), str1 - - # str1 = stmt1.get_import_statement() - # str2 = stmt2.get_import_statement() - # if str1.startswith('from ') and not str2.startswith('from '): - # return 1 - # if not str1.startswith('from ') and str2.startswith('from '): - # return -1 - # return cmp(str1, str2) - - -def _move_imports(self, imports, index, blank_lines): - if imports: - imports[0].move(index, blank_lines) - index += 1 - if len(imports) > 1: - for stmt in imports[1:]: - stmt.move(index) - index += 1 - return index - - -def handle_long_imports(self, maxdots, maxlength): - visitor = actions.LongImportVisitor( - self._current_folder(), self.project, maxdots, maxlength - ) - for import_statement in self.imports: - if not import_statement.readonly: - import_statement.accept(visitor) - for import_info in visitor.new_imports: - self.add_import(import_info) - return visitor.to_be_renamed - - -def remove_pyname(self, pyname): - """Removes pyname when imported in ``from mod import x``""" - visitor = actions.RemovePyNameVisitor( - self.project, self.pymodule, pyname, self._current_folder() - ) - for import_stmt in self.imports: - import_stmt.accept(visitor) - - - -def get_first_decorator_or_function_start_line(node): - decorators = getattr(node, "decorator_list", []) - first_line = min([decorator.lineno for decorator in decorators] + [node.lineno]) - return first_line - - - -def _count_blank_lines(get_line, start, end, step=1): - count = 0 - for idx in range(start, end, step): - if get_line(idx).strip() == "": - count += 1 - else: - break - return count - - - -class _OneTimeSelector: - @others - -def __init__(self, names): - self.names = names - self.selected_names = set() - - -def import_assist(self, starting): - """Return a list of ``(name, module)`` tuples - - This function tries to find modules that have a global name - that starts with `starting`. - """ - # XXX: breaking if gave up! use generators - result = [] - for module in self.names: - for global_name in self.names[module]: - if global_name.startswith(starting): - result.append((global_name, module)) - return result - - -def __call__(self, imported_primary): - if self._can_name_be_added(imported_primary): - for name in self._get_dotted_tokens(imported_primary): - self.selected_names.add(name) - return True - return False - - -def _get_dotted_tokens(self, imported_primary): - tokens = imported_primary.split(".") - for i in range(len(tokens)): - yield ".".join(tokens[: i + 1]) - - -def _can_name_be_added(self, imported_primary): - for name in self._get_dotted_tokens(imported_primary): - if name in self.names and name not in self.selected_names: - return True - return False - - - -class _UnboundNameFinder: - @others - -def __init__(self, pyobject): - self.pyobject = pyobject - - -def _visit_child_scope(self, node): - pyobject = ( - self.pyobject.get_module() - .get_scope() - .get_inner_scope_for_line(node.lineno) - .pyobject - ) - visitor = _LocalUnboundNameFinder(pyobject, self) - for child in ast.get_child_nodes(node): - ast.walk(child, visitor) - - -def _FunctionDef(self, node): - self._visit_child_scope(node) - - -def _ClassDef(self, node): - self._visit_child_scope(node) - - -def _Name(self, node): - if self._get_root()._is_node_interesting(node) and not self.is_bound(node.id): - self.add_unbound(node.id) - - -def _Attribute(self, node): - result = [] - while isinstance(node, ast.Attribute): - result.append(node.attr) - node = node.value - if isinstance(node, ast.Name): - result.append(node.id) - primary = ".".join(reversed(result)) - if self._get_root()._is_node_interesting(node) and not self.is_bound( - primary - ): - self.add_unbound(primary) - else: - ast.walk(node, self) - - -def get_modules(self, name): - """Return the list of modules that have global `name`""" - return [module for module in self.names if name in self.names[module]] - - -def _get_root(self): - pass - - -def is_bound(self, name, propagated=False): - pass - - -def add_unbound(self, name): - pass - - - -class _GlobalUnboundNameFinder(_UnboundNameFinder): - @others - -def __init__(self, pymodule, wanted_pyobject): - super().__init__(pymodule) - self.unbound = set() - self.names = set() - for name, pyname in pymodule._get_structural_attributes().items(): - if not isinstance(pyname, (pynames.ImportedName, pynames.ImportedModule)): - self.names.add(name) - wanted_scope = wanted_pyobject.get_scope() - self.start = wanted_scope.get_start() - self.end = wanted_scope.get_end() + 1 - - -def _get_root(self): - return self - - -def is_bound(self, primary, propagated=False): - name = primary.split(".")[0] - return name in self.names - - -def add_unbound(self, name): - names = name.split(".") - for i in range(len(names)): - self.unbound.add(".".join(names[: i + 1])) - - -def _is_node_interesting(self, node): - return self.start <= node.lineno < self.end - - - -class _LocalUnboundNameFinder(_UnboundNameFinder): - @others - -def get_all_names(self): - """Return the list of all cached global names""" - result = set() - for module in self.names: - result.update(set(self.names[module])) - return result - - -def __init__(self, pyobject, parent): - super().__init__(pyobject) - self.parent = parent - - -def _get_root(self): - return self.parent._get_root() - - -def is_bound(self, primary, propagated=False): - name = primary.split(".")[0] - if propagated: - names = self.pyobject.get_scope().get_propagated_names() - else: - names = self.pyobject.get_scope().get_names() - return name in names or self.parent.is_bound(name, propagated=True) - - -def add_unbound(self, name): - self.parent.add_unbound(name) - - - -class _GlobalImportFinder: - @others - -def __init__(self, pymodule): - self.current_folder = None - if pymodule.get_resource(): - self.current_folder = pymodule.get_resource().parent - self.pymodule = pymodule - self.imports = [] - self.pymodule = pymodule - self.lines = self.pymodule.lines - - -def visit_import(self, node, end_line): - start_line = node.lineno - import_statement = importinfo.ImportStatement( - importinfo.NormalImport(self._get_names(node.names)), - start_line, - end_line, - self._get_text(start_line, end_line), - blank_lines=self._count_empty_lines_before(start_line), - ) - self.imports.append(import_statement) - - -def _count_empty_lines_before(self, lineno): - return _count_blank_lines(self.lines.get_line, lineno - 1, 0, -1) - - -def _count_empty_lines_after(self, lineno): - return _count_blank_lines(self.lines.get_line, lineno + 1, self.lines.length()) - - -def get_separating_line_count(self): - if not self.imports: - return 0 - return self._count_empty_lines_after(self.imports[-1].end_line - 1) - - -def _get_block_end(self, lineno): - end_line = lineno - base_indents = _get_line_indents(self.lines[lineno]) - for i in range(lineno + 1, len(self.lines)): - if _get_line_indents(self.lines[i]) >= base_indents: - end_line = i - else: - break - return end_line - - -def get_name_locations(self, name): - """Return a list of ``(resource, lineno)`` tuples""" - result = [] - for module in self.names: - if name in self.names[module]: - try: - pymodule = self.project.get_module(module) - if name in pymodule: - pyname = pymodule[name] - module, lineno = pyname.get_definition_location() - if module is not None: - resource = module.get_module().get_resource() - if resource is not None and lineno is not None: - result.append((resource, lineno)) - except exceptions.ModuleNotFoundError: - pass - return result - - -def _get_text(self, start_line, end_line): - result = [self.lines.get_line(index) for index in range(start_line, end_line)] - return "\n".join(result) - - -def visit_from(self, node, end_line): - level = 0 - if node.level: - level = node.level - import_info = importinfo.FromImport( - node.module or "", # see comment at rope.base.ast.walk - level, - self._get_names(node.names), - ) - start_line = node.lineno - self.imports.append( - importinfo.ImportStatement( - import_info, - node.lineno, - end_line, - self._get_text(start_line, end_line), - blank_lines=self._count_empty_lines_before(start_line), - ) - ) - - -def _get_names(self, alias_names): - return [(alias.name, alias.asname) for alias in alias_names] - - -def find_import_statements(self): - nodes = self.pymodule.get_ast().body - for index, node in enumerate(nodes): - if isinstance(node, (ast.Import, ast.ImportFrom)): - lines = self.pymodule.logical_lines - end_line = lines.logical_line_in(node.lineno)[1] + 1 - if isinstance(node, ast.Import): - self.visit_import(node, end_line) - if isinstance(node, ast.ImportFrom): - self.visit_from(node, end_line) - return self.imports - -@path C:/Repos/ekr-rope/rope/refactor/importutils/ -"""A package for handling imports - -This package provides tools for modifying module imports after -refactorings or as a separate task. - -""" -import rope.base.evaluate -from rope.base import libutils -from rope.base.change import ChangeSet, ChangeContents -from rope.refactor import occurrences, rename -from rope.refactor.importutils import module_imports, actions -from rope.refactor.importutils.importinfo import NormalImport, FromImport -import rope.base.codeanalyze - - -@others -@language python -@tabwidth -4 - -class ImportOrganizer: - """Perform some import-related commands - - Each method returns a `rope.base.change.Change` object. - - """ - - @others - -def __init__(self, project): - self.project = project - self.import_tools = ImportTools(self.project) - - -def organize_imports(self, resource, offset=None): - return self._perform_command_on_import_tools( - self.import_tools.organize_imports, resource, offset - ) - - -def expand_star_imports(self, resource, offset=None): - return self._perform_command_on_import_tools( - self.import_tools.expand_stars, resource, offset - ) - - -def froms_to_imports(self, resource, offset=None): - return self._perform_command_on_import_tools( - self.import_tools.froms_to_imports, resource, offset - ) - - -def generate_cache( - self, resources=None, underlined=None, task_handle=taskhandle.NullTaskHandle() -): - """Generate global name cache for project files - - If `resources` is a list of `rope.base.resource.File`, only - those files are searched; otherwise all python modules in the - project are cached. - - """ - if resources is None: - resources = self.project.get_python_files() - job_set = task_handle.create_jobset( - "Generating autoimport cache", len(resources) - ) - for file in resources: - job_set.started_job("Working on <%s>" % file.path) - self.update_resource(file, underlined) - job_set.finished_job() - - -def relatives_to_absolutes(self, resource, offset=None): - return self._perform_command_on_import_tools( - self.import_tools.relatives_to_absolutes, resource, offset - ) - - -def handle_long_imports(self, resource, offset=None): - return self._perform_command_on_import_tools( - self.import_tools.handle_long_imports, resource, offset - ) - - -def _perform_command_on_import_tools(self, method, resource, offset): - pymodule = self.project.get_pymodule(resource) - before_performing = pymodule.source_code - import_filter = None - if offset is not None: - import_filter = self._line_filter(pymodule.lines.get_line_number(offset)) - result = method(pymodule, import_filter=import_filter) - if result is not None and result != before_performing: - changes = ChangeSet( - method.__name__.replace("_", " ") + " in <%s>" % resource.path - ) - changes.add_change(ChangeContents(resource, result)) - return changes - - -def _line_filter(self, lineno): - def import_filter(import_stmt): - return import_stmt.start_line <= lineno < import_stmt.end_line - - return import_filter - - - -class ImportTools: - @others - -def __init__(self, project): - self.project = project - - -def get_import(self, resource): - """The import statement for `resource`""" - module_name = libutils.modname(resource) - return NormalImport(((module_name, None),)) - - -def get_from_import(self, resource, name): - """The from import statement for `name` in `resource`""" - module_name = libutils.modname(resource) - names = [] - if isinstance(name, list): - names = [(imported, None) for imported in name] - else: - names = [ - (name, None), - ] - return FromImport(module_name, 0, tuple(names)) - - -def module_imports(self, module, imports_filter=None): - return module_imports.ModuleImports(self.project, module, imports_filter) - - -def froms_to_imports(self, pymodule, import_filter=None): - pymodule = self._clean_up_imports(pymodule, import_filter) - module_imports = self.module_imports(pymodule, import_filter) - for import_stmt in module_imports.imports: - if import_stmt.readonly or not self._is_transformable_to_normal( - import_stmt.import_info - ): - continue - pymodule = self._from_to_normal(pymodule, import_stmt) - - # Adding normal imports in place of froms - module_imports = self.module_imports(pymodule, import_filter) - for import_stmt in module_imports.imports: - if not import_stmt.readonly and self._is_transformable_to_normal( - import_stmt.import_info - ): - import_stmt.import_info = NormalImport( - ((import_stmt.import_info.module_name, None),) - ) - module_imports.remove_duplicates() - return module_imports.get_changed_source() - - -def generate_modules_cache( - self, modules, underlined=None, task_handle=taskhandle.NullTaskHandle() -): - """Generate global name cache for modules listed in `modules`""" - job_set = task_handle.create_jobset( - "Generating autoimport cache for modules", len(modules) - ) - for modname in modules: - job_set.started_job("Working on <%s>" % modname) - if modname.endswith(".*"): - mod = self.project.find_module(modname[:-2]) - if mod: - for sub in submodules(mod): - self.update_resource(sub, underlined) - else: - self.update_module(modname, underlined) - job_set.finished_job() - - -def expand_stars(self, pymodule, import_filter=None): - module_imports = self.module_imports(pymodule, import_filter) - module_imports.expand_stars() - return module_imports.get_changed_source() - - -def _from_to_normal(self, pymodule, import_stmt): - resource = pymodule.get_resource() - from_import = import_stmt.import_info - module_name = from_import.module_name - for name, alias in from_import.names_and_aliases: - imported = name - if alias is not None: - imported = alias - occurrence_finder = occurrences.create_finder( - self.project, imported, pymodule[imported], imports=False - ) - source = rename.rename_in_module( - occurrence_finder, - module_name + "." + name, - pymodule=pymodule, - replace_primary=True, - ) - if source is not None: - pymodule = libutils.get_string_module(self.project, source, resource) - return pymodule - - -def _clean_up_imports(self, pymodule, import_filter): - resource = pymodule.get_resource() - module_with_imports = self.module_imports(pymodule, import_filter) - module_with_imports.expand_stars() - source = module_with_imports.get_changed_source() - if source is not None: - pymodule = libutils.get_string_module(self.project, source, resource) - source = self.relatives_to_absolutes(pymodule) - if source is not None: - pymodule = libutils.get_string_module(self.project, source, resource) - - module_with_imports = self.module_imports(pymodule, import_filter) - module_with_imports.remove_duplicates() - module_with_imports.remove_unused_imports() - source = module_with_imports.get_changed_source() - if source is not None: - pymodule = libutils.get_string_module(self.project, source, resource) - return pymodule - - -def relatives_to_absolutes(self, pymodule, import_filter=None): - module_imports = self.module_imports(pymodule, import_filter) - to_be_absolute_list = module_imports.get_relative_to_absolute_list() - for name, absolute_name in to_be_absolute_list: - pymodule = self._rename_in_module(pymodule, name, absolute_name) - module_imports = self.module_imports(pymodule, import_filter) - module_imports.get_relative_to_absolute_list() - source = module_imports.get_changed_source() - if source is None: - source = pymodule.source_code - return source - - -def _is_transformable_to_normal(self, import_info): - return isinstance(import_info, FromImport) - - -def organize_imports( - self, - pymodule, - unused=True, - duplicates=True, - selfs=True, - sort=True, - import_filter=None, -): - if unused or duplicates: - module_imports = self.module_imports(pymodule, import_filter) - if unused: - module_imports.remove_unused_imports() - if self.project.prefs.get("split_imports"): - module_imports.force_single_imports() - if duplicates: - module_imports.remove_duplicates() - source = module_imports.get_changed_source() - if source is not None: - pymodule = libutils.get_string_module( - self.project, source, pymodule.get_resource() - ) - if selfs: - pymodule = self._remove_self_imports(pymodule, import_filter) - if sort: - return self.sort_imports(pymodule, import_filter) - else: - return pymodule.source_code - - -def _remove_self_imports(self, pymodule, import_filter=None): - module_imports = self.module_imports(pymodule, import_filter) - ( - to_be_fixed, - to_be_renamed, - ) = module_imports.get_self_import_fix_and_rename_list() - for name in to_be_fixed: - try: - pymodule = self._rename_in_module(pymodule, name, "", till_dot=True) - except ValueError: - # There is a self import with direct access to it - return pymodule - for name, new_name in to_be_renamed: - pymodule = self._rename_in_module(pymodule, name, new_name) - module_imports = self.module_imports(pymodule, import_filter) - module_imports.get_self_import_fix_and_rename_list() - source = module_imports.get_changed_source() - if source is not None: - pymodule = libutils.get_string_module( - self.project, source, pymodule.get_resource() - ) - return pymodule - - -def _rename_in_module(self, pymodule, name, new_name, till_dot=False): - old_name = name.split(".")[-1] - old_pyname = rope.base.evaluate.eval_str(pymodule.get_scope(), name) - occurrence_finder = occurrences.create_finder( - self.project, old_name, old_pyname, imports=False - ) - changes = rope.base.codeanalyze.ChangeCollector(pymodule.source_code) - for occurrence in occurrence_finder.find_occurrences(pymodule=pymodule): - start, end = occurrence.get_primary_range() - if till_dot: - new_end = pymodule.source_code.index(".", end) + 1 - space = pymodule.source_code[end : new_end - 1].strip() - if not space == "": - for c in space: - if not c.isspace() and c not in "\\": - raise ValueError() - end = new_end - changes.add_change(start, end, new_name) - source = changes.get_changed() - if source is not None: - pymodule = libutils.get_string_module( - self.project, source, pymodule.get_resource() - ) - return pymodule - - -def sort_imports(self, pymodule, import_filter=None): - module_imports = self.module_imports(pymodule, import_filter) - module_imports.sort_imports() - return module_imports.get_changed_source() - - -def handle_long_imports( - self, pymodule, maxdots=2, maxlength=27, import_filter=None -): - # IDEA: `maxdots` and `maxlength` can be specified in project config - # adding new from imports - module_imports = self.module_imports(pymodule, import_filter) - to_be_fixed = module_imports.handle_long_imports(maxdots, maxlength) - # performing the renaming - pymodule = libutils.get_string_module( - self.project, - module_imports.get_changed_source(), - resource=pymodule.get_resource(), - ) - for name in to_be_fixed: - pymodule = self._rename_in_module(pymodule, name, name.split(".")[-1]) - # organizing imports - return self.organize_imports( - pymodule, selfs=False, sort=False, import_filter=import_filter - ) - - - -def clear_cache(self): - """Clear all entries in global-name cache - - It might be a good idea to use this function before - regenerating global names. - - """ - self.names.clear() - - -def get_imports(project, pydefined): - """A shortcut for getting the `ImportInfo` used in a scope""" - pymodule = pydefined.get_module() - module = module_imports.ModuleImports(project, pymodule) - if pymodule == pydefined: - return [stmt.import_info for stmt in module.imports] - return module.get_used_imports(pydefined) - - - -def get_module_imports(project, pymodule): - """A shortcut for creating a `module_imports.ModuleImports` object""" - return module_imports.ModuleImports(project, pymodule) - - - -def add_import(project, pymodule, module_name, name=None): - imports = get_module_imports(project, pymodule) - candidates = [] - names = [] - selected_import = None - # from mod import name - if name is not None: - from_import = FromImport(module_name, 0, [(name, None)]) - names.append(name) - candidates.append(from_import) - # from pkg import mod - if "." in module_name: - pkg, mod = module_name.rsplit(".", 1) - from_import = FromImport(pkg, 0, [(mod, None)]) - if project.prefs.get("prefer_module_from_imports"): - selected_import = from_import - candidates.append(from_import) - if name: - names.append(mod + "." + name) - else: - names.append(mod) - # import mod - normal_import = NormalImport([(module_name, None)]) - if name: - names.append(module_name + "." + name) - else: - names.append(module_name) - - candidates.append(normal_import) - - visitor = actions.AddingVisitor(project, candidates) - if selected_import is None: - selected_import = normal_import - for import_statement in imports.imports: - if import_statement.accept(visitor): - selected_import = visitor.import_info - break - imports.add_import(selected_import) - imported_name = names[candidates.index(selected_import)] - return imports.get_changed_source(), imported_name - - -@path C:/Repos/ekr-rope/ropetest/ -from textwrap import dedent - -from rope.base.builtins import Str - -import unittest - -import rope.base.libutils -import rope.base.oi -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class DynamicOITest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project(validate_objectdb=True) - self.pycore = self.project.pycore - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_dti(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - return eval("arg") - a_var = a_func(a_func) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - self.assertEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) - - -def test_module_dti(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - code = dedent("""\ - import mod1 - def a_func(arg): - return eval("arg") - a_var = a_func(mod1) - """) - mod2.write(code) - self.pycore.run_module(mod2).wait_process() - pymod2 = self.project.get_pymodule(mod2) - self.assertEqual(self.project.get_pymodule(mod1), pymod2["a_var"].get_object()) - - -def find_insertion_line(self, code): - """Guess at what line the new import should be inserted""" - match = re.search(r"^(def|class)\s+", code) - if match is not None: - code = code[: match.start()] - try: - pymodule = libutils.get_string_module(self.project, code) - except exceptions.ModuleSyntaxError: - return 1 - testmodname = "__rope_testmodule_rope" - importinfo = importutils.NormalImport(((testmodname, None),)) - module_imports = importutils.get_module_imports(self.project, pymodule) - module_imports.add_import(importinfo) - code = module_imports.get_changed_source() - offset = code.index(testmodname) - lineno = code.count("\n", 0, offset) + 1 - return lineno - - -def test_class_from_another_module_dti(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - code1 = dedent("""\ - class AClass(object): - pass - """) - code2 = dedent("""\ - from mod1 import AClass - - def a_func(arg): - return eval("arg") - a_var = a_func(AClass) - """) - mod1.write(code1) - mod2.write(code2) - self.pycore.run_module(mod2).wait_process() - # pymod1 = self.project.get_pymodule(mod1) - pymod2 = self.project.get_pymodule(mod2) - self.assertEqual(pymod2["AClass"].get_object(), pymod2["a_var"].get_object()) - - -def test_class_dti(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class AClass(object): - pass - - def a_func(arg): - return eval("arg") - a_var = a_func(AClass) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - self.assertEqual(pymod["AClass"].get_object(), pymod["a_var"].get_object()) - - -def test_instance_dti(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class AClass(object): - pass - - def a_func(arg): - return eval("arg()") - a_var = a_func(AClass) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - self.assertEqual( - pymod["AClass"].get_object(), pymod["a_var"].get_object().get_type() - ) - - -def test_method_dti(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class AClass(object): - def a_method(self, arg): - return eval("arg()") - an_instance = AClass() - a_var = an_instance.a_method(AClass) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - self.assertEqual( - pymod["AClass"].get_object(), pymod["a_var"].get_object().get_type() - ) - - -def test_function_argument_dti(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - pass - a_func(a_func) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pyscope = self.project.get_pymodule(mod).get_scope() - self.assertEqual( - pyscope["a_func"].get_object(), pyscope.get_scopes()[0]["arg"].get_object() - ) - - -def test_classes_with_the_same_name(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - class AClass(object): - pass - return eval("arg") - class AClass(object): - pass - a_var = a_func(AClass) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - self.assertEqual(pymod["AClass"].get_object(), pymod["a_var"].get_object()) - - -def test_nested_classes(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(): - class AClass(object): - pass - return AClass - def another_func(arg): - return eval("arg") - a_var = another_func(a_func()) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pyscope = self.project.get_pymodule(mod).get_scope() - self.assertEqual( - pyscope.get_scopes()[0]["AClass"].get_object(), - pyscope["a_var"].get_object(), - ) - - -def test_function_argument_dti2(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg, a_builtin_type): - pass - a_func(a_func, []) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pyscope = self.project.get_pymodule(mod).get_scope() - self.assertEqual( - pyscope["a_func"].get_object(), pyscope.get_scopes()[0]["arg"].get_object() - ) - - -def test_dti_and_concluded_data_invalidation(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - return eval("arg") - a_var = a_func(a_func) - """) - mod.write(code) - pymod = self.project.get_pymodule(mod) - pymod["a_var"].get_object() - self.pycore.run_module(mod).wait_process() - self.assertEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) - - -def test_list_objects_and_dynamicoi(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - pass - def a_func(arg): - return eval("arg") - a_var = a_func([C()])[0] - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def update_resource(self, resource, underlined=None): - """Update the cache for global names in `resource`""" - try: - pymodule = self.project.get_pymodule(resource) - modname = self._module_name(resource) - self._add_names(pymodule, modname, underlined) - except exceptions.ModuleSyntaxError: - pass - - -def test_for_loops_and_dynamicoi(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - pass - def a_func(arg): - return eval("arg") - for c in a_func([C()]): - a_var = c - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_dict_objects_and_dynamicoi(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - pass - def a_func(arg): - return eval("arg") - a_var = a_func({1: C()})[1] - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_dict_keys_and_dynamicoi(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - pass - def a_func(arg): - return eval("arg") - a_var = list(a_func({C(): 1}))[0] - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_dict_keys_and_dynamicoi2(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(arg): - return eval("arg") - a, b = a_func((C1(), C2())) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_strs_and_dynamicoi(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - return eval("arg") - a_var = a_func("hey") - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - a_var = pymod["a_var"].get_object() - self.assertTrue(isinstance(a_var.get_type(), rope.base.builtins.Str)) - - -def test_textual_transformations(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - pass - def f(): - pass - a_var = C() - a_list = [C()] - a_str = "hey" - a_file = open("file.txt") - """) - mod.write(code) - to_pyobject = rope.base.oi.transform.TextualToPyObject(self.project) - to_textual = rope.base.oi.transform.PyObjectToTextual(self.project) - pymod = self.project.get_pymodule(mod) - - def complex_to_textual(pyobject): - return to_textual.transform( - to_pyobject.transform(to_textual.transform(pyobject)) - ) - - test_variables = [ - ("C", ("defined", "mod.py", "C")), - ("f", ("defined", "mod.py", "f")), - ("a_var", ("instance", ("defined", "mod.py", "C"))), - ("a_list", ("builtin", "list", ("instance", ("defined", "mod.py", "C")))), - ("a_str", ("builtin", "str")), - ("a_file", ("builtin", "file")), - ] - test_cases = [(pymod[v].get_object(), r) for v, r in test_variables] - test_cases += [ - (pymod, ("defined", "mod.py")), - ( - rope.base.builtins.builtins["enumerate"].get_object(), - ("builtin", "function", "enumerate"), - ), - ] - for var, result in test_cases: - self.assertEqual(to_textual.transform(var), result) - self.assertEqual(complex_to_textual(var), result) - - -def test_arguments_with_keywords(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(arg): - return eval("arg") - a = a_func(arg=C1()) - b = a_func(arg=C2()) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_a_function_with_different_returns(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(arg): - return eval("arg") - a = a_func(C1()) - b = a_func(C2()) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_a_function_with_different_returns2(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(p): - if p == C1: - return C1() - else: - return C2() - a = a_func(C1) - b = a_func(C2) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_ignoring_star_args(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(p, *args): - if p == C1: - return C1() - else: - return C2() - a = a_func(C1, 1) - b = a_func(C2, 2) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def update_module(self, modname, underlined=None): - """Update the cache for global names in `modname` module - - `modname` is the name of a module. - """ - try: - pymodule = self.project.get_module(modname) - self._add_names(pymodule, modname, underlined) - except exceptions.ModuleNotFoundError: - pass - - -def test_ignoring_double_star_args(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(p, *kwds, **args): - if p == C1: - return C1() - else: - return C2() - a = a_func(C1, kwd=1) - b = a_func(C2, kwd=2) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_invalidating_data_after_changing(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - return eval("arg") - a_var = a_func(a_func) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - mod.write(code.replace("a_func", "newfunc")) - mod.write(code) - pymod = self.project.get_pymodule(mod) - self.assertNotEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) - - -def test_invalidating_data_after_moving(self): - mod2 = testutils.create_module(self.project, "mod2") - mod2.write("class C(object):\n pass\n") - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - import mod2 - def a_func(arg): - return eval(arg) - a_var = a_func("mod2.C") - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - mod.move("newmod.py") - pymod = self.project.get_module("newmod") - pymod2 = self.project.get_pymodule(mod2) - self.assertEqual(pymod2["C"].get_object(), pymod["a_var"].get_object()) - - - -class NewStaticOITest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project(validate_objectdb=True) - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_static_oi_for_simple_function_calls(self): - code = dedent("""\ - class C(object): - pass - def f(p): - pass - f(C()) - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - f_scope = pymod["f"].get_object().get_scope() - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(c_class, p_type) - - -def test_static_oi_not_failing_when_callin_callables(self): - code = dedent("""\ - class C(object): - pass - C() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - - -def test_static_oi_for_nested_calls(self): - code = dedent("""\ - class C(object): - pass - def f(p): - pass - def g(p): - return p - f(g(C())) - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - f_scope = pymod["f"].get_object().get_scope() - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(c_class, p_type) - - -def test_static_oi_class_methods(self): - code = dedent("""\ - class C(object): - def f(self, p): - pass - C().f(C())""") - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - f_scope = c_class["f"].get_object().get_scope() - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(c_class, p_type) - - -def _module_name(self, resource): - return libutils.modname(resource) - - -def test_static_oi_preventing_soi_maximum_recursion_exceptions(self): - code = dedent("""\ - item = {} - for item in item.keys(): - pass - """) - self.mod.write(code) - try: - self.pycore.analyze_module(self.mod) - except RuntimeError as e: - self.fail(str(e)) - - -def test_static_oi_for_infer_return_typs_from_funcs_based_on_params(self): - code = dedent("""\ - class C(object): - pass - def func(p): - return p - a_var = func(C()) - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_a_function_with_different_returns(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(arg): - return arg - a = a_func(C1()) - b = a_func(C2()) - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_not_reporting_out_of_date_information(self): - code = dedent("""\ - class C1(object): - pass - def f(arg): - return C1() - a_var = f() - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - - self.mod.write(code.replace("C1", "C2")) - pymod = self.project.get_pymodule(self.mod) - c2_class = pymod["C2"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c2_class, a_var.get_type()) - - -def test_invalidating_concluded_data_in_a_function(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write(dedent("""\ - def func(arg): - temp = arg - return temp - """)) - mod2.write(dedent("""\ - import mod1 - class C1(object): - pass - class C2(object): - pass - a_var = mod1.func(C1()) - """)) - pymod2 = self.project.get_pymodule(mod2) - c1_class = pymod2["C1"].get_object() - a_var = pymod2["a_var"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - - mod2.write(mod2.read()[: mod2.read().rfind("C1()")] + "C2())\n") - pymod2 = self.project.get_pymodule(mod2) - c2_class = pymod2["C2"].get_object() - a_var = pymod2["a_var"].get_object() - self.assertEqual(c2_class, a_var.get_type()) - - -def test_handling_generator_functions_for_strs(self): - self.mod.write(dedent("""\ - class C(object): - pass - def f(p): - yield p() - for c in f(C): - a_var = c - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -# TODO: Returning a generator for functions that yield unknowns -@unittest.skip("Returning a generator that yields unknowns") -def xxx_test_handl_generator_functions_when_unknown_type_is_yielded(self): - self.mod.write(dedent("""\ - class C(object): - pass - def f(): - yield eval("C()") - a_var = f() - """)) - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["a_var"].get_object() - self.assertTrue(isinstance(a_var.get_type(), rope.base.builtins.Generator)) - - -def test_static_oi_for_lists_depending_on_append_function(self): - code = dedent("""\ - class C(object): - pass - l = list() - l.append(C()) - a_var = l.pop() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_static_oi_for_lists_per_object_for_get_item(self): - code = dedent("""\ - class C(object): - pass - l = list() - l.append(C()) - a_var = l[0] - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_static_oi_for_lists_per_object_for_fields(self): - code = dedent("""\ - class C(object): - pass - class A(object): - def __init__(self): - self.l = [] - def set(self): - self.l.append(C()) - a = A() - a.set() - a_var = a.l[0] - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def _add_names(self, pymodule, modname, underlined): - if underlined is None: - underlined = self.underlined - globals = [] - if isinstance(pymodule, pyobjects.PyDefinedObject): - attributes = pymodule._get_structural_attributes() - else: - attributes = pymodule.get_attributes() - for name, pyname in attributes.items(): - if not underlined and name.startswith("_"): - continue - if isinstance(pyname, (pynames.AssignedName, pynames.DefinedName)): - globals.append(name) - if isinstance(pymodule, builtins.BuiltinModule): - globals.append(name) - self.names[modname] = globals - - -def test_static_oi_for_lists_per_object_for_set_item(self): - code = dedent("""\ - class C(object): - pass - l = [None] - l[0] = C() - a_var = l[0] - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_static_oi_for_lists_per_object_for_extending_lists(self): - code = dedent("""\ - class C(object): - pass - l = [] - l.append(C()) - l2 = [] - l2.extend(l) - a_var = l2[0] - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_static_oi_for_lists_per_object_for_iters(self): - code = dedent("""\ - class C(object): - pass - l = [] - l.append(C()) - for c in l: - a_var = c - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_static_oi_for_dicts_depending_on_append_function(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {} - d[C1()] = C2() - a, b = d.popitem() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_static_oi_for_dicts_depending_on_for_loops(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {} - d[C1()] = C2() - for k, v in d.items(): - a = k - b = v - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_static_oi_for_dicts_depending_on_update(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {} - d[C1()] = C2() - d2 = {} - d2.update(d) - a, b = d2.popitem() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_static_oi_for_dicts_depending_on_update_on_seqs(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {} - d.update([(C1(), C2())]) - a, b = d.popitem() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_static_oi_for_sets_per_object_for_set_item(self): - code = dedent("""\ - class C(object): - pass - s = set() - s.add(C()) - a_var = s.pop() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_properties_and_calling_get_property(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - c1 = C1() - def get_c1(self): - return self.c1 - p = property(get_c1) - c2 = C2() - a_var = c2.p - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - - -def test_soi_on_constructors(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - def __init__(self, arg): - self.attr = arg - c2 = C2(C1()) - a_var = c2.attr""") - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - - -def _write(self): - self.project.data_files.write_data("globalnames", self.names) - - -def test_soi_on_literal_assignment(self): - code = 'a_var = ""' - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["a_var"].get_object() - self.assertEqual(Str, type(a_var.get_type())) - - -@testutils.only_for_versions_higher("3.6") -def test_soi_on_typed_assignment(self): - code = "a_var: str" - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["a_var"].get_object() - self.assertEqual(Str, type(a_var.get_type())) - - -def test_not_saving_unknown_function_returns(self): - mod2 = testutils.create_module(self.project, "mod2") - self.mod.write(dedent("""\ - class C(object): - pass - l = [] - l.append(C()) - """)) - mod2.write(dedent("""\ - import mod - def f(): - return mod.l.pop() - a_var = f() - """)) - pymod = self.project.get_pymodule(self.mod) - pymod2 = self.project.get_pymodule(mod2) - c_class = pymod["C"].get_object() - a_var = pymod2["a_var"] - - self.pycore.analyze_module(mod2) - self.assertNotEqual(c_class, a_var.get_object().get_type()) - - self.pycore.analyze_module(self.mod) - self.assertEqual(c_class, a_var.get_object().get_type()) - - -def test_using_the_best_callinfo(self): - code = dedent("""\ - class C1(object): - pass - def f(arg1, arg2, arg3): - pass - f("", None, C1()) - f("", C1(), None) - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - f_scope = pymod["f"].get_object().get_scope() - arg2 = f_scope["arg2"].get_object() - self.assertEqual(c1_class, arg2.get_type()) - - -def test_call_function_and_parameters(self): - code = dedent("""\ - class A(object): - def __call__(self, p): - pass - A()("") - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - scope = self.project.get_pymodule(self.mod).get_scope() - p_object = scope.get_scopes()[0].get_scopes()[0]["p"].get_object() - self.assertTrue(isinstance(p_object.get_type(), rope.base.builtins.Str)) - - -def test_report_change_in_libutils(self): - self.project.prefs["automatic_soa"] = True - code = dedent("""\ - class C(object): - pass - def f(p): - pass - f(C()) - """) - with open(self.mod.real_path, "w") as mod_file: - mod_file.write(code) - - rope.base.libutils.report_change(self.project, self.mod.real_path, "") - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - f_scope = pymod["f"].get_object().get_scope() - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(c_class, p_type) - - -def test_report_libutils_and_analyze_all_modules(self): - code = dedent("""\ - class C(object): - pass - def f(p): - pass - f(C()) - """) - self.mod.write(code) - rope.base.libutils.analyze_modules(self.project) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - f_scope = pymod["f"].get_object().get_scope() - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(c_class, p_type) - - -def test_validation_problems_for_objectdb_retrievals(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write(dedent("""\ - l = [] - var = l.pop() - """)) - mod2.write(dedent("""\ - import mod1 - - class C(object): - pass - mod1.l.append(C()) - """)) - self.pycore.analyze_module(mod2) - - pymod2 = self.project.get_pymodule(mod2) - c_class = pymod2["C"].get_object() - pymod1 = self.project.get_pymodule(mod1) - var_pyname = pymod1["var"] - self.assertEqual(c_class, var_pyname.get_object().get_type()) - mod2.write(dedent("""\ - import mod1 - - mod1.l.append("") - """)) - self.assertNotEqual( - c_class, var_pyname.get_object().get_type(), "Class `C` no more exists" - ) - - -def test_validation_problems_for_changing_builtin_types(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - l = [] - l.append("") - """)) - self.pycore.analyze_module(mod1) - - mod1.write(dedent("""\ - l = {} - v = l["key"] - """)) - pymod1 = self.project.get_pymodule(mod1) # noqa - var = pymod1["v"].get_object() # noqa - - -def test_always_returning_containing_class_for_selfs(self): - code = dedent("""\ - class A(object): - def f(p): - return p - class B(object): - pass - b = B() - b.f() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - a_class = pymod["A"].get_object() - f_scope = a_class.get_scope().get_scopes()[0] - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(a_class, p_type) - - -def _get_stmt_end(self, lineno): - base_indents = _get_line_indents(self.lines[lineno]) - for i in range(lineno + 1, len(self.lines)): - if _get_line_indents(self.lines[i]) <= base_indents: - return i - 1 - return lineno - - -def _changed(self, resource): - if not resource.is_folder(): - self.update_resource(resource) - - -def test_following_function_calls_when_asked_to(self): - code = dedent("""\ - class A(object): - pass - class C(object): - def __init__(self, arg): - self.attr = arg - def f(p): - return C(p) - c = f(A()) - x = c.attr - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod, followed_calls=1) - pymod = self.project.get_pymodule(self.mod) - a_class = pymod["A"].get_object() - x_var = pymod["x"].get_object().get_type() - self.assertEqual(a_class, x_var) - - -def test_set_comprehension(self): - code = dedent("""\ - x = {s.strip() for s in X()} - x.add('x') - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - x_var = pymod["x"].pyobject.get() - -@path C:/Repos/ekr-rope/ropetest/ -from textwrap import dedent - -import unittest - -from rope.base import builtins, libutils, pyobjects -from ropetest import testutils -from rope.base.builtins import Dict - - -@others -@language python -@tabwidth -4 - -class BuiltinTypesTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_case(self): - self.mod.write("l = []\n") - pymod = self.project.get_pymodule(self.mod) - self.assertTrue("append" in pymod["l"].get_object()) - - -def test_holding_type_information(self): - self.mod.write(dedent("""\ - class C(object): - pass - l = [C()] - a_var = l.pop() - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_get_items(self): - self.mod.write(dedent("""\ - class C(object): - def __getitem__(self, i): - return C() - c = C() - a_var = c[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_get_items_for_lists(self): - self.mod.write(dedent("""\ - class C(object): - pass - l = [C()] - a_var = l[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def _moved(self, resource, newresource): - if not resource.is_folder(): - modname = self._module_name(resource) - if modname in self.names: - del self.names[modname] - self.update_resource(newresource) - - -def test_get_items_from_slices(self): - self.mod.write(dedent("""\ - class C(object): - pass - l = [C()] - a_var = l[:].pop() - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_simple_for_loops(self): - self.mod.write(dedent("""\ - class C(object): - pass - l = [C()] - for c in l: - a_var = c - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_definition_location_for_loop_variables(self): - self.mod.write(dedent("""\ - class C(object): - pass - l = [C()] - for c in l: - pass - """)) - pymod = self.project.get_pymodule(self.mod) - c_var = pymod["c"] - self.assertEqual((pymod, 4), c_var.get_definition_location()) - - -def test_simple_case_for_dicts(self): - self.mod.write("d = {}\n") - pymod = self.project.get_pymodule(self.mod) - self.assertTrue("get" in pymod["d"].get_object()) - - -def test_get_item_for_dicts(self): - self.mod.write(dedent("""\ - class C(object): - pass - d = {1: C()} - a_var = d[1] - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_dict_function_parent(self): - self.mod.write(dedent("""\ - d = {1: 2} - a_var = d.keys() - """)) - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["d"].get_object()["keys"].get_object() - self.assertEqual(type(a_var.parent), Dict) - - -def test_popping_dicts(self): - self.mod.write(dedent("""\ - class C(object): - pass - d = {1: C()} - a_var = d.pop(1) - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_getting_keys_from_dicts(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {C1(): C2()} - for c in d.keys(): - a_var = c - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C1"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_getting_values_from_dicts(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {C1(): C2()} - for c in d.values(): - a_var = c - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C2"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_getting_iterkeys_from_dicts(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {C1(): C2()} - for c in d.keys(): - a_var = c - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C1"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def _removed(self, resource): - if not resource.is_folder(): - modname = self._module_name(resource) - if modname in self.names: - del self.names[modname] - - - -def test_getting_itervalues_from_dicts(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {C1(): C2()} - for c in d.values(): - a_var = c - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C2"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_using_copy_for_dicts(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {C1(): C2()} - for c in d.copy(): - a_var = c - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C1"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_tuple_assignments_for_items(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {C1(): C2()} - key, value = d.items()[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - key = pymod["key"].get_object() - value = pymod["value"].get_object() - self.assertEqual(c1_class, key.get_type()) - self.assertEqual(c2_class, value.get_type()) - - -def test_tuple_assignment_for_lists(self): - self.mod.write(dedent("""\ - class C(object): - pass - l = [C(), C()] - a, b = l - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c_class, a_var.get_type()) - self.assertEqual(c_class, b_var.get_type()) - - -def test_tuple_assignments_for_iteritems_in_fors(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {C1(): C2()} - for x, y in d.items(): - a = x; - b = y - """)) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_simple_tuple_assignments(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - a, b = C1(), C2() - """)) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_overriding_builtin_names(self): - self.mod.write(dedent("""\ - class C(object): - pass - list = C - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - list_var = pymod["list"].get_object() - self.assertEqual(c_class, list_var) - - -def test_simple_builtin_scope_test(self): - self.mod.write("l = list()\n") - pymod = self.project.get_pymodule(self.mod) - self.assertTrue("append" in pymod["l"].get_object()) - - -def test_simple_sets(self): - self.mod.write("s = set()\n") - pymod = self.project.get_pymodule(self.mod) - self.assertTrue("add" in pymod["s"].get_object()) - - -def test_making_lists_using_the_passed_argument_to_init(self): - self.mod.write(dedent("""\ - class C(object): - pass - l1 = [C()] - l2 = list(l1) - a_var = l2.pop() - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def submodules(mod): - if isinstance(mod, resources.File): - if mod.name.endswith(".py") and mod.name != "__init__.py": - return {mod} - return set() - if not mod.has_child("__init__.py"): - return set() - result = {mod} - for child in mod.get_children(): - result |= submodules(child) - return result - -def test_making_tuples_using_the_passed_argument_to_init(self): - self.mod.write(dedent("""\ - class C(object): - pass - l1 = [C()] - l2 = tuple(l1) - a_var = l2[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_making_sets_using_the_passed_argument_to_init(self): - self.mod.write(dedent("""\ - class C(object): - pass - l1 = [C()] - l2 = set(l1) - a_var = l2.pop() - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_making_dicts_using_the_passed_argument_to_init(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - l1 = [(C1(), C2())] - l2 = dict(l1) - a, b = l2.items()[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_range_builtin_function(self): - self.mod.write("l = range(1)\n") - pymod = self.project.get_pymodule(self.mod) - l = pymod["l"].get_object() - self.assertTrue("append" in l) - - -def test_reversed_builtin_function(self): - self.mod.write(dedent("""\ - class C(object): - pass - l = [C()] - for x in reversed(l): - a_var = x - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_sorted_builtin_function(self): - self.mod.write(dedent("""\ - class C(object): - pass - l = [C()] - a_var = sorted(l).pop() - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_super_builtin_function(self): - self.mod.write(dedent("""\ - class C(object): - pass - class A(object): - def a_f(self): - return C() - class B(A): - def b_f(self): - return super(B, self).a_f() - a_var = B.b_f() - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_file_builtin_type(self): - self.mod.write(dedent("""\ - for line in open("file.txt"): - a_var = line - """)) - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["a_var"].get_object() - self.assertTrue(isinstance(a_var.get_type(), builtins.Str)) - - -def test_property_builtin_type(self): - self.mod.write("p = property()\n") - pymod = self.project.get_pymodule(self.mod) - p_var = pymod["p"].get_object() - self.assertTrue("fget" in p_var) - - -def test_lambda_functions(self): - self.mod.write("l = lambda: 1\n") - pymod = self.project.get_pymodule(self.mod) - l_var = pymod["l"].get_object() - self.assertEqual(pyobjects.get_base_type("Function"), l_var.get_type()) - - -@path C:/Repos/ekr-rope/rope/contrib/autoimport/ -"""AutoImport module for rope.""" -import re -import sqlite3 -import sys -from collections import OrderedDict -from concurrent.futures import Future, ProcessPoolExecutor, as_completed -from itertools import chain -from pathlib import Path -from typing import Generator, Iterable, List, Optional, Set, Tuple, Iterator - -from rope.base import exceptions, libutils, resourceobserver, taskhandle -from rope.base.project import Project -from rope.base.resources import Resource -from rope.contrib.autoimport.defs import ( - ModuleFile, - Name, - NameType, - Package, - PackageType, - SearchResult, - Source, -) -from rope.contrib.autoimport.parse import get_names -from rope.contrib.autoimport.utils import ( - get_files, - get_modname_from_path, - get_package_tuple, - sort_and_deduplicate, - sort_and_deduplicate_tuple, -) -from rope.refactor import importutils -from rope.contrib.autoimport import models - - -@others -@language python -@tabwidth -4 - -def test_lambda_function_definition(self): - self.mod.write("l = lambda x, y = 2, *a, **b: x + y\n") - pymod = self.project.get_pymodule(self.mod) - l_var = pymod["l"].get_object() - self.assertTrue(l_var.get_name() is not None) - self.assertEqual(len(l_var.get_param_names()), 4) - self.assertEqual((pymod, 1), pymod["l"].get_definition_location()) - - -def test_lambdas_that_return_unknown(self): - self.mod.write("a_var = (lambda: None)()\n") - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["a_var"].get_object() - self.assertTrue(a_var is not None) - - -def test_builtin_zip_function(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - c1_list = [C1()] - c2_list = [C2()] - a, b = zip(c1_list, c2_list)[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_builtin_zip_function_with_more_than_two_args(self): - self.mod.write(dedent("""\ - class C1(object): - pass - class C2(object): - pass - c1_list = [C1()] - c2_list = [C2()] - a, b, c = zip(c1_list, c2_list, c1_list)[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - c_var = pymod["c"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - self.assertEqual(c1_class, c_var.get_type()) - - -def test_wrong_arguments_to_zip_function(self): - self.mod.write(dedent("""\ - class C1(object): - pass - c1_list = [C1()] - a, b = zip(c1_list, 1)[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() # noqa - self.assertEqual(c1_class, a_var.get_type()) - - -def test_enumerate_builtin_function(self): - self.mod.write(dedent("""\ - class C(object): - pass - l = [C()] - for i, x in enumerate(l): - a_var = x - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_builtin_class_get_name(self): - self.assertEqual("object", builtins.builtins["object"].get_object().get_name()) - self.assertEqual( - "property", builtins.builtins["property"].get_object().get_name() - ) - - -def test_star_args_and_double_star_args(self): - self.mod.write(dedent("""\ - def func(p, *args, **kwds): - pass - """)) - pymod = self.project.get_pymodule(self.mod) - func_scope = pymod["func"].get_object().get_scope() - args = func_scope["args"].get_object() - kwds = func_scope["kwds"].get_object() - self.assertTrue(isinstance(args.get_type(), builtins.List)) - self.assertTrue(isinstance(kwds.get_type(), builtins.Dict)) - - -def test_simple_list_comprehension_test(self): - self.mod.write("a_var = [i for i in range(10)]\n") - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["a_var"].get_object() - self.assertTrue(isinstance(a_var.get_type(), builtins.List)) - - -def test_simple_list_generator_expression(self): - self.mod.write("a_var = (i for i in range(10))\n") - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["a_var"].get_object() - self.assertTrue(isinstance(a_var.get_type(), builtins.Iterator)) - - -def get_future_names( - packages: List[Package], underlined: bool, job_set: taskhandle.BaseJobSet -) -> Generator[Future, None, None]: - """Get all names as futures.""" - with ProcessPoolExecutor() as executor: - for package in packages: - for module in get_files(package, underlined): - job_set.started_job(module.modname) - job_set.increment() - yield executor.submit(get_names, module, package) - - - -def test_iter_builtin_function(self): - self.mod.write(dedent("""\ - class C(object): - pass - l = [C()] - for c in iter(l): - a_var = c - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_simple_int_type(self): - self.mod.write("l = 1\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - builtins.builtins["int"].get_object(), pymod["l"].get_object().get_type() - ) - - -def test_simple_float_type(self): - self.mod.write("l = 1.0\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - builtins.builtins["float"].get_object(), pymod["l"].get_object().get_type() - ) - - -def test_simple_float_type2(self): - self.mod.write("l = 1e1\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - builtins.builtins["float"].get_object(), pymod["l"].get_object().get_type() - ) - - -def test_simple_complex_type(self): - self.mod.write("l = 1.0j\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - builtins.builtins["complex"].get_object(), - pymod["l"].get_object().get_type(), - ) - - -def test_handling_unaryop_on_ints(self): - self.mod.write("l = -(1)\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - builtins.builtins["int"].get_object(), pymod["l"].get_object().get_type() - ) - - -def test_handling_binop_on_ints(self): - self.mod.write("l = 1 + 1\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - builtins.builtins["int"].get_object(), pymod["l"].get_object().get_type() - ) - - -def test_handling_compares(self): - self.mod.write("l = 1 == 1\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - builtins.builtins["bool"].get_object(), pymod["l"].get_object().get_type() - ) - - -def test_handling_boolops(self): - self.mod.write("l = 1 and 2\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - builtins.builtins["int"].get_object(), pymod["l"].get_object().get_type() - ) - - -def test_binary_or_left_value_unknown(self): - code = "var = (asdsd or 3)\n" - pymod = libutils.get_string_module(self.project, code) - self.assertEqual( - builtins.builtins["int"].get_object(), pymod["var"].get_object().get_type() - ) - - -def filter_packages( - packages: Iterable[Package], underlined: bool, existing: List[str] -) -> Iterable[Package]: - """Filter list of packages to parse.""" - if underlined: - - def filter_package(package: Package) -> bool: - return package.name not in existing - - else: - - def filter_package(package: Package) -> bool: - return package.name not in existing and not package.name.startswith("_") - - return filter(filter_package, packages) - - - -def test_unknown_return_object(self): - src = dedent("""\ - import sys - def foo(): - res = set(sys.builtin_module_names) - if foo: res.add(bar) - """) - self.project.prefs["import_dynload_stdmods"] = True - self.mod.write(src) - self.project.pycore.analyze_module(self.mod) - - -def test_abstractmethods_attribute(self): - # see http://bugs.python.org/issue10006 for details - src = "class SubType(type): pass\nsubtype = SubType()\n" - self.mod.write(src) - self.project.pycore.analyze_module(self.mod) - - - -class BuiltinModulesTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project( - extension_modules=["time", "invalid", "invalid.sub"] - ) - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_case(self): - self.mod.write("import time") - pymod = self.project.get_pymodule(self.mod) - self.assertTrue("time" in pymod["time"].get_object()) - - -def test_ignored_extensions(self): - self.mod.write("import os") - pymod = self.project.get_pymodule(self.mod) - self.assertTrue("rename" not in pymod["os"].get_object()) - - -def test_ignored_extensions_2(self): - self.mod.write("import os") - pymod = self.project.get_pymodule(self.mod) - self.assertTrue("rename" not in pymod["os"].get_object()) - - -def test_nonexistent_modules(self): - self.mod.write("import invalid") - pymod = self.project.get_pymodule(self.mod) - pymod["invalid"].get_object() - - -def test_nonexistent_modules_2(self): - self.mod.write(dedent("""\ - import invalid - import invalid.sub - """)) - pymod = self.project.get_pymodule(self.mod) - invalid = pymod["invalid"].get_object() - self.assertTrue("sub" in invalid) - - -class AutoImport: - """A class for finding the module that provides a name. - - This class maintains a cache of global names in python modules. - Note that this cache is not accurate and might be out of date. - - """ - - connection: sqlite3.Connection - underlined: bool - project: Project - project_package: Package - - @others - -def test_time_in_std_mods(self): - import rope.base.stdmods - - self.assertTrue("time" in rope.base.stdmods.standard_modules()) - - -def test_timemodule_normalizes_to_time(self): - import rope.base.stdmods - - self.assertEqual(rope.base.stdmods.normalize_so_name("timemodule.so"), "time") - -@path C:/Repos/ekr-rope/ropetest/ -from textwrap import dedent - -import unittest - -import rope.base.evaluate -from rope.base import libutils -from rope.base import exceptions, worder, codeanalyze -from rope.base.codeanalyze import SourceLinesAdapter, LogicalLineFinder, get_block_start -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class SourceLinesAdapterTest(unittest.TestCase): - @others - -def test_source_lines_simple(self): - to_lines = SourceLinesAdapter("line1\nline2\n") - self.assertEqual("line1", to_lines.get_line(1)) - self.assertEqual("line2", to_lines.get_line(2)) - self.assertEqual("", to_lines.get_line(3)) - self.assertEqual(3, to_lines.length()) - - -def test_source_lines_get_line_number(self): - to_lines = SourceLinesAdapter("line1\nline2\n") - self.assertEqual(1, to_lines.get_line_number(0)) - self.assertEqual(1, to_lines.get_line_number(5)) - self.assertEqual(2, to_lines.get_line_number(7)) - self.assertEqual(3, to_lines.get_line_number(12)) - - -def test_source_lines_get_line_start(self): - to_lines = SourceLinesAdapter("line1\nline2\n") - self.assertEqual(0, to_lines.get_line_start(1)) - self.assertEqual(6, to_lines.get_line_start(2)) - self.assertEqual(12, to_lines.get_line_start(3)) - - -def test_source_lines_get_line_end(self): - to_lines = SourceLinesAdapter("line1\nline2\n") - self.assertEqual(5, to_lines.get_line_end(1)) - self.assertEqual(11, to_lines.get_line_end(2)) - self.assertEqual(12, to_lines.get_line_end(3)) - - -def test_source_lines_last_line_with_no_new_line(self): - to_lines = SourceLinesAdapter("line1") - self.assertEqual(1, to_lines.get_line_number(5)) - - - -class WordRangeFinderTest(unittest.TestCase): - @others - -def __init__(self, project: Project, observe=True, underlined=False, memory=True): - """Construct an AutoImport object. - - Parameters - ___________ - project : rope.base.project.Project - the project to use for project imports - observe : bool - if true, listen for project changes and update the cache. - underlined : bool - If `underlined` is `True`, underlined names are cached, too. - memory : bool - if true, don't persist to disk - """ - self.project = project - project_package = get_package_tuple(Path(project.root.real_path), project) - assert project_package is not None - assert project_package.path is not None - self.project_package = project_package - self.underlined = underlined - db_path: str - if memory or project.ropefolder is None: - db_path = ":memory:" - else: - db_path = str(Path(project.ropefolder.real_path) / "autoimport.db") - self.connection = sqlite3.connect(db_path) - self._setup_db() - if observe: - observer = resourceobserver.ResourceObserver( - changed=self._changed, moved=self._moved, removed=self._removed - ) - project.add_observer(observer) - - -def _find_primary(self, code, offset): - word_finder = worder.Worder(code) - return word_finder.get_primary_at(offset) - - -def _annotated_code(self, annotated_code): - """ - Split annotated code into raw code and annotation. - - Odd lines in `annotated_code` is the actual Python code. - - Even lines in `annotated_code` are single-char annotation for the - previous line. - - The annotation may contain one extra character which annotates the - newline/end of line character. - """ - code_lines = annotated_code.splitlines()[::2] - annotations_lines = annotated_code.splitlines()[1::2] - if len(annotations_lines) < len(code_lines): - annotations_lines.append("") - for idx, (line, line_ann) in enumerate(zip(code_lines, annotations_lines)): - newline_ann_char = 1 # for annotation of the end of line character - self.assertLessEqual( - len(line_ann), - len(line) + newline_ann_char, - msg="Extra character in annotations", - ) - line_ann = line_ann.rstrip() - line_ann += " " * (len(line) - len(line_ann)) - if len(line_ann) != len(line) + newline_ann_char: - line_ann += " " - self.assertEqual(len(line_ann), len(line) + newline_ann_char) - annotations_lines[idx] = line_ann - code, annotations = "\n".join(code_lines), "\n".join(annotations_lines) - if code[-1] != "\n": - annotations = annotations[:-1] - self.assertEqual(len(code) + code.count("\n"), len(annotations)) - return code, annotations - - -def _make_offset_annotation(self, code, func): - """ - Create annotation by calling `func(offset)` for every offset in `code`. - - For example, when the annotated code looks like so: - - import a.b.c.d - ++++++++ - - This means that `func(offset)` returns True whenever offset points to - the 'a.b.c.d' part and returns False everywhere else. - """ - - def _annotation_char(offset): - ann_char = "+" if func(offset) else " " - if code[offset] == "\n": - ann_char = ann_char + "\n" - return ann_char - - return "".join([_annotation_char(offset) for offset in range(len(code))]) - - -def assert_equal_annotation(self, code, expected, actual): - if expected != actual: - msg = ["Annotation does not match:\n"] - for line, line_exp, line_actual in zip( - code.splitlines(), expected.splitlines(), actual.splitlines() - ): - msg.append(" " + line + "\n") - if line_exp != line_actual: - msg.append("e " + line_exp + "\n") - msg.append("a " + line_actual + "\n") - self.fail("".join(msg)) - - -def test_keyword_before_parens(self): - code = dedent("""\ - if (a_var).an_attr: - pass - """) - self.assertEqual("(a_var).an_attr", self._find_primary(code, code.index(":"))) - - -def test_inside_parans(self): - code = "a_func(a_var)" - self.assertEqual("a_var", self._find_primary(code, 10)) - - -def test_simple_names(self): - code = "a_var = 10" - self.assertEqual("a_var", self._find_primary(code, 3)) - - -def test_function_calls(self): - code = "sample_function()" - self.assertEqual("sample_function", self._find_primary(code, 10)) - - -def test_attribute_accesses(self): - code = "a_var.an_attr" - self.assertEqual("a_var.an_attr", self._find_primary(code, 10)) - - -def test_word_finder_on_word_beginning(self): - code = "print(a_var)\n" - word_finder = worder.Worder(code) - result = word_finder.get_word_at(code.index("a_var")) - self.assertEqual("a_var", result) - - -def _setup_db(self): - models.Name.create_table(self.connection) - models.Package.create_table(self.connection) - self.connection.commit() - - -def test_word_finder_on_primary_beginning(self): - code = "print(a_var)\n" - result = self._find_primary(code, code.index("a_var")) - self.assertEqual("a_var", result) - - -def test_word_finder_on_word_ending(self): - code = "print(a_var)\n" - word_finder = worder.Worder(code) - result = word_finder.get_word_at(code.index("a_var") + 5) - self.assertEqual("a_var", result) - - -def test_word_finder_on_primary_ending(self): - code = "print(a_var)\n" - result = self._find_primary(code, code.index("a_var") + 5) - self.assertEqual("a_var", result) - - -def test_word_finder_on_primaries_with_dots_inside_parens(self): - code = "(a_var.\nattr)" - result = self._find_primary(code, code.index("attr") + 1) - self.assertEqual("a_var.\nattr", result) - - -def test_word_finder_on_primary_like_keyword(self): - code = "is_keyword = False\n" - result = self._find_primary(code, 1) - self.assertEqual("is_keyword", result) - - -def test_keyword_before_parens_no_space(self): - code = dedent("""\ - if(a_var).an_attr: - pass - """) - self.assertEqual("(a_var).an_attr", self._find_primary(code, code.index(":"))) - - -def test_strings(self): - code = '"a string".split()' - self.assertEqual('"a string".split', self._find_primary(code, 14)) - - -def test_function_calls2(self): - code = 'file("afile.txt").read()' - self.assertEqual('file("afile.txt").read', self._find_primary(code, 18)) - - -def test_parens(self): - code = '("afile.txt").split()' - self.assertEqual('("afile.txt").split', self._find_primary(code, 18)) - - -def test_function_with_no_param(self): - code = "AClass().a_func()" - self.assertEqual("AClass().a_func", self._find_primary(code, 12)) - - -def _fix_incomplete_try_blocks(self, lineno, indents): - block_start = lineno - last_indents = indents - while block_start > 0: - block_start = ( - rope.base.codeanalyze.get_block_start( - ArrayLinesAdapter(self.lines), block_start - ) - - 1 - ) - if self.lines[block_start].strip().startswith("try:"): - indents = _get_line_indents(self.lines[block_start]) - if indents > last_indents: - continue - last_indents = indents - block_end = self._find_matching_deindent(block_start) - line = self.lines[block_end].strip() - if not ( - line.startswith("finally:") - or line.startswith("except ") - or line.startswith("except:") - ): - self._insert(block_end, " " * indents + "finally:") - self._insert(block_end + 1, " " * indents + " pass") - - -def import_assist(self, starting: str): - """ - Find modules that have a global name that starts with `starting`. - - For a more complete list, use the search or search_full methods. - - Parameters - __________ - starting : str - what all the names should start with - Return - __________ - Return a list of ``(name, module)`` tuples - """ - results = self._execute( - models.Name.import_assist.select("name", "module", "source"), (starting,) - ).fetchall() - return sort_and_deduplicate_tuple( - results - ) # Remove duplicates from multiple occurrences of the same item - - -def test_function_with_multiple_param(self): - code = 'AClass(a_param, another_param, "a string").a_func()' - self.assertEqual( - 'AClass(a_param, another_param, "a string").a_func', - self._find_primary(code, 44), - ) - - -def test_param_expressions(self): - code = "AClass(an_object.an_attr).a_func()" - self.assertEqual("an_object.an_attr", self._find_primary(code, 20)) - - -def test_string_parens(self): - code = 'a_func("(").an_attr' - self.assertEqual('a_func("(").an_attr', self._find_primary(code, 16)) - - -def test_extra_spaces(self): - code = 'a_func ( "(" ) . an_attr' - self.assertEqual('a_func ( "(" ) . an_attr', self._find_primary(code, 26)) - - -def test_relative_import(self): - code = "from .module import smt" - self.assertEqual(".module", self._find_primary(code, 5)) - - -def test_functions_on_ending_parens(self): - code = "A()" - self.assertEqual("A()", self._find_primary(code, 2)) - - -def test_splitted_statement(self): - word_finder = worder.Worder("an_object.an_attr") - self.assertEqual( - ("an_object", "an_at", 10), word_finder.get_splitted_primary_before(15) - ) - - -def test_empty_splitted_statement(self): - word_finder = worder.Worder("an_attr") - self.assertEqual(("", "an_at", 0), word_finder.get_splitted_primary_before(5)) - - -def test_empty_splitted_statement2(self): - word_finder = worder.Worder("an_object.") - self.assertEqual( - ("an_object", "", 10), word_finder.get_splitted_primary_before(10) - ) - - -def test_empty_splitted_statement3(self): - word_finder = worder.Worder("") - self.assertEqual(("", "", 0), word_finder.get_splitted_primary_before(0)) - - -def search(self, name: str, exact_match: bool = False) -> List[Tuple[str, str]]: - """ - Search both modules and names for an import string. - - This is a simple wrapper around search_full with basic sorting based on Source. - - Returns a sorted list of import statement, modname pairs - """ - results: List[Tuple[str, str, int]] = [ - (statement, import_name, source) - for statement, import_name, source, type in self.search_full( - name, exact_match - ) - ] - return sort_and_deduplicate_tuple(results) - - -def test_empty_splitted_statement4(self): - word_finder = worder.Worder("a_var = ") - self.assertEqual(("", "", 8), word_finder.get_splitted_primary_before(8)) - - -def test_empty_splitted_statement5(self): - word_finder = worder.Worder("a.") - self.assertEqual(("a", "", 2), word_finder.get_splitted_primary_before(2)) - - -def test_operators_inside_parens(self): - code = "(a_var + another_var).reverse()" - self.assertEqual("(a_var + another_var).reverse", self._find_primary(code, 25)) - - -def test_dictionaries(self): - code = 'print({1: "one", 2: "two"}.keys())' - self.assertEqual('{1: "one", 2: "two"}.keys', self._find_primary(code, 29)) - - -def test_following_parens(self): - code = "a_var = a_func()()" - result = self._find_primary(code, code.index(")(") + 3) - self.assertEqual("a_func()()", result) - - -def test_comments_for_finding_statements(self): - code = "# var2 . \n var3" - self.assertEqual("var3", self._find_primary(code, code.index("3"))) - - -def test_str_in_comments_for_finding_statements(self): - code = '# "var2" . \n var3' - self.assertEqual("var3", self._find_primary(code, code.index("3"))) - - -def test_comments_for_finding_statements2(self): - code = 'var1 + "# var2".\n var3' - self.assertEqual("var3", self._find_primary(code, 21)) - - -def test_comments_for_finding_statements3(self): - code = '"" + # var2.\n var3' - self.assertEqual("var3", self._find_primary(code, 21)) - - -def test_is_import_statement(self): - code, annotations = self._annotated_code(annotated_code=dedent("""\ - import a.b.c.d - ++++++++ - from a.b import c - - import a.b.c.d as d - +++++++++++++ - from a.b import c as e - - from a.b import ( - - abc - - ) - - result = a.b.c.d.f() - - """)) - word_finder = worder.Worder(code) - self.assert_equal_annotation( - code, - annotations, - self._make_offset_annotation(code, word_finder.is_import_statement), - ) - - -def search_full( - self, - name: str, - exact_match: bool = False, - ignored_names: Set[str] = set(), -) -> Generator[SearchResult, None, None]: - """ - Search both modules and names for an import string. - - Parameters - __________ - name: str - Name to search for - exact_match: bool - If using exact_match, only search for that name. - Otherwise, search for any name starting with that name. - ignored_names : Set[str] - Will ignore any names in this set - - Return - __________ - Unsorted Generator of SearchResults. Each is guaranteed to be unique. - """ - results = set(self._search_name(name, exact_match)) - results = results.union(self._search_module(name, exact_match)) - for result in results: - if result.name not in ignored_names: - yield result - - -def test_is_import_statement_finding(self): - code = dedent("""\ - import mod - a_var = 10 - """) - word_finder = worder.Worder(code) - self.assertTrue(word_finder.is_import_statement(code.index("mod") + 1)) - self.assertFalse(word_finder.is_import_statement(code.index("a_var") + 1)) - - -def test_is_import_statement_finding2(self): - code = dedent("""\ - import a.b.c.d - result = a.b.c.d.f() - """) - word_finder = worder.Worder(code) - self.assertFalse(word_finder.is_import_statement(code.rindex("d") + 1)) - - -def test_word_parens_range(self): - code = dedent("""\ - s = str() - s.title() - """) - word_finder = worder.Worder(code) - result = word_finder.get_word_parens_range(code.rindex("()") - 1) - self.assertEqual((len(code) - 3, len(code) - 1), result) - - -def test_getting_primary_before_get_index(self): - code = "\na = (b + c).d[0]()\n" - result = self._find_primary(code, len(code) - 2) - self.assertEqual("(b + c).d[0]()", result) - - -def test_getting_primary_and_strings_at_the_end_of_line(self): - code = "f('\\'')\n" - result = self._find_primary(code, len(code) - 1) # noqa - - -def test_getting_primary_and_not_crossing_newlines(self): - code = "\na = (b + c)\n(4 + 1).x\n" - result = self._find_primary(code, len(code) - 1) - self.assertEqual("(4 + 1).x", result) - - -# XXX: concatenated string literals -def xxx_test_getting_primary_cancatenating_strs(self): - code = 's = "a"\n"b" "c"\n' - result = self._find_primary(code, len(code) - 2) - self.assertEqual('"b" "c"', result) - - -def test_is_a_function_being_called_with_parens_on_next_line(self): - code = "func\n(1, 2)\n" - word_finder = worder.Worder(code) - self.assertFalse(word_finder.is_a_function_being_called(1)) - - -# XXX: handling triple quotes -def xxx_test_triple_quotes(self): - code = 's = """string"""\n' - result = self._find_primary(code, len(code) - 1) - self.assertEqual('"""string"""', result) - - -def test_triple_quotes_spanning_multiple_lines(self): - code = 's = """\\\nl1\nl2\n """\n' - result = self._find_primary(code, len(code) - 2) - self.assertEqual('"""\\\nl1\nl2\n """', result) - - -def _search_name( - self, name: str, exact_match: bool = False -) -> Generator[SearchResult, None, None]: - """ - Search both names for available imports. - - Returns the import statement, import name, source, and type. - """ - if not exact_match: - name = name + "%" # Makes the query a starts_with query - for import_name, module, source, name_type in self._execute( - models.Name.search_by_name_like.select("name", "module", "source", "type"), - (name,), - ): - yield ( - SearchResult( - f"from {module} import {import_name}", - import_name, - source, - name_type, - ) - ) - - -def test_get_word_parens_range_and_string_literals(self): - code = 'f(1, ")", 2)\n' - word_finder = worder.Worder(code) - result = word_finder.get_word_parens_range(0) - self.assertEqual((1, len(code) - 1), result) - - -def test_is_assigned_here_for_equality_test(self): - code = "a == 1\n" - word_finder = worder.Worder(code) - self.assertFalse(word_finder.is_assigned_here(0)) - - -def test_is_assigned_here_for_not_equal_test(self): - code = "a != 1\n" - word_finder = worder.Worder(code) - self.assertFalse(word_finder.is_assigned_here(0)) - - -# XXX: is_assigned_here should work for tuple assignments -def xxx_test_is_assigned_here_for_tuple_assignment(self): - code = "a, b = (1, 2)\n" - word_finder = worder.Worder(code) - self.assertTrue(word_finder.is_assigned_here(0)) - - -def test_is_from_statement(self): - code, annotations = self._annotated_code(annotated_code=dedent("""\ - import a.b.c.d - - from a.b import c - +++++++++++++ - import a.b.c.d as d - - from a.b import c as e - ++++++++++++++++++ - from a.b import ( - +++++++++++++ - abc - ++++++++ - ) - ++ - result = a.b.c.d.f() - - """)) - word_finder = worder.Worder(code) - self.assert_equal_annotation( - code, - annotations, - self._make_offset_annotation(code, word_finder.is_from_statement), - ) - - -def test_is_from_statement_module(self): - code, annotations = self._annotated_code(annotated_code=dedent("""\ - import a.b.c.d - - from a.b import c - +++++ - import a.b.c.d as d - - from a.b import c as e - +++++ - from a.b import ( - +++++ - abc - - ) - - result = a.b.c.d.f() - - """)) - word_finder = worder.Worder(code) - self.assert_equal_annotation( - code, - annotations, - self._make_offset_annotation(code, word_finder.is_from_statement_module), - ) - - -def test_is_import_statement_aliased_module(self): - code, annotations = self._annotated_code(annotated_code=dedent("""\ - import a.b.c.d - - from a.b import c - - import a.b.c.d as d - +++++++ - from a.b import c as e - - from a.b import ( - - abc - - ) - - import mod1, \\ - - mod2 as c, mod3, mod4 as d - +++++ +++++ - result = a.b.c.d.f() - - """)) - word_finder = worder.Worder(code) - self.assert_equal_annotation( - code, - annotations, - self._make_offset_annotation( - code, word_finder.is_import_statement_aliased_module - ), - ) - - -def test_is_from_aliased(self): - code, annotations = self._annotated_code(annotated_code=dedent("""\ - import a.b.c.d - - from a.b import c - - import a.b.c.d as d - - from a.b import c as e - ++ - from a.b import ( - - abc - - ) - - from a.b import mod1, \\ - - mod2 as c, mod3, mod4 as d - +++++ +++++ - result = a.b.c.d.f() - - """)) - word_finder = worder.Worder(code) - self.assert_equal_annotation( - code, - annotations, - self._make_offset_annotation(code, word_finder.is_from_aliased), - ) - - -def test_is_from_with_from_import_and_multiline_parens(self): - code = "from mod import \\\n (f,\n g, h)\n" - word_finder = worder.Worder(code) - self.assertTrue(word_finder.is_from_statement(code.rindex("g"))) - - -def test_is_from_with_from_import_and_line_breaks_in_the_middle(self): - code = "from mod import f,\\\n g\n" - word_finder = worder.Worder(code) - self.assertTrue(word_finder.is_from_statement(code.rindex("g"))) - - -def _search_module( - self, name: str, exact_match: bool = False -) -> Generator[SearchResult, None, None]: - """ - Search both modules for available imports. - - Returns the import statement, import name, source, and type. - """ - if not exact_match: - name = name + "%" # Makes the query a starts_with query - for module, source in self._execute( - models.Name.search_submodule_like.select("module", "source"), (name,) - ): - parts = module.split(".") - import_name = parts[-1] - remaining = parts[0] - for part in parts[1:-1]: - remaining += "." - remaining += part - yield ( - SearchResult( - f"from {remaining} import {import_name}", - import_name, - source, - NameType.Module.value, - ) - ) - for module, source in self._execute( - models.Name.search_module_like.select("module", "source"), (name,) - ): - if "." in module: - continue - yield SearchResult( - f"import {module}", module, source, NameType.Module.value - ) - - -def test_is_function_keyword_parameter(self): - code, annotations = self._annotated_code(annotated_code=dedent("""\ - func(param=1) - ++++++ - func( - - param=1 - ++++++ - ) - - def func(param=1): - ++++++ - pass - - """)) - word_finder = worder.Worder(code) - self.assert_equal_annotation( - code, - annotations, - self._make_offset_annotation( - code, word_finder.is_function_keyword_parameter - ), - ) - - -def test_one_letter_is_function_keyword_parameter(self): - code = "f(p=1)\n" - word_finder = worder.Worder(code) - index = code.rindex("p") - self.assertTrue(word_finder.is_function_keyword_parameter(index)) - - -def test_find_parens_start(self): - code = "f(p)\n" - finder = worder.Worder(code) - self.assertEqual(1, finder.find_parens_start_from_inside(2)) - - -def test_underlined_find_parens_start(self): - code = 'f(p="")\n' - finder = worder.Worder(code) - self.assertEqual(1, finder._find_parens_start(len(code) - 2)) - - -def test_find_parens_start_with_multiple_entries(self): - code = "myfunc(p1, p2, p3\n" - finder = worder.Worder(code) - self.assertEqual( - code.index("("), finder.find_parens_start_from_inside(len(code) - 1) - ) - - -def test_find_parens_start_with_nested_parens(self): - code = "myfunc(p1, (p2, p3), p4\n" - finder = worder.Worder(code) - self.assertEqual( - code.index("("), finder.find_parens_start_from_inside(len(code) - 1) - ) - - -def test_find_parens_start_with_parens_in_strs(self): - code = 'myfunc(p1, "(", p4\n' - finder = worder.Worder(code) - self.assertEqual( - code.index("("), finder.find_parens_start_from_inside(len(code) - 1) - ) - - -def test_find_parens_start_with_parens_in_strs_in_multiple_lines(self): - code = 'myfunc (\np1\n , \n "(" \n, \np4\n' - finder = worder.Worder(code) - self.assertEqual( - code.index("("), finder.find_parens_start_from_inside(len(code) - 1) - ) - - -def test_is_on_function_call_keyword(self): - code, annotations = self._annotated_code(annotated_code=dedent("""\ - myfunc(va - +++ - """)) - - finder = worder.Worder(code) - self.assert_equal_annotation( - code, - annotations, - self._make_offset_annotation(code, finder.is_on_function_call_keyword), - ) - - -def test_is_on_function_keyword_partial(self): - code = "myfunc(va" - finder = worder.Worder(code) - self.assertTrue(finder.is_on_function_call_keyword(len(code) - 1)) - - -def get_modules(self, name) -> List[str]: - """Get the list of modules that have global `name`.""" - results = self._execute( - models.Name.search_by_name_like.select("module", "source"), (name,) - ).fetchall() - return sort_and_deduplicate(results) - - -def test_get_word_range_with_fstring(self): - code = dedent('''\ - auth = 8 - my_var = f"some value {auth}" - print(auth) - other_val = "some other"''') - finder = worder.Worder(code) - self.assertEqual(finder.get_word_range(45), (45, 49)) - - - -class ScopeNameFinderTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -# FIXME: in normal scopes the interpreter raises `UnboundLocalName` -# exception, but not in class bodies -def xxx_test_global_name_in_class_body(self): - code = dedent("""\ - a_var = 10 - class C(object): - a_var = a_var - """) - scope = libutils.get_string_scope(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) - result = name_finder.get_pyname_at(len(code) - 3) - self.assertEqual(scope["a_var"], result) - - -def test_class_variable_attribute_in_class_body(self): - code = dedent("""\ - a_var = 10 - class C(object): - a_var = a_var - """) - scope = libutils.get_string_scope(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) - a_var_pyname = scope["C"].get_object()["a_var"] - result = name_finder.get_pyname_at(len(code) - 12) - self.assertEqual(a_var_pyname, result) - - -def test_class_variable_attribute_in_class_body2(self): - code = dedent("""\ - a_var = 10 - class C(object): - a_var \\ - = a_var - """) - scope = libutils.get_string_scope(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) - a_var_pyname = scope["C"].get_object()["a_var"] - result = name_finder.get_pyname_at(len(code) - 12) - self.assertEqual(a_var_pyname, result) - - -def test_class_method_attribute_in_class_body(self): - code = dedent("""\ - class C(object): - def a_method(self): - pass - """) - scope = libutils.get_string_scope(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) - a_method_pyname = scope["C"].get_object()["a_method"] - result = name_finder.get_pyname_at(code.index("a_method") + 2) - self.assertEqual(a_method_pyname, result) - - -def test_inner_class_attribute_in_class_body(self): - code = dedent("""\ - class C(object): - class CC(object): - pass - """) - scope = libutils.get_string_scope(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) - a_class_pyname = scope["C"].get_object()["CC"] - result = name_finder.get_pyname_at(code.index("CC") + 2) - self.assertEqual(a_class_pyname, result) - - -def test_class_method_in_class_body_but_not_indexed(self): - code = dedent("""\ - class C(object): - def func(self, func): - pass - """) - scope = libutils.get_string_scope(self.project, code) - a_func_pyname = scope.get_scopes()[0].get_scopes()[0]["func"] - name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) - result = name_finder.get_pyname_at(code.index(", func") + 3) - self.assertEqual(a_func_pyname, result) - - -def get_all_names(self) -> List[str]: - """Get the list of all cached global names.""" - return self._execute(models.Name.objects.select("name")).fetchall() - - -def test_function_but_not_indexed(self): - code = dedent("""\ - def a_func(a_func): - pass - """) - scope = libutils.get_string_scope(self.project, code) - a_func_pyname = scope["a_func"] - name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) - result = name_finder.get_pyname_at(code.index("a_func") + 3) - self.assertEqual(a_func_pyname, result) - - -def test_modules_after_from_statements(self): - root_folder = self.project.root - mod = testutils.create_module(self.project, "mod", root_folder) - mod.write(dedent("""\ - def a_func(): - pass - """)) - code = "from mod import a_func\n" - scope = libutils.get_string_scope(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) - mod_pyobject = self.project.get_pymodule(mod) - found_pyname = name_finder.get_pyname_at(code.index("mod") + 1) - self.assertEqual(mod_pyobject, found_pyname.get_object()) - - -def test_renaming_functions_with_from_import_and_parens(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - def afunc(): - pass - """)) - code = dedent("""\ - from mod1 import ( - afunc as func) - """) - scope = libutils.get_string_scope(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(scope.pyobject) - mod_pyobject = self.project.get_pymodule(mod1) - afunc = mod_pyobject["afunc"] - found_pyname = name_finder.get_pyname_at(code.index("afunc") + 1) - self.assertEqual(afunc.get_object(), found_pyname.get_object()) - - -@testutils.only_for("2.5") -def test_relative_modules_after_from_statements(self): - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) - mod1 = testutils.create_module(self.project, "mod1", pkg1) - mod2 = testutils.create_module(self.project, "mod2", pkg2) - mod1.write(dedent("""\ - def a_func(): - pass - """)) - code = "from ..mod1 import a_func\n" - mod2.write(code) - mod2_scope = self.project.get_pymodule(mod2).get_scope() - name_finder = rope.base.evaluate.ScopeNameFinder(mod2_scope.pyobject) - mod1_pyobject = self.project.get_pymodule(mod1) - found_pyname = name_finder.get_pyname_at(code.index("mod1") + 1) - self.assertEqual(mod1_pyobject, found_pyname.get_object()) - - -def test_relative_modules_after_from_statements2(self): - mod1 = testutils.create_module(self.project, "mod1") - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) - mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa - mod1.write("import pkg1.pkg2.mod2") - - mod1_scope = self.project.get_pymodule(mod1).get_scope() - name_finder = rope.base.evaluate.ScopeNameFinder(mod1_scope.pyobject) - pkg2_pyobject = self.project.get_pymodule(pkg2) - found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) - self.assertEqual(pkg2_pyobject, found_pyname.get_object()) - - -def test_get_pyname_at_on_language_keywords(self): - code = dedent("""\ - def a_func(a_func): - pass - """) - pymod = libutils.get_string_module(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(pymod) - with self.assertRaises(exceptions.RopeError): - name_finder.get_pyname_at(code.index("pass")) - - -def test_one_liners(self): - code = dedent("""\ - var = 1 - def f(): var = 2 - print(var) - """) - pymod = libutils.get_string_module(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(pymod) - pyname = name_finder.get_pyname_at(code.rindex("var")) - self.assertEqual(pymod["var"], pyname) - - -def test_one_liners_with_line_breaks(self): - code = dedent("""\ - var = 1 - def f( - ): var = 2 - print(var) - """) - pymod = libutils.get_string_module(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(pymod) - pyname = name_finder.get_pyname_at(code.rindex("var")) - self.assertEqual(pymod["var"], pyname) - - -def test_one_liners_with_line_breaks2(self): - code = dedent("""\ - var = 1 - def f( - p): var = 2 - print(var) - """) - pymod = libutils.get_string_module(self.project, code) - name_finder = rope.base.evaluate.ScopeNameFinder(pymod) - pyname = name_finder.get_pyname_at(code.rindex("var")) - self.assertEqual(pymod["var"], pyname) - - -def test_var_in_list_comprehension_differs_from_var_outside(self): - code = "var = 1\n[var for var in range(1)]\n" - pymod = libutils.get_string_module(self.project, code) - - name_finder = rope.base.evaluate.ScopeNameFinder(pymod) - - outside_pyname = name_finder.get_pyname_at(code.index("var")) - inside_pyname = name_finder.get_pyname_at(code.rindex("var")) - - self.assertNotEqual(outside_pyname, inside_pyname) - - - -def _dump_all(self) -> Tuple[List[Name], List[Package]]: - """Dump the entire database.""" - name_results = self._execute(models.Name.objects.select_star()).fetchall() - package_results = self._execute(models.Package.objects.select_star()).fetchall() - return name_results, package_results - - -class LogicalLineFinderTest(unittest.TestCase): - @others - -def _logical_finder(self, code): - return LogicalLineFinder(SourceLinesAdapter(code)) - - -def test_normal_lines(self): - code = "a_var = 10" - line_finder = self._logical_finder(code) - self.assertEqual((1, 1), line_finder.logical_line_in(1)) - - -def test_normal_lines2(self): - code = dedent("""\ - another = 10 - a_var = 20 - """) - line_finder = self._logical_finder(code) - self.assertEqual((1, 1), line_finder.logical_line_in(1)) - self.assertEqual((2, 2), line_finder.logical_line_in(2)) - - -def test_implicit_continuation(self): - code = "a_var = 3 + \\\n 4 + \\\n 5" - line_finder = self._logical_finder(code) - self.assertEqual((1, 3), line_finder.logical_line_in(2)) - - -def test_explicit_continuation(self): - code = dedent("""\ - print(2) - a_var = (3 + - 4, - 5) - """) - line_finder = self._logical_finder(code) - self.assertEqual((2, 4), line_finder.logical_line_in(2)) - - -def test_explicit_continuation_comments(self): - code = "#\na_var = 3\n" - line_finder = self._logical_finder(code) - self.assertEqual((2, 2), line_finder.logical_line_in(2)) - - -def test_multiple_indented_ifs(self): - code = dedent("""\ - if True: - if True: - if True: - pass - a = 10 - """) - line_finder = self._logical_finder(code) - self.assertEqual((5, 5), line_finder.logical_line_in(5)) - - -def test_list_comprehensions_and_fors(self): - code = dedent("""\ - a_list = [i - for i in range(10)] - """) - line_finder = self._logical_finder(code) - self.assertEqual((1, 2), line_finder.logical_line_in(2)) - - -def test_generator_expressions_and_fors(self): - code = dedent("""\ - a_list = (i - for i in range(10)) - """) - line_finder = self._logical_finder(code) - self.assertEqual((1, 2), line_finder.logical_line_in(2)) - - -def generate_cache( - self, - resources: List[Resource] = None, - underlined: bool = False, - task_handle: taskhandle.BaseTaskHandle = taskhandle.NullTaskHandle(), -): - """Generate global name cache for project files. - - If `resources` is a list of `rope.base.resource.File`, only - those files are searched; otherwise all python modules in the - project are cached. - """ - if resources is None: - resources = self.project.get_python_files() - job_set = task_handle.create_jobset( - "Generating autoimport cache", len(resources) - ) - self._execute( - models.Package.delete_by_package_name, (self.project_package.name,) - ) - futures = [] - with ProcessPoolExecutor() as executor: - for file in resources: - job_set.started_job(f"Working on {file.path}") - module = self._resource_to_module(file, underlined) - futures.append(executor.submit(get_names, module, self.project_package)) - for future in as_completed(futures): - self._add_names(future.result()) - job_set.finished_job() - self.connection.commit() - - -def test_fors_and_block_start(self): - code = dedent("""\ - l = range(10) - for i in l: - print(i) - """) - self.assertEqual(2, get_block_start(SourceLinesAdapter(code), 2)) - - -def test_problems_with_inner_indentations(self): - code = dedent("""\ - if True: - if True: - if True: - pass - a = \\ - 1 - """) - line_finder = self._logical_finder(code) - self.assertEqual((5, 6), line_finder.logical_line_in(6)) - - -def test_problems_with_inner_indentations2(self): - code = dedent("""\ - if True: - if True: - pass - a = 1 - """) - line_finder = self._logical_finder(code) - self.assertEqual((4, 4), line_finder.logical_line_in(4)) - - -def test_logical_lines_for_else(self): - code = dedent("""\ - if True: - pass - else: - pass - """) - line_finder = self._logical_finder(code) - self.assertEqual((3, 3), line_finder.logical_line_in(3)) - - -def test_logical_lines_for_lines_with_wrong_continues(self): - code = "var = 1 + \\" - line_finder = self._logical_finder(code) - self.assertEqual((1, 1), line_finder.logical_line_in(1)) - - -def test_logical_lines_for_multiline_string_with_extra_quotes_front(self): - code = '""""Docs."""\na = 1\n' - line_finder = self._logical_finder(code) - self.assertEqual((2, 2), line_finder.logical_line_in(2)) - - -def test_logical_lines_for_multiline_string_with_escaped_quotes(self): - code = '"""Quotes \\""" "\\"" \' """\na = 1\n' - line_finder = self._logical_finder(code) - self.assertEqual((2, 2), line_finder.logical_line_in(2)) - - -def test_generating_line_starts(self): - code = dedent("""\ - a = 1 - a = 2 - - a = 3 - """) - line_finder = self._logical_finder(code) - self.assertEqual([1, 2, 4], list(line_finder.generate_starts())) - - -def test_generating_line_starts2(self): - code = "a = 1\na = 2\n\na = \\ 3\n" - line_finder = self._logical_finder(code) - self.assertEqual([2, 4], list(line_finder.generate_starts(2))) - - -def test_generating_line_starts3(self): - code = "a = 1\na = 2\n\na = \\ 3\n" - line_finder = self._logical_finder(code) - self.assertEqual([2], list(line_finder.generate_starts(2, 3))) - - -def generate_modules_cache( - self, - modules: List[str] = None, - task_handle: taskhandle.BaseTaskHandle = taskhandle.NullTaskHandle(), - single_thread: bool = False, - underlined: Optional[bool] = None, -): - """ - Generate global name cache for external modules listed in `modules`. - - If no modules are provided, it will generate a cache for every module available. - This method searches in your sys.path and configured python folders. - Do not use this for generating your own project's internal names, - use generate_resource_cache for that instead. - """ - underlined = self.underlined if underlined is None else underlined - - packages: List[Package] = ( - self._get_available_packages() - if modules is None - else list(self._get_packages_from_modules(modules)) - ) - - existing = self._get_packages_from_cache() - packages = list(filter_packages(packages, underlined, existing)) - if len(packages) == 0: - return - self._add_packages(packages) - job_set = task_handle.create_jobset("Generating autoimport cache", 0) - if single_thread: - for package in packages: - for module in get_files(package, underlined): - job_set.started_job(module.modname) - for name in get_names(module, package): - self._add_name(name) - job_set.finished_job() - else: - for future_name in as_completed( - get_future_names(packages, underlined, job_set) - ): - self._add_names(future_name.result()) - job_set.finished_job() - - self.connection.commit() - - -def test_generating_line_starts_for_multi_line_statements(self): - code = "\na = \\\n 1 + \\\n 1\n" - line_finder = self._logical_finder(code) - self.assertEqual([2], list(line_finder.generate_starts())) - - -def test_generating_line_starts_and_unmatched_deindents(self): - code = dedent("""\ - if True: - if True: - if True: - a = 1 - b = 1 - """) - line_finder = self._logical_finder(code) - self.assertEqual([4, 5], list(line_finder.generate_starts(4))) - - -def test_false_triple_quoted_string(self): - code = dedent("""\ - def foo(): - a = 0 - p = 'foo''' - - def bar(): - a = 1 - a += 1 - """) - line_finder = self._logical_finder(code) - self.assertEqual([1, 2, 3, 5, 6, 7], list(line_finder.generate_starts())) - self.assertEqual((3, 3), line_finder.logical_line_in(3)) - self.assertEqual([5, 6, 7], list(line_finder.generate_starts(4))) - - - -class TokenizerLogicalLineFinderTest(LogicalLineFinderTest): - def _logical_finder(self, code): - lines = SourceLinesAdapter(code) - return codeanalyze.CachingLogicalLineFinder( - lines, codeanalyze.tokenizer_generator - ) - - - -class CustomLogicalLineFinderTest(LogicalLineFinderTest): - def _logical_finder(self, code): - lines = SourceLinesAdapter(code) - return codeanalyze.CachingLogicalLineFinder(lines, codeanalyze.custom_generator) - -@path C:/Repos/ekr-rope/ropetest/ -import base64 -import hashlib -import hmac -import multiprocessing - -try: - import cPickle as pickle -except ImportError: - import pickle -import socket - -import unittest - - -from rope.base.oi import doa - - -@others -@language python -@tabwidth -4 - -def cve_2014_3539_attacker(data_port, payload): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect(("127.0.0.1", data_port)) - s_file = s.makefile("wb") - s_file.write(payload) - s.close() - - - -class DOATest(unittest.TestCase): - @others - -def try_CVE_2014_3539_exploit(self, receiver, payload): - # Simulated attacker writing to the socket - # Assume the attacker guesses the port correctly; 3037 is used by - # default if it is available. - attacker_proc = multiprocessing.Process( - target=cve_2014_3539_attacker, args=(receiver.data_port, payload) - ) - - attacker_proc.start() - received_objs = list(receiver.receive_data()) - attacker_proc.join() - return received_objs - - -def test_CVE_2014_3539_no_encoding(self): - # Attacker sends pickled data to the receiver socket. - receiver = doa._SocketReceiver() - - payload = pickle.dumps("def foo():\n return 123\n") - received_objs = self.try_CVE_2014_3539_exploit(receiver, payload) - - # Make sure the exploit did not run - self.assertEqual(0, len(received_objs)) - - -def _find_matching_deindent(self, line_number): - indents = _get_line_indents(self.lines[line_number]) - current_line = line_number + 1 - while current_line < len(self.lines): - line = self.lines[current_line] - if not line.strip().startswith("#") and not line.strip() == "": - # HACK: We should have used logical lines here - if _get_line_indents(self.lines[current_line]) <= indents: - return current_line - current_line += 1 - return len(self.lines) - 1 - - -def _get_packages_from_modules(self, modules: List[str]) -> Iterator[Package]: - for modname in modules: - package = self._find_package_path(modname) - if package is None: - continue - yield package - - -def test_CVE_2014_3539_signature_mismatch(self): - # Attacker sends well-formed data with an incorrect signature. - receiver = doa._SocketReceiver() - - pickled_data = pickle.dumps( - "def foo():\n return 123\n", pickle.HIGHEST_PROTOCOL - ) - digest = hmac.new(b"invalid-key", pickled_data, hashlib.sha256).digest() - payload = ( - base64.b64encode(digest) + b":" + base64.b64encode(pickled_data) + b"\n" - ) - received_objs = self.try_CVE_2014_3539_exploit(receiver, payload) - - # Make sure the exploit did not run - self.assertEqual(0, len(received_objs)) - - -def test_CVE_2014_3539_sanity(self): - # Tests that sending valid, signed data on the socket does work. - receiver = doa._SocketReceiver() - - pickled_data = base64.b64encode( - pickle.dumps("def foo():\n return 123\n", pickle.HIGHEST_PROTOCOL) - ) - digest = hmac.new(receiver.key, pickled_data, hashlib.sha256).digest() - payload = base64.b64encode(digest) + b":" + pickled_data + b"\n" - received_objs = self.try_CVE_2014_3539_exploit(receiver, payload) - - # Make sure the exploit did not run - self.assertEqual(1, len(received_objs)) - - -def test_compare_digest_compat(self): - self.assertTrue(doa._compat_compare_digest("", "")) - self.assertTrue(doa._compat_compare_digest("abc", "abc")) - self.assertFalse(doa._compat_compare_digest("abc", "abd")) - self.assertFalse(doa._compat_compare_digest("abc", "abcd")) - -@path C:/Repos/ekr-rope/ropetest/ -import unittest - -import rope.base.history -from rope.base import exceptions -import rope.base.change -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class HistoryTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.history = self.project.history - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_undoing_writes(self): - my_file = self.project.root.create_file("my_file.txt") - my_file.write("text1") - self.history.undo() - self.assertEqual("", my_file.read()) - - -def test_moving_files(self): - my_file = self.project.root.create_file("my_file.txt") - my_file.move("new_file.txt") - self.history.undo() - self.assertEqual("", my_file.read()) - - -def test_moving_files_to_folders(self): - my_file = self.project.root.create_file("my_file.txt") - my_folder = self.project.root.create_folder("my_folder") - my_file.move(my_folder.path) - self.history.undo() - self.assertEqual("", my_file.read()) - - -def update_module(self, module: str): - """Update a module in the cache, or add it if it doesn't exist.""" - self._del_if_exist(module) - self.generate_modules_cache([module]) - - -def test_writing_files_that_does_not_change_contents(self): - my_file = self.project.root.create_file("my_file.txt") - my_file.write("") - self.project.history.undo() - self.assertFalse(my_file.exists()) - - - -class IsolatedHistoryTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.history = rope.base.history.History(self.project) - self.file1 = self.project.root.create_file("file1.txt") - self.file2 = self.project.root.create_file("file2.txt") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_undo(self): - change = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change) - self.assertEqual("1", self.file1.read()) - self.history.undo() - self.assertEqual("", self.file1.read()) - - -def test_tobe_undone(self): - change1 = rope.base.change.ChangeContents(self.file1, "1") - self.assertEqual(None, self.history.tobe_undone) - self.history.do(change1) - self.assertEqual(change1, self.history.tobe_undone) - change2 = rope.base.change.ChangeContents(self.file1, "2") - self.history.do(change2) - self.assertEqual(change2, self.history.tobe_undone) - self.history.undo() - self.assertEqual(change1, self.history.tobe_undone) - - -def test_tobe_redone(self): - change = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change) - self.assertEqual(None, self.history.tobe_redone) - self.history.undo() - self.assertEqual(change, self.history.tobe_redone) - - -def test_undo_limit(self): - history = rope.base.history.History(self.project, maxundos=1) - history.do(rope.base.change.ChangeContents(self.file1, "1")) - history.do(rope.base.change.ChangeContents(self.file1, "2")) - try: - history.undo() - with self.assertRaises(exceptions.HistoryError): - history.undo() - finally: - self.assertEqual("1", self.file1.read()) - - -def test_simple_redo(self): - change = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change) - self.history.undo() - self.history.redo() - self.assertEqual("1", self.file1.read()) - - -def test_simple_re_undo(self): - change = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change) - self.history.undo() - self.history.redo() - self.history.undo() - self.assertEqual("", self.file1.read()) - - -def close(self): - """Close the autoimport database.""" - self.connection.commit() - self.connection.close() - - -def test_multiple_undos(self): - change = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change) - change = rope.base.change.ChangeContents(self.file1, "2") - self.history.do(change) - self.history.undo() - self.assertEqual("1", self.file1.read()) - change = rope.base.change.ChangeContents(self.file1, "3") - self.history.do(change) - self.history.undo() - self.assertEqual("1", self.file1.read()) - self.history.redo() - self.assertEqual("3", self.file1.read()) - - -def test_undo_list_underflow(self): - with self.assertRaises(exceptions.HistoryError): - self.history.undo() - - -def test_redo_list_underflow(self): - with self.assertRaises(exceptions.HistoryError): - self.history.redo() - - -def test_dropping_undone_changes(self): - self.file1.write("1") - with self.assertRaises(exceptions.HistoryError): - self.history.undo(drop=True) - self.history.redo() - - -def test_undoing_choosen_changes(self): - change = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change) - self.history.undo(change) - self.assertEqual("", self.file1.read()) - self.assertFalse(self.history.undo_list) - - -def test_undoing_choosen_changes2(self): - change1 = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change1) - self.history.do(rope.base.change.ChangeContents(self.file1, "2")) - self.history.undo(change1) - self.assertEqual("", self.file1.read()) - self.assertFalse(self.history.undo_list) - - -def test_undoing_choosen_changes_not_undoing_others(self): - change1 = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change1) - self.history.do(rope.base.change.ChangeContents(self.file2, "2")) - self.history.undo(change1) - self.assertEqual("", self.file1.read()) - self.assertEqual("2", self.file2.read()) - - -def test_undoing_writing_after_moving(self): - change1 = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change1) - self.history.do(rope.base.change.MoveResource(self.file1, "file3.txt")) - file3 = self.project.get_resource("file3.txt") - self.history.undo(change1) - self.assertEqual("", self.file1.read()) - self.assertFalse(file3.exists()) - - -def test_undoing_folder_movements_for_undoing_writes_inside_it(self): - folder = self.project.root.create_folder("folder") - file3 = folder.create_file("file3.txt") - change1 = rope.base.change.ChangeContents(file3, "1") - self.history.do(change1) - self.history.do(rope.base.change.MoveResource(folder, "new_folder")) - new_folder = self.project.get_resource("new_folder") - self.history.undo(change1) - self.assertEqual("", file3.read()) - self.assertFalse(new_folder.exists()) - - -def test_undoing_changes_that_depend_on_a_dependant_change(self): - change1 = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change1) - changes = rope.base.change.ChangeSet("2nd change") - changes.add_change(rope.base.change.ChangeContents(self.file1, "2")) - changes.add_change(rope.base.change.ChangeContents(self.file2, "2")) - self.history.do(changes) - self.history.do(rope.base.change.MoveResource(self.file2, "file3.txt")) - file3 = self.project.get_resource("file3.txt") - - self.history.undo(change1) - self.assertEqual("", self.file1.read()) - self.assertEqual("", self.file2.read()) - self.assertFalse(file3.exists()) - - -def get_name_locations(self, name): - """Return a list of ``(resource, lineno)`` tuples.""" - result = [] - modules = self._execute( - models.Name.search_by_name_like.select("module"), (name,) - ).fetchall() - for module in modules: - try: - module_name = module[0] - if module_name.startswith(f"{self.project_package.name}."): - module_name = ".".join(module_name.split(".")) - pymodule = self.project.get_module(module_name) - if name in pymodule: - pyname = pymodule[name] - module, lineno = pyname.get_definition_location() - if module is not None: - resource = module.get_module().get_resource() - if resource is not None and lineno is not None: - result.append((resource, lineno)) - except exceptions.ModuleNotFoundError: - pass - return result - - -def test_undoing_writes_for_undoing_folder_movements_containing_it(self): - folder = self.project.root.create_folder("folder") - old_file = folder.create_file("file3.txt") - change1 = rope.base.change.MoveResource(folder, "new_folder") - self.history.do(change1) - new_file = self.project.get_resource("new_folder/file3.txt") - self.history.do(rope.base.change.ChangeContents(new_file, "1")) - self.history.undo(change1) - self.assertEqual("", old_file.read()) - self.assertFalse(new_file.exists()) - - -def test_undoing_not_available_change(self): - change = rope.base.change.ChangeContents(self.file1, "1") - with self.assertRaises(exceptions.HistoryError): - self.history.undo(change) - - -def test_ignoring_ignored_resources(self): - self.project.set("ignored_resources", ["ignored*"]) - ignored = self.project.get_file("ignored.txt") - change = rope.base.change.CreateResource(ignored) - self.history.do(change) - self.assertTrue(ignored.exists()) - self.assertEqual(0, len(self.history.undo_list)) - - -def test_get_file_undo_list_simple(self): - change = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change) - self.assertEqual({change}, set(self.history.get_file_undo_list(self.file1))) - - -def test_get_file_undo_list_for_moves(self): - change = rope.base.change.MoveResource(self.file1, "file2.txt") - self.history.do(change) - self.assertEqual({change}, set(self.history.get_file_undo_list(self.file1))) - - -# XXX: What happens for moves before the file is created? -def xxx_test_get_file_undo_list_and_moving_its_contining_folder(self): - folder = self.project.root.create_folder("folder") - old_file = folder.create_file("file3.txt") - change1 = rope.base.change.MoveResource(folder, "new_folder") - self.history.do(change1) - self.assertEqual({change1}, set(self.history.get_file_undo_list(old_file))) - - -def test_clearing_redo_list_after_do(self): - change = rope.base.change.ChangeContents(self.file1, "1") - self.history.do(change) - self.history.undo() - self.history.do(change) - self.assertEqual(0, len(self.history.redo_list)) - - -def test_undoing_a_not_yet_performed_change(self): - change = rope.base.change.ChangeContents(self.file1, "1") - str(change) - with self.assertRaises(exceptions.HistoryError): - change.undo() - - -def test_clearing_up_the_history(self): - change1 = rope.base.change.ChangeContents(self.file1, "1") - change2 = rope.base.change.ChangeContents(self.file1, "2") - self.history.do(change1) - self.history.do(change2) - self.history.undo() - self.history.clear() - self.assertEqual(0, len(self.history.undo_list)) - self.assertEqual(0, len(self.history.redo_list)) - - -def test_redoing_choosen_changes_not_undoing_others(self): - change1 = rope.base.change.ChangeContents(self.file1, "1") - change2 = rope.base.change.ChangeContents(self.file2, "2") - self.history.do(change1) - self.history.do(change2) - self.history.undo() - self.history.undo() - redone = self.history.redo(change2) - self.assertEqual([change2], redone) - self.assertEqual("", self.file1.read()) - self.assertEqual("2", self.file2.read()) - - - -def clear_cache(self): - """Clear all entries in global-name cache. - - It might be a good idea to use this function before - regenerating global names. - - """ - self._execute(models.Name.objects.drop_table()) - self._execute(models.Package.objects.drop_table()) - self._setup_db() - self.connection.commit() - - -class SavingHistoryTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.history = rope.base.history.History(self.project) - self.to_data = rope.base.change.ChangeToData() - self.to_change = rope.base.change.DataToChange(self.project) - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_set_saving(self): - data = self.to_data(rope.base.change.ChangeSet("testing")) - change = self.to_change(data) - self.assertEqual("testing", str(change)) - - -def test_simple_change_content_saving(self): - myfile = self.project.get_file("myfile.txt") - myfile.create() - myfile.write("1") - data = self.to_data(rope.base.change.ChangeContents(myfile, "2")) - change = self.to_change(data) - self.history.do(change) - self.assertEqual("2", myfile.read()) - self.history.undo() - self.assertEqual("1", change.old_contents) - - -def test_move_resource_saving(self): - myfile = self.project.root.create_file("myfile.txt") - myfolder = self.project.root.create_folder("myfolder") - data = self.to_data(rope.base.change.MoveResource(myfile, "myfolder")) - change = self.to_change(data) - self.history.do(change) - self.assertFalse(myfile.exists()) - self.assertTrue(myfolder.has_child("myfile.txt")) - self.history.undo() - self.assertTrue(myfile.exists()) - self.assertFalse(myfolder.has_child("myfile.txt")) - - -def test_move_resource_saving_for_folders(self): - myfolder = self.project.root.create_folder("myfolder") - newfolder = self.project.get_folder("newfolder") - change = rope.base.change.MoveResource(myfolder, "newfolder") - self.history.do(change) - - data = self.to_data(change) - change = self.to_change(data) - change.undo() - self.assertTrue(myfolder.exists()) - self.assertFalse(newfolder.exists()) - - -def test_create_file_saving(self): - myfile = self.project.get_file("myfile.txt") - data = self.to_data( - rope.base.change.CreateFile(self.project.root, "myfile.txt") - ) - change = self.to_change(data) - self.history.do(change) - self.assertTrue(myfile.exists()) - self.history.undo() - self.assertFalse(myfile.exists()) - - -def test_create_folder_saving(self): - myfolder = self.project.get_folder("myfolder") - data = self.to_data( - rope.base.change.CreateFolder(self.project.root, "myfolder") - ) - change = self.to_change(data) - self.history.do(change) - self.assertTrue(myfolder.exists()) - self.history.undo() - self.assertFalse(myfolder.exists()) - - -def test_create_resource_saving(self): - myfile = self.project.get_file("myfile.txt") - data = self.to_data(rope.base.change.CreateResource(myfile)) - change = self.to_change(data) - self.history.do(change) - self.assertTrue(myfile.exists()) - self.history.undo() - self.assertFalse(myfile.exists()) - - -def find_insertion_line(self, code): - """Guess at what line the new import should be inserted.""" - match = re.search(r"^(def|class)\s+", code) - if match is not None: - code = code[: match.start()] - try: - pymodule = libutils.get_string_module(self.project, code) - except exceptions.ModuleSyntaxError: - return 1 - testmodname = "__rope_testmodule_rope" - importinfo = importutils.NormalImport(((testmodname, None),)) - module_imports = importutils.get_module_imports(self.project, pymodule) - module_imports.add_import(importinfo) - code = module_imports.get_changed_source() - offset = code.index(testmodname) - lineno = code.count("\n", 0, offset) + 1 - return lineno - - -def test_remove_resource_saving(self): - myfile = self.project.root.create_file("myfile.txt") - data = self.to_data(rope.base.change.RemoveResource(myfile)) - change = self.to_change(data) - self.history.do(change) - self.assertFalse(myfile.exists()) - - -def test_change_set_saving(self): - change = rope.base.change.ChangeSet("testing") - myfile = self.project.get_file("myfile.txt") - change.add_change(rope.base.change.CreateResource(myfile)) - change.add_change(rope.base.change.ChangeContents(myfile, "1")) - - data = self.to_data(change) - change = self.to_change(data) - self.history.do(change) - self.assertEqual("1", myfile.read()) - self.history.undo() - self.assertFalse(myfile.exists()) - - -def test_writing_and_reading_history(self): - history_file = self.project.get_file("history.pickle") # noqa - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") - history.do(rope.base.change.CreateResource(myfile)) - history.write() - - history = rope.base.history.History(self.project) - history.undo() - self.assertFalse(myfile.exists()) - - -def test_writing_and_reading_history2(self): - history_file = self.project.get_file("history.pickle") # noqa - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") - history.do(rope.base.change.CreateResource(myfile)) - history.undo() - history.write() - - history = rope.base.history.History(self.project) - history.redo() - self.assertTrue(myfile.exists()) - -@path C:/Repos/ekr-rope/ropetest/ -import unittest - - -from rope.base.oi import objectdb, memorydb -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -def _do_for_all_dbs(function): - def called(self): - for db in self.dbs: - function(self, db) - - return called - - - -class _MockValidation: - @others - -def is_value_valid(self, value): - return value != -1 - - -def is_more_valid(self, new, old): - return new != -1 - - -def is_file_valid(self, path): - return path != "invalid" - - -def update_resource( - self, resource: Resource, underlined: bool = False, commit: bool = True -): - """Update the cache for global names in `resource`.""" - underlined = underlined if underlined else self.underlined - module = self._resource_to_module(resource, underlined) - self._del_if_exist(module_name=module.modname, commit=False) - for name in get_names(module, self.project_package): - self._add_name(name) - if commit: - self.connection.commit() - - -def is_scope_valid(self, path, key): - return path != "invalid" and key != "invalid" - - - -class _MockFileListObserver: - - log = "" - - @others - -def added(self, path): - self.log += "added %s " % path - - -def removed(self, path): - self.log += "removed %s " % path - - - -class ObjectDBTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - validation = _MockValidation() - self.dbs = [objectdb.ObjectDB(memorydb.MemoryDB(self.project), validation)] - - -def tearDown(self): - for db in self.dbs: - db.write() - testutils.remove_project(self.project) - super().tearDown() - - -@_do_for_all_dbs -def test_simple_per_name(self, db): - db.add_pername("file", "key", "name", 1) - self.assertEqual(1, db.get_pername("file", "key", "name")) - - -@_do_for_all_dbs -def test_simple_per_name_does_not_exist(self, db): - self.assertEqual(None, db.get_pername("file", "key", "name")) - - -@_do_for_all_dbs -def test_simple_per_name_after_syncing(self, db): - db.add_pername("file", "key", "name", 1) - db.write() - self.assertEqual(1, db.get_pername("file", "key", "name")) - - -def _changed(self, resource): - if not resource.is_folder(): - self.update_resource(resource) - - -@_do_for_all_dbs -def test_getting_returned(self, db): - db.add_callinfo("file", "key", (1, 2), 3) - self.assertEqual(3, db.get_returned("file", "key", (1, 2))) - - -@_do_for_all_dbs -def test_getting_returned_when_does_not_match(self, db): - db.add_callinfo("file", "key", (1, 2), 3) - self.assertEqual(None, db.get_returned("file", "key", (1, 1))) - - -@_do_for_all_dbs -def test_getting_call_info(self, db): - db.add_callinfo("file", "key", (1, 2), 3) - - call_infos = list(db.get_callinfos("file", "key")) - self.assertEqual(1, len(call_infos)) - self.assertEqual((1, 2), call_infos[0].get_parameters()) - self.assertEqual(3, call_infos[0].get_returned()) - - -@_do_for_all_dbs -def test_invalid_per_name(self, db): - db.add_pername("file", "key", "name", -1) - self.assertEqual(None, db.get_pername("file", "key", "name")) - - -@_do_for_all_dbs -def test_overwriting_per_name(self, db): - db.add_pername("file", "key", "name", 1) - db.add_pername("file", "key", "name", 2) - self.assertEqual(2, db.get_pername("file", "key", "name")) - - -@_do_for_all_dbs -def test_not_overwriting_with_invalid_per_name(self, db): - db.add_pername("file", "key", "name", 1) - db.add_pername("file", "key", "name", -1) - self.assertEqual(1, db.get_pername("file", "key", "name")) - - -@_do_for_all_dbs -def test_getting_invalid_returned(self, db): - db.add_callinfo("file", "key", (1, 2), -1) - self.assertEqual(None, db.get_returned("file", "key", (1, 2))) - - -@_do_for_all_dbs -def test_not_overwriting_with_invalid_returned(self, db): - db.add_callinfo("file", "key", (1, 2), 3) - db.add_callinfo("file", "key", (1, 2), -1) - self.assertEqual(3, db.get_returned("file", "key", (1, 2))) - - -@_do_for_all_dbs -def test_get_files(self, db): - db.add_callinfo("file1", "key", (1, 2), 3) - db.add_callinfo("file2", "key", (1, 2), 3) - self.assertEqual({"file1", "file2"}, set(db.get_files())) - - -@_do_for_all_dbs -def test_validating_files(self, db): - db.add_callinfo("invalid", "key", (1, 2), 3) - db.validate_files() - self.assertEqual(0, len(db.get_files())) - - -def _moved(self, resource: Resource, newresource: Resource): - if not resource.is_folder(): - modname = self._resource_to_module(resource).modname - self._del_if_exist(modname) - self.update_resource(newresource) - - -@_do_for_all_dbs -def test_validating_file_for_scopes(self, db): - db.add_callinfo("file", "invalid", (1, 2), 3) - db.validate_file("file") - self.assertEqual(1, len(db.get_files())) - self.assertEqual(0, len(list(db.get_callinfos("file", "invalid")))) - - -@_do_for_all_dbs -def test_validating_file_moved(self, db): - db.add_callinfo("file", "key", (1, 2), 3) - - db.file_moved("file", "newfile") - self.assertEqual(1, len(db.get_files())) - self.assertEqual(1, len(list(db.get_callinfos("newfile", "key")))) - - -@_do_for_all_dbs -def test_using_file_list_observer(self, db): - db.add_callinfo("invalid", "key", (1, 2), 3) - observer = _MockFileListObserver() - db.add_file_list_observer(observer) - db.validate_files() - self.assertEqual("removed invalid ", observer.log) - -@path C:/Repos/ekr-rope/ropetest/ -from textwrap import dedent - -import unittest - -import rope.base.project -import rope.base.builtins -from rope.base import libutils -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class ObjectInferTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_type_inferencing(self): - code = dedent("""\ - class Sample(object): - pass - a_var = Sample() - """) - scope = libutils.get_string_scope(self.project, code) - sample_class = scope["Sample"].get_object() - a_var = scope["a_var"].get_object() - self.assertEqual(sample_class, a_var.get_type()) - - -def test_simple_type_inferencing_classes_defined_in_holding_scope(self): - code = dedent("""\ - class Sample(object): - pass - def a_func(): - a_var = Sample() - """) - scope = libutils.get_string_scope(self.project, code) - sample_class = scope["Sample"].get_object() - a_var = scope["a_func"].get_object().get_scope()["a_var"].get_object() - self.assertEqual(sample_class, a_var.get_type()) - - -def test_simple_type_inferencing_classes_in_class_methods(self): - code = dedent("""\ - class Sample(object): - pass - class Another(object): - def a_method(): - a_var = Sample() - """) - scope = libutils.get_string_scope(self.project, code) - sample_class = scope["Sample"].get_object() - another_class = scope["Another"].get_object() - a_var = another_class["a_method"].get_object().get_scope()["a_var"].get_object() - self.assertEqual(sample_class, a_var.get_type()) - - -def _del_if_exist(self, module_name, commit: bool = True): - self._execute(models.Name.delete_by_module_name, (module_name,)) - if commit: - self.connection.commit() - - -def test_simple_type_inferencing_class_attributes(self): - code = dedent("""\ - class Sample(object): - pass - class Another(object): - def __init__(self): - self.a_var = Sample() - """) - scope = libutils.get_string_scope(self.project, code) - sample_class = scope["Sample"].get_object() - another_class = scope["Another"].get_object() - a_var = another_class["a_var"].get_object() - self.assertEqual(sample_class, a_var.get_type()) - - -def test_simple_type_inferencing_for_in_class_assignments(self): - code = dedent("""\ - class Sample(object): - pass - class Another(object): - an_attr = Sample() - """) - scope = libutils.get_string_scope(self.project, code) - sample_class = scope["Sample"].get_object() - another_class = scope["Another"].get_object() - an_attr = another_class["an_attr"].get_object() - self.assertEqual(sample_class, an_attr.get_type()) - - -def test_simple_type_inferencing_for_chained_assignments(self): - mod = dedent("""\ - class Sample(object): - pass - copied_sample = Sample""") - mod_scope = libutils.get_string_scope(self.project, mod) - sample_class = mod_scope["Sample"] - copied_sample = mod_scope["copied_sample"] - self.assertEqual(sample_class.get_object(), copied_sample.get_object()) - - -def test_following_chained_assignments_avoiding_circles(self): - mod = dedent("""\ - class Sample(object): - pass - sample_class = Sample - sample_class = sample_class - """) - mod_scope = libutils.get_string_scope(self.project, mod) - sample_class = mod_scope["Sample"] - sample_class_var = mod_scope["sample_class"] - self.assertEqual(sample_class.get_object(), sample_class_var.get_object()) - - -def test_function_returned_object_static_type_inference1(self): - src = dedent("""\ - class Sample(object): - pass - def a_func(): - return Sample - a_var = a_func() - """) - scope = libutils.get_string_scope(self.project, src) - sample_class = scope["Sample"] - a_var = scope["a_var"] - self.assertEqual(sample_class.get_object(), a_var.get_object()) - - -def test_function_returned_object_static_type_inference2(self): - src = dedent("""\ - class Sample(object): - pass - def a_func(): - return Sample() - a_var = a_func() - """) - scope = libutils.get_string_scope(self.project, src) - sample_class = scope["Sample"].get_object() - a_var = scope["a_var"].get_object() - self.assertEqual(sample_class, a_var.get_type()) - - -def test_recursive_function_returned_object_static_type_inference(self): - src = dedent("""\ - class Sample(object): - pass - def a_func(): - if True: - return Sample() - else: - return a_func() - a_var = a_func() - """) - scope = libutils.get_string_scope(self.project, src) - sample_class = scope["Sample"].get_object() - a_var = scope["a_var"].get_object() - self.assertEqual(sample_class, a_var.get_type()) - - -def test_func_returned_obj_using_call_spec_func_static_type_infer(self): - src = dedent("""\ - class Sample(object): - def __call__(self): - return Sample - sample = Sample() - a_var = sample()""") - scope = libutils.get_string_scope(self.project, src) - sample_class = scope["Sample"] - a_var = scope["a_var"] - self.assertEqual(sample_class.get_object(), a_var.get_object()) - - -def test_list_type_inferencing(self): - src = dedent("""\ - class Sample(object): - pass - a_var = [Sample()] - """) - scope = libutils.get_string_scope(self.project, src) - sample_class = scope["Sample"].get_object() - a_var = scope["a_var"].get_object() - self.assertNotEqual(sample_class, a_var.get_type()) - - -def test_attributed_object_inference(self): - src = dedent("""\ - class Sample(object): - def __init__(self): - self.a_var = None - def set(self): - self.a_var = Sample() - """) - scope = libutils.get_string_scope(self.project, src) - sample_class = scope["Sample"].get_object() - a_var = sample_class["a_var"].get_object() - self.assertEqual(sample_class, a_var.get_type()) - - -def _set(self, lineno, line): - self.diffs[self.origs[lineno]] += len(line) - len(self.lines[lineno]) - self.lines[lineno] = line - - -def _get_python_folders(self) -> List[Path]: - def filter_folders(folder: Path) -> bool: - return folder.is_dir() and folder.as_posix() != "/usr/bin" - - folders = self.project.get_python_path_folders() - folder_paths = map(lambda folder: Path(folder.real_path), folders) - folder_paths = filter(filter_folders, folder_paths) - return list(OrderedDict.fromkeys(folder_paths)) - - -def test_getting_property_attributes(self): - src = dedent("""\ - class A(object): - pass - def f(*args): - return A() - class B(object): - p = property(f) - a_var = B().p - """) - pymod = libutils.get_string_module(self.project, src) - a_class = pymod["A"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(a_class, a_var.get_type()) - - -def test_getting_property_attributes_with_method_getters(self): - src = dedent("""\ - class A(object): - pass - class B(object): - def p_get(self): - return A() - p = property(p_get) - a_var = B().p - """) - pymod = libutils.get_string_module(self.project, src) - a_class = pymod["A"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(a_class, a_var.get_type()) - - -def test_lambda_functions(self): - code = dedent("""\ - class C(object): - pass - l = lambda: C() - a_var = l()""") - mod = libutils.get_string_module(self.project, code) - c_class = mod["C"].get_object() - a_var = mod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_mixing_subscript_with_tuple_assigns(self): - code = dedent("""\ - class C(object): - attr = 0 - d = {} - d[0], b = (0, C()) - """) - mod = libutils.get_string_module(self.project, code) - c_class = mod["C"].get_object() - a_var = mod["b"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_mixing_ass_attr_with_tuple_assignment(self): - code = dedent("""\ - class C(object): - attr = 0 - c = C() - c.attr, b = (0, C()) - """) - mod = libutils.get_string_module(self.project, code) - c_class = mod["C"].get_object() - a_var = mod["b"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_mixing_slice_with_tuple_assigns(self): - code = dedent("""\ - class C(object): - attr = 0 - d = [None] * 3 - d[0:2], b = ((0,), C()) - """) - mod = libutils.get_string_module(self.project, code) - - c_class = mod["C"].get_object() - a_var = mod["b"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_nested_tuple_assignments(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - a, (b, c) = (C1(), (C2(), C1())) - """) - mod = libutils.get_string_module(self.project, code) - - c1_class = mod["C1"].get_object() - c2_class = mod["C2"].get_object() - a_var = mod["a"].get_object() - b_var = mod["b"].get_object() - c_var = mod["c"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - self.assertEqual(c1_class, c_var.get_type()) - - -def test_empty_tuples(self): - code = dedent("""\ - t = () - a, b = t - """) - mod = libutils.get_string_module(self.project, code) - - a = mod["a"].get_object() # noqa - - -def test_handling_generator_functions(self): - code = dedent("""\ - class C(object): - pass - def f(): - yield C() - for c in f(): - a_var = c - """) - mod = libutils.get_string_module(self.project, code) - c_class = mod["C"].get_object() - a_var = mod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_handling_generator_functions_for_strs(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - def f(): - yield "" - for s in f(): - a_var = s - """)) - pymod = self.project.get_pymodule(mod) - a_var = pymod["a_var"].get_object() - self.assertTrue(isinstance(a_var.get_type(), rope.base.builtins.Str)) - - -def _get_available_packages(self) -> List[Package]: - packages: List[Package] = [ - Package(module, Source.BUILTIN, None, PackageType.BUILTIN) - for module in sys.builtin_module_names - ] - for folder in self._get_python_folders(): - for package in folder.iterdir(): - package_tuple = get_package_tuple(package, self.project) - if package_tuple is None: - continue - packages.append(package_tuple) - return packages - - -def test_considering_nones_to_be_unknowns(self): - code = dedent("""\ - class C(object): - pass - a_var = None - a_var = C() - a_var = None - """) - mod = libutils.get_string_module(self.project, code) - c_class = mod["C"].get_object() - a_var = mod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_basic_list_comprehensions(self): - code = dedent("""\ - class C(object): - pass - l = [C() for i in range(1)] - a_var = l[0] - """) - mod = libutils.get_string_module(self.project, code) - c_class = mod["C"].get_object() - a_var = mod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_basic_generator_expressions(self): - code = dedent("""\ - class C(object): - pass - l = (C() for i in range(1)) - a_var = list(l)[0] - """) - mod = libutils.get_string_module(self.project, code) - c_class = mod["C"].get_object() - a_var = mod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_list_comprehensions_and_loop_var(self): - code = dedent("""\ - class C(object): - pass - c_objects = [C(), C()] - l = [c for c in c_objects] - a_var = l[0] - """) - mod = libutils.get_string_module(self.project, code) - c_class = mod["C"].get_object() - a_var = mod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_list_comprehensions_and_multiple_loop_var(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - l = [(c1, c2) for c1 in [C1()] for c2 in [C2()]] - a, b = l[0] - """) - mod = libutils.get_string_module(self.project, code) - c1_class = mod["C1"].get_object() - c2_class = mod["C2"].get_object() - a_var = mod["a"].get_object() - b_var = mod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_list_comprehensions_and_multiple_iters(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - l = [(c1, c2) for c1, c2 in [(C1(), C2())]] - a, b = l[0] - """) - mod = libutils.get_string_module(self.project, code) - - c1_class = mod["C1"].get_object() - c2_class = mod["C2"].get_object() - a_var = mod["a"].get_object() - b_var = mod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_we_know_the_type_of_catched_exceptions(self): - code = dedent("""\ - class MyError(Exception): - pass - try: - raise MyError() - except MyError as e: - pass - """) - mod = libutils.get_string_module(self.project, code) - my_error = mod["MyError"].get_object() - e_var = mod["e"].get_object() - self.assertEqual(my_error, e_var.get_type()) - - -def test_we_know_the_type_of_catched_multiple_excepts(self): - code = dedent("""\ - class MyError(Exception): - pass - try: - raise MyError() - except (MyError, Exception) as e: - pass - """) - mod = libutils.get_string_module(self.project, code) - my_error = mod["MyError"].get_object() - e_var = mod["e"].get_object() - self.assertEqual(my_error, e_var.get_type()) - - -def test_using_property_as_decorators(self): - code = dedent("""\ - class A(object): - pass - class B(object): - @property - def f(self): - return A() - b = B() - var = b.f - """) - mod = libutils.get_string_module(self.project, code) - var = mod["var"].get_object() - a = mod["A"].get_object() - self.assertEqual(a, var.get_type()) - - -def test_using_property_as_decorators_and_passing_parameter(self): - code = dedent("""\ - class B(object): - @property - def f(self): - return self - b = B() - var = b.f - """) - mod = libutils.get_string_module(self.project, code) - var = mod["var"].get_object() - a = mod["B"].get_object() - self.assertEqual(a, var.get_type()) - -def _add_packages(self, packages: List[Package]): - data = [(p.name, str(p.path)) for p in packages] - self._executemany(models.Package.objects.insert_into(), data) - - -@path C:/Repos/ekr-rope/ropetest/ -import os.path -import shutil -from textwrap import dedent - -import pytest - -from rope.base.exceptions import RopeError, ResourceNotFoundError -from rope.base.fscommands import FileSystemCommands -from rope.base.libutils import path_to_resource -from rope.base.project import Project, NoProject, _realpath -from rope.base.resourceobserver import FilteredResourceObserver -from ropetest import testutils - - -import unittest - - -@others -@language python -@tabwidth -4 - -class ProjectTest(unittest.TestCase): - @others - -def setUp(self): - unittest.TestCase.setUp(self) - self.project = testutils.sample_project( - foldername="sampleproject", ropefolder=None - ) - self.project_root = self.project.address - self._make_sample_project() - self.no_project = NoProject() - - -def _make_sample_project(self): - self.sample_file = "sample_file.txt" - self.sample_path = os.path.join(self.project_root, "sample_file.txt") - if not os.path.exists(self.project_root): - os.mkdir(self.project_root) - self.sample_folder = "sample_folder" - os.mkdir(os.path.join(self.project_root, self.sample_folder)) - sample = open(self.sample_path, "w") - sample.write("sample text\n") - sample.close() - - -def tearDown(self): - testutils.remove_project(self.project) - unittest.TestCase.tearDown(self) - - -def test_project_creation(self): - self.assertEqual(_realpath(self.project_root), self.project.address) - - -def test_getting_project_file(self): - project_file = self.project.get_resource(self.sample_file) - self.assertTrue(project_file is not None) - - -def test_project_file_reading(self): - projectFile = self.project.get_resource(self.sample_file) - self.assertEqual("sample text\n", projectFile.read()) - - -def test_getting_not_existing_project_file(self): - with self.assertRaises(ResourceNotFoundError): - self.project.get_resource("DoesNotExistFile.txt") - - -def test_writing_in_project_files(self): - project_file = self.project.get_resource(self.sample_file) - project_file.write("another text\n") - self.assertEqual("another text\n", project_file.read()) - - -def _get_packages_from_cache(self) -> List[str]: - existing: List[str] = list( - chain(*self._execute(models.Package.objects.select_star()).fetchall()) - ) - existing.append(self.project_package.name) - return existing - - -def test_creating_files(self): - project_file = "newfile.txt" - self.project.root.create_file(project_file) - newFile = self.project.get_resource(project_file) - self.assertTrue(newFile is not None) - - -def test_creating_files_that_already_exist(self): - with self.assertRaises(RopeError): - self.project.root.create_file(self.sample_file) - - -def test_making_root_folder_if_it_does_not_exist(self): - project = Project("sampleproject2") - try: - self.assertTrue( - os.path.exists("sampleproject2") and os.path.isdir("sampleproject2") - ) - finally: - testutils.remove_project(project) - - -def test_failure_when_project_root_exists_and_is_a_file(self): - project_root = "sampleproject2" - try: - open(project_root, "w").close() - with self.assertRaises(RopeError): - Project(project_root) - finally: - testutils.remove_recursively(project_root) - - -def test_creating_folders(self): - folderName = "SampleFolder" - self.project.root.create_folder(folderName) - folderPath = os.path.join(self.project.address, folderName) - self.assertTrue(os.path.exists(folderPath) and os.path.isdir(folderPath)) - - -def test_making_folder_that_already_exists(self): - folderName = "SampleFolder" - with self.assertRaises(RopeError): - self.project.root.create_folder(folderName) - self.project.root.create_folder(folderName) - - -def test_failing_if_creating_folder_while_file_already_exists(self): - folderName = "SampleFolder" - with self.assertRaises(RopeError): - self.project.root.create_file(folderName) - self.project.root.create_folder(folderName) - - -def test_creating_file_inside_folder(self): - folder_name = "sampleFolder" - file_name = "sample2.txt" - file_path = folder_name + "/" + file_name - parent_folder = self.project.root.create_folder(folder_name) - parent_folder.create_file(file_name) - file = self.project.get_resource(file_path) - file.write("sample notes") - self.assertEqual(file_path, file.path) - self.assertEqual( - "sample notes", open(os.path.join(self.project.address, file_path)).read() - ) - - -def test_failing_when_creating_file_inside_non_existent_folder(self): - with self.assertRaises(ResourceNotFoundError): - self.project.root.create_file("NonexistentFolder/SomeFile.txt") - - -def test_nested_directories(self): - folder_name = "SampleFolder" - parent = self.project.root.create_folder(folder_name) - parent.create_folder(folder_name) - folder_path = os.path.join(self.project.address, folder_name, folder_name) - self.assertTrue(os.path.exists(folder_path) and os.path.isdir(folder_path)) - - -def _removed(self, resource): - if not resource.is_folder(): - modname = self._resource_to_module(resource).modname - self._del_if_exist(modname) - - -def test_removing_files(self): - self.assertTrue(os.path.exists(self.sample_path)) - self.project.get_resource(self.sample_file).remove() - self.assertFalse(os.path.exists(self.sample_path)) - - -def test_removing_files_invalidating_in_project_resource_pool(self): - root_folder = self.project.root - my_file = root_folder.create_file("my_file.txt") - my_file.remove() - self.assertFalse(root_folder.has_child("my_file.txt")) - - -def test_removing_directories(self): - self.assertTrue( - os.path.exists(os.path.join(self.project.address, self.sample_folder)) - ) - self.project.get_resource(self.sample_folder).remove() - self.assertFalse( - os.path.exists(os.path.join(self.project.address, self.sample_folder)) - ) - - -def test_removing_non_existent_files(self): - with self.assertRaises(ResourceNotFoundError): - self.project.get_resource("NonExistentFile.txt").remove() - - -def test_removing_nested_files(self): - file_name = self.sample_folder + "/sample_file.txt" - self.project.root.create_file(file_name) - self.project.get_resource(file_name).remove() - self.assertTrue( - os.path.exists(os.path.join(self.project.address, self.sample_folder)) - ) - self.assertTrue( - not os.path.exists(os.path.join(self.project.address, file_name)) - ) - - -def test_file_get_name(self): - file = self.project.get_resource(self.sample_file) - self.assertEqual(self.sample_file, file.name) - file_name = "nestedFile.txt" - parent = self.project.get_resource(self.sample_folder) - filePath = self.sample_folder + "/" + file_name - parent.create_file(file_name) - nestedFile = self.project.get_resource(filePath) - self.assertEqual(file_name, nestedFile.name) - - -def test_folder_get_name(self): - folder = self.project.get_resource(self.sample_folder) - self.assertEqual(self.sample_folder, folder.name) - - -def test_file_get_path(self): - file = self.project.get_resource(self.sample_file) - self.assertEqual(self.sample_file, file.path) - fileName = "nestedFile.txt" - parent = self.project.get_resource(self.sample_folder) - filePath = self.sample_folder + "/" + fileName - parent.create_file(fileName) - nestedFile = self.project.get_resource(filePath) - self.assertEqual(filePath, nestedFile.path) - - -def test_folder_get_path(self): - folder = self.project.get_resource(self.sample_folder) - self.assertEqual(self.sample_folder, folder.path) - - -def test_is_folder(self): - self.assertTrue(self.project.get_resource(self.sample_folder).is_folder()) - self.assertTrue(not self.project.get_resource(self.sample_file).is_folder()) - - -def _add_future_names(self, names: Future): - self._add_names(names.result()) - - -def testget_children(self): - children = self.project.get_resource(self.sample_folder).get_children() - self.assertEqual([], children) - - -def test_nonempty_get_children(self): - file_name = "nestedfile.txt" - filePath = self.sample_folder + "/" + file_name - parent = self.project.get_resource(self.sample_folder) - parent.create_file(file_name) - children = parent.get_children() - self.assertEqual(1, len(children)) - self.assertEqual(filePath, children[0].path) - - -def test_nonempty_get_children2(self): - file_name = "nestedfile.txt" - folder_name = "nestedfolder.txt" - filePath = self.sample_folder + "/" + file_name - folderPath = self.sample_folder + "/" + folder_name - parent = self.project.get_resource(self.sample_folder) - parent.create_file(file_name) - parent.create_folder(folder_name) - children = parent.get_children() - self.assertEqual(2, len(children)) - self.assertTrue(filePath == children[0].path or filePath == children[1].path) - self.assertTrue( - folderPath == children[0].path or folderPath == children[1].path - ) - - -def test_does_not_fail_for_permission_denied(self): - bad_dir = os.path.join(self.sample_folder, "bad_dir") - os.makedirs(bad_dir) - self.addCleanup(shutil.rmtree, bad_dir) - os.chmod(bad_dir, 0o000) - try: - parent = self.project.get_resource(self.sample_folder) - - parent.get_children() - - finally: - os.chmod(bad_dir, 0o755) - - -def test_getting_files(self): - files = self.project.root.get_files() - self.assertEqual(1, len(files)) - self.assertTrue(self.project.get_resource(self.sample_file) in files) - - -def test_getting_folders(self): - folders = self.project.root.get_folders() - self.assertEqual(1, len(folders)) - self.assertTrue(self.project.get_resource(self.sample_folder) in folders) - - -def test_nested_folder_get_files(self): - parent = self.project.root.create_folder("top") - parent.create_file("file1.txt") - parent.create_file("file2.txt") - files = parent.get_files() - self.assertEqual(2, len(files)) - self.assertTrue(self.project.get_resource("top/file2.txt") in files) - self.assertEqual(0, len(parent.get_folders())) - - -def test_nested_folder_get_folders(self): - parent = self.project.root.create_folder("top") - parent.create_folder("dir1") - parent.create_folder("dir2") - folders = parent.get_folders() - self.assertEqual(2, len(folders)) - self.assertTrue(self.project.get_resource("top/dir1") in folders) - self.assertEqual(0, len(parent.get_files())) - - -def test_root_folder(self): - root_folder = self.project.root - self.assertEqual(2, len(root_folder.get_children())) - self.assertEqual("", root_folder.path) - self.assertEqual("", root_folder.name) - - -def test_get_all_files(self): - files = tuple(self.project.get_files()) - self.assertEqual(1, len(files)) - self.assertEqual(self.sample_file, files[0].name) - - -@staticmethod -def _convert_name(name: Name) -> tuple: - return ( - name.name, - name.modname, - name.package, - name.source.value, - name.name_type.value, - ) - - -def test_get_all_files_after_changing(self): - self.assertEqual(1, len(self.project.get_files())) - myfile = self.project.root.create_file("myfile.txt") - self.assertEqual(2, len(self.project.get_files())) - myfile.move("newfile.txt") - self.assertEqual(2, len(self.project.get_files())) - self.project.get_file("newfile.txt").remove() - self.assertEqual(1, len(self.project.get_files())) - - -def test_multifile_get_all_files(self): - fileName = "nestedFile.txt" - parent = self.project.get_resource(self.sample_folder) - parent.create_file(fileName) - files = list(self.project.get_files()) - self.assertEqual(2, len(files)) - self.assertTrue(fileName == files[0].name or fileName == files[1].name) - - -def test_ignoring_dot_pyc_files_in_get_files(self): - root = self.project.address - src_folder = os.path.join(root, "src") - os.mkdir(src_folder) - test_pyc = os.path.join(src_folder, "test.pyc") - open(test_pyc, "w").close() - for x in self.project.get_files(): - self.assertNotEqual("src/test.pyc", x.path) - - -def test_folder_creating_files(self): - projectFile = "NewFile.txt" - self.project.root.create_file(projectFile) - new_file = self.project.get_resource(projectFile) - self.assertTrue(new_file is not None and not new_file.is_folder()) - - -def test_folder_creating_nested_files(self): - project_file = "NewFile.txt" - parent_folder = self.project.get_resource(self.sample_folder) - parent_folder.create_file(project_file) - new_file = self.project.get_resource(self.sample_folder + "/" + project_file) - self.assertTrue(new_file is not None and not new_file.is_folder()) - - -def test_folder_creating_files2(self): - projectFile = "newfolder" - self.project.root.create_folder(projectFile) - new_folder = self.project.get_resource(projectFile) - self.assertTrue(new_folder is not None and new_folder.is_folder()) - - -def test_folder_creating_nested_files2(self): - project_file = "newfolder" - parent_folder = self.project.get_resource(self.sample_folder) - parent_folder.create_folder(project_file) - new_folder = self.project.get_resource(self.sample_folder + "/" + project_file) - self.assertTrue(new_folder is not None and new_folder.is_folder()) - - -def test_folder_get_child(self): - folder = self.project.root - folder.create_file("myfile.txt") - folder.create_folder("myfolder") - self.assertEqual( - self.project.get_resource("myfile.txt"), folder.get_child("myfile.txt") - ) - self.assertEqual( - self.project.get_resource("myfolder"), folder.get_child("myfolder") - ) - - -def test_folder_get_child_nested(self): - root = self.project.root - folder = root.create_folder("myfolder") - folder.create_file("myfile.txt") - folder.create_folder("myfolder") - self.assertEqual( - self.project.get_resource("myfolder/myfile.txt"), - folder.get_child("myfile.txt"), - ) - self.assertEqual( - self.project.get_resource("myfolder/myfolder"), folder.get_child("myfolder") - ) - - -def test_project_root_is_root_folder(self): - self.assertEqual("", self.project.root.path) - - -def _add_names(self, names: Iterable[Name]): - if names is not None: - self._executemany( - models.Name.objects.insert_into(), - [self._convert_name(name) for name in names], - ) - - -def test_moving_files(self): - root_folder = self.project.root - my_file = root_folder.create_file("my_file.txt") - my_file.move("my_other_file.txt") - self.assertFalse(my_file.exists()) - root_folder.get_child("my_other_file.txt") - - -def test_moving_folders(self): - root_folder = self.project.root - my_folder = root_folder.create_folder("my_folder") - my_file = my_folder.create_file("my_file.txt") - my_folder.move("new_folder") - self.assertFalse(root_folder.has_child("my_folder")) - self.assertFalse(my_file.exists()) - self.assertTrue(root_folder.get_child("new_folder") is not None) - - -def test_moving_destination_folders(self): - root_folder = self.project.root - my_folder = root_folder.create_folder("my_folder") - my_file = root_folder.create_file("my_file.txt") - my_file.move("my_folder") - self.assertFalse(root_folder.has_child("my_file.txt")) - self.assertFalse(my_file.exists()) - my_folder.get_child("my_file.txt") - - -def test_moving_files_and_resource_objects(self): - root_folder = self.project.root - my_file = root_folder.create_file("my_file.txt") - old_hash = hash(my_file) - my_file.move("my_other_file.txt") - self.assertEqual(old_hash, hash(my_file)) - - -def test_file_encoding_reading(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = ( - b"# -*- coding: utf-8 -*-\n" - + br"#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" - ).decode("utf8") - file = open(sample_file.real_path, "wb") - file.write(contents.encode("utf-8")) - file.close() - self.assertEqual(contents, sample_file.read()) - - -def test_file_encoding_writing(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = ( - b"# -*- coding: utf-8 -*-\n" + br"\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" - ).decode("utf8") - sample_file.write(contents) - self.assertEqual(contents, sample_file.read()) - - -def test_using_utf8_when_writing_in_case_of_errors(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = br"\n\N{LATIN SMALL LETTER I WITH DIAERESIS}\n".decode("utf8") - sample_file.write(contents) - self.assertEqual(contents, sample_file.read()) - - -def test_encoding_declaration_in_the_second_line(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"\n# -*- coding: latin-1 -*-\n\xa9\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertEqual(contents, sample_file.read().encode("latin-1")) - - -def test_not_an_encoding_declaration(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"def my_method(self, encoding='latin-1'):\n var = {}\n\xc2\xa9\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertEqual(contents, sample_file.read().encode("utf-8")) - self.assertNotEqual(contents, sample_file.read().encode("latin-1")) - - -def test_read_bytes(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"\n# -*- coding: latin-1 -*-\n\xa9\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertEqual(contents, sample_file.read_bytes()) - - -def _add_name(self, name: Name): - self._execute(models.Name.objects.insert_into(), self._convert_name(name)) - - -def test_file_with_unix_line_ending(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"1\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertIsNone(sample_file.newlines) - self.assertEqual("1\n", sample_file.read()) - self.assertEqual("\n", sample_file.newlines) - - sample_file.write("1\n") - self.assertEqual(b"1\n", sample_file.read_bytes()) - - -def test_file_with_dos_line_ending(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"1\r\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertIsNone(sample_file.newlines) - self.assertEqual("1\n", sample_file.read()) - self.assertEqual("\r\n", sample_file.newlines) - - sample_file.write("1\n") - self.assertEqual(b"1\r\n", sample_file.read_bytes()) - - -def test_file_with_mac_line_ending(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"1\r" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertIsNone(sample_file.newlines) - self.assertEqual("1\n", sample_file.read()) - self.assertEqual("\r", sample_file.newlines) - - sample_file.write("1\n") - self.assertEqual(b"1\r", sample_file.read_bytes()) - - -def test_file_binary(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"1\r\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertIsNone(sample_file.newlines) - self.assertEqual(b"1\r\n", sample_file.read_bytes()) - self.assertIsNone(sample_file.newlines) - - sample_file.write(b"1\nx\r") - self.assertEqual((b"1\nx\r"), sample_file.read_bytes()) - - -# TODO: Detecting utf-16 encoding -def xxx_test_using_utf16(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"# -*- coding: utf-16 -*-\n# This is a sample file ...\n" - file = open(sample_file.real_path, "w") - file.write(contents.encode("utf-16")) - file.close() - sample_file.write(contents) - self.assertEqual(contents, sample_file.read()) - - -# XXX: supporting utf_8_sig -def xxx_test_file_encoding_reading_for_notepad_styles(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = "#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" - file = open(sample_file.real_path, "w") - # file.write('\xef\xbb\xbf') - file.write(contents.encode("utf-8-sig")) - file.close() - self.assertEqual(contents, sample_file.read()) - - -def test_using_project_get_file(self): - myfile = self.project.get_file(self.sample_file) - self.assertTrue(myfile.exists()) - - -def test_using_file_create(self): - myfile = self.project.get_file("myfile.txt") - self.assertFalse(myfile.exists()) - myfile.create() - self.assertTrue(myfile.exists()) - self.assertFalse(myfile.is_folder()) - - -def test_using_folder_create(self): - myfolder = self.project.get_folder("myfolder") - self.assertFalse(myfolder.exists()) - myfolder.create() - self.assertTrue(myfolder.exists()) - self.assertTrue(myfolder.is_folder()) - - -def test_exception_when_creating_twice(self): - with self.assertRaises(RopeError): - myfile = self.project.get_file("myfile.txt") - myfile.create() - myfile.create() - - -def _find_package_path(self, target_name: str) -> Optional[Package]: - if target_name in sys.builtin_module_names: - return Package(target_name, Source.BUILTIN, None, PackageType.BUILTIN) - for folder in self._get_python_folders(): - for package in folder.iterdir(): - package_tuple = get_package_tuple(package, self.project) - if package_tuple is None: - continue - name, source, package_path, package_type = package_tuple - if name == target_name: - return package_tuple - - return None - - -def test_exception_when_parent_does_not_exist(self): - with self.assertRaises(ResourceNotFoundError): - myfile = self.project.get_file("myfolder/myfile.txt") - myfile.create() - - -def test_simple_path_to_resource(self): - myfile = self.project.root.create_file("myfile.txt") - self.assertEqual(myfile, path_to_resource(self.project, myfile.real_path)) - self.assertEqual( - myfile, path_to_resource(self.project, myfile.real_path, type="file") - ) - myfolder = self.project.root.create_folder("myfolder") - self.assertEqual(myfolder, path_to_resource(self.project, myfolder.real_path)) - self.assertEqual( - myfolder, path_to_resource(self.project, myfolder.real_path, type="folder") - ) - - -@testutils.skipNotPOSIX() -def test_ignoring_symlinks_inside_project(self): - project2 = testutils.sample_project(folder_name="sampleproject2") - mod = project2.root.create_file("mod.py") - try: - path = os.path.join(self.project.address, "linkedfile.txt") - os.symlink(mod.real_path, path) - files = self.project.root.get_files() - self.assertEqual(1, len(files)) - finally: - testutils.remove_project(project2) - - -def test_getting_empty_source_folders(self): - self.assertEqual([], self.project.get_source_folders()) - - -def test_root_source_folder(self): - self.project.root.create_file("sample.py") - source_folders = self.project.get_source_folders() - self.assertEqual(1, len(source_folders)) - self.assertTrue(self.project.root in source_folders) - - -def test_root_source_folder2(self): - self.project.root.create_file("mod1.py") - self.project.root.create_file("mod2.py") - source_folders = self.project.get_source_folders() - self.assertEqual(1, len(source_folders)) - self.assertTrue(self.project.root in source_folders) - - -def test_src_source_folder(self): - src = self.project.root.create_folder("src") - src.create_file("sample.py") - source_folders = self.project.get_source_folders() - self.assertEqual(1, len(source_folders)) - self.assertTrue(self.project.get_resource("src") in source_folders) - - -def test_packages(self): - src = self.project.root.create_folder("src") - pkg = src.create_folder("package") - pkg.create_file("__init__.py") - source_folders = self.project.get_source_folders() - self.assertEqual(1, len(source_folders)) - self.assertTrue(src in source_folders) - - -def test_multi_source_folders(self): - src = self.project.root.create_folder("src") - package = src.create_folder("package") - package.create_file("__init__.py") - test = self.project.root.create_folder("test") - test.create_file("alltests.py") - source_folders = self.project.get_source_folders() - self.assertEqual(2, len(source_folders)) - self.assertTrue(src in source_folders) - self.assertTrue(test in source_folders) - - -def test_multi_source_folders2(self): - testutils.create_module(self.project, "mod1") - src = self.project.root.create_folder("src") - package = testutils.create_package(self.project, "package", src) - testutils.create_module(self.project, "mod2", package) - source_folders = self.project.get_source_folders() - self.assertEqual(2, len(source_folders)) - self.assertTrue(self.project.root in source_folders and src in source_folders) - - - -def _insert(self, lineno, line): - self.diffs[self.origs[lineno]] += len(line) + 1 - self.origs.insert(lineno, self.origs[lineno]) - self.lines.insert(lineno, line) - - - -def _resource_to_module( - self, resource: Resource, underlined: bool = False -) -> ModuleFile: - assert self.project_package.path - underlined = underlined if underlined else self.underlined - resource_path: Path = Path(resource.real_path) - # The project doesn't need its name added to the path, - # since the standard python file layout accounts for that - # so we set add_package_name to False - resource_modname: str = get_modname_from_path( - resource_path, self.project_package.path, add_package_name=False - ) - return ModuleFile( - resource_path, - resource_modname, - underlined, - resource_path.name == "__init__.py", - ) - - -class ResourceObserverTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_resource_change_observer(self): - sample_file = self.project.root.create_file("my_file.txt") - sample_file.write("a sample file version 1") - sample_observer = _SampleObserver() - self.project.add_observer(sample_observer) - sample_file.write("a sample file version 2") - self.assertEqual(1, sample_observer.change_count) - self.assertEqual(sample_file, sample_observer.last_changed) - - -def test_resource_change_observer_after_removal(self): - sample_file = self.project.root.create_file("my_file.txt") - sample_file.write("text") - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [sample_file]) - ) - sample_file.remove() - self.assertEqual(1, sample_observer.change_count) - self.assertEqual(sample_file, sample_observer.last_removed) - - -def test_resource_change_observer2(self): - sample_file = self.project.root.create_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(sample_observer) - self.project.remove_observer(sample_observer) - sample_file.write("a sample file version 2") - self.assertEqual(0, sample_observer.change_count) - - -def test_resource_change_observer_for_folders(self): - root_folder = self.project.root - my_folder = root_folder.create_folder("my_folder") - my_folder_observer = _SampleObserver() - root_folder_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(my_folder_observer, [my_folder]) - ) - self.project.add_observer( - FilteredResourceObserver(root_folder_observer, [root_folder]) - ) - my_file = my_folder.create_file("my_file.txt") - self.assertEqual(1, my_folder_observer.change_count) - my_file.move("another_file.txt") - self.assertEqual(2, my_folder_observer.change_count) - self.assertEqual(1, root_folder_observer.change_count) - self.project.get_resource("another_file.txt").remove() - self.assertEqual(2, my_folder_observer.change_count) - self.assertEqual(2, root_folder_observer.change_count) - - -def test_resource_change_observer_after_moving(self): - sample_file = self.project.root.create_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(sample_observer) - sample_file.move("new_file.txt") - self.assertEqual(1, sample_observer.change_count) - self.assertEqual( - (sample_file, self.project.get_resource("new_file.txt")), - sample_observer.last_moved, - ) - - -def test_revalidating_files(self): - root = self.project.root - my_file = root.create_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) - os.remove(my_file.real_path) - self.project.validate(root) - self.assertEqual(my_file, sample_observer.last_removed) - self.assertEqual(1, sample_observer.change_count) - - -def test_revalidating_files_and_no_changes2(self): - root = self.project.root - my_file = root.create_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) - self.project.validate(root) - self.assertEqual(None, sample_observer.last_moved) - self.assertEqual(0, sample_observer.change_count) - - -def _execute(self, query: models.FinalQuery, *args, **kwargs): - assert isinstance(query, models.FinalQuery) - return self.connection.execute(query._query, *args, **kwargs) - - -def test_revalidating_folders(self): - root = self.project.root - my_folder = root.create_folder("myfolder") - my_file = my_folder.create_file("myfile.txt") # noqa - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [my_folder]) - ) - testutils.remove_recursively(my_folder.real_path) - self.project.validate(root) - self.assertEqual(my_folder, sample_observer.last_removed) - self.assertEqual(1, sample_observer.change_count) - - -def test_removing_and_adding_resources_to_filtered_observer(self): - my_file = self.project.root.create_file("my_file.txt") - sample_observer = _SampleObserver() - filtered_observer = FilteredResourceObserver(sample_observer) - self.project.add_observer(filtered_observer) - my_file.write("1") - self.assertEqual(0, sample_observer.change_count) - filtered_observer.add_resource(my_file) - my_file.write("2") - self.assertEqual(1, sample_observer.change_count) - filtered_observer.remove_resource(my_file) - my_file.write("3") - self.assertEqual(1, sample_observer.change_count) - - -def test_validation_and_changing_files(self): - my_file = self.project.root.create_file("my_file.txt") - sample_observer = _SampleObserver() - timekeeper = _MockChangeIndicator() - filtered_observer = FilteredResourceObserver( - sample_observer, [my_file], timekeeper=timekeeper - ) - self.project.add_observer(filtered_observer) - self._write_file(my_file.real_path) - timekeeper.set_indicator(my_file, 1) - self.project.validate(self.project.root) - self.assertEqual(1, sample_observer.change_count) - - -def test_validation_and_changing_files2(self): - my_file = self.project.root.create_file("my_file.txt") - sample_observer = _SampleObserver() - timekeeper = _MockChangeIndicator() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [my_file], timekeeper=timekeeper) - ) - timekeeper.set_indicator(my_file, 1) - my_file.write("hey") - self.assertEqual(1, sample_observer.change_count) - self.project.validate(self.project.root) - self.assertEqual(1, sample_observer.change_count) - - -def test_not_reporting_multiple_changes_to_folders(self): - root = self.project.root - file1 = root.create_file("file1.txt") - file2 = root.create_file("file2.txt") - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [root, file1, file2]) - ) - os.remove(file1.real_path) - os.remove(file2.real_path) - self.assertEqual(0, sample_observer.change_count) - self.project.validate(self.project.root) - self.assertEqual(3, sample_observer.change_count) - - -def _write_file(self, path): - my_file = open(path, "w") - my_file.write("\n") - my_file.close() - - -def test_moving_and_being_interested_about_a_folder_and_a_child(self): - my_folder = self.project.root.create_folder("my_folder") - my_file = my_folder.create_file("my_file.txt") - sample_observer = _SampleObserver() - filtered_observer = FilteredResourceObserver( - sample_observer, [my_folder, my_file] - ) - self.project.add_observer(filtered_observer) - my_folder.move("new_folder") - self.assertEqual(2, sample_observer.change_count) - - -def test_contains_for_folders(self): - folder1 = self.project.root.create_folder("folder") - folder2 = self.project.root.create_folder("folder2") - self.assertFalse(folder1.contains(folder2)) - - -def test_validating_when_created(self): - root = self.project.root - my_file = self.project.get_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) - open(my_file.real_path, "w").close() - self.project.validate(root) - self.assertEqual(my_file, sample_observer.last_created) - self.assertEqual(1, sample_observer.change_count) - - -def test_validating_twice_when_created(self): - root = self.project.root - my_file = self.project.get_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) - open(my_file.real_path, "w").close() - self.project.validate(root) - self.project.validate(root) - self.assertEqual(my_file, sample_observer.last_created) - self.assertEqual(1, sample_observer.change_count) - - -def _executemany(self, query: models.FinalQuery, *args, **kwargs): - assert isinstance(query, models.FinalQuery) - return self.connection.executemany(query._query, *args, **kwargs) - -def test_changes_and_adding_resources(self): - root = self.project.root # noqa - file1 = self.project.get_file("file1.txt") - file2 = self.project.get_file("file2.txt") - file1.create() - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [file1, file2]) - ) - file1.move(file2.path) - self.assertEqual(2, sample_observer.change_count) - self.assertEqual(file2, sample_observer.last_created) - self.assertEqual((file1, file2), sample_observer.last_moved) - - -def test_validating_get_files_list(self): - root = self.project.root # noqa - self.assertEqual(0, len(self.project.get_files())) - file = open(os.path.join(self.project.address, "myfile.txt"), "w") - file.close() - self.project.validate() - self.assertEqual(1, len(self.project.get_files())) - - -def test_clear_observered_resources_for_filtered_observers(self): - sample_file = self.project.root.create_file("myfile.txt") - sample_observer = _SampleObserver() - filtered = FilteredResourceObserver(sample_observer) - self.project.add_observer(filtered) - filtered.add_resource(sample_file) - filtered.clear_resources() - sample_file.write("1") - self.assertEqual(0, sample_observer.change_count) - - - -class _MockChangeIndicator: - @others - -def __init__(self): - self.times = {} - - -def set_indicator(self, resource, time): - self.times[resource] = time - - -def get_indicator(self, resource): - return self.times.get(resource, 0) - - - -class _SampleObserver: - @others - -def __init__(self): - self.change_count = 0 - self.last_changed = None - self.last_moved = None - self.last_created = None - self.last_removed = None - - -def resource_changed(self, resource): - self.last_changed = resource - self.change_count += 1 - - -@path C:/Repos/ekr-rope/rope/contrib/autoimport/ -"""Utility functions for the autoimport code.""" -import pathlib -import sys -from collections import OrderedDict -from typing import Generator, List, Optional, Tuple - -from rope.base.project import Project - -from .defs import ModuleCompiled, ModuleFile, ModuleInfo, Package, PackageType, Source - - -@others -@language python -@tabwidth -4 - -def resource_moved(self, resource, new_resource): - self.last_moved = (resource, new_resource) - self.change_count += 1 - - -def resource_created(self, resource): - self.last_created = resource - self.change_count += 1 - - -def resource_removed(self, resource): - self.last_removed = resource - self.change_count += 1 - - - -class OutOfProjectTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.test_directory = "temp_test_directory" - testutils.remove_recursively(self.test_directory) - os.mkdir(self.test_directory) - self.project = testutils.sample_project() - self.no_project = NoProject() - - -def tearDown(self): - testutils.remove_project(self.project) - testutils.remove_recursively(self.test_directory) - super().tearDown() - - -def test_simple_out_of_project_file(self): - sample_file_path = os.path.join(self.test_directory, "sample.txt") - sample_file = open(sample_file_path, "w") - sample_file.write("sample content\n") - sample_file.close() - sample_resource = self.no_project.get_resource(sample_file_path) - self.assertEqual("sample content\n", sample_resource.read()) - - -def test_simple_out_of_project_folder(self): - sample_folder_path = os.path.join(self.test_directory, "sample_folder") - os.mkdir(sample_folder_path) - sample_folder = self.no_project.get_resource(sample_folder_path) - self.assertEqual([], sample_folder.get_children()) - - sample_file_path = os.path.join(sample_folder_path, "sample.txt") - open(sample_file_path, "w").close() - sample_resource = self.no_project.get_resource(sample_file_path) - self.assertEqual(sample_resource, sample_folder.get_children()[0]) - - -def test_using_absolute_path(self): - sample_file_path = os.path.join(self.test_directory, "sample.txt") - open(sample_file_path, "w").close() - normal_sample_resource = self.no_project.get_resource(sample_file_path) - absolute_sample_resource = self.no_project.get_resource( - os.path.abspath(sample_file_path) - ) - self.assertEqual(normal_sample_resource, absolute_sample_resource) - - -def test_folder_get_child(self): - sample_folder_path = os.path.join(self.test_directory, "sample_folder") - os.mkdir(sample_folder_path) - sample_folder = self.no_project.get_resource(sample_folder_path) - self.assertEqual([], sample_folder.get_children()) - - sample_file_path = os.path.join(sample_folder_path, "sample.txt") - open(sample_file_path, "w").close() - sample_resource = self.no_project.get_resource(sample_file_path) - self.assertTrue(sample_folder.has_child("sample.txt")) - self.assertFalse(sample_folder.has_child("doesnothave.txt")) - self.assertEqual(sample_resource, sample_folder.get_child("sample.txt")) - - -def get_package_tuple( - package_path: pathlib.Path, project: Optional[Project] = None -) -> Optional[Package]: - """ - Get package name and type from a path. - - Checks for common issues, such as not being a viable python module - Returns None if not a viable package. - """ - package_name = package_path.name - package_type: PackageType - if package_name.startswith(".") or package_name == "__pycache__": - return None - if package_name.endswith((".egg-info", ".dist-info")): - return None - if package_path.is_file(): - if package_name.endswith(".so"): - package_name = package_name.split(".")[0] - package_type = PackageType.COMPILED - elif package_name.endswith(".pyd"): - package_name = package_name.split(".")[0] - package_type = PackageType.COMPILED - elif package_name.endswith(".py"): - package_name = package_path.stem - package_type = PackageType.SINGLE_FILE - else: - return None - else: - package_type = PackageType.STANDARD - package_source: Source = get_package_source(package_path, project, package_name) - return Package(package_name, package_source, package_path, package_type) - - - -def test_out_of_project_files_and_path_to_resource(self): - sample_file_path = os.path.join(self.test_directory, "sample.txt") - sample_file = open(sample_file_path, "w") - sample_file.write("sample content\n") - sample_file.close() - sample_resource = self.no_project.get_resource(sample_file_path) - self.assertEqual( - sample_resource, path_to_resource(self.project, sample_file_path) - ) - - - -class _MockFSCommands: - @others - -def __init__(self): - self.log = "" - self.fscommands = FileSystemCommands() - - -def create_file(self, path): - self.log += "create_file " - self.fscommands.create_file(path) - - -def create_folder(self, path): - self.log += "create_folder " - self.fscommands.create_folder(path) - - -def move(self, path, new_location): - self.log += "move " - self.fscommands.move(path, new_location) - - -def remove(self, path): - self.log += "remove " - self.fscommands.remove(path) - - -def read(self, path): - self.log += "read " - return self.fscommands.read(path) - - - -class _DeprecatedFSCommands: - @others - -def __init__(self): - self.log = "" - self.fscommands = FileSystemCommands() - - -def get_package_source( - package: pathlib.Path, project: Optional[Project], name: str -) -> Source: - """Detect the source of a given package. Rudimentary implementation.""" - if name in sys.builtin_module_names: - return Source.BUILTIN - if project is not None and project.address in str(package): - return Source.PROJECT - if "site-packages" in package.parts: - return Source.SITE_PACKAGE - if sys.version_info < (3, 10, 0): - if str(package).startswith(sys.prefix): - return Source.STANDARD - else: - if name in sys.stdlib_module_names: - return Source.STANDARD - return Source.UNKNOWN - - - -def create_file(self, path): - self.log += "create_file " - self.fscommands.create_file(path) - - -def create_folder(self, path): - self.log += "create_folder " - self.fscommands.create_folder(path) - - -def move(self, path, new_location): - self.log += "move " - self.fscommands.move(path, new_location) - - -def remove(self, path): - self.log += "remove " - self.fscommands.remove(path) - - - -class RopeFolderTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = None - - -def tearDown(self): - if self.project: - testutils.remove_project(self.project) - super().tearDown() - - -def test_none_project_rope_folder(self): - self.project = testutils.sample_project(ropefolder=None) - self.assertTrue(self.project.ropefolder is None) - - -def test_getting_project_rope_folder(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - self.assertTrue(self.project.ropefolder.exists()) - self.assertTrue(".ropeproject", self.project.ropefolder.path) - - -def test_setting_ignored_resources(self): - self.project = testutils.sample_project(ignored_resources=["myfile.txt"]) - myfile = self.project.get_file("myfile.txt") - file2 = self.project.get_file("file2.txt") - self.assertTrue(self.project.is_ignored(myfile)) - self.assertFalse(self.project.is_ignored(file2)) - - -def get_modname_from_path( - modpath: pathlib.Path, package_path: pathlib.Path, add_package_name: bool = True -) -> str: - """Get module name from a path in respect to package.""" - package_name: str = package_path.stem - rel_path_parts = modpath.relative_to(package_path).parts - modname = "" - if len(rel_path_parts) > 0: - for part in rel_path_parts[:-1]: - modname += part - modname += "." - if rel_path_parts[-1] == "__init__": - modname = modname[:-1] - else: - modname = modname + modpath.stem - if add_package_name: - modname = package_name if modname == "" else package_name + "." + modname - else: - assert modname != "." - return modname - - - -def test_ignored_folders(self): - self.project = testutils.sample_project(ignored_resources=["myfolder"]) - myfolder = self.project.root.create_folder("myfolder") - self.assertTrue(self.project.is_ignored(myfolder)) - myfile = myfolder.create_file("myfile.txt") - self.assertTrue(self.project.is_ignored(myfile)) - - -def test_ignored_resources_and_get_files(self): - self.project = testutils.sample_project( - ignored_resources=["myfile.txt"], ropefolder=None - ) - myfile = self.project.get_file("myfile.txt") - self.assertEqual(0, len(self.project.get_files())) - myfile.create() - self.assertEqual(0, len(self.project.get_files())) - - -def test_ignored_resources_and_get_files2(self): - self.project = testutils.sample_project( - ignored_resources=["myfile.txt"], ropefolder=None - ) - myfile = self.project.root.create_file("myfile.txt") # noqa - self.assertEqual(0, len(self.project.get_files())) - - -def test_setting_ignored_resources_patterns(self): - self.project = testutils.sample_project(ignored_resources=["m?file.*"]) - myfile = self.project.get_file("myfile.txt") - file2 = self.project.get_file("file2.txt") - self.assertTrue(self.project.is_ignored(myfile)) - self.assertFalse(self.project.is_ignored(file2)) - - -def test_star_should_not_include_slashes(self): - self.project = testutils.sample_project(ignored_resources=["f*.txt"]) - folder = self.project.root.create_folder("folder") - file1 = folder.create_file("myfile.txt") - file2 = folder.create_file("file2.txt") - self.assertFalse(self.project.is_ignored(file1)) - self.assertTrue(self.project.is_ignored(file2)) - - -def test_normal_fscommands(self): - fscommands = _MockFSCommands() - self.project = testutils.sample_project(fscommands=fscommands) - myfile = self.project.get_file("myfile.txt") - myfile.create() - self.assertTrue("create_file ", fscommands.log) - - -def test_fscommands_and_ignored_resources(self): - fscommands = _MockFSCommands() - self.project = testutils.sample_project( - fscommands=fscommands, ignored_resources=["myfile.txt"], ropefolder=None - ) - myfile = self.project.get_file("myfile.txt") - myfile.create() - self.assertEqual("", fscommands.log) - - -def test_deprecated_fscommands(self): - fscommands = _DeprecatedFSCommands() - self.project = testutils.sample_project(fscommands=fscommands) - myfile = self.project.get_file("myfile.txt") - myfile.create() - self.assertTrue("create_file ", fscommands.log) - - -def test_ignored_resources_and_prefixes(self): - self.project = testutils.sample_project(ignored_resources=[".hg"]) - myfile = self.project.root.create_file(".hgignore") - self.assertFalse(self.project.is_ignored(myfile)) - - -def test_loading_config_dot_py(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - config = self.project.get_file(".ropeproject/config.py") - if not config.exists(): - config.create() - config.write(dedent("""\ - def set_prefs(prefs): - prefs["ignored_resources"] = ["myfile.txt"] - def project_opened(project): - project.root.create_file("loaded") - """)) - self.project.close() - self.project = Project(self.project.address, ropefolder=".ropeproject") - self.assertTrue(self.project.get_file("loaded").exists()) - myfile = self.project.get_file("myfile.txt") - self.assertTrue(self.project.is_ignored(myfile)) - - -def sort_and_deduplicate(results: List[Tuple[str, int]]) -> List[str]: - """Sort and deduplicate a list of name, source entries.""" - results = sorted(results, key=lambda y: y[-1]) - results_sorted = [name for name, source in results] - return list(OrderedDict.fromkeys(results_sorted)) - - - -def test_loading_pyproject(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - config = self.project.get_file("pyproject.toml") - if not config.exists(): - config.create() - config.write(dedent("""\ - [tool.rope] - ignored_resources=["pyproject.py"] - """)) - self.project.close() - self.project = Project(self.project.address, ropefolder=".ropeproject") - myfile = self.project.get_file("pyproject.py") - self.assertTrue(self.project.is_ignored(myfile)) - - -def test_loading_pyproject_empty_file(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - config = self.project.get_file("pyproject.toml") - if not config.exists(): - config.create() - config.write("") - self.project.close() - self.project = Project(self.project.address, ropefolder=".ropeproject") - myfile = self.project.get_file("pyproject.py") - self.assertFalse(self.project.is_ignored(myfile)) - - -def test_loading_pyproject_no_tool_section(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - config = self.project.get_file("pyproject.toml") - if not config.exists(): - config.create() - config.write(dedent("""\ - [project] - name = 'testproject' - """)) - self.project.close() - self.project = Project(self.project.address, ropefolder=".ropeproject") - myfile = self.project.get_file("pyproject.py") - self.assertFalse(self.project.is_ignored(myfile)) - - -def test_loading_pyproject_no_tool_rope_section(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - config = self.project.get_file("pyproject.toml") - if not config.exists(): - config.create() - config.write(dedent("""\ - [tool.anothertool] - name = 'testproject' - """)) - self.project.close() - self.project = Project(self.project.address, ropefolder=".ropeproject") - myfile = self.project.get_file("pyproject.py") - self.assertFalse(self.project.is_ignored(myfile)) - - -def test_ignoring_syntax_errors(self): - self.project = testutils.sample_project( - ropefolder=None, ignore_syntax_errors=True - ) - mod = testutils.create_module(self.project, "mod") - mod.write("xyz print") - pymod = self.project.get_pymodule(mod) # noqa - - -def test_compressed_history(self): - self.project = testutils.sample_project(compress_history=True) - mod = testutils.create_module(self.project, "mod") - mod.write("") - - -def test_compressed_objectdb(self): - self.project = testutils.sample_project(compress_objectdb=True) - mod = testutils.create_module(self.project, "mod") - self.project.pycore.analyze_module(mod) - - -def test_nested_dot_ropeproject_folder(self): - self.project = testutils.sample_project(ropefolder=".f1/f2") - ropefolder = self.project.ropefolder - self.assertEqual(".f1/f2", ropefolder.path) - self.assertTrue(ropefolder.exists()) - -@path C:/Repos/ekr-rope/ropetest/ -import sys -from textwrap import dedent - -from rope.base.builtins import File, BuiltinClass - -import unittest - -from rope.base import exceptions -from rope.base import libutils -from rope.base.pycore import _TextChangeDetector -from rope.base.pyobjects import get_base_type, AbstractFunction -from rope.base.pynamesdef import AssignedName -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class PyCoreTest(unittest.TestCase): - @others - -def sort_and_deduplicate_tuple( - results: List[Tuple[str, str, int]] -) -> List[Tuple[str, str]]: - """Sort and deduplicate a list of name, module, source entries.""" - results = sorted(results, key=lambda y: y[-1]) - results_sorted = [result[:-1] for result in results] - return list(OrderedDict.fromkeys(results_sorted)) - - - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_module(self): - testutils.create_module(self.project, "mod") - result = self.project.get_module("mod") - self.assertEqual(get_base_type("Module"), result.type) - self.assertEqual(0, len(result.get_attributes())) - - -def test_nested_modules(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) # noqa - package = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), package.get_type()) - self.assertEqual(1, len(package.get_attributes())) - module = package["mod"].get_object() - self.assertEqual(get_base_type("Module"), module.get_type()) - - -def test_package(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) # noqa - result = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), result.type) - - -def test_simple_class(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - class SampleClass(object): - pass - """)) - mod_element = self.project.get_module("mod") - result = mod_element["SampleClass"].get_object() - self.assertEqual(get_base_type("Type"), result.get_type()) - - -def test_simple_function(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - def sample_function(): - pass - """)) - mod_element = self.project.get_module("mod") - result = mod_element["sample_function"].get_object() - self.assertEqual(get_base_type("Function"), result.get_type()) - - -def test_class_methods(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class SampleClass(object): - def sample_method(self): - pass - """) - mod.write(code) - mod_element = self.project.get_module("mod") - sample_class = mod_element["SampleClass"].get_object() - self.assertTrue("sample_method" in sample_class) - method = sample_class["sample_method"].get_object() - self.assertEqual(get_base_type("Function"), method.get_type()) - - -def test_global_variable_without_type_annotation(self): - mod = testutils.create_module(self.project, "mod") - mod.write("var = 10") - mod_element = self.project.get_module("mod") - var = mod_element["var"] - self.assertEqual(AssignedName, type(var)) - - -@testutils.only_for_versions_higher("3.6") -def test_global_variable_with_type_annotation(self): - mod = testutils.create_module(self.project, "mod") - mod.write("py3_var: str = foo_bar") - mod_element = self.project.get_module("mod") - py3_var = mod_element["py3_var"] - self.assertEqual(AssignedName, type(py3_var)) - - -def should_parse(path: pathlib.Path, underlined: bool) -> bool: - if underlined: - return True - for part in path.parts: - if part.startswith("_"): - return False - return True - - - -def test_class_variables(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - class SampleClass(object): - var = 10 - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["SampleClass"].get_object() - var = sample_class["var"] # noqa - - -def test_class_attributes_set_in_init(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - class C(object): - def __init__(self): - self.var = 20 - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["C"].get_object() - var = sample_class["var"] # noqa - - -def test_class_attributes_set_in_init_overwriting_a_defined(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - def __init__(self): - self.f = 20 - def f(): - pass - """) - mod.write(code) - mod_element = self.project.get_module("mod") - sample_class = mod_element["C"].get_object() - f = sample_class["f"].get_object() - self.assertTrue(isinstance(f, AbstractFunction)) - - -def test_classes_inside_other_classes(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class SampleClass(object): - class InnerClass(object): - pass - - """) - mod.write(code) - mod_element = self.project.get_module("mod") - sample_class = mod_element["SampleClass"].get_object() - var = sample_class["InnerClass"].get_object() - self.assertEqual(get_base_type("Type"), var.get_type()) - - -def test_non_existent_module(self): - with self.assertRaises(exceptions.ModuleNotFoundError): - self.project.get_module("doesnotexistmodule") - - -def test_imported_names(self): - testutils.create_module(self.project, "mod1") - mod = testutils.create_module(self.project, "mod2") - mod.write("import mod1\n") - module = self.project.get_module("mod2") - imported_sys = module["mod1"].get_object() - self.assertEqual(get_base_type("Module"), imported_sys.get_type()) - - -def test_imported_as_names(self): - testutils.create_module(self.project, "mod1") - mod = testutils.create_module(self.project, "mod2") - mod.write("import mod1 as my_import\n") - module = self.project.get_module("mod2") - imported_mod = module["my_import"].get_object() - self.assertEqual(get_base_type("Module"), imported_mod.get_type()) - - -def test_get_string_module(self): - code = dedent("""\ - class Sample(object): - pass - """) - mod = libutils.get_string_module(self.project, code) - sample_class = mod["Sample"].get_object() - self.assertEqual(get_base_type("Type"), sample_class.get_type()) - - -def test_get_string_module_with_extra_spaces(self): - code = "a = 10\n " - mod = libutils.get_string_module(self.project, code) # noqa - - -def test_parameter_info_for_functions(self): - code = dedent("""\ - def func(param1, param2=10, *param3, **param4): - pass""") - mod = libutils.get_string_module(self.project, code) - sample_function = mod["func"] - self.assertEqual( - ["param1", "param2", "param3", "param4"], - sample_function.get_object().get_param_names(), - ) - - -def _logical_start(lines, lineno, check_prev=False): - logical_finder = LogicalLineFinder(ArrayLinesAdapter(lines)) - if check_prev: - prev = lineno - 1 - while prev > 0: - start, end = logical_finder.logical_line_in(prev) - if end is None or start <= lineno < end: - return start - if start <= prev: - break - prev -= 1 - return logical_finder.logical_line_in(lineno)[0] - - - -def get_files( - package: Package, underlined: bool = False -) -> Generator[ModuleInfo, None, None]: - """Find all files to parse in a given path using __init__.py.""" - if package.type in (PackageType.COMPILED, PackageType.BUILTIN): - if package.source in (Source.STANDARD, Source.BUILTIN): - yield ModuleCompiled(None, package.name, underlined, True) - elif package.type == PackageType.SINGLE_FILE: - assert package.path - assert package.path.suffix == ".py" - yield ModuleFile(package.path, package.path.stem, underlined, False) - else: - assert package.path - for file in package.path.glob("*.py"): - if file.name == "__init__.py": - yield ModuleFile( - file, - get_modname_from_path(file.parent, package.path), - underlined, - True, - ) - elif should_parse(file, underlined): - yield ModuleFile( - file, get_modname_from_path(file, package.path), underlined, False - ) - -# FIXME: Not found modules -def xxx_test_not_found_module_is_module(self): - code = "import doesnotexist\n" - mod = libutils.get_string_module(self.project, code) - self.assertEqual( - get_base_type("Module"), mod["doesnotexist"].get_object().get_type() - ) - - -def test_mixing_scopes_and_objects_hierarchy(self): - code = "var = 200\n" - mod = libutils.get_string_module(self.project, code) - scope = mod.get_scope() - self.assertTrue("var" in scope.get_names()) - - -def test_inheriting_base_class_attributes(self): - code = dedent("""\ - class Base(object): - def method(self): - pass - class Derived(Base): - pass - """) - mod = libutils.get_string_module(self.project, code) - derived = mod["Derived"].get_object() - self.assertTrue("method" in derived) - self.assertEqual( - get_base_type("Function"), derived["method"].get_object().get_type() - ) - - -def test_inheriting_multiple_base_class_attributes(self): - code = dedent("""\ - class Base1(object): - def method1(self): - pass - class Base2(object): - def method2(self): - pass - class Derived(Base1, Base2): - pass - """) - mod = libutils.get_string_module(self.project, code) - derived = mod["Derived"].get_object() - self.assertTrue("method1" in derived) - self.assertTrue("method2" in derived) - - -def test_inherit_multiple_base_class_attrs_with_the_same_name(self): - code = dedent("""\ - class Base1(object): - def method(self): - pass - class Base2(object): - def method(self): - pass - class Derived(Base1, Base2): - pass - """) - mod = libutils.get_string_module(self.project, code) - base1 = mod["Base1"].get_object() - derived = mod["Derived"].get_object() - self.assertEqual(base1["method"].get_object(), derived["method"].get_object()) - - -def test_inheriting_unknown_base_class(self): - code = dedent("""\ - class Derived(NotFound): - def f(self): - pass - """) - mod = libutils.get_string_module(self.project, code) - derived = mod["Derived"].get_object() - self.assertTrue("f" in derived) - - -def test_module_creation(self): - new_module = testutils.create_module(self.project, "module") - self.assertFalse(new_module.is_folder()) - self.assertEqual(self.project.get_resource("module.py"), new_module) - - -def test_packaged_module_creation(self): - package = self.project.root.create_folder("package") # noqa - new_module = testutils.create_module(self.project, "package.module") - self.assertEqual(self.project.get_resource("package/module.py"), new_module) - - -def test_packaged_module_creation_with_nested_src(self): - src = self.project.root.create_folder("src") - src.create_folder("pkg") - new_module = testutils.create_module(self.project, "pkg.mod", src) - self.assertEqual(self.project.get_resource("src/pkg/mod.py"), new_module) - - -def test_package_creation(self): - new_package = testutils.create_package(self.project, "pkg") - self.assertTrue(new_package.is_folder()) - self.assertEqual(self.project.get_resource("pkg"), new_package) - self.assertEqual( - self.project.get_resource("pkg/__init__.py"), - new_package.get_child("__init__.py"), - ) - - -@path C:/Repos/ekr-rope/rope/contrib/autoimport/ -"""AutoImport module for rope.""" -from .pickle import AutoImport as _PickleAutoImport -from .sqlite import AutoImport as _SqliteAutoImport - - -AutoImport = _PickleAutoImport - -__all__ = ["AutoImport"] -@language python -@tabwidth -4 - -def test_nested_package_creation(self): - testutils.create_package(self.project, "pkg1") - nested_package = testutils.create_package(self.project, "pkg1.pkg2") - self.assertEqual(self.project.get_resource("pkg1/pkg2"), nested_package) - - -def test_packaged_package_creation_with_nested_src(self): - src = self.project.root.create_folder("src") - testutils.create_package(self.project, "pkg1", src) - nested_package = testutils.create_package(self.project, "pkg1.pkg2", src) - self.assertEqual(self.project.get_resource("src/pkg1/pkg2"), nested_package) - - -def test_find_module(self): - src = self.project.root.create_folder("src") - samplemod = testutils.create_module(self.project, "samplemod", src) - found_module = self.project.find_module("samplemod") - self.assertEqual(samplemod, found_module) - - -def test_find_nested_module(self): - src = self.project.root.create_folder("src") - samplepkg = testutils.create_package(self.project, "samplepkg", src) - samplemod = testutils.create_module(self.project, "samplemod", samplepkg) - found_module = self.project.find_module("samplepkg.samplemod") - self.assertEqual(samplemod, found_module) - - -def test_find_multiple_module(self): - src = self.project.root.create_folder("src") - samplemod1 = testutils.create_module(self.project, "samplemod", src) - samplemod2 = testutils.create_module(self.project, "samplemod") - test = self.project.root.create_folder("test") - samplemod3 = testutils.create_module(self.project, "samplemod", test) - found_module = self.project.find_module("samplemod") - self.assertTrue( - samplemod1 == found_module - or samplemod2 == found_module - or samplemod3 == found_module - ) - - -def test_find_module_packages(self): - src = self.project.root - samplepkg = testutils.create_package(self.project, "samplepkg", src) - found_module = self.project.find_module("samplepkg") - self.assertEqual(samplepkg, found_module) - - -def test_find_module_when_module_and_package_with_the_same_name(self): - src = self.project.root - testutils.create_module(self.project, "sample", src) - samplepkg = testutils.create_package(self.project, "sample", src) - found_module = self.project.find_module("sample") - self.assertEqual(samplepkg, found_module) - - -def test_source_folders_preference(self): - testutils.create_package(self.project, "pkg1") - testutils.create_package(self.project, "pkg1.src2") - lost = testutils.create_module(self.project, "pkg1.src2.lost") - self.assertEqual(self.project.find_module("lost"), None) - self.project.close() - from rope.base.project import Project - - self.project = Project(self.project.address, source_folders=["pkg1/src2"]) - self.assertEqual(self.project.find_module("lost"), lost) - - -def test_get_pyname_definition_location(self): - code = "a_var = 20\n" - mod = libutils.get_string_module(self.project, code) - a_var = mod["a_var"] - self.assertEqual((mod, 1), a_var.get_definition_location()) - - -def test_get_pyname_definition_location_functions(self): - code = dedent("""\ - def a_func(): - pass - """) - mod = libutils.get_string_module(self.project, code) - a_func = mod["a_func"] - self.assertEqual((mod, 1), a_func.get_definition_location()) - - - -def test_get_pyname_definition_location_class(self): - code = dedent("""\ - class AClass(object): - pass - - """) - mod = libutils.get_string_module(self.project, code) - a_class = mod["AClass"] - self.assertEqual((mod, 1), a_class.get_definition_location()) - - -def test_get_pyname_definition_location_local_variables(self): - code = dedent("""\ - def a_func(): - a_var = 10 - """) - mod = libutils.get_string_module(self.project, code) - a_func_scope = mod.get_scope().get_scopes()[0] - a_var = a_func_scope["a_var"] - self.assertEqual((mod, 2), a_var.get_definition_location()) - - -def test_get_pyname_definition_location_reassigning(self): - code = dedent("""\ - a_var = 20 - a_var=30 - """) - mod = libutils.get_string_module(self.project, code) - a_var = mod["a_var"] - self.assertEqual((mod, 1), a_var.get_definition_location()) - - -def test_get_pyname_definition_location_importes(self): - testutils.create_module(self.project, "mod") - code = "import mod\n" - mod = libutils.get_string_module(self.project, code) - imported_module = self.project.get_module("mod") - module_pyname = mod["mod"] - self.assertEqual((imported_module, 1), module_pyname.get_definition_location()) - - -def test_get_pyname_definition_location_imports(self): - module_resource = testutils.create_module(self.project, "mod") - module_resource.write(dedent("""\ - - def a_func(): - pass - """)) - imported_module = self.project.get_module("mod") - code = dedent("""\ - from mod import a_func - """) - mod = libutils.get_string_module(self.project, code) - a_func = mod["a_func"] - self.assertEqual((imported_module, 2), a_func.get_definition_location()) - - -def test_get_pyname_definition_location_parameters(self): - code = dedent("""\ - def a_func(param1, param2): - a_var = param - """) - mod = libutils.get_string_module(self.project, code) - a_func_scope = mod.get_scope().get_scopes()[0] - param1 = a_func_scope["param1"] - self.assertEqual((mod, 1), param1.get_definition_location()) - param2 = a_func_scope["param2"] - self.assertEqual((mod, 1), param2.get_definition_location()) - - -def test_module_get_resource(self): - module_resource = testutils.create_module(self.project, "mod") - module = self.project.get_module("mod") - self.assertEqual(module_resource, module.get_resource()) - code = dedent("""\ - from mod import a_func - """) - string_module = libutils.get_string_module(self.project, code) - self.assertEqual(None, string_module.get_resource()) - - -def test_get_pyname_definition_location_class2(self): - code = dedent("""\ - class AClass(object): - def __init__(self): - self.an_attr = 10 - """) - mod = libutils.get_string_module(self.project, code) - a_class = mod["AClass"].get_object() - an_attr = a_class["an_attr"] - self.assertEqual((mod, 3), an_attr.get_definition_location()) - - -def test_import_not_found_module_get_definition_location(self): - code = "import doesnotexist\n" - mod = libutils.get_string_module(self.project, code) - does_not_exist = mod["doesnotexist"] - self.assertEqual((None, None), does_not_exist.get_definition_location()) - - -def test_from_not_found_module_get_definition_location(self): - code = "from doesnotexist import Sample\n" - mod = libutils.get_string_module(self.project, code) - sample = mod["Sample"] - self.assertEqual((None, None), sample.get_definition_location()) - - -@path C:/Repos/ekr-rope/rope/refactor/ -import copy - -import rope.base.exceptions -from rope.base import codeanalyze -from rope.base import evaluate -from rope.base import pyobjects -from rope.base import taskhandle -from rope.base import utils -from rope.base import worder -from rope.base.change import ChangeContents, ChangeSet -from rope.refactor import occurrences, functionutils - - -@others -@language python -@tabwidth -4 - -def test_from_package_import_module_get_definition_location(self): - pkg = testutils.create_package(self.project, "pkg") - testutils.create_module(self.project, "mod", pkg) - pkg_mod = self.project.get_module("pkg.mod") - code = "from pkg import mod\n" - mod = libutils.get_string_module(self.project, code) - imported_mod = mod["mod"] - self.assertEqual((pkg_mod, 1), imported_mod.get_definition_location()) - - -def test_get_module_for_defined_pyobjects(self): - code = dedent("""\ - class AClass(object): - pass - """) - mod = libutils.get_string_module(self.project, code) - a_class = mod["AClass"].get_object() - self.assertEqual(mod, a_class.get_module()) - - -def test_get_definition_location_for_packages(self): - testutils.create_package(self.project, "pkg") - init_module = self.project.get_module("pkg.__init__") - code = "import pkg\n" - mod = libutils.get_string_module(self.project, code) - pkg_pyname = mod["pkg"] - self.assertEqual((init_module, 1), pkg_pyname.get_definition_location()) - - -def test_get_definition_location_for_filtered_packages(self): - pkg = testutils.create_package(self.project, "pkg") - testutils.create_module(self.project, "mod", pkg) - init_module = self.project.get_module("pkg.__init__") - code = "import pkg.mod" - mod = libutils.get_string_module(self.project, code) - pkg_pyname = mod["pkg"] - self.assertEqual((init_module, 1), pkg_pyname.get_definition_location()) - - -def test_out_of_project_modules(self): - code = "import rope.base.project as project\n" - scope = libutils.get_string_scope(self.project, code) - imported_module = scope["project"].get_object() - self.assertTrue("Project" in imported_module) - - -def test_file_encoding_reading(self): - contents = ( - "# -*- coding: utf-8 -*-\n" + "#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" - ) - mod = testutils.create_module(self.project, "mod") - mod.write(contents) - self.project.get_module("mod") - - -def test_global_keyword(self): - code = dedent("""\ - a_var = 1 - def a_func(): - global a_var - """) - mod = libutils.get_string_module(self.project, code) - global_var = mod["a_var"] - func_scope = mod["a_func"].get_object().get_scope() - local_var = func_scope["a_var"] - self.assertEqual(global_var, local_var) - - -def test_not_leaking_for_vars_inside_parent_scope(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - def f(self): - for my_var1, my_var2 in []: - pass - """) - mod.write(code) - pymod = self.pycore.resource_to_pyobject(mod) - c_class = pymod["C"].get_object() - self.assertFalse("my_var1" in c_class) - self.assertFalse("my_var2" in c_class) - - -def test_not_leaking_for_vars_inside_parent_scope2(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - def f(self): - for my_var in []: - pass - """) - mod.write(code) - pymod = self.pycore.resource_to_pyobject(mod) - c_class = pymod["C"].get_object() - self.assertFalse("my_var" in c_class) - - -def test_variables_defined_in_excepts(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - try: - myvar1 = 1 - except: - myvar2 = 1 - finally: - myvar3 = 1 - """) - mod.write(code) - pymod = self.pycore.resource_to_pyobject(mod) - self.assertTrue("myvar1" in pymod) - self.assertTrue("myvar2" in pymod) - self.assertTrue("myvar3" in pymod) - - -class ChangeSignature: - @others - -def test_not_leaking_tuple_assigned_names_inside_parent_scope(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - def f(self): - var1, var2 = range(2) - """) - mod.write(code) - pymod = self.pycore.resource_to_pyobject(mod) - c_class = pymod["C"].get_object() - self.assertFalse("var1" in c_class) - - -@testutils.only_for("2.5") -def test_with_statement_variables(self): - code = dedent("""\ - import threading - with threading.lock() as var: pass - """) - if sys.version_info < (2, 6, 0): - code = "from __future__ import with_statement\n" + code - pymod = libutils.get_string_module(self.project, code) - self.assertTrue("var" in pymod) - - -@testutils.only_for("2.5") -def test_with_statement_variables_and_tuple_assignment(self): - code = dedent("""\ - class A(object): - def __enter__(self): return (1, 2) - def __exit__(self, type, value, tb): - pass - with A() as (a, b): - pass - """) - if sys.version_info < (2, 6, 0): - code = "from __future__ import with_statement\n" + code - pymod = libutils.get_string_module(self.project, code) - self.assertTrue("a" in pymod) - self.assertTrue("b" in pymod) - - -@testutils.only_for("2.5") -def test_with_statement_variable_type(self): - code = dedent("""\ - class A(object): - def __enter__(self): - return self - def __exit__(self, type, value, tb): - pass - with A() as var: - pass - """) - if sys.version_info < (2, 6, 0): - code = "from __future__ import with_statement\n" + code - pymod = libutils.get_string_module(self.project, code) - a_class = pymod["A"].get_object() - var = pymod["var"].get_object() - self.assertEqual(a_class, var.get_type()) - - -@testutils.only_for("2.7") -def test_nested_with_statement_variable_type(self): - code = dedent("""\ - class A(object): - def __enter__(self): - return self - def __exit__(self, type, value, tb): - pass - class B(object): - def __enter__(self): - return self - def __exit__(self, type, value, tb): - pass - with A() as var_a, B() as var_b: - pass - """) - if sys.version_info < (2, 6, 0): - code = "from __future__ import with_statement\n" + code - pymod = libutils.get_string_module(self.project, code) - a_class = pymod["A"].get_object() - var_a = pymod["var_a"].get_object() - self.assertEqual(a_class, var_a.get_type()) - - b_class = pymod["B"].get_object() - var_b = pymod["var_b"].get_object() - self.assertEqual(b_class, var_b.get_type()) - - -@testutils.only_for("2.5") -def test_with_statement_with_no_vars(self): - code = dedent("""\ - with open("file"): pass - """) - if sys.version_info < (2, 6, 0): - code = "from __future__ import with_statement\n" + code - pymod = libutils.get_string_module(self.project, code) - pymod.get_attributes() - - -def test_with_statement(self): - code = dedent("""\ - a = 10 - with open("file") as f: pass - """) - pymod = libutils.get_string_module(self.project, code) - assigned = pymod.get_attribute("a") - self.assertEqual(BuiltinClass, type(assigned.get_object().get_type())) - - assigned = pymod.get_attribute("f") - self.assertEqual(File, type(assigned.get_object().get_type())) - - -def test_check_for_else_block(self): - code = dedent("""\ - for i in range(10): - pass - else: - myvar = 1 - """) - mod = libutils.get_string_module(self.project, code) - a_var = mod["myvar"] - self.assertEqual((mod, 4), a_var.get_definition_location()) - - -def test_check_names_defined_in_whiles(self): - code = dedent("""\ - while False: - myvar = 1 - """) - mod = libutils.get_string_module(self.project, code) - a_var = mod["myvar"] - self.assertEqual((mod, 2), a_var.get_definition_location()) - - -def test_get_definition_location_in_tuple_assnames(self): - code = dedent("""\ - def f(x): - x.z, a = range(2) - """) - mod = libutils.get_string_module(self.project, code) - x = mod["f"].get_object().get_scope()["x"] - a = mod["f"].get_object().get_scope()["a"] - self.assertEqual((mod, 1), x.get_definition_location()) - self.assertEqual((mod, 2), a.get_definition_location()) - - -def __init__(self, project, resource, offset): - self.project = project - self.resource = resource - self.offset = offset - self._set_name_and_pyname() - if ( - self.pyname is None - or self.pyname.get_object() is None - or not isinstance(self.pyname.get_object(), pyobjects.PyFunction) - ): - raise rope.base.exceptions.RefactoringError( - "Change method signature should be performed on functions" - ) - - -def test_syntax_errors_in_code(self): - with self.assertRaises(exceptions.ModuleSyntaxError): - libutils.get_string_module(self.project, "xyx print\n") - - -def test_holding_error_location_information(self): - try: - libutils.get_string_module(self.project, "xyx print\n") - except exceptions.ModuleSyntaxError as e: - self.assertEqual(1, e.lineno) - - -def test_no_exceptions_on_module_encoding_problems(self): - mod = testutils.create_module(self.project, "mod") - contents = b"\nsdsdsd\n\xa9\n" - file = open(mod.real_path, "wb") - file.write(contents) - file.close() - mod.read() - - -def test_syntax_errors_when_cannot_decode_file2(self): - mod = testutils.create_module(self.project, "mod") - contents = b"\n\xa9\n" - file = open(mod.real_path, "wb") - file.write(contents) - file.close() - with self.assertRaises(exceptions.ModuleSyntaxError): - self.pycore.resource_to_pyobject(mod) - - -def test_syntax_errors_when_null_bytes(self): - mod = testutils.create_module(self.project, "mod") - contents = b"\n\x00\n" - file = open(mod.real_path, "wb") - file.write(contents) - file.close() - with self.assertRaises(exceptions.ModuleSyntaxError): - self.pycore.resource_to_pyobject(mod) - - -def test_syntax_errors_when_bad_strs(self): - mod = testutils.create_module(self.project, "mod") - contents = b'\n"\\x0"\n' - file = open(mod.real_path, "wb") - file.write(contents) - file.close() - with self.assertRaises(exceptions.ModuleSyntaxError): - self.pycore.resource_to_pyobject(mod) - - -def test_not_reaching_maximum_recursions_with_from_star_imports(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("from mod2 import *\n") - mod2.write("from mod1 import *\n") - pymod1 = self.pycore.resource_to_pyobject(mod1) - pymod1.get_attributes() - - -def test_not_reaching_maximum_recursions_when_importing_variables(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("from mod2 import myvar\n") - mod2.write("from mod1 import myvar\n") - pymod1 = self.pycore.resource_to_pyobject(mod1) - pymod1["myvar"].get_object() - - -def test_not_reaching_maximum_recursions_when_importing_variables2(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write("from mod1 import myvar\n") - pymod1 = self.pycore.resource_to_pyobject(mod1) - pymod1["myvar"].get_object() - - -def test_pyobject_equality_should_compare_types(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - var1 = "" - var2 = "" - """)) - pymod1 = self.pycore.resource_to_pyobject(mod1) - self.assertEqual(pymod1["var1"].get_object(), pymod1["var2"].get_object()) - - - -def _set_name_and_pyname(self): - self.name = worder.get_name_at(self.resource, self.offset) - this_pymodule = self.project.get_pymodule(self.resource) - self.primary, self.pyname = evaluate.eval_location2(this_pymodule, self.offset) - if self.pyname is None: - return - pyobject = self.pyname.get_object() - if isinstance(pyobject, pyobjects.PyClass) and "__init__" in pyobject: - self.pyname = pyobject["__init__"] - self.name = "__init__" - pyobject = self.pyname.get_object() - self.others = None - if ( - self.name == "__init__" - and isinstance(pyobject, pyobjects.PyFunction) - and isinstance(pyobject.parent, pyobjects.PyClass) - ): - pyclass = pyobject.parent - self.others = (pyclass.get_name(), pyclass.parent[pyclass.get_name()]) - - -class PyCoreInProjectsTest(unittest.TestCase): - @others - -def setUp(self): - super(self.__class__, self).setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - samplemod = testutils.create_module(self.project, "samplemod") - code = dedent("""\ - class SampleClass(object): - def sample_method(): - pass - - def sample_func(): - pass - sample_var = 10 - - def _underlined_func(): - pass - - """) - samplemod.write(code) - package = testutils.create_package(self.project, "package") - testutils.create_module(self.project, "nestedmod", package) - - -def tearDown(self): - testutils.remove_project(self.project) - super(self.__class__, self).tearDown() - - -def test_simple_import(self): - code = "import samplemod\n" - mod = libutils.get_string_module(self.project, code) - samplemod = mod["samplemod"].get_object() - self.assertEqual(get_base_type("Module"), samplemod.get_type()) - - -def test_from_import_class(self): - code = "from samplemod import SampleClass\n" - mod = libutils.get_string_module(self.project, code) - result = mod["SampleClass"].get_object() - self.assertEqual(get_base_type("Type"), result.get_type()) - self.assertTrue("sample_func" not in mod.get_attributes()) - - -def test_from_import_star(self): - code = "from samplemod import *\n" - mod = libutils.get_string_module(self.project, code) - self.assertEqual( - get_base_type("Type"), mod["SampleClass"].get_object().get_type() - ) - self.assertEqual( - get_base_type("Function"), mod["sample_func"].get_object().get_type() - ) - self.assertTrue(mod["sample_var"] is not None) - - -def test_from_import_star_overwriting(self): - code = dedent("""\ - from samplemod import * - class SampleClass(object): - pass - """) - mod = libutils.get_string_module(self.project, code) - samplemod = self.project.get_module("samplemod") - sample_class = samplemod["SampleClass"].get_object() - self.assertNotEqual( - sample_class, mod.get_attributes()["SampleClass"].get_object() - ) - - -def test_from_import_star_not_imporing_underlined(self): - code = "from samplemod import *" - mod = libutils.get_string_module(self.project, code) - self.assertTrue("_underlined_func" not in mod.get_attributes()) - - -def test_from_import_star_imports_in_functions(self): - code = dedent("""\ - def f(): - from os import * - """) - mod = libutils.get_string_module(self.project, code) - mod["f"].get_object().get_scope().get_names() - - -def test_from_package_import_mod(self): - code = "from package import nestedmod\n" - mod = libutils.get_string_module(self.project, code) - self.assertEqual( - get_base_type("Module"), mod["nestedmod"].get_object().get_type() - ) - - -def _change_calls( - self, - call_changer, - in_hierarchy=None, - resources=None, - handle=taskhandle.NullTaskHandle(), -): - if resources is None: - resources = self.project.get_python_files() - changes = ChangeSet("Changing signature of <%s>" % self.name) - job_set = handle.create_jobset("Collecting Changes", len(resources)) - finder = occurrences.create_finder( - self.project, - self.name, - self.pyname, - instance=self.primary, - in_hierarchy=in_hierarchy and self.is_method(), - ) - if self.others: - name, pyname = self.others - constructor_finder = occurrences.create_finder( - self.project, name, pyname, only_calls=True - ) - finder = _MultipleFinders([finder, constructor_finder]) - for file in resources: - job_set.started_job(file.path) - change_calls = _ChangeCallsInModule( - self.project, finder, file, call_changer - ) - changed_file = change_calls.get_changed_module() - if changed_file is not None: - changes.add_change(ChangeContents(file, changed_file)) - job_set.finished_job() - return changes - - -# XXX: Deciding to import everything on import start from packages -def xxx_test_from_package_import_star(self): - code = "from package import *\n" - mod = libutils.get_string_module(self.project, code) - self.assertTrue("nestedmod" not in mod.get_attributes()) - - -def test_unknown_when_module_cannot_be_found(self): - code = "from doesnotexist import nestedmod\n" - mod = libutils.get_string_module(self.project, code) - self.assertTrue("nestedmod" in mod) - - -def test_from_import_function(self): - code = dedent("""\ - def f(): - from samplemod import SampleClass - """) - scope = libutils.get_string_scope(self.project, code) - self.assertEqual( - get_base_type("Type"), - scope.get_scopes()[0]["SampleClass"].get_object().get_type(), - ) - - -def test_circular_imports(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("import mod2\n") - mod2.write("import mod1\n") - self.project.get_module("mod1") - - -def test_circular_imports2(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write(dedent("""\ - from mod2 import Sample2 - class Sample1(object): - pass - """)) - mod2.write(dedent("""\ - from mod1 import Sample1 - class Sample2(object): - pass - """)) - self.project.get_module("mod1").get_attributes() - - -def test_multi_dot_imports(self): - pkg = testutils.create_package(self.project, "pkg") - pkg_mod = testutils.create_module(self.project, "mod", pkg) - pkg_mod.write(dedent("""\ - def sample_func(): - pass - """)) - code = "import pkg.mod\n" - mod = libutils.get_string_module(self.project, code) - self.assertTrue("pkg" in mod) - self.assertTrue("sample_func" in mod["pkg"].get_object()["mod"].get_object()) - - -def test_multi_dot_imports2(self): - pkg = testutils.create_package(self.project, "pkg") - testutils.create_module(self.project, "mod1", pkg) - testutils.create_module(self.project, "mod2", pkg) - code = dedent("""\ - import pkg.mod1 - import pkg.mod2 - """) - mod = libutils.get_string_module(self.project, code) - package = mod["pkg"].get_object() - self.assertEqual(2, len(package.get_attributes())) - self.assertTrue("mod1" in package and "mod2" in package) - - -def test_multi_dot_imports3(self): - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) - testutils.create_module(self.project, "mod1", pkg2) - testutils.create_module(self.project, "mod2", pkg2) - code = dedent("""\ - import pkg1.pkg2.mod1 - import pkg1.pkg2.mod2 - """) - mod = libutils.get_string_module(self.project, code) - package1 = mod["pkg1"].get_object() - package2 = package1["pkg2"].get_object() - self.assertEqual(2, len(package2.get_attributes())) - self.assertTrue("mod1" in package2 and "mod2" in package2) - - -def test_multi_dot_imports_as(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod1.write(dedent("""\ - def f(): - pass - """)) - code = "import pkg.mod1 as mod1\n" - mod = libutils.get_string_module(self.project, code) - module = mod["mod1"].get_object() - self.assertTrue("f" in module) - - -# TODO: not showing unimported names as attributes of packages -def xxx_test_from_package_import_package(self): - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) - testutils.create_module(self.project, "mod", pkg2) - code = "from pkg1 import pkg2\n" - mod = libutils.get_string_module(self.project, code) - package = mod["pkg2"] - self.assertEqual(0, len(package.get_attributes())) - - -def get_args(self): - """Get function arguments. - - Return a list of ``(name, default)`` tuples for all but star - and double star arguments. For arguments that don't have a - default, `None` will be used. - """ - return self._definfo().args_with_defaults - - -def test_invalidating_cache_after_resource_change(self): - module = testutils.create_module(self.project, "mod") - module.write("import sys\n") - mod1 = self.project.get_module("mod") - self.assertTrue("var" not in mod1.get_attributes()) - module.write("var = 10\n") - mod2 = self.project.get_module("mod") - self.assertTrue("var" in mod2) - - -def test_invalidating_cache_after_resource_change_for_init_dot_pys(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod") - init_dot_py = pkg.get_child("__init__.py") - init_dot_py.write("a_var = 10\n") - mod.write("import pkg\n") - pymod = self.project.get_module("mod") - self.assertTrue("a_var" in pymod["pkg"].get_object()) - init_dot_py.write("new_var = 10\n") - self.assertTrue("a_var" not in pymod["pkg"].get_object().get_attributes()) - - -def test_invalidating_cache_after_rsrc_chng_for_nested_init_dot_pys(self): - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) - mod = testutils.create_module(self.project, "mod") - init_dot_py = pkg2.get_child("__init__.py") - init_dot_py.write("a_var = 10\n") - mod.write("import pkg1\n") - pymod = self.project.get_module("mod") - self.assertTrue("a_var" in pymod["pkg1"].get_object()["pkg2"].get_object()) - init_dot_py.write("new_var = 10\n") - self.assertTrue("a_var" not in pymod["pkg1"].get_object()["pkg2"].get_object()) - - -def test_from_import_nonexistent_module(self): - code = "from doesnotexistmod import DoesNotExistClass\n" - mod = libutils.get_string_module(self.project, code) - self.assertTrue("DoesNotExistClass" in mod) - self.assertEqual( - get_base_type("Unknown"), mod["DoesNotExistClass"].get_object().get_type() - ) - - -def test_from_import_nonexistent_name(self): - code = "from samplemod import DoesNotExistClass\n" - mod = libutils.get_string_module(self.project, code) - self.assertTrue("DoesNotExistClass" in mod) - self.assertEqual( - get_base_type("Unknown"), mod["DoesNotExistClass"].get_object().get_type() - ) - - -def test_not_considering_imported_names_as_sub_scopes(self): - code = "from samplemod import SampleClass\n" - scope = libutils.get_string_scope(self.project, code) - self.assertEqual(0, len(scope.get_scopes())) - - -def test_not_considering_imported_modules_as_sub_scopes(self): - code = "import samplemod\n" - scope = libutils.get_string_scope(self.project, code) - self.assertEqual(0, len(scope.get_scopes())) - - -def test_inheriting_dotted_base_class(self): - code = dedent("""\ - import samplemod - class Derived(samplemod.SampleClass): - pass - """) - mod = libutils.get_string_module(self.project, code) - derived = mod["Derived"].get_object() - self.assertTrue("sample_method" in derived) - - -def test_self_in_methods(self): - code = dedent("""\ - class Sample(object): - def func(self): - pass - """) - scope = libutils.get_string_scope(self.project, code) - sample_class = scope["Sample"].get_object() - func_scope = scope.get_scopes()[0].get_scopes()[0] - self.assertEqual(sample_class, func_scope["self"].get_object().get_type()) - self.assertTrue("func" in func_scope["self"].get_object()) - - -def test_none_assignments_in_classes(self): - code = dedent("""\ - class C(object): - var = "" - def f(self): - self.var += "".join([]) - """) - scope = libutils.get_string_scope(self.project, code) - c_class = scope["C"].get_object() - self.assertTrue("var" in c_class) - - -def is_method(self): - pyfunction = self.pyname.get_object() - return isinstance(pyfunction.parent, pyobjects.PyClass) - - -def test_self_in_methods_with_decorators(self): - code = dedent("""\ - class Sample(object): - @staticmethod - def func(self): - pass - """) - scope = libutils.get_string_scope(self.project, code) - sample_class = scope["Sample"].get_object() - func_scope = scope.get_scopes()[0].get_scopes()[0] - self.assertNotEqual(sample_class, func_scope["self"].get_object().get_type()) - - -def test_location_of_imports_when_importing(self): - mod = testutils.create_module(self.project, "mod") - mod.write("from samplemod import SampleClass\n") - code = "from mod import SampleClass\n" - scope = libutils.get_string_scope(self.project, code) - sample_class = scope["SampleClass"] - samplemod = self.project.get_module("samplemod") - self.assertEqual((samplemod, 1), sample_class.get_definition_location()) - - -def test_nested_modules(self): - pkg = testutils.create_package(self.project, "pkg") - testutils.create_module(self.project, "mod", pkg) - imported_module = self.project.get_module("pkg.mod") - code = "import pkg.mod\n" - scope = libutils.get_string_scope(self.project, code) - mod_pyobject = scope["pkg"].get_object()["mod"] - self.assertEqual((imported_module, 1), mod_pyobject.get_definition_location()) - - -def test_reading_init_dot_py(self): - pkg = testutils.create_package(self.project, "pkg") - init_dot_py = pkg.get_child("__init__.py") - init_dot_py.write("a_var = 1\n") - pkg_object = self.project.get_module("pkg") - self.assertTrue("a_var" in pkg_object) - - -def test_relative_imports(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod2.write("import mod1\n") - mod1_object = self.pycore.resource_to_pyobject(mod1) - mod2_object = self.pycore.resource_to_pyobject(mod2) - self.assertEqual(mod1_object, mod2_object.get_attributes()["mod1"].get_object()) - - -def test_relative_froms(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod1.write(dedent("""\ - def a_func(): - pass - """)) - mod2.write("from mod1 import a_func\n") - mod1_object = self.pycore.resource_to_pyobject(mod1) - mod2_object = self.pycore.resource_to_pyobject(mod2) - self.assertEqual( - mod1_object["a_func"].get_object(), mod2_object["a_func"].get_object() - ) - - -def test_relative_imports_for_string_modules(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod2.write("import mod1\n") - mod1_object = self.pycore.resource_to_pyobject(mod1) - mod2_object = libutils.get_string_module(self.project, mod2.read(), mod2) - self.assertEqual(mod1_object, mod2_object["mod1"].get_object()) - - -def test_relative_imports_for_string_scopes(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod2.write("import mod1\n") - mod1_object = self.pycore.resource_to_pyobject(mod1) - mod2_scope = libutils.get_string_scope(self.project, mod2.read(), mod2) - self.assertEqual(mod1_object, mod2_scope["mod1"].get_object()) - - -@testutils.only_for("2.5") -def test_new_style_relative_imports(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod2.write("from . import mod1\n") - mod1_object = self.pycore.resource_to_pyobject(mod1) - mod2_object = self.pycore.resource_to_pyobject(mod2) - self.assertEqual(mod1_object, mod2_object["mod1"].get_object()) - - -@testutils.only_for("2.5") -def test_new_style_relative_imports2(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod1.write(dedent("""\ - def a_func(): - pass - """)) - mod2.write("from ..mod1 import a_func\n") - mod1_object = self.pycore.resource_to_pyobject(mod1) - mod2_object = self.pycore.resource_to_pyobject(mod2) - self.assertEqual( - mod1_object["a_func"].get_object(), mod2_object["a_func"].get_object() - ) - - -def _get_line_indents(line): - return rope.base.codeanalyze.count_line_indents(line) - -@utils.deprecated("Use `ChangeSignature.get_args()` instead") -def get_definition_info(self): - return self._definfo() - - -def test_invalidating_cache_for_from_imports_after_resource_change(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - def a_func(): - print(1) - """)) - mod1.write(dedent("""\ - from mod2 import a_func - a_func() - """)) - - pymod1 = self.project.get_module("mod1") - pymod2 = self.project.get_module("mod2") - self.assertEqual(pymod1["a_func"].get_object(), pymod2["a_func"].get_object()) - mod2.write(mod2.read() + "\n") - pymod2 = self.project.get_module("mod2") - self.assertEqual(pymod1["a_func"].get_object(), pymod2["a_func"].get_object()) - - -def test_invalidating_superclasses_after_change(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write(dedent("""\ - class A(object): - def func1(self): - pass - """)) - mod2.write(dedent("""\ - import mod1 - class B(mod1.A): - pass - """)) - - b_class = self.project.get_module("mod2")["B"].get_object() - self.assertTrue("func1" in b_class) - - mod1.write(dedent("""\ - class A(object): - def func2(self): - pass - """)) - self.assertTrue("func2" in b_class) - - -def test_caching_pymodule_with_syntax_errors(self): - self.project.prefs["ignore_syntax_errors"] = True - self.project.prefs["automatic_soa"] = True - self.project.pycore._init_automatic_soa() - source = dedent("""\ - import sys - ab cd - """) - mod = testutils.create_module(self.project, "mod") - mod.write(source) - from rope.contrib import fixsyntax - - fixer = fixsyntax.FixSyntax(self.project, source, mod, 10) - pymodule = fixer.get_pymodule() - self.assertTrue(pymodule.source_code.startswith("import sys\npass\n")) - - - -class TextChangeDetectorTest(unittest.TestCase): - @others - -def test_trivial_case(self): - detector = _TextChangeDetector("\n", "\n") - self.assertFalse(detector.is_changed(1, 1)) - - -def test_one_line_change(self): - detector = _TextChangeDetector("1\n2\n", "1\n3\n") - self.assertFalse(detector.is_changed(1, 1)) - self.assertTrue(detector.is_changed(2, 2)) - - -def test_line_expansion(self): - detector = _TextChangeDetector("1\n2\n", "1\n3\n4\n2\n") - self.assertFalse(detector.is_changed(1, 1)) - self.assertFalse(detector.is_changed(2, 2)) - - -def test_line_removals(self): - detector = _TextChangeDetector("1\n3\n4\n2\n", "1\n2\n") - self.assertFalse(detector.is_changed(1, 1)) - self.assertTrue(detector.is_changed(2, 3)) - self.assertFalse(detector.is_changed(4, 4)) - - -def test_multi_line_checks(self): - detector = _TextChangeDetector("1\n2\n", "1\n3\n") - self.assertTrue(detector.is_changed(1, 2)) - - -def test_consume_change(self): - detector = _TextChangeDetector("1\n2\n", "1\n3\n") - self.assertTrue(detector.is_changed(1, 2)) - self.assertTrue(detector.consume_changes(1, 2)) - self.assertFalse(detector.is_changed(1, 2)) - - - -def _definfo(self): - return functionutils.DefinitionInfo.read(self.pyname.get_object()) - - -class PyCoreProjectConfigsTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = None - - -def tearDown(self): - if self.project: - testutils.remove_project(self.project) - super().tearDown() - - -def test_python_files_config(self): - self.project = testutils.sample_project(python_files=["myscript"]) - myscript = self.project.root.create_file("myscript") - self.assertTrue(self.project.pycore.is_python_file(myscript)) - - -def test_ignore_bad_imports(self): - self.project = testutils.sample_project(ignore_bad_imports=True) - code = "import some_nonexistent_module\n" - pymod = libutils.get_string_module(self.project, code) - self.assertFalse("some_nonexistent_module" in pymod) - - -def test_ignore_bad_imports_for_froms(self): - self.project = testutils.sample_project(ignore_bad_imports=True) - code = "from some_nonexistent_module import var\n" - pymod = libutils.get_string_module(self.project, code) - self.assertFalse("var" in pymod) - - -def test_reporting_syntax_errors_with_force_errors(self): - self.project = testutils.sample_project(ignore_syntax_errors=True) - mod = testutils.create_module(self.project, "mod") - mod.write("syntax error ...\n") - with self.assertRaises(exceptions.ModuleSyntaxError): - self.project.pycore.resource_to_pyobject(mod, force_errors=True) - - -def test_reporting_syntax_errors_in_strings_with_force_errors(self): - self.project = testutils.sample_project(ignore_syntax_errors=True) - with self.assertRaises(exceptions.ModuleSyntaxError): - libutils.get_string_module( - self.project, "syntax error ...", force_errors=True - ) - - -def test_not_raising_errors_for_strings_with_ignore_errors(self): - self.project = testutils.sample_project(ignore_syntax_errors=True) - libutils.get_string_module(self.project, "syntax error ...") - - -def test_reporting_syntax_errors_with_force_errors_for_packages(self): - self.project = testutils.sample_project(ignore_syntax_errors=True) - pkg = testutils.create_package(self.project, "pkg") - pkg.get_child("__init__.py").write("syntax error ...\n") - with self.assertRaises(exceptions.ModuleSyntaxError): - self.project.pycore.resource_to_pyobject(pkg, force_errors=True) - -@utils.deprecated() -def normalize(self): - changer = _FunctionChangers( - self.pyname.get_object(), self.get_definition_info(), [ArgumentNormalizer()] - ) - return self._change_calls(changer) - - -@path C:/Repos/ekr-rope/ropetest/ -import unittest - -from textwrap import dedent - -from rope.base import libutils -from rope.base.pyobjects import get_base_type -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class PyCoreScopesTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_scope(self): - code = dedent("""\ - def sample_func(): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - sample_func = scope["sample_func"].get_object() - self.assertEqual(get_base_type("Function"), sample_func.get_type()) - - -def test_simple_function_scope(self): - code = dedent("""\ - def sample_func(): - a = 10 - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(1, len(scope.get_scopes())) - sample_func_scope = scope.get_scopes()[0] - self.assertEqual(1, len(sample_func_scope.get_names())) - self.assertEqual(0, len(sample_func_scope.get_scopes())) - - -def test_classes_inside_function_scopes(self): - code = dedent("""\ - def sample_func(): - class SampleClass(object): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(1, len(scope.get_scopes())) - sample_func_scope = scope.get_scopes()[0] - self.assertEqual( - get_base_type("Type"), - sample_func_scope["SampleClass"].get_object().get_type(), - ) - - -def test_list_comprehension_scope_inside_assignment(self): - code = "a_var = [b_var + d_var for b_var, c_var in e_var]\n" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual( - list(sorted(scope.get_defined_names())), - ["a_var"], - ) - self.assertEqual( - list(sorted(scope.get_scopes()[0].get_defined_names())), - ["b_var", "c_var"], - ) - - -def test_list_comprehension_scope(self): - code = "[b_var + d_var for b_var, c_var in e_var]\n" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual( - list(sorted(scope.get_scopes()[0].get_defined_names())), - ["b_var", "c_var"], - ) - - -def test_set_comprehension_scope(self): - code = "{b_var + d_var for b_var, c_var in e_var}\n" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual( - list(sorted(scope.get_scopes()[0].get_defined_names())), - ["b_var", "c_var"], - ) - - -@utils.deprecated() -def remove(self, index): - changer = _FunctionChangers( - self.pyname.get_object(), - self.get_definition_info(), - [ArgumentRemover(index)], - ) - return self._change_calls(changer) - - -def test_generator_comprehension_scope(self): - code = "(b_var + d_var for b_var, c_var in e_var)\n" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual( - list(sorted(scope.get_scopes()[0].get_defined_names())), - ["b_var", "c_var"], - ) - - -def test_dict_comprehension_scope(self): - code = "{b_var: d_var for b_var, c_var in e_var}\n" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual( - list(sorted(scope.get_scopes()[0].get_defined_names())), - ["b_var", "c_var"], - ) - - -@testutils.only_for_versions_higher("3.8") -def test_inline_assignment(self): - code = """values = (a_var := 2,)""" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual( - list(sorted(scope.get_defined_names())), - ["a_var", "values"], - ) - - -@testutils.only_for_versions_higher("3.8") -def test_inline_assignment_in_comprehensions(self): - code = dedent("""\ - [ - (a_var := b_var + (f_var := g_var)) - for b_var in [(j_var := i_var) - for i_var in c_var] if a_var + (h_var := d_var) - ] - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual( - list(sorted(scope.get_scopes()[0].get_defined_names())), - ["a_var", "b_var", "f_var"], - ) - self.assertEqual( - list(sorted(scope.get_scopes()[0].get_scopes()[0].get_defined_names())), - ["i_var", "j_var"], - ) - - -def test_nested_comprehension(self): - code = dedent("""\ - [ - b_var + d_var for b_var, c_var in [ - e_var for e_var in f_var - ] - ] - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual( - list(sorted(scope.get_scopes()[0].get_defined_names())), - ["b_var", "c_var"], - ) - self.assertEqual( - list(sorted(scope.get_scopes()[0].get_scopes()[0].get_defined_names())), - ["e_var"], - ) - - -def test_simple_class_scope(self): - code = dedent("""\ - class SampleClass(object): - def f(self): - var = 10 - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(1, len(scope.get_scopes())) - sample_class_scope = scope.get_scopes()[0] - self.assertTrue("f" in sample_class_scope) - self.assertEqual(1, len(sample_class_scope.get_scopes())) - f_in_class = sample_class_scope.get_scopes()[0] - self.assertTrue("var" in f_in_class) - - -def test_get_lineno(self): - code = dedent("""\ - - def sample_func(): - a = 10 - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(1, len(scope.get_scopes())) - sample_func_scope = scope.get_scopes()[0] - self.assertEqual(1, scope.get_start()) - self.assertEqual(2, sample_func_scope.get_start()) - - -def test_scope_kind(self): - code = dedent("""\ - class SampleClass(object): - pass - def sample_func(): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - sample_class_scope = scope.get_scopes()[0] - sample_func_scope = scope.get_scopes()[1] - self.assertEqual("Module", scope.get_kind()) - self.assertEqual("Class", sample_class_scope.get_kind()) - self.assertEqual("Function", sample_func_scope.get_kind()) - - -def test_function_parameters_in_scope_names(self): - code = dedent("""\ - def sample_func(param): - a = 10 - """) - scope = libutils.get_string_scope(self.project, code) - - sample_func_scope = scope.get_scopes()[0] - self.assertTrue("param" in sample_func_scope) - - -def test_get_names_contains_only_names_defined_in_a_scope(self): - code = dedent("""\ - var1 = 10 - def sample_func(param): - var2 = 20 - """) - scope = libutils.get_string_scope(self.project, code) - - sample_func_scope = scope.get_scopes()[0] - self.assertTrue("var1" not in sample_func_scope) - - -@utils.deprecated() -def add(self, index, name, default=None, value=None): - changer = _FunctionChangers( - self.pyname.get_object(), - self.get_definition_info(), - [ArgumentAdder(index, name, default, value)], - ) - return self._change_calls(changer) - - -def test_scope_lookup(self): - code = dedent("""\ - var1 = 10 - def sample_func(param): - var2 = 20 - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertTrue(scope.lookup("var2") is None) - self.assertEqual( - get_base_type("Function"), - scope.lookup("sample_func").get_object().get_type(), - ) - sample_func_scope = scope.get_scopes()[0] - self.assertTrue(sample_func_scope.lookup("var1") is not None) - - -def test_function_scopes(self): - code = dedent("""\ - def func(): - var = 10 - """) - scope = libutils.get_string_scope(self.project, code) - - func_scope = scope.get_scopes()[0] - self.assertTrue("var" in func_scope) - - -def test_function_scopes_classes(self): - code = dedent("""\ - def func(): - class Sample(object): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - func_scope = scope.get_scopes()[0] - self.assertTrue("Sample" in func_scope) - - -def test_function_getting_scope(self): - code = dedent("""\ - def func(): var = 10 - """) - mod = libutils.get_string_module(self.project, code) - - func_scope = mod["func"].get_object().get_scope() - self.assertTrue("var" in func_scope) - - -def test_scopes_in_function_scopes(self): - code = dedent("""\ - def func(): - def inner(): - var = 10 - """) - scope = libutils.get_string_scope(self.project, code) - - func_scope = scope.get_scopes()[0] - inner_scope = func_scope.get_scopes()[0] - self.assertTrue("var" in inner_scope) - - -def test_for_variables_in_scopes(self): - code = dedent("""\ - for a_var in range(10): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertTrue("a_var" in scope) - - -def test_assists_inside_fors(self): - code = dedent("""\ - for i in range(10): - a_var = i - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertTrue("a_var" in scope) - - -def test_first_parameter_of_a_method(self): - code = dedent("""\ - class AClass(object): - def a_func(self, param): - pass - """) - a_class = libutils.get_string_module(self.project, code)["AClass"].get_object() - function_scope = a_class["a_func"].get_object().get_scope() - self.assertEqual(a_class, function_scope["self"].get_object().get_type()) - self.assertNotEqual(a_class, function_scope["param"].get_object().get_type()) - - -def test_first_parameter_of_static_methods(self): - code = dedent("""\ - class AClass(object): - @staticmethod - def a_func(param): - pass - """) - a_class = libutils.get_string_module(self.project, code)["AClass"].get_object() - function_scope = a_class["a_func"].get_object().get_scope() - self.assertNotEqual(a_class, function_scope["param"].get_object().get_type()) - - -def test_first_parameter_of_class_methods(self): - code = dedent("""\ - class AClass(object): - @classmethod - def a_func(cls): - pass - """) - a_class = libutils.get_string_module(self.project, code)["AClass"].get_object() - function_scope = a_class["a_func"].get_object().get_scope() - self.assertEqual(a_class, function_scope["cls"].get_object()) - - -@utils.deprecated() -def inline_default(self, index): - changer = _FunctionChangers( - self.pyname.get_object(), - self.get_definition_info(), - [ArgumentDefaultInliner(index)], - ) - return self._change_calls(changer) - - -def test_first_parameter_with_self_as_name_and_unknown_decorator(self): - code = dedent("""\ - def my_decorator(func): - return func - class AClass(object): - @my_decorator - def a_func(self): - pass - """) - a_class = libutils.get_string_module(self.project, code)["AClass"].get_object() - function_scope = a_class["a_func"].get_object().get_scope() - self.assertEqual(a_class, function_scope["self"].get_object().get_type()) - - -def test_inside_class_scope_attribute_lookup(self): - code = dedent("""\ - class C(object): - an_attr = 1 - def a_func(self): - pass""") - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(1, len(scope.get_scopes())) - c_scope = scope.get_scopes()[0] - self.assertTrue("an_attr" in c_scope.get_names()) - self.assertTrue(c_scope.lookup("an_attr") is not None) - f_in_c = c_scope.get_scopes()[0] - self.assertTrue(f_in_c.lookup("an_attr") is None) - - -def test_inside_class_scope_attribute_lookup2(self): - code = dedent("""\ - class C(object): - def __init__(self): - self.an_attr = 1 - def a_func(self): - pass""") - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(1, len(scope.get_scopes())) - c_scope = scope.get_scopes()[0] - f_in_c = c_scope.get_scopes()[0] - self.assertTrue(f_in_c.lookup("an_attr") is None) - - -def test_get_inner_scope_for_staticmethods(self): - code = dedent("""\ - class C(object): - @staticmethod - def a_func(self): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - c_scope = scope.get_scopes()[0] - f_in_c = c_scope.get_scopes()[0] - self.assertEqual(f_in_c, scope.get_inner_scope_for_line(4)) - - -def test_get_scope_for_offset_for_comprehension(self): - code = "a = [i for i in range(10)]\n" - scope = libutils.get_string_scope(self.project, code) - - c_scope = scope.get_scopes()[0] - self.assertEqual(c_scope, scope.get_inner_scope_for_offset(10)) - self.assertEqual(scope, scope.get_inner_scope_for_offset(1)) - - -def test_get_scope_for_offset_for_in_nested_comprehension(self): - code = "[i for i in [j for j in k]]\n" - scope = libutils.get_string_scope(self.project, code) - - c_scope = scope.get_scopes()[0] - self.assertEqual(c_scope, scope.get_inner_scope_for_offset(5)) - inner_scope = c_scope.get_scopes()[0] - self.assertEqual(inner_scope, scope.get_inner_scope_for_offset(15)) - - -def test_get_scope_for_offset_for_scope_with_indent(self): - code = dedent("""\ - def f(a): - print(a) - """) - scope = libutils.get_string_scope(self.project, code) - - inner_scope = scope.get_scopes()[0] - self.assertEqual(inner_scope, scope.get_inner_scope_for_offset(10)) - - -@testutils.only_for("3.5") -def test_get_scope_for_offset_for_function_scope_and_async_with_statement(self): - scope = libutils.get_string_scope( - self.project, - dedent("""\ - async def func(): - async with a_func() as var: - print(var) - """), - ) - inner_scope = scope.get_scopes()[0] - self.assertEqual(inner_scope, scope.get_inner_scope_for_offset(27)) - - -def test_getting_overwritten_scopes(self): - code = dedent("""\ - def f(): - pass - def f(): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(2, len(scope.get_scopes())) - f1_scope = scope.get_scopes()[0] - f2_scope = scope.get_scopes()[1] - self.assertNotEqual(f1_scope, f2_scope) - - -def test_assigning_builtin_names(self): - code = "range = 1\n" - mod = libutils.get_string_module(self.project, code) - - range = mod.get_scope().lookup("range") - self.assertEqual((mod, 1), range.get_definition_location()) - - -@utils.deprecated() -def reorder(self, new_ordering): - changer = _FunctionChangers( - self.pyname.get_object(), - self.get_definition_info(), - [ArgumentReorderer(new_ordering)], - ) - return self._change_calls(changer) - - -def test_get_inner_scope_and_logical_lines(self): - code = dedent('''\ - class C(object): - def f(): - s = """ - 1 - 2 - """ - a = 1 - ''') - scope = libutils.get_string_scope(self.project, code) - - c_scope = scope.get_scopes()[0] - f_in_c = c_scope.get_scopes()[0] - self.assertEqual(f_in_c, scope.get_inner_scope_for_line(7)) - - -def test_getting_defined_names_for_classes(self): - code = dedent("""\ - class A(object): - def a(self): - pass - class B(A): - def b(self): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - a_scope = scope["A"].get_object().get_scope() # noqa - b_scope = scope["B"].get_object().get_scope() - self.assertTrue("a" in b_scope.get_names()) - self.assertTrue("b" in b_scope.get_names()) - self.assertTrue("a" not in b_scope.get_defined_names()) - self.assertTrue("b" in b_scope.get_defined_names()) - - -def test_getting_defined_names_for_modules(self): - code = dedent("""\ - class A(object): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertTrue("open" in scope.get_names()) - self.assertTrue("A" in scope.get_names()) - self.assertTrue("open" not in scope.get_defined_names()) - self.assertTrue("A" in scope.get_defined_names()) - - -def test_get_inner_scope_for_list_comprhension_with_many_targets(self): - code = "a = [(i, j) for i,j in enumerate(range(10))]\n" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(len(scope.get_scopes()), 1) - self.assertNotIn("i", scope) - self.assertNotIn("j", scope) - self.assertIn("i", scope.get_scopes()[0]) - self.assertIn("j", scope.get_scopes()[0]) - - -def test_get_inner_scope_for_generator(self): - code = "a = (i for i in range(10))\n" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(len(scope.get_scopes()), 1) - self.assertNotIn("i", scope) - self.assertIn("i", scope.get_scopes()[0]) - - -def test_get_inner_scope_for_set_comprehension(self): - code = "a = {i for i in range(10)}\n" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(len(scope.get_scopes()), 1) - self.assertNotIn("i", scope) - self.assertIn("i", scope.get_scopes()[0]) - - -def test_get_inner_scope_for_dict_comprehension(self): - code = "a = {i:i for i in range(10)}\n" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(len(scope.get_scopes()), 1) - self.assertNotIn("i", scope) - self.assertIn("i", scope.get_scopes()[0]) - - -def test_get_inner_scope_for_nested_list_comprhension(self): - code = "a = [[i + j for j in range(10)] for i in range(10)]\n" - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(len(scope.get_scopes()), 1) - self.assertNotIn("i", scope) - self.assertNotIn("j", scope) - self.assertIn("i", scope.get_scopes()[0]) - self.assertEqual(len(scope.get_scopes()[0].get_scopes()), 1) - self.assertIn("j", scope.get_scopes()[0].get_scopes()[0]) - self.assertIn("i", scope.get_scopes()[0].get_scopes()[0]) - - -def test_get_scope_region(self): - scope = libutils.get_string_scope( - self.project, - dedent(""" - def func1(ala): - pass - - def func2(o): - pass - """), - ) - - self.assertEqual(scope.get_region(), (0, 48)) - self.assertEqual(scope.get_scopes()[0].get_region(), (1, 24)) - self.assertEqual(scope.get_scopes()[1].get_region(), (26, 47)) - - -def test_only_get_inner_scope_region(self): - scope = libutils.get_string_scope( - self.project, - dedent(""" - def func1(ala): - pass - - def func2(o): - pass - """), - ) - - self.assertEqual(scope.get_scopes()[1].get_region(), (26, 47)) - -def get_changes( - self, - changers, - in_hierarchy=False, - resources=None, - task_handle=taskhandle.NullTaskHandle(), -): - """Get changes caused by this refactoring - - `changers` is a list of `_ArgumentChanger`. If `in_hierarchy` - is `True` the changers are applied to all matching methods in - the class hierarchy. - `resources` can be a list of `rope.base.resource.File` that - should be searched for occurrences; if `None` all python files - in the project are searched. - - """ - function_changer = _FunctionChangers( - self.pyname.get_object(), self._definfo(), changers - ) - return self._change_calls( - function_changer, in_hierarchy, resources, task_handle - ) - - - -@path C:/Repos/ekr-rope/ropetest/ -import pathlib -import tempfile - -import pytest - -from rope.base import libutils, resources, pyobjectsdef -from rope.base.project import Project -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -@pytest.fixture -def project(): - proj = testutils.sample_project() - yield proj - testutils.remove_project(proj) - - - -@pytest.fixture -def mod(project): - return testutils.create_module(project, "mod") - - - -@pytest.fixture -def mod1(project): - testutils.create_package(project, "pkg1") - return testutils.create_module(project, "pkg1.mod1") - - - -def test_repr_project(): - with tempfile.TemporaryDirectory() as folder: - folder = pathlib.Path(folder).resolve() - obj = testutils.sample_project(folder) - assert isinstance(obj, Project) - assert repr(obj) == f'<rope.base.project.Project "{folder}">' - - - -def test_repr_file(project): - obj = project.get_file("test/file.py") - assert isinstance(obj, resources.File) - assert repr(obj).startswith('<rope.base.resources.File "test/file.py" at 0x') - - - -def test_repr_folder(project): - obj = project.get_folder("test/folder") - assert isinstance(obj, resources.Folder) - assert repr(obj).startswith('<rope.base.resources.Folder "test/folder" at 0x') - - - -def test_repr_pyobjectsdef_pymodule(project, mod1): - obj = project.get_module("pkg1.mod1") - assert isinstance(obj, pyobjectsdef.PyModule) - assert repr(obj).startswith('<rope.base.pyobjectsdef.PyModule "pkg1.mod1" at 0x') - - - -def test_repr_pyobjectsdef_pymodule_without_associated_resource(project): - obj = pyobjectsdef.PyModule(project.pycore, "a = 1") - assert isinstance(obj, pyobjectsdef.PyModule) - assert repr(obj).startswith('<rope.base.pyobjectsdef.PyModule "" at 0x') - - - -def test_repr_pyobjectsdef_pypackage(project, mod1): - obj = project.get_module("pkg1") - assert isinstance(obj, pyobjectsdef.PyPackage) - assert repr(obj).startswith('<rope.base.pyobjectsdef.PyPackage "pkg1" at 0x') - - - -class _FunctionChangers: - @others - -def test_repr_pyobjectsdef_pypackage_without_associated_resource(project, mod1): - obj = pyobjectsdef.PyPackage(project.pycore) - assert isinstance(obj, pyobjectsdef.PyPackage) - assert repr(obj).startswith('<rope.base.pyobjectsdef.PyPackage "" at 0x') - - - -def test_repr_pyobjectsdef_pyfunction(project, mod1): - code = """def func(arg): pass""" - mod = libutils.get_string_module(project, code, mod1) - obj = mod.get_attribute("func").pyobject - assert isinstance(obj, pyobjectsdef.PyFunction) - assert repr(obj).startswith( - '<rope.base.pyobjectsdef.PyFunction "pkg1.mod1::func" at 0x' - ) - - - -def test_repr_pyobjectsdef_pyfunction_without_associated_resource(project): - code = """def func(arg): pass""" - mod = libutils.get_string_module(project, code) - obj = mod.get_attribute("func").pyobject - assert isinstance(obj, pyobjectsdef.PyFunction) - assert repr(obj).startswith('<rope.base.pyobjectsdef.PyFunction "::func" at 0x') - - - -def test_repr_pyobjectsdef_pyclass(project, mod1): - code = """class MyClass: pass""" - mod = libutils.get_string_module(project, code, mod1) - obj = mod.get_attribute("MyClass").pyobject - assert isinstance(obj, pyobjectsdef.PyClass) - assert repr(obj).startswith( - '<rope.base.pyobjectsdef.PyClass "pkg1.mod1::MyClass" at 0x' - ) - - - -def test_repr_pyobjectsdef_pyclass_without_associated_resource(project): - code = """class MyClass: pass""" - mod = libutils.get_string_module(project, code) - obj = mod.get_attribute("MyClass").pyobject - assert isinstance(obj, pyobjectsdef.PyClass) - assert repr(obj).startswith('<rope.base.pyobjectsdef.PyClass "::MyClass" at 0x') - - - -def test_repr_pyobjectsdef_pycomprehension(project, mod1): - code = """[a for a in b]""" - mod = libutils.get_string_module(project, code, mod1) - mod._create_structural_attributes() - assert len(mod.defineds) == 1 - obj = mod.defineds[0] - assert isinstance(obj, pyobjectsdef.PyComprehension) - assert repr(obj).startswith( - '<rope.base.pyobjectsdef.PyComprehension "pkg1.mod1::<comprehension>" at 0x' - ) - - - -def test_repr_pyobjectsdef_pycomprehension_without_associated_resource(project): - code = """[a for a in b]""" - mod = libutils.get_string_module(project, code) - mod._create_structural_attributes() - assert len(mod.defineds) == 1 - obj = mod.defineds[0] - assert isinstance(obj, pyobjectsdef.PyComprehension) - assert repr(obj).startswith( - '<rope.base.pyobjectsdef.PyComprehension "::<comprehension>" at 0x' - ) - -@path C:/Repos/ekr-rope/ropetest/ -import os -from textwrap import dedent - -import unittest - - -from rope.base import exceptions -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class PythonFileRunnerTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - - -def __init__(self, pyfunction, definition_info, changers=None): - self.pyfunction = pyfunction - self.definition_info = definition_info - self.changers = changers - self.changed_definition_infos = self._get_changed_definition_infos() - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def make_sample_python_file(self, file_path, get_text_function_source=None): - self.project.root.create_file(file_path) - file = self.project.get_resource(file_path) - if not get_text_function_source: - get_text_function_source = "def get_text():\n return 'run'\n\n" - file_content = ( - get_text_function_source + "output = open('output.txt', 'w')\n" - "output.write(get_text())\noutput.close()\n" - ) - file.write(file_content) - - -def get_output_file_content(self, file_path): - try: - output_path = "" - last_slash = file_path.rfind("/") - if last_slash != -1: - output_path = file_path[0 : last_slash + 1] - file = self.project.get_resource(output_path + "output.txt") - return file.read() - except exceptions.ResourceNotFoundError: - return "" - - -def test_making_runner(self): - file_path = "sample.py" - self.make_sample_python_file(file_path) - file_resource = self.project.get_resource(file_path) - runner = self.pycore.run_module(file_resource) - runner.wait_process() - self.assertEqual("run", self.get_output_file_content(file_path)) - - -def test_passing_arguments(self): - file_path = "sample.py" - function_source = dedent("""\ - import sys - def get_text(): - return str(sys.argv[1:]) - """) - self.make_sample_python_file(file_path, function_source) - file_resource = self.project.get_resource(file_path) - runner = self.pycore.run_module(file_resource, args=["hello", "world"]) - runner.wait_process() - self.assertTrue( - self.get_output_file_content(file_path).endswith("['hello', 'world']") - ) - - -def test_passing_arguments_with_spaces(self): - file_path = "sample.py" - function_source = dedent("""\ - import sys - def get_text(): - return str(sys.argv[1:]) - """) - self.make_sample_python_file(file_path, function_source) - file_resource = self.project.get_resource(file_path) - runner = self.pycore.run_module(file_resource, args=["hello world"]) - runner.wait_process() - self.assertTrue( - self.get_output_file_content(file_path).endswith("['hello world']") - ) - - -def test_killing_runner(self): - file_path = "sample.py" - code = dedent("""\ - def get_text(): - import time - time.sleep(1) - return 'run' - """) - self.make_sample_python_file( - file_path, - code, - ) - file_resource = self.project.get_resource(file_path) - runner = self.pycore.run_module(file_resource) - runner.kill_process() - self.assertEqual("", self.get_output_file_content(file_path)) - - -def test_running_nested_files(self): - self.project.root.create_folder("src") - file_path = "src/sample.py" - self.make_sample_python_file(file_path) - file_resource = self.project.get_resource(file_path) - runner = self.pycore.run_module(file_resource) - runner.wait_process() - self.assertEqual("run", self.get_output_file_content(file_path)) - - -def test_setting_process_input(self): - file_path = "sample.py" - code = dedent("""\ - def get_text(): - import sys - return sys.stdin.readline() - """) - self.make_sample_python_file(file_path, code) - temp_file_name = "processtest.tmp" - try: - temp_file = open(temp_file_name, "w") - temp_file.write("input text\n") - temp_file.close() - file_resource = self.project.get_resource(file_path) - stdin = open(temp_file_name) - runner = self.pycore.run_module(file_resource, stdin=stdin) - runner.wait_process() - stdin.close() - self.assertEqual("input text\n", self.get_output_file_content(file_path)) - finally: - os.remove(temp_file_name) - - -def test_setting_process_output(self): - file_path = "sample.py" - code = dedent("""\ - def get_text(): - print('output text') - return 'run' - """) - self.make_sample_python_file(file_path, code) - temp_file_name = "processtest.tmp" - try: - file_resource = self.project.get_resource(file_path) - stdout = open(temp_file_name, "w") - runner = self.pycore.run_module(file_resource, stdout=stdout) - runner.wait_process() - stdout.close() - temp_file = open(temp_file_name) - self.assertEqual("output text\n", temp_file.read()) - temp_file.close() - finally: - os.remove(temp_file_name) - - -@path C:/Repos/ekr-rope/rope/contrib/ -import rope.base.evaluate -from rope.base import libutils -from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze -from rope.refactor import sourceutils, importutils, functionutils, suites - - -@others -@language python -@tabwidth -4 - -def _get_changed_definition_infos(self): - result = [] - definition_info = self.definition_info - result.append(definition_info) - for changer in self.changers: - definition_info = copy.deepcopy(definition_info) - changer.change_definition_info(definition_info) - result.append(definition_info) - return result - - -def test_setting_pythonpath(self): - src = self.project.root.create_folder("src") - src.create_file("sample.py") - src.get_child("sample.py").write("def f():\n pass\n") - self.project.root.create_folder("test") - file_path = "test/test.py" - code = dedent("""\ - def get_text(): - import sample - sample.f() - return'run' - """) - self.make_sample_python_file(file_path, code) - file_resource = self.project.get_resource(file_path) - runner = self.pycore.run_module(file_resource) - runner.wait_process() - self.assertEqual("run", self.get_output_file_content(file_path)) - - -def test_making_runner_when_doi_is_disabled(self): - self.project.set("enable_doi", False) - file_path = "sample.py" - self.make_sample_python_file(file_path) - file_resource = self.project.get_resource(file_path) - runner = self.pycore.run_module(file_resource) - runner.wait_process() - self.assertEqual("run", self.get_output_file_content(file_path)) - -@path C:/Repos/ekr-rope/ropetest/ -import unittest - -from rope.base import simplify - - -@others -@language python -@tabwidth -4 - -class SimplifyTest(unittest.TestCase): - @others - -def test_trivial_case(self): - self.assertEqual("", simplify.real_code("")) - - -def test_empty_strs(self): - code = 's = ""\n' - self.assertEqual(code, simplify.real_code(code)) - - -def test_blanking_strs(self): - code = 's = "..."\n' - self.assertEqual('s = " "\n', simplify.real_code(code)) - - -def test_changing_to_double_quotes(self): - code = "s = ''\n" - self.assertEqual('s = ""\n', simplify.real_code(code)) - - -def test_changing_to_double_quotes2(self): - code = 's = """\n"""\n' - self.assertEqual('s = " "\n', simplify.real_code(code)) - - -def test_removing_comments(self): - code = "# c\n" - self.assertEqual(" \n", simplify.real_code(code)) - - -def change_definition(self, call): - return self.changed_definition_infos[-1].to_string() - - -def test_removing_comments_that_contain_strings(self): - code = '# "c"\n' - self.assertEqual(" \n", simplify.real_code(code)) - - -def test_removing_strings_containing_comments(self): - code = '"#c"\n' - self.assertEqual('" "\n', simplify.real_code(code)) - - -def test_joining_implicit_continuations(self): - code = "(\n)\n" - self.assertEqual("( )\n", simplify.real_code(code)) - - -def test_joining_explicit_continuations(self): - code = "1 + \\\n 2\n" - self.assertEqual("1 + 2\n", simplify.real_code(code)) - - -def test_replacing_tabs(self): - code = "1\t+\t2\n" - self.assertEqual("1 + 2\n", simplify.real_code(code)) - - -def test_replacing_semicolons(self): - code = "a = 1;b = 2\n" - self.assertEqual("a = 1\nb = 2\n", simplify.real_code(code)) - - -def test_simplifying_f_string(self): - code = 's = f"..{hello}.."\n' - self.assertEqual('s = f"..{hello}.."\n', simplify.real_code(code)) - - -def test_simplifying_f_string_containing_quotes(self): - code = """s = f"..'{hello}'.."\n""" - self.assertEqual("""s = f"..'{hello}'.."\n""", simplify.real_code(code)) - - -def test_simplifying_uppercase_f_string_containing_quotes(self): - code = """s = Fr"..'{hello}'.."\n""" - self.assertEqual("""s = Fr"..'{hello}'.."\n""", simplify.real_code(code)) - -@path C:/Repos/ekr-rope/ropetest/ -import os.path -import shutil -import sys -import logging - -logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) -import unittest - -import rope.base.project -from rope.contrib import generate - - -@others -@language python -@tabwidth -4 - -def change_call(self, primary, pyname, call): - call_info = functionutils.CallInfo.read( - primary, pyname, self.definition_info, call - ) - mapping = functionutils.ArgumentMapping(self.definition_info, call_info) - - for definition_info, changer in zip( - self.changed_definition_infos, self.changers - ): - changer.change_argument_mapping(definition_info, mapping) - - return mapping.to_call_info(self.changed_definition_infos[-1]).to_string() - - - -def sample_project(root=None, foldername=None, **kwds): - if root is None: - root = "sample_project" - if foldername: - root = foldername - # HACK: Using ``/dev/shm/`` for faster tests - if os.name == "posix": - if os.path.isdir("/dev/shm") and os.access("/dev/shm", os.W_OK): - root = "/dev/shm/" + root - elif os.path.isdir("/tmp") and os.access("/tmp", os.W_OK): - root = "/tmp/" + root - logging.debug("Using %s as root of the project.", root) - # Using these prefs for faster tests - prefs = { - "save_objectdb": False, - "save_history": False, - "validate_objectdb": False, - "automatic_soa": False, - "ignored_resources": [".ropeproject", "*.pyc"], - "import_dynload_stdmods": False, - } - prefs.update(kwds) - remove_recursively(root) - project = rope.base.project.Project(root, **prefs) - return project - - - -create_module = generate.create_module -create_package = generate.create_package - - - -def remove_project(project): - project.close() - remove_recursively(project.address) - - - -def remove_recursively(path): - import time - - # windows sometimes raises exceptions instead of removing files - if os.name == "nt" or sys.platform == "cygwin": - for i in range(12): - try: - _remove_recursively(path) - except OSError as e: - if e.errno not in (13, 16, 32): - raise - time.sleep(0.3) - else: - break - else: - _remove_recursively(path) - - - -def _remove_recursively(path): - if not os.path.exists(path): - return - if os.path.isfile(path): - os.remove(path) - else: - shutil.rmtree(path) - - - -def parse_version(version): - return tuple(map(int, version.split("."))) - - - -def only_for(version): - """Should be used as a decorator for a unittest.TestCase test method""" - return unittest.skipIf( - sys.version_info < parse_version(version), - "This test requires at least {0} version of Python.".format(version), - ) - - - -def only_for_versions_lower(version): - """Should be used as a decorator for a unittest.TestCase test method""" - return unittest.skipIf( - sys.version_info > parse_version(version), - "This test requires version of Python lower than {0}".format(version), - ) - - - -def only_for_versions_higher(version): - """Should be used as a decorator for a unittest.TestCase test method""" - return unittest.skipIf( - sys.version_info < parse_version(version), - "This test requires version of Python higher than {0}".format(version), - ) - - - -def skipNotPOSIX(): - return unittest.skipIf(os.name != "posix", "This test works only on POSIX") - - - -class _ArgumentChanger: - def change_definition_info(self, definition_info): - pass - - def change_argument_mapping(self, definition_info, argument_mapping): - pass - - - -def time_limit(timeout): - if not any(procname in sys.argv[0] for procname in {"pytest", "py.test"}): - # no-op when running tests without pytest - return lambda *args, **kwargs: lambda func: func - - # do a local import so we don't import pytest when running without pytest - import pytest - - # this prevents infinite loop/recursion from taking forever in CI - return pytest.mark.time_limit(timeout) - -@path C:/Repos/ekr-rope/ropetest/ -import unittest -from textwrap import dedent -from textwrap import dedent, indent - -import pytest - -from rope.base.oi.type_hinting import evaluate -from rope.contrib.codeassist import code_assist -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class AbstractHintingTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _assist(self, code, offset=None, resource=None, **kwds): - if offset is None: - offset = len(code) - return code_assist(self.project, code, offset, resource, **kwds) - - -def assert_completion_in_result(self, name, scope, result): - for proposal in result: - if proposal.name == name and proposal.scope == scope: - return - self.fail( - "completion <%s> in scope %r not proposed, available names: %r" - % (name, scope, [(i.name, i.scope) for i in result]) - ) - - -def assert_completion_not_in_result(self, name, scope, result): - for proposal in result: - if proposal.name == name and proposal.scope == scope: - self.fail("completion <%s> was proposed" % name) - - -def run(self, result=None): - if self.__class__.__name__.startswith("Abstract"): - return - super().run(result) - - - -class DocstringParamHintingTest(AbstractHintingTest): - @others - -class ArgumentNormalizer(_ArgumentChanger): - pass - - - -def test_hint_param(self): - code = dedent('''\ - class Sample(object): - def a_method(self, a_arg): - """:type a_arg: threading.Thread""" - a_arg.is_a''') - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hierarchical_hint_param(self): - code = dedent('''\ - class ISample(object): - def a_method(self, a_arg): - """:type a_arg: threading.Thread""" - - - class Sample(ISample): - def a_method(self, a_arg): - a_arg.is_a''') - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - - -class DocstringReturnHintingTest(AbstractHintingTest): - @others - -def test_hierarchical_hint_rtype(self): - code = dedent('''\ - class ISample(object): - def b_method(self): - """:rtype: threading.Thread""" - - - class Sample(ISample): - def b_method(self): - pass - def a_method(self): - self.b_method().is_a''') - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def fix_indents(hint): -return indent(hint, " " * 12).strip() - - - -class AbstractAssignmentHintingTest(AbstractHintingTest): - @others - -def _make_class_hint(self, type_str): - raise NotImplementedError - - -def _make_constructor_hint(self, type_str): - raise NotImplementedError - - -def test_hint_attr(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("threading.Thread"))} - def a_method(self): - self.a_attr.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hierarchical_hint_attr(self): - code = dedent(f"""\ - class ISample(object): - {fix_indents(self._make_class_hint("threading.Thread"))} - - - class Sample(ISample): - a_attr = None - def a_method(self): - self.a_attr.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_defined_by_constructor(self): - code = dedent(f"""\ - class Sample(object): - def __init__(self, arg): - {fix_indents(self._make_constructor_hint("threading.Thread"))} - def a_method(self): - self.a_attr.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -class ArgumentRemover(_ArgumentChanger): - @others - -def test_hint_attr_redefined_by_constructor(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("threading.Thread"))} - def __init__(self): - self.a_attr = None - def a_method(self): - self.a_attr.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hierarchical_hint_attr_redefined_by_constructor(self): - code = dedent(f"""\ - class ISample(object): - {fix_indents(self._make_class_hint("threading.Thread"))} - - - class Sample(ISample): - def __init__(self): - self.a_attr = None - def a_method(self): - self.a_attr.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_attr_for_pre_defined_type(self): - code = dedent(f"""\ - class Other(object): - def is_alive(self): - pass - - - class Sample(object): - {fix_indents(self._make_class_hint("Other"))} - def a_method(self): - self.a_attr.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_attr_for_post_defined_type(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("Other"))} - def a_method(self): - self.a_attr.is_a""") - offset = len(code) - code += dedent(f"""\ - - - class Other(object): - def is_alive(self): - pass - """) - result = self._assist(code, offset) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_parametrized_list(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("list[threading.Thread]"))} - def a_method(self): - for i in self.a_attr: - i.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_parametrized_tuple(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("tuple[threading.Thread]"))} - def a_method(self): - for i in self.a_attr: - i.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_parametrized_set(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("set[threading.Thread]"))} - def a_method(self): - for i in self.a_attr: - i.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_parametrized_iterable(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("collections.Iterable[threading.Thread]"))} - def a_method(self): - for i in self.a_attr: - i.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_parametrized_iterator(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("collections.Iterator[threading.Thread]"))} - def a_method(self): - for i in self.a_attr: - i.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_parametrized_dict_key(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("dict[str, threading.Thread]"))} - def a_method(self): - for i in self.a_attr.keys(): - i.sta""") - result = self._assist(code) - self.assert_completion_in_result("startswith", "builtin", result) - - -def __init__(self, index): - self.index = index - - -def test_hint_parametrized_dict_value(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("dict[str, threading.Thread]"))} - def a_method(self): - for i in self.a_attr.values(): - i.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_parametrized_nested_tuple_list(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("tuple[list[threading.Thread]]"))} - def a_method(self): - for j in self.a_attr: - for i in j: - i.is_a""") - result = self._assist(code) - self.assert_completion_in_result("is_alive", "attribute", result) - - -def test_hint_or(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("str | threading.Thread"))} - def a_method(self): - for i in self.a_attr.values(): - i.is_a""") - result = self._assist(code) - try: - # Be sure, there isn't errors currently - self.assert_completion_in_result('is_alive', 'attribute', result) - except AssertionError as e: - pytest.xfail("failing configuration (but should work)") - - -def test_hint_nonexistent(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("sdfdsf.asdfasdf.sdfasdf.Dffg"))} - def a_method(self): - for i in self.a_attr.values(): - i.is_a""") - result = self._assist(code) - self.assertEqual(result, []) - - -def test_hint_invalid_syntax(self): - code = dedent(f"""\ - class Sample(object): - {fix_indents(self._make_class_hint("sdf | & # &*"))} - def a_method(self): - for i in self.a_attr.values(): - i.is_a""") - result = self._assist(code) - self.assertEqual(result, []) - - - -class DocstringNoneAssignmentHintingTest(AbstractAssignmentHintingTest): - @others - -def _make_class_hint(self, type_str): - hint = dedent(f'''\ - """:type a_attr: {type_str}""" - a_attr = None - ''') - return indent(hint, " " * 4) - - -def _make_constructor_hint(self, type_str): - hint = dedent(f'''\ - """:type arg: {type_str}""" - self.a_attr = arg - ''') - return indent(hint, " " * 8) - - - -class DocstringNotImplementedAssignmentHintingTest(AbstractAssignmentHintingTest): - @others - -def _make_class_hint(self, type_str): - hint = dedent(f'''\ - """:type a_attr: {type_str}""" - a_attr = NotImplemented - ''') - return indent(hint, " " * 4) - - -def change_definition_info(self, call_info): - if self.index < len(call_info.args_with_defaults): - del call_info.args_with_defaults[self.index] - elif ( - self.index == len(call_info.args_with_defaults) - and call_info.args_arg is not None - ): - call_info.args_arg = None - elif ( - self.index == len(call_info.args_with_defaults) - and call_info.args_arg is None - and call_info.keywords_arg is not None - ) or ( - self.index == len(call_info.args_with_defaults) + 1 - and call_info.args_arg is not None - and call_info.keywords_arg is not None - ): - call_info.keywords_arg = None - - -def _make_constructor_hint(self, type_str): - hint = dedent(f'''\ - """:type arg: {type_str}""" - self.a_attr = arg - ''') - return indent(hint, " " * 8) - - - -class PEP0484CommentNoneAssignmentHintingTest(AbstractAssignmentHintingTest): - def _make_class_hint(self, type_str): - hint = dedent(f"""\ - a_attr = None # type: {type_str} - """) - return indent(hint, " " * 4) - - def _make_constructor_hint(self, type_str): - hint = dedent(f"""\ - self.a_attr = None # type: {type_str} - """) - return indent(hint, " " * 8) - - - -class PEP0484CommentNotImplementedAssignmentHintingTest(AbstractAssignmentHintingTest): - def _make_class_hint(self, type_str): - hint = dedent(f"""\ - a_attr = NotImplemented # type: {type_str} - """) - return indent(hint, " " * 4) - - def _make_constructor_hint(self, type_str): - hint = dedent(f"""\ - self.a_attr = NotImplemented # type: {type_str} - """) - return indent(hint, " " * 8) - - - -class EvaluateTest(unittest.TestCase): - @others - -def test_parser(self): - tests = [ - ("Foo", "(name Foo)"), - ("mod1.Foo", "(name mod1.Foo)"), - ("mod1.mod2.Foo", "(name mod1.mod2.Foo)"), - ("Foo[Bar]", "('[' (name Foo) [(name Bar)])"), - ( - "Foo[Bar1, Bar2, Bar3]", - "('[' (name Foo) [(name Bar1), (name Bar2), (name Bar3)])", - ), - ("Foo[Bar[Baz]]", "('[' (name Foo) [('[' (name Bar) [(name Baz)])])"), - ( - "Foo[Bar1[Baz1], Bar2[Baz2]]", - "('[' (name Foo) [('[' (name Bar1) [(name Baz1)]), ('[' (name Bar2) [(name Baz2)])])", - ), - ("mod1.mod2.Foo[Bar]", "('[' (name mod1.mod2.Foo) [(name Bar)])"), - ( - "mod1.mod2.Foo[mod1.mod2.Bar]", - "('[' (name mod1.mod2.Foo) [(name mod1.mod2.Bar)])", - ), - ( - "mod1.mod2.Foo[Bar1, Bar2, Bar3]", - "('[' (name mod1.mod2.Foo) [(name Bar1), (name Bar2), (name Bar3)])", - ), - ( - "mod1.mod2.Foo[mod1.mod2.Bar[mod1.mod2.Baz]]", - "('[' (name mod1.mod2.Foo) [('[' (name mod1.mod2.Bar) [(name mod1.mod2.Baz)])])", - ), - ( - "mod1.mod2.Foo[mod1.mod2.Bar1[mod1.mod2.Baz1], mod1.mod2.Bar2[mod1.mod2.Baz2]]", - "('[' (name mod1.mod2.Foo) [('[' (name mod1.mod2.Bar1) [(name mod1.mod2.Baz1)]), ('[' (name mod1.mod2.Bar2) [(name mod1.mod2.Baz2)])])", - ), - ("(Foo, Bar) -> Baz", "('(' [(name Foo), (name Bar)] (name Baz))"), - ( - "(mod1.mod2.Foo[mod1.mod2.Bar1[mod1.mod2.Baz1], mod1.mod2.Bar2[mod1.mod2.Baz2]], mod1.mod2.Bar[mod1.mod2.Bar1[mod1.mod2.Baz1], mod1.mod2.Bar2[mod1.mod2.Baz2]]) -> mod1.mod2.Baz[mod1.mod2.Bar1[mod1.mod2.Baz1], mod1.mod2.Bar2[mod1.mod2.Baz2]]", - "('(' [('[' (name mod1.mod2.Foo) [('[' (name mod1.mod2.Bar1) [(name mod1.mod2.Baz1)]), ('[' (name mod1.mod2.Bar2) [(name mod1.mod2.Baz2)])]), ('[' (name mod1.mod2.Bar) [('[' (name mod1.mod2.Bar1) [(name mod1.mod2.Baz1)]), ('[' (name mod1.mod2.Bar2) [(name mod1.mod2.Baz2)])])] ('[' (name mod1.mod2.Baz) [('[' (name mod1.mod2.Bar1) [(name mod1.mod2.Baz1)]), ('[' (name mod1.mod2.Bar2) [(name mod1.mod2.Baz2)])]))", - ), - ( - "(Foo, Bar) -> Baz | Foo[Bar[Baz]]", - "('|' ('(' [(name Foo), (name Bar)] (name Baz)) ('[' (name Foo) [('[' (name Bar) [(name Baz)])]))", - ), - ( - "Foo[Bar[Baz | (Foo, Bar) -> Baz]]", - "('[' (name Foo) [('[' (name Bar) [('|' (name Baz) ('(' [(name Foo), (name Bar)] (name Baz)))])])", - ), - ] - - for t, expected in tests: - result = repr(evaluate.compile(t)) - self.assertEqual(expected, result) - - - -class RegressionHintingTest(AbstractHintingTest): - @others - -def test_hierarchical_hint_for_mutable_attr_type(self): - """Test for #157, AttributeError: 'PyObject' object has no attribute 'get_doc'""" - code = dedent("""\ - class SuperClass(object): - def __init__(self): - self.foo = None - - - class SubClass(SuperClass): - def __init__(self): - super(SubClass, self).__init__() - self.bar = 3 - - - def foo(self): - return self.bar""") - result = self._assist(code) - self.assert_completion_in_result("bar", "attribute", result) - -@path C:/Repos/ekr-rope/ropetest/ -import sys - -import unittest - -import ropetest.projecttest -import ropetest.codeanalyzetest -import ropetest.doatest -import ropetest.type_hinting_test -import ropetest.pycoretest -import ropetest.pyscopestest -import ropetest.objectinfertest -import ropetest.objectdbtest -import ropetest.advanced_oi_test -import ropetest.runmodtest -import ropetest.builtinstest -import ropetest.historytest -import ropetest.simplifytest - -import ropetest.contrib -import ropetest.refactor - - -@others -if __name__ == "__main__": - runner = unittest.TextTestRunner() - result = runner.run(suite()) - sys.exit(not result.wasSuccessful()) -@language python -@tabwidth -4 - -def suite(): - result = unittest.TestSuite() - result.addTests(ropetest.projecttest.suite()) - result.addTests(ropetest.codeanalyzetest.suite()) - result.addTests(ropetest.doatest.suite()) - result.addTests(ropetest.type_hinting_test.suite()) - result.addTests(ropetest.pycoretest.suite()) - result.addTests(ropetest.pyscopestest.suite()) - result.addTests(ropetest.objectinfertest.suite()) - result.addTests(ropetest.objectdbtest.suite()) - result.addTests(ropetest.advanced_oi_test.suite()) - result.addTests(ropetest.runmodtest.suite()) - result.addTests(ropetest.builtinstest.suite()) - result.addTests(ropetest.historytest.suite()) - result.addTests(ropetest.simplifytest.suite()) - - result.addTests(ropetest.refactor.suite()) - result.addTests(ropetest.contrib.suite()) - - return result - - - - -def change_argument_mapping(self, definition_info, mapping): - if self.index < len(definition_info.args_with_defaults): - name = definition_info.args_with_defaults[0] - if name in mapping.param_dict: - del mapping.param_dict[name] - - - -@path C:/Repos/ekr-rope/ropetest/contrib/ -import unittest - -from rope.contrib.autoimport import sqlite as autoimport -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class AutoImportTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project(extension_modules=["sys"]) - self.mod1 = testutils.create_module(self.project, "mod1") - self.pkg = testutils.create_package(self.project, "pkg") - self.mod2 = testutils.create_module(self.project, "mod2", self.pkg) - self.importer = autoimport.AutoImport(self.project, observe=False) - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_case(self): - self.assertEqual([], self.importer.import_assist("A")) - - -def test_update_resource(self): - self.mod1.write("myvar = None\n") - self.importer.update_resource(self.mod1) - self.assertEqual([("myvar", "mod1")], self.importer.import_assist("myva")) - - -def test_update_non_existent_module(self): - self.importer.update_module("does_not_exists_this") - self.assertEqual([], self.importer.import_assist("myva")) - - -def test_module_with_syntax_errors(self): - self.mod1.write("this is a syntax error\n") - self.importer.update_resource(self.mod1) - self.assertEqual([], self.importer.import_assist("myva")) - - -def test_excluding_imported_names(self): - self.mod1.write("import pkg\n") - self.importer.update_resource(self.mod1) - self.assertEqual([], self.importer.import_assist("pkg")) - - -def test_get_modules(self): - self.mod1.write("myvar = None\n") - self.importer.update_resource(self.mod1) - self.assertEqual(["mod1"], self.importer.get_modules("myvar")) - - -class ArgumentAdder(_ArgumentChanger): - @others - -def test_get_modules_inside_packages(self): - self.mod1.write("myvar = None\n") - self.mod2.write("myvar = None\n") - self.importer.update_resource(self.mod1) - self.importer.update_resource(self.mod2) - self.assertEqual({"mod1", "pkg.mod2"}, set(self.importer.get_modules("myvar"))) - - -def test_trivial_insertion_line(self): - result = self.importer.find_insertion_line("") - self.assertEqual(1, result) - - -def test_insertion_line(self): - result = self.importer.find_insertion_line("import mod\n") - self.assertEqual(2, result) - - -def test_insertion_line_with_pydocs(self): - result = self.importer.find_insertion_line('"""docs\n\ndocs"""\nimport mod\n') - self.assertEqual(5, result) - - -def test_insertion_line_with_multiple_imports(self): - result = self.importer.find_insertion_line("import mod1\n\nimport mod2\n") - self.assertEqual(4, result) - - -def test_insertion_line_with_blank_lines(self): - result = self.importer.find_insertion_line("import mod1\n\n# comment\n") - self.assertEqual(2, result) - - -def test_empty_cache(self): - self.mod1.write("myvar = None\n") - self.importer.update_resource(self.mod1) - self.assertEqual(["mod1"], self.importer.get_modules("myvar")) - self.importer.clear_cache() - self.assertEqual([], self.importer.get_modules("myvar")) - - -def test_not_caching_underlined_names(self): - self.mod1.write("_myvar = None\n") - self.importer.update_resource(self.mod1, underlined=False) - self.assertEqual([], self.importer.get_modules("_myvar")) - self.importer.update_resource(self.mod1, underlined=True) - self.assertEqual(["mod1"], self.importer.get_modules("_myvar")) - - -def test_caching_underlined_names_passing_to_the_constructor(self): - importer = autoimport.AutoImport(self.project, False, True) - self.mod1.write("_myvar = None\n") - importer.update_resource(self.mod1) - self.assertEqual(["mod1"], importer.get_modules("_myvar")) - - -def test_name_locations(self): - self.mod1.write("myvar = None\n") - self.importer.update_resource(self.mod1) - self.assertEqual([(self.mod1, 1)], self.importer.get_name_locations("myvar")) - - -def __init__(self, project, code, resource, maxfixes=1): - self.project = project - self.code = code - self.resource = resource - self.maxfixes = maxfixes - - -def create_generate(kind, project, resource, offset, goal_resource=None): - """A factory for creating `Generate` objects - - `kind` can be 'variable', 'function', 'class', 'module' or - 'package'. - - """ - generate = eval("Generate" + kind.title()) - return generate(project, resource, offset, goal_resource=goal_resource) - - - -def __init__(self, index, name, default=None, value=None): - self.index = index - self.name = name - self.default = default - self.value = value - - -def test_name_locations_with_multiple_occurrences(self): - self.mod1.write("myvar = None\n") - self.mod2.write("\nmyvar = None\n") - self.importer.update_resource(self.mod1) - self.importer.update_resource(self.mod2) - self.assertEqual( - {(self.mod1, 1), (self.mod2, 2)}, - set(self.importer.get_name_locations("myvar")), - ) - - -def test_handling_builtin_modules(self): - self.importer.update_module("sys") - self.assertIn("sys", self.importer.get_modules("exit")) - - -def test_search_submodule(self): - self.importer.update_module("build") - import_statement = ("from build import env", "env") - self.assertIn(import_statement, self.importer.search("env", exact_match=True)) - self.assertIn(import_statement, self.importer.search("en")) - self.assertIn(import_statement, self.importer.search("env")) - - -def test_search_module(self): - self.importer.update_module("os") - import_statement = ("import os", "os") - self.assertIn(import_statement, self.importer.search("os", exact_match=True)) - self.assertIn(import_statement, self.importer.search("os")) - self.assertIn(import_statement, self.importer.search("o")) - - -def test_search(self): - self.importer.update_module("typing") - import_statement = ("from typing import Dict", "Dict") - self.assertIn(import_statement, self.importer.search("Dict", exact_match=True)) - self.assertIn(import_statement, self.importer.search("Dict")) - self.assertIn(import_statement, self.importer.search("Dic")) - self.assertIn(import_statement, self.importer.search("Di")) - self.assertIn(import_statement, self.importer.search("D")) - - -def test_generate_full_cache(self): - """The single thread test takes much longer than the multithread test but is easier to debug""" - single_thread = False - self.importer.generate_modules_cache(single_thread=single_thread) - self.assertIn(("from typing import Dict", "Dict"), self.importer.search("Dict")) - self.assertTrue(len(self.importer._dump_all()) > 0) - for table in self.importer._dump_all(): - self.assertTrue(len(table) > 0) - - - -class AutoImportObservingTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.mod1 = testutils.create_module(self.project, "mod1") - self.pkg = testutils.create_package(self.project, "pkg") - self.mod2 = testutils.create_module(self.project, "mod2", self.pkg) - self.importer = autoimport.AutoImport(self.project, observe=True) - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_writing_files(self): - self.mod1.write("myvar = None\n") - self.assertEqual(["mod1"], self.importer.get_modules("myvar")) - - -def change_definition_info(self, definition_info): - for pair in definition_info.args_with_defaults: - if pair[0] == self.name: - raise rope.base.exceptions.RefactoringError( - "Adding duplicate parameter: <%s>." % self.name - ) - definition_info.args_with_defaults.insert(self.index, (self.name, self.default)) - - -def test_moving_files(self): - self.mod1.write("myvar = None\n") - self.mod1.move("mod3.py") - self.assertEqual(["mod3"], self.importer.get_modules("myvar")) - - -def test_removing_files(self): - self.mod1.write("myvar = None\n") - self.mod1.remove() - self.assertEqual([], self.importer.get_modules("myvar")) - -@path C:/Repos/ekr-rope/ropetest/contrib/ -import unittest - - -import rope.base.history -import rope.contrib.changestack -import rope.base.change -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class ChangeStackTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_change_stack(self): - myfile = self.project.root.create_file("myfile.txt") - myfile.write("1") - stack = rope.contrib.changestack.ChangeStack(self.project) - stack.push(rope.base.change.ChangeContents(myfile, "2")) - self.assertEqual("2", myfile.read()) - stack.push(rope.base.change.ChangeContents(myfile, "3")) - self.assertEqual("3", myfile.read()) - stack.pop_all() - self.assertEqual("1", myfile.read()) - changes = stack.merged() - self.project.do(changes) - self.assertEqual("3", myfile.read()) - -@path C:/Repos/ekr-rope/ropetest/contrib/ -import os.path -from textwrap import dedent - -import unittest - -from rope.base import exceptions -from rope.contrib.codeassist import ( - get_definition_location, - get_doc, - starting_expression, - code_assist, - sorted_proposals, - starting_offset, - get_calltip, - get_canonical_path, -) -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class CodeAssistTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - -def change_argument_mapping(self, definition_info, mapping): - if self.value is not None: - mapping.param_dict[self.name] = self.value - - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _assist(self, code, offset=None, **args): - if offset is None: - offset = len(code) - return code_assist(self.project, code, offset, **args) - - -def test_simple_assist(self): - self._assist("", 0) - - -def assert_completion_in_result(self, name, scope, result, type=None): - for proposal in result: - if proposal.name == name: - self.assertEqual( - scope, - proposal.scope, - "proposal <%s> has wrong scope, expected " - "%r, got %r" % (name, scope, proposal.scope), - ) - if type is not None: - self.assertEqual( - type, - proposal.type, - "proposal <%s> has wrong type, expected " - "%r, got %r" % (name, type, proposal.type), - ) - return - self.fail("completion <%s> not proposed" % name) - - -def assert_completion_not_in_result(self, name, scope, result): - for proposal in result: - if proposal.name == name and proposal.scope == scope: - self.fail("completion <%s> was proposed" % name) - - -def test_completing_global_variables(self): - code = dedent("""\ - my_global = 10 - t = my""") - result = self._assist(code) - self.assert_completion_in_result("my_global", "global", result) - - -def test_not_proposing_unmatched_vars(self): - code = dedent("""\ - my_global = 10 - t = you""") - result = self._assist(code) - self.assert_completion_not_in_result("my_global", "global", result) - - -def test_not_proposing_unmatched_vars_with_underlined_starting(self): - code = dedent("""\ - my_global = 10 - t = your_""") - result = self._assist(code) - self.assert_completion_not_in_result("my_global", "global", result) - - -def test_not_proposing_local_assigns_as_global_completions(self): - code = dedent("""\ - def f(): my_global = 10 - t = my_""") - result = self._assist(code) - self.assert_completion_not_in_result("my_global", "global", result) - - -def test_proposing_functions(self): - code = dedent("""\ - def my_func(): return 2 - t = my_""") - result = self._assist(code) - self.assert_completion_in_result("my_func", "global", result) - - -class ArgumentDefaultInliner(_ArgumentChanger): - @others - -def test_proposing_classes(self): - code = dedent("""\ - class Sample(object): pass - t = Sam""") - result = self._assist(code) - self.assert_completion_in_result("Sample", "global", result) - - -def test_proposing_each_name_at_most_once(self): - code = dedent("""\ - variable = 10 - variable = 20 - t = vari""") - result = self._assist(code) - count = len([x for x in result if x.name == "variable" and x.scope == "global"]) - self.assertEqual(1, count) - - -def test_throwing_exception_in_case_of_syntax_errors(self): - code = dedent("""\ - sample (sdf+) - """) - with self.assertRaises(exceptions.ModuleSyntaxError): - self._assist(code, maxfixes=0) - - -def test_fixing_errors_with_maxfixes(self): - code = dedent("""\ - def f(): - sldj sldj - def g(): - ran""") - result = self._assist(code, maxfixes=2) - self.assertTrue(len(result) > 0) - - -def test_ignoring_errors_in_current_line(self): - code = dedent("""\ - def my_func(): - return 2 - t = """) - result = self._assist(code) - self.assert_completion_in_result("my_func", "global", result) - - -def test_not_reporting_variables_in_current_line(self): - code = dedent("""\ - def my_func(): return 2 - t = my_""") - result = self._assist(code) - self.assert_completion_not_in_result("my_", "global", result) - - -def test_completion_result(self): - code = dedent("""\ - my_global = 10 - t = my""") - self.assertEqual(len(code) - 2, starting_offset(code, len(code))) - - -def test_completing_imported_names(self): - code = dedent("""\ - import sys - a = sy""") - result = self._assist(code) - self.assert_completion_in_result("sys", "imported", result) - - -def test_completing_imported_names_with_as(self): - code = dedent("""\ - import sys as mysys - a = mys""") - result = self._assist(code) - self.assert_completion_in_result("mysys", "imported", result) - - -def test_not_completing_imported_names_with_as(self): - code = dedent("""\ - import sys as mysys - a = sy""") - result = self._assist(code) - self.assert_completion_not_in_result("sys", "global", result) - - -def __init__(self, index): - self.index = index - self.remove = False - - -def test_including_matching_builtins_types(self): - code = "my_var = Excep" - result = self._assist(code) - self.assert_completion_in_result("Exception", "builtin", result) - self.assert_completion_not_in_result("zip", "builtin", result) - - -def test_including_matching_builtins_functions(self): - code = "my_var = zi" - result = self._assist(code) - self.assert_completion_in_result("zip", "builtin", result) - - -def test_builtin_instances(self): - # ``import_dynload_stdmods`` pref is disabled for test project. - # we need to have it enabled to make pycore._find_module() - # load ``sys`` module. - self.project.prefs["import_dynload_stdmods"] = True - code = dedent("""\ - from sys import stdout - stdout.wr""") - result = self._assist(code) - self.assert_completion_in_result("write", "builtin", result) - self.assert_completion_in_result("writelines", "builtin", result) - - -def test_including_keywords(self): - code = "fo" - result = self._assist(code) - self.assert_completion_in_result("for", "keyword", result) - - -def test_not_reporting_proposals_after_dot(self): - code = dedent("""\ - a_dict = {} - key = 3 - a_dict.ke""") - result = self._assist(code) - self.assert_completion_not_in_result("key", "global", result) - - -def test_proposing_local_variables_in_functions(self): - code = dedent("""\ - def f(self): - my_var = 10 - my_""") - result = self._assist(code) - self.assert_completion_in_result("my_var", "local", result) - - -def test_local_variables_override_global_ones(self): - code = dedent("""\ - my_var = 20 - def f(self): - my_var = 10 - my_""") - result = self._assist(code) - self.assert_completion_in_result("my_var", "local", result) - - -def test_not_including_class_body_variables(self): - code = dedent("""\ - class C(object): - my_var = 20 - def f(self): - a = 20 - my_""") - result = self._assist(code) - self.assert_completion_not_in_result("my_var", "local", result) - - -def test_nested_functions(self): - code = dedent("""\ - def my_func(): - func_var = 20 - def inner_func(): - a = 20 - func""") - result = self._assist(code) - self.assert_completion_in_result("func_var", "local", result) - - -def test_scope_endpoint_selection(self): - code = dedent("""\ - def my_func(): - func_var = 20 - """) - result = self._assist(code) - self.assert_completion_not_in_result("func_var", "local", result) - - -def change_definition_info(self, definition_info): - if self.remove: - definition_info.args_with_defaults[self.index] = ( - definition_info.args_with_defaults[self.index][0], - None, - ) - - -def test_scope_better_endpoint_selection(self): - code = dedent("""\ - if True: - def f(): - my_var = 10 - my_""") - result = self._assist(code) - self.assert_completion_not_in_result("my_var", "local", result) - - -def test_imports_inside_function(self): - code = dedent("""\ - def f(): - import sys - sy""") - result = self._assist(code) - self.assert_completion_in_result("sys", "imported", result) - - -def test_imports_inside_function_dont_mix_with_globals(self): - code = dedent("""\ - def f(): - import sys - sy""") - result = self._assist(code) - self.assert_completion_not_in_result("sys", "local", result) - - -def test_nested_classes_local_names(self): - code = dedent("""\ - global_var = 10 - def my_func(): - func_var = 20 - class C(object): - def another_func(self): - local_var = 10 - func""") - result = self._assist(code) - self.assert_completion_in_result("func_var", "local", result) - - -def test_nested_classes_global(self): - code = dedent("""\ - global_var = 10 - def my_func(): - func_var = 20 - class C(object): - def another_func(self): - local_var = 10 - globa""") - result = self._assist(code) - self.assert_completion_in_result("global_var", "global", result) - - -def test_nested_classes_global_function(self): - code = dedent("""\ - global_var = 10 - def my_func(): - func_var = 20 - class C(object): - def another_func(self): - local_var = 10 - my_f""") - result = self._assist(code) - self.assert_completion_in_result("my_func", "global", result) - - -def test_proposing_function_parameters_in_functions(self): - code = dedent("""\ - def my_func(my_param): - my_var = 20 - my_""") - result = self._assist(code) - self.assert_completion_in_result("my_param", "local", result) - - -def test_proposing_function_keyword_parameters_in_functions(self): - code = dedent("""\ - def my_func(my_param, *my_list, **my_kws): - my_var = 20 - my_""") - result = self._assist(code) - self.assert_completion_in_result("my_param", "local", result) - self.assert_completion_in_result("my_list", "local", result) - self.assert_completion_in_result("my_kws", "local", result) - - -def test_not_proposing_unmatching_function_parameters_in_functions(self): - code = dedent("""\ - def my_func(my_param): - my_var = 20 - you_""") - result = self._assist(code) - self.assert_completion_not_in_result("my_param", "local", result) - - -def test_ignoring_current_statement(self): - code = dedent("""\ - my_var = 10 - my_tuple = (10, - my_""") - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def change_argument_mapping(self, definition_info, mapping): - default = definition_info.args_with_defaults[self.index][1] - name = definition_info.args_with_defaults[self.index][0] - if default is not None and name not in mapping.param_dict: - mapping.param_dict[name] = default - - - -def test_ignoring_current_statement_brackets_continuation(self): - code = dedent("""\ - my_var = 10 - 'hello'[10: - my_""") - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def test_ignoring_current_statement_explicit_continuation(self): - code = dedent("""\ - my_var = 10 - my_var2 = 2 + \\ - my_""") - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def test_ignor_current_statement_while_the_first_stmnt_of_the_block(self): - code = dedent("""\ - my_var = 10 - def f(): - my_""") - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def test_ignor_current_stmnt_while_current_line_ends_with_a_colon(self): - code = dedent("""\ - my_var = 10 - if my_: - pass""") - result = self._assist(code, 18) - self.assert_completion_in_result("my_var", "global", result) - - -def test_ignoring_string_contents(self): - code = "my_var = '('\nmy_" - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def test_ignoring_comment_contents(self): - code = "my_var = 10 #(\nmy_" - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def test_ignoring_string_contents_backslash_plus_quotes(self): - code = "my_var = '\\''\nmy_" - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def test_ignoring_string_contents_backslash_plus_backslash(self): - code = "my_var = '\\\\'\nmy_" - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def test_not_proposing_later_defined_variables_in_current_block(self): - code = dedent("""\ - my_ - my_var = 10 - """) - result = self._assist(code, 3, later_locals=False) - self.assert_completion_not_in_result("my_var", "global", result) - - -def test_not_proposing_later_defined_variables_in_current_function(self): - code = dedent("""\ - def f(): - my_ - my_var = 10 - """) - result = self._assist(code, 16, later_locals=False) - self.assert_completion_not_in_result("my_var", "local", result) - - -class ArgumentReorderer(_ArgumentChanger): - @others - -def test_ignoring_string_contents_with_triple_quotes(self): - code = "my_var = '''(\n'('''\nmy_" - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def test_ignoring_string_contents_with_triple_quotes_and_backslash(self): - code = 'my_var = """\\"""("""\nmy_' - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def test_ignor_str_contents_with_triple_quotes_and_double_backslash(self): - code = 'my_var = """\\\\"""\nmy_' - result = self._assist(code) - self.assert_completion_in_result("my_var", "global", result) - - -def test_reporting_params_when_in_the_first_line_of_a_function(self): - code = dedent("""\ - def f(param): - para""") - result = self._assist(code) - self.assert_completion_in_result("param", "local", result) - - -def test_code_assist_when_having_a_two_line_function_header(self): - code = dedent("""\ - def f(param1, - param2): - para""") - result = self._assist(code) - self.assert_completion_in_result("param1", "local", result) - - -def test_code_assist_with_function_with_two_line_return(self): - code = dedent("""\ - def f(param1, param2): - return(param1, - para""") - result = self._assist(code) - self.assert_completion_in_result("param2", "local", result) - - -def test_get_definition_location(self): - code = dedent("""\ - def a_func(): - pass - a_func()""") - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, 1), result) - - -def test_get_definition_location_underlined_names(self): - code = dedent("""\ - def a_sample_func(): - pass - a_sample_func()""") - result = get_definition_location(self.project, code, len(code) - 11) - self.assertEqual((None, 1), result) - - -def test_get_definition_location_dotted_names_method(self): - code = dedent("""\ - class AClass(object): - @staticmethod - def a_method(): - pass - AClass.a_method()""") - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, 3), result) - - -def test_get_definition_location_dotted_names_property(self): - code = dedent("""\ - class AClass(object): - @property - @somedecorator - def a_method(): - pass - AClass.a_method()""") - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, 4), result) - - -def __init__(self, new_order, autodef=None): - """Construct an `ArgumentReorderer` - - Note that the `new_order` is a list containing the new - position of parameters; not the position each parameter - is going to be moved to. (changed in ``0.5m4``) - - For example changing ``f(a, b, c)`` to ``f(c, a, b)`` - requires passing ``[2, 0, 1]`` and *not* ``[1, 2, 0]``. - - The `autodef` (automatic default) argument, forces rope to use - it as a default if a default is needed after the change. That - happens when an argument without default is moved after - another that has a default value. Note that `autodef` should - be a string or `None`; the latter disables adding automatic - default. - - """ - self.new_order = new_order - self.autodef = autodef - - -def test_get_definition_location_dotted_names_free_function(self): - code = dedent("""\ - @custom_decorator - def a_method(): - pass - a_method()""") - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, 2), result) - - -@testutils.only_for_versions_higher("3.5") -def test_get_definition_location_dotted_names_async_def(self): - code = dedent("""\ - class AClass(object): - @property - @decorator2 - async def a_method(): - pass - AClass.a_method()""") - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, 4), result) - - -def test_get_definition_location_dotted_names_class(self): - code = dedent("""\ - @custom_decorator - class AClass(object): - def a_method(): - pass - AClass.a_method()""") - result = get_definition_location(self.project, code, len(code) - 12) - self.assertEqual((None, 2), result) - - -def test_get_definition_location_dotted_names_with_space(self): - code = dedent("""\ - class AClass(object): - @staticmethod - def a_method(): - - pass - AClass.a_method()""") - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, 3), result) - - -def test_get_definition_location_dotted_names_inline_body(self): - code = dedent("""\ - class AClass(object): - @staticmethod - def a_method(): pass - AClass.a_method()""") - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, 3), result) - - -def test_get_definition_location_dotted_names_inline_body_split_arg(self): - code = dedent("""\ - class AClass(object): - @staticmethod - def a_method( - self, - arg1 - ): pass - AClass.a_method()""") - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, 3), result) - - -def test_get_definition_location_dotted_module_names(self): - module_resource = testutils.create_module(self.project, "mod") - module_resource.write("def a_func():\n pass\n") - code = "import mod\nmod.a_func()" - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((module_resource, 1), result) - - -def test_get_definition_location_for_nested_packages(self): - mod1 = testutils.create_module(self.project, "mod1") - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) - mod1.write("import pkg1.pkg2.mod2") - - init_dot_py = pkg2.get_child("__init__.py") - found_pyname = get_definition_location( - self.project, mod1.read(), mod1.read().index("pkg2") + 1 - ) - self.assertEqual(init_dot_py, found_pyname[0]) - - -def test_get_definition_location_unknown(self): - code = "a_func()\n" - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, None), result) - - -def test_get_definition_location_dot_spaces(self): - code = dedent("""\ - class AClass(object): - @staticmethod - def a_method(): - pass - AClass.\\ - a_method()""") - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, 3), result) - - -def change_definition_info(self, definition_info): - new_args = list(definition_info.args_with_defaults) - for new_index, index in enumerate(self.new_order): - new_args[new_index] = definition_info.args_with_defaults[index] - seen_default = False - for index, (arg, default) in enumerate(list(new_args)): - if default is not None: - seen_default = True - if seen_default and default is None and self.autodef is not None: - new_args[index] = (arg, self.autodef) - definition_info.args_with_defaults = new_args - - - -def test_get_definition_location_dot_line_break_inside_parens(self): - code = dedent("""\ - class A(object): - def a_method(self): - pass - (A. - a_method)""") - result = get_definition_location( - self.project, code, code.rindex("a_method") + 1 - ) - self.assertEqual((None, 2), result) - - -def test_if_scopes_in_other_scopes_for_get_definition_location(self): - code = dedent("""\ - def f(a_var): - pass - a_var = 10 - if True: - print(a_var) - """) - result = get_definition_location(self.project, code, len(code) - 3) - self.assertEqual((None, 3), result) - - -def test_get_definition_location_false_triple_quoted_string(self): - code = dedent('''\ - def foo(): - a = 0 - p = "foo""" - - def bar(): - a = 1 - a += 1 - ''') - result = get_definition_location(self.project, code, code.index("a += 1")) - self.assertEqual((None, 6), result) - - -def test_code_assists_in_parens(self): - code = dedent("""\ - def a_func(a_var): - pass - a_var = 10 - a_func(a_""") - result = self._assist(code) - self.assert_completion_in_result("a_var", "global", result) - - -def test_simple_type_inferencing(self): - code = dedent("""\ - class Sample(object): - def __init__(self, a_param): - pass - def a_method(self): - pass - Sample("hey").a_""") - result = self._assist(code) - self.assert_completion_in_result("a_method", "attribute", result) - - -def test_proposals_sorter(self): - code = dedent("""\ - def my_sample_function(self): - my_sample_var = 20 - my_sample_""") - proposals = sorted_proposals(self._assist(code)) - self.assertEqual("my_sample_var", proposals[0].name) - self.assertEqual("my_sample_function", proposals[1].name) - - -def test_proposals_sorter_for_methods_and_attributes(self): - code = dedent("""\ - class A(object): - def __init__(self): - self.my_a_var = 10 - def my_b_func(self): - pass - def my_c_func(self): - pass - a_var = A() - a_var.my_""") - proposals = sorted_proposals(self._assist(code)) - self.assertEqual("my_b_func", proposals[0].name) - self.assertEqual("my_c_func", proposals[1].name) - self.assertEqual("my_a_var", proposals[2].name) - - -def test_proposals_sorter_for_global_methods_and_funcs(self): - code = dedent("""\ - def my_b_func(self): - pass - my_a_var = 10 - my_""") - proposals = sorted_proposals(self._assist(code)) - self.assertEqual("my_b_func", proposals[0].name) - self.assertEqual("my_a_var", proposals[1].name) - - -def test_proposals_sorter_underlined_methods(self): - code = dedent("""\ - class A(object): - def _my_func(self): - self.my_a_var = 10 - def my_func(self): - pass - a_var = A() - a_var.""") - proposals = sorted_proposals(self._assist(code)) - self.assertEqual("my_func", proposals[0].name) - self.assertEqual("_my_func", proposals[1].name) - - -def test_proposals_sorter_and_scope_prefs(self): - code = dedent("""\ - my_global_var = 1 - def func(self): - my_local_var = 2 - my_""") - result = self._assist(code) - proposals = sorted_proposals(result, scopepref=["global", "local"]) - self.assertEqual("my_global_var", proposals[0].name) - self.assertEqual("my_local_var", proposals[1].name) - - -def create_module(project, name, sourcefolder=None): - """Creates a module and returns a `rope.base.resources.File`""" - if sourcefolder is None: - sourcefolder = project.root - packages = name.split(".") - parent = sourcefolder - for package in packages[:-1]: - parent = parent.get_child(package) - return parent.create_file(packages[-1] + ".py") - - - -class _ChangeCallsInModule: - @others - -def test_proposals_sorter_and_type_prefs(self): - code = dedent("""\ - my_global_var = 1 - def my_global_func(self): - pass - my_""") - result = self._assist(code) - proposals = sorted_proposals(result, typepref=["instance", "function"]) - self.assertEqual("my_global_var", proposals[0].name) - self.assertEqual("my_global_func", proposals[1].name) - - -def test_proposals_sorter_and_missing_type_in_typepref(self): - code = dedent("""\ - my_global_var = 1 - def my_global_func(): - pass - my_""") - result = self._assist(code) - proposals = sorted_proposals(result, typepref=["function"]) # noqa - - -def test_get_pydoc_unicode(self): - src = dedent('''\ - # coding: utf-8 - def foo(): - u"юникод-объект"''') - doc = get_doc(self.project, src, src.index("foo") + 1) - self.assertTrue(isinstance(doc, str)) - self.assertTrue("юникод-объект" in doc) - - -def test_get_pydoc_utf8_bytestring(self): - src = dedent('''\ - # coding: utf-8 - def foo(): - "байтстринг"''') - doc = get_doc(self.project, src, src.index("foo") + 1) - self.assertTrue(isinstance(doc, str)) - self.assertTrue("байтстринг" in doc) - - -def test_get_pydoc_for_functions(self): - src = dedent('''\ - def a_func(): - """a function""" - a_var = 10 - a_func()''') - self.assertTrue(get_doc(self.project, src, len(src) - 4).endswith("a function")) - get_doc(self.project, src, len(src) - 4).index("a_func()") - - -def test_get_pydoc_for_classes(self): - src = dedent("""\ - class AClass(object): - pass - """) - get_doc(self.project, src, src.index("AClass") + 1).index("AClass") - - -def test_get_pydoc_for_classes_with_init(self): - src = dedent("""\ - class AClass(object): - def __init__(self): - pass - """) - get_doc(self.project, src, src.index("AClass") + 1).index("AClass") - - -def test_get_pydoc_for_modules(self): - mod = testutils.create_module(self.project, "mod") - mod.write('"""a module"""\n') - src = "import mod\nmod" - self.assertEqual("a module", get_doc(self.project, src, len(src) - 1)) - - -def test_get_pydoc_for_builtins(self): - src = "print(object)\n" - self.assertTrue(get_doc(self.project, src, src.index("obj")) is not None) - - -def test_get_pydoc_for_methods_should_include_class_name(self): - src = dedent('''\ - class AClass(object): - def a_method(self): - """hey""" - pass - ''') - doc = get_doc(self.project, src, src.index("a_method") + 1) - doc.index("AClass.a_method") - doc.index("hey") - - -def __init__(self, project, occurrence_finder, resource, call_changer): - self.project = project - self.occurrence_finder = occurrence_finder - self.resource = resource - self.call_changer = call_changer - - -def test_get_pydoc_for_meths_should_inc_methods_from_super_classes(self): - src = dedent('''\ - class A(object): - def a_method(self): - """hey1""" - pass - class B(A): - def a_method(self): - """hey2""" - pass - ''') - doc = get_doc(self.project, src, src.rindex("a_method") + 1) - doc.index("A.a_method") - doc.index("hey1") - doc.index("B.a_method") - doc.index("hey2") - - -def test_get_pydoc_for_classes_should_name_super_classes(self): - src = dedent("""\ - class A(object): - pass - class B(A): - pass - """) - doc = get_doc(self.project, src, src.rindex("B") + 1) - doc.index("B(A)") - - -def test_get_pydoc_for_builtin_functions(self): - src = dedent("""\ - s = "hey" - s.replace - """) - doc = get_doc(self.project, src, src.rindex("replace") + 1) - self.assertTrue(doc is not None) - - -def test_commenting_errors_before_offset(self): - src = dedent("""\ - lsjd lsjdf - s = "hey" - s.replace() - """) - doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa - - -def test_proposing_variables_defined_till_the_end_of_scope(self): - code = dedent("""\ - if True: - a_v - a_var = 10 - """) - result = self._assist(code, code.index("a_v") + 3) - self.assert_completion_in_result("a_var", "global", result) - - -def test_completing_in_uncomplete_try_blocks(self): - code = dedent("""\ - try: - a_var = 10 - a_""") - result = self._assist(code) - self.assert_completion_in_result("a_var", "global", result) - - -def test_completing_in_uncomplete_try_blocks_in_functions(self): - code = dedent("""\ - def a_func(): - try: - a_var = 10 - a_""") - result = self._assist(code) - self.assert_completion_in_result("a_var", "local", result) - - -def test_already_complete_try_blocks_with_finally(self): - code = dedent("""\ - def a_func(): - try: - a_var = 10 - a_""") - result = self._assist(code) - self.assert_completion_in_result("a_var", "local", result) - - -def test_already_complete_try_blocks_with_finally2(self): - code = dedent("""\ - try: - a_var = 10 - a_ - finally: - pass - """) - result = self._assist(code, code.rindex("a_") + 2) - self.assert_completion_in_result("a_var", "global", result) - - -def test_already_complete_try_blocks_with_except(self): - code = dedent("""\ - try: - a_var = 10 - a_ - except Exception: - pass - """) - result = self._assist(code, code.rindex("a_") + 2) - self.assert_completion_in_result("a_var", "global", result) - - -def get_changed_module(self): - word_finder = worder.Worder(self.source) - change_collector = codeanalyze.ChangeCollector(self.source) - for occurrence in self.occurrence_finder.find_occurrences(self.resource): - if not occurrence.is_called() and not occurrence.is_defined(): - continue - start, end = occurrence.get_primary_range() - begin_parens, end_parens = word_finder.get_word_parens_range(end - 1) - if occurrence.is_called(): - primary, pyname = occurrence.get_primary_and_pyname() - changed_call = self.call_changer.change_call( - primary, pyname, self.source[start:end_parens] - ) - else: - changed_call = self.call_changer.change_definition( - self.source[start:end_parens] - ) - if changed_call is not None: - change_collector.add_change(start, end_parens, changed_call) - return change_collector.get_changed() - - -def test_already_complete_try_blocks_with_except2(self): - code = dedent("""\ - a_var = 10 - try: - another_var = a_ - another_var = 10 - except Exception: - pass - """) - result = self._assist(code, code.rindex("a_") + 2) - self.assert_completion_in_result("a_var", "global", result) - - -def test_completing_ifs_in_uncomplete_try_blocks(self): - code = dedent("""\ - try: - if True: - a_var = 10 - a_""") - result = self._assist(code) - self.assert_completion_in_result("a_var", "global", result) - - -def test_completing_ifs_in_uncomplete_try_blocks2(self): - code = dedent("""\ - try: - if True: - a_var = 10 - a_""") - result = self._assist(code) - self.assert_completion_in_result("a_var", "global", result) - - -def test_completing_excepts_in_uncomplete_try_blocks(self): - code = dedent("""\ - try: - pass - except Exc""") - result = self._assist(code) - self.assert_completion_in_result("Exception", "builtin", result) - - -def test_and_normal_complete_blocks_and_single_fixing(self): - code = dedent("""\ - try: - range. - except: - pass - """) - result = self._assist(code, code.index("."), maxfixes=1) # noqa - - -def test_nested_blocks(self): - code = dedent("""\ - a_var = 10 - try: - try: - a_v""") - result = self._assist(code) - self.assert_completion_in_result("a_var", "global", result) - - -def test_proposing_function_keywords_when_calling(self): - code = dedent("""\ - def f(p): - pass - f(p""") - result = self._assist(code) - self.assert_completion_in_result("p=", "parameter_keyword", result) - - -def test_proposing_function_keywords_when_calling_for_non_functions(self): - code = dedent("""\ - f = 1 - f(p""") - result = self._assist(code) # noqa - - -def test_proposing_function_keywords_when_calling_extra_spaces(self): - code = dedent("""\ - def f(p): - pass - f( p""") - result = self._assist(code) - self.assert_completion_in_result("p=", "parameter_keyword", result) - - -def test_proposing_function_keywords_when_calling_on_second_argument(self): - code = dedent("""\ - def f(p1, p2): - pass - f(1, p""") - result = self._assist(code) - self.assert_completion_in_result("p2=", "parameter_keyword", result) - - -@property -@utils.saveit -def pymodule(self): - return self.project.get_pymodule(self.resource) - - -def test_proposing_function_keywords_when_calling_not_proposing_args(self): - code = dedent("""\ - def f(p1, *args): - pass - f(1, a""") - result = self._assist(code) - self.assert_completion_not_in_result("args=", "parameter_keyword", result) - - -def test_propos_function_kwrds_when_call_with_no_noth_after_parens(self): - code = dedent("""\ - def f(p): - pass - f(""") - result = self._assist(code) - self.assert_completion_in_result("p=", "parameter_keyword", result) - - -def test_propos_function_kwrds_when_call_with_no_noth_after_parens2(self): - code = dedent("""\ - def f(p): - pass - def g(): - h = f - f(""") - result = self._assist(code) - self.assert_completion_in_result("p=", "parameter_keyword", result) - - -def test_codeassists_before_opening_of_parens(self): - code = dedent("""\ - def f(p): - pass - a_var = 1 - f(1) - """) - result = self._assist(code, code.rindex("f") + 1) - self.assert_completion_not_in_result("a_var", "global", result) - - -def test_codeassist_before_single_line_indents(self): - code = dedent("""\ - myvar = 1 - if True: - (myv - if True: - pass - """) - result = self._assist(code, code.rindex("myv") + 3) - self.assert_completion_not_in_result("myvar", "local", result) - - -def test_codeassist_before_line_indents_in_a_blank_line(self): - code = dedent("""\ - myvar = 1 - if True: - - if True: - pass - """) - result = self._assist(code, code.rindex(" ") + 4) - self.assert_completion_not_in_result("myvar", "local", result) - - -def test_simple_get_calltips(self): - src = dedent("""\ - def f(): - pass - var = f() - """) - doc = get_calltip(self.project, src, src.rindex("f")) - self.assertEqual("f()", doc) - - -def test_get_calltips_for_classes(self): - src = dedent("""\ - class C(object): - def __init__(self): - pass - C(""") - doc = get_calltip(self.project, src, len(src) - 1) - self.assertEqual("C.__init__(self)", doc) - - -def test_get_calltips_for_objects_with_call(self): - src = dedent("""\ - class C(object): - def __call__(self, p): - pass - c = C() - c(1,""") - doc = get_calltip(self.project, src, src.rindex("c")) - self.assertEqual("C.__call__(self, p)", doc) - - -def test_get_calltips_and_including_module_name(self): - src = dedent("""\ - class C(object): - def __call__(self, p): - pass - c = C() - c(1,""") - mod = testutils.create_module(self.project, "mod") - mod.write(src) - doc = get_calltip(self.project, src, src.rindex("c"), mod) - self.assertEqual("mod.C.__call__(self, p)", doc) - - -@property -@utils.saveit -def source(self): - if self.resource is not None: - return self.resource.read() - else: - return self.pymodule.source_code - - -def test_get_calltips_and_including_module_name_2(self): - src = "range()\n" - doc = get_calltip(self.project, src, 1, ignore_unknown=True) - self.assertTrue(doc is None) - - -def test_removing_self_parameter(self): - src = dedent("""\ - class C(object): - def f(self): - pass - C().f()""") - doc = get_calltip(self.project, src, src.rindex("f"), remove_self=True) - self.assertEqual("C.f()", doc) - - -def test_removing_self_parameter_and_more_than_one_parameter(self): - src = dedent("""\ - class C(object): - def f(self, p1): - pass - C().f()""") - doc = get_calltip(self.project, src, src.rindex("f"), remove_self=True) - self.assertEqual("C.f(p1)", doc) - - -def test_lambda_calltip(self): - src = dedent("""\ - foo = lambda x, y=1: None - foo()""") - doc = get_calltip(self.project, src, src.rindex("f")) - self.assertEqual(doc, "lambda(x, y)") - - -def test_keyword_before_parens(self): - code = dedent("""\ - if (1).: - pass""") - result = self._assist(code, offset=len("if (1).")) - self.assertTrue(result) - - -# TESTING PROPOSAL'S KINDS AND TYPES. -# SEE RELATION MATRIX IN `CompletionProposal`'s DOCSTRING - - -def test_local_variable_completion_proposal(self): - code = dedent("""\ - def foo(): - xvar = 5 - x""") - result = self._assist(code) - self.assert_completion_in_result("xvar", "local", result, "instance") - - -def test_global_variable_completion_proposal(self): - code = dedent("""\ - yvar = 5 - y""") - result = self._assist(code) - self.assert_completion_in_result("yvar", "global", result, "instance") - - -def test_builtin_variable_completion_proposal(self): - for varname in ("False", "True"): - result = self._assist(varname[0]) - self.assert_completion_in_result( - varname, "builtin", result, type="instance" - ) - - -def test_attribute_variable_completion_proposal(self): - code = dedent("""\ - class AClass(object): - def foo(self): - self.bar = 1 - self.b""") - result = self._assist(code) - self.assert_completion_in_result("bar", "attribute", result, type="instance") - - -@property -@utils.saveit -def lines(self): - return self.pymodule.lines - - - -def test_local_class_completion_proposal(self): - code = dedent("""\ - def foo(): - class LocalClass(object): pass - Lo""") - result = self._assist(code) - self.assert_completion_in_result("LocalClass", "local", result, type="class") - - -def test_global_class_completion_proposal(self): - code = dedent("""\ - class GlobalClass(object): pass - Gl""") - result = self._assist(code) - self.assert_completion_in_result("GlobalClass", "global", result, type="class") - - -def test_builtin_class_completion_proposal(self): - for varname in ("object", "dict", "file"): - result = self._assist(varname[0]) - self.assert_completion_in_result(varname, "builtin", result, type="class") - - -def test_attribute_class_completion_proposal(self): - code = dedent("""\ - class Outer(object): - class Inner(object): pass - Outer.""") - result = self._assist(code) - self.assert_completion_in_result("Inner", "attribute", result, type="class") - - -def test_local_function_completion_proposal(self): - code = dedent("""\ - def outer(): - def inner(): pass - in""") - result = self._assist(code) - self.assert_completion_in_result("inner", "local", result, type="function") - - -def test_global_function_completion_proposal(self): - code = dedent("""\ - def foo(): pass - f""") - result = self._assist(code) - self.assert_completion_in_result("foo", "global", result, type="function") - - -def test_builtin_function_completion_proposal(self): - code = "a" - result = self._assist(code) - for expected in ("all", "any", "abs"): - self.assert_completion_in_result( - expected, "builtin", result, type="function" - ) - - -def test_attribute_function_completion_proposal(self): - code = dedent("""\ - class Some(object): - def method(self): - self.""") - result = self._assist(code) - self.assert_completion_in_result("method", "attribute", result, type="function") - - -def test_local_module_completion_proposal(self): - code = dedent("""\ - def foo(): - import types - t""") - result = self._assist(code) - self.assert_completion_in_result("types", "imported", result, type="module") - - -def test_global_module_completion_proposal(self): - code = dedent("""\ - import operator - o""") - result = self._assist(code) - self.assert_completion_in_result("operator", "imported", result, type="module") - - -class _MultipleFinders: - @others - -def test_attribute_module_completion_proposal(self): - code = dedent("""\ - class Some(object): - import os - Some.o""") - result = self._assist(code) - self.assert_completion_in_result("os", "imported", result, type="module") - - -def test_builtin_exception_completion_proposal(self): - code = dedent("""\ - def blah(): - Z""") - result = self._assist(code) - self.assert_completion_in_result( - "ZeroDivisionError", "builtin", result, type="class" - ) - - -def test_keyword_completion_proposal(self): - code = "f" - result = self._assist(code) - self.assert_completion_in_result("for", "keyword", result, type=None) - self.assert_completion_in_result("from", "keyword", result, type=None) - - -def test_parameter_keyword_completion_proposal(self): - code = dedent("""\ - def func(abc, aloha, alpha, amigo): pass - func(a""") - result = self._assist(code) - for expected in ("abc=", "aloha=", "alpha=", "amigo="): - self.assert_completion_in_result( - expected, "parameter_keyword", result, type=None - ) - - -def test_object_path_global(self): - code = "GLOBAL_VARIABLE = 42\n" - resource = testutils.create_module(self.project, "mod") - resource.write(code) - result = get_canonical_path(self.project, resource, 1) - mod_path = os.path.join(self.project.address, "mod.py") - self.assertEqual( - result, [(mod_path, "MODULE"), ("GLOBAL_VARIABLE", "VARIABLE")] - ) - - -def test_object_path_attribute(self): - code = dedent("""\ - class Foo(object): - attr = 42 - """) - resource = testutils.create_module(self.project, "mod") - resource.write(code) - result = get_canonical_path(self.project, resource, 24) - mod_path = os.path.join(self.project.address, "mod.py") - self.assertEqual( - result, [(mod_path, "MODULE"), ("Foo", "CLASS"), ("attr", "VARIABLE")] - ) - - -def test_object_path_subclass(self): - code = dedent("""\ - class Foo(object): - class Bar(object): - pass - """) - resource = testutils.create_module(self.project, "mod") - resource.write(code) - result = get_canonical_path(self.project, resource, 30) - mod_path = os.path.join(self.project.address, "mod.py") - self.assertEqual( - result, [(mod_path, "MODULE"), ("Foo", "CLASS"), ("Bar", "CLASS")] - ) - - -def test_object_path_method_parameter(self): - code = dedent("""\ - class Foo(object): - def bar(self, a, b, c): - pass - """) - resource = testutils.create_module(self.project, "mod") - resource.write(code) - result = get_canonical_path(self.project, resource, 41) - mod_path = os.path.join(self.project.address, "mod.py") - self.assertEqual( - result, - [ - (mod_path, "MODULE"), - ("Foo", "CLASS"), - ("bar", "FUNCTION"), - ("b", "PARAMETER"), - ], - ) - - -def test_object_path_variable(self): - code = dedent("""\ - def bar(a): - x = a + 42 - """) - resource = testutils.create_module(self.project, "mod") - resource.write(code) - result = get_canonical_path(self.project, resource, 17) - mod_path = os.path.join(self.project.address, "mod.py") - self.assertEqual( - result, [(mod_path, "MODULE"), ("bar", "FUNCTION"), ("x", "VARIABLE")] - ) - - - -class CodeAssistInProjectsTest(unittest.TestCase): - @others - -def __init__(self, finders): - self.finders = finders - - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - samplemod = testutils.create_module(self.project, "samplemod") - code = dedent("""\ - class SampleClass(object): - def sample_method(): - pass - - def sample_func(): - pass - sample_var = 10 - - def _underlined_func(): - pass - - """) - samplemod.write(code) - package = testutils.create_package(self.project, "package") - nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa - - -def tearDown(self): - testutils.remove_project(self.project) - super(self.__class__, self).tearDown() - - -def _assist(self, code, resource=None, **kwds): - return code_assist(self.project, code, len(code), resource, **kwds) - - -def assert_completion_in_result(self, name, scope, result): - for proposal in result: - if proposal.name == name and proposal.scope == scope: - return - self.fail("completion <%s> not proposed" % name) - - -def assert_completion_not_in_result(self, name, scope, result): - for proposal in result: - if proposal.name == name and proposal.scope == scope: - self.fail("completion <%s> was proposed" % name) - - -def test_simple_import(self): - code = dedent("""\ - import samplemod - sample""") - result = self._assist(code) - self.assert_completion_in_result("samplemod", "imported", result) - - -def test_from_import_class(self): - code = dedent("""\ - from samplemod import SampleClass - Sample""") - result = self._assist(code) - self.assert_completion_in_result("SampleClass", "imported", result) - - -def test_from_import_function(self): - code = dedent("""\ - from samplemod import sample_func - sample""") - result = self._assist(code) - self.assert_completion_in_result("sample_func", "imported", result) - - -def test_from_import_variable(self): - code = dedent("""\ - from samplemod import sample_var - sample""") - result = self._assist(code) - self.assert_completion_in_result("sample_var", "imported", result) - - -def test_from_imports_inside_functions(self): - code = dedent("""\ - def f(): - from samplemod import SampleClass - Sample""") - result = self._assist(code) - self.assert_completion_in_result("SampleClass", "imported", result) - - -def find_occurrences(self, resource=None, pymodule=None): - all_occurrences = [] - for finder in self.finders: - all_occurrences.extend(finder.find_occurrences(resource, pymodule)) - all_occurrences.sort(key=lambda x: x.get_primary_range()) - return all_occurrences - -def test_from_import_only_imports_imported(self): - code = dedent("""\ - from samplemod import sample_func - Sample""") - result = self._assist(code) - self.assert_completion_not_in_result("SampleClass", "global", result) - - -def test_from_import_star(self): - code = dedent("""\ - from samplemod import * - Sample""") - result = self._assist(code) - self.assert_completion_in_result("SampleClass", "imported", result) - - -def test_from_import_star2(self): - code = dedent("""\ - from samplemod import * - sample""") - result = self._assist(code) - self.assert_completion_in_result("sample_func", "imported", result) - self.assert_completion_in_result("sample_var", "imported", result) - - -def test_from_import_star_not_imporing_underlined(self): - code = dedent("""\ - from samplemod import * - _under""") - result = self._assist(code) - self.assert_completion_not_in_result("_underlined_func", "global", result) - - -def test_from_package_import_mod(self): - code = dedent("""\ - from package import nestedmod - nest""") - result = self._assist(code) - self.assert_completion_in_result("nestedmod", "imported", result) - - -def test_completing_after_dot(self): - code = dedent("""\ - class SampleClass(object): - def sample_method(self): - pass - SampleClass.sam""") - result = self._assist(code) - self.assert_completion_in_result("sample_method", "attribute", result) - - -def test_completing_after_multiple_dots(self): - code = dedent("""\ - class Class1(object): - class Class2(object): - def sample_method(self): - pass - Class1.Class2.sam""") - result = self._assist(code) - self.assert_completion_in_result("sample_method", "attribute", result) - - -def test_completing_after_self_dot(self): - code = dedent("""\ - class Sample(object): - def method1(self): - pass - def method2(self): - self.m""") - result = self._assist(code) - self.assert_completion_in_result("method1", "attribute", result) - - -def test_result_start_offset_for_dotted_completions(self): - code = dedent("""\ - class Sample(object): - def method1(self): - pass - Sample.me""") - self.assertEqual(len(code) - 2, starting_offset(code, len(code))) - - -def test_backslash_after_dots(self): - code = dedent("""\ - class Sample(object): - def a_method(self): - pass - Sample.\\ - a_m""") - result = self._assist(code) - self.assert_completion_in_result("a_method", "attribute", result) - - -@path C:/Repos/ekr-rope/rope/refactor/ -from rope.base import evaluate -from rope.base import exceptions -from rope.base import libutils -from rope.base import pynames -from rope.base import taskhandle -from rope.base import utils -from rope.base import worder -from rope.base.change import ChangeSet, ChangeContents -from rope.refactor import sourceutils, occurrences - - -@others -@language python -@tabwidth -4 - -def test_not_proposing_global_names_after_dot(self): - code = dedent("""\ - class Sample(object): - def a_method(self): - pass - Sample.""") - result = self._assist(code) - self.assert_completion_not_in_result("Sample", "global", result) - - -def test_assist_on_relative_imports(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod1.write(dedent("""\ - def a_func(): - pass - """)) - code = dedent("""\ - import mod1 - mod1.""") - result = self._assist(code, resource=mod2) - self.assert_completion_in_result("a_func", "imported", result) - - -def test_get_location_on_relative_imports(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod1.write(dedent("""\ - def a_func(): - pass - """)) - code = dedent("""\ - import mod1 - mod1.a_func - """) - result = get_definition_location(self.project, code, len(code) - 2, mod2) - self.assertEqual((mod1, 1), result) - - -def test_get_definition_location_for_builtins(self): - code = "import sys\n" - result = get_definition_location(self.project, code, len(code) - 2) - self.assertEqual((None, None), result) - - -def test_get_doc_on_relative_imports(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod1.write(dedent('''\ - def a_func(): - """hey""" - pass - ''')) - code = dedent("""\ - import mod1 - mod1.a_func - """) - result = get_doc(self.project, code, len(code) - 2, mod2) - self.assertTrue(result.endswith("hey")) - - -def test_get_doc_on_from_import_module(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent('''\ - """mod1 docs""" - var = 1 - ''')) - code = "from mod1 import var\n" - result = get_doc(self.project, code, code.index("mod1")) - result.index("mod1 docs") - - -def test_fixing_errors_with_maxfixes_in_resources(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def f(): - sldj sldj - def g(): - ran""") - mod.write(code) - result = self._assist(code, maxfixes=2, resource=mod) - self.assertTrue(len(result) > 0) - - -def test_completing_names_after_from_import(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("myvar = None\n") - result = self._assist("from mod1 import myva", resource=mod2) - self.assertTrue(len(result) > 0) - self.assert_completion_in_result("myvar", "global", result) - - -def test_completing_names_after_from_import_and_sorted_proposals(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("myvar = None\n") - result = self._assist("from mod1 import myva", resource=mod2) - result = sorted_proposals(result) - self.assertTrue(len(result) > 0) - self.assert_completion_in_result("myvar", "global", result) - - -def test_completing_names_after_from_import2(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("myvar = None\n") - result = self._assist("from mod1 import ", resource=mod2) - self.assertTrue(len(result) > 0) - self.assert_completion_in_result("myvar", "global", result) - - -def create_package(project, name, sourcefolder=None): - """Creates a package and returns a `rope.base.resources.Folder`""" - if sourcefolder is None: - sourcefolder = project.root - packages = name.split(".") - parent = sourcefolder - for package in packages[:-1]: - parent = parent.get_child(package) - made_packages = parent.create_folder(packages[-1]) - made_packages.create_file("__init__.py") - return made_packages - - - -class EncapsulateField: - @others - -def test_starting_expression(self): - code = dedent("""\ - l = list() - l.app""") - self.assertEqual("l.app", starting_expression(code, len(code))) - -@path C:/Repos/ekr-rope/ropetest/contrib/ -from textwrap import dedent - -import unittest - - -from rope.contrib import finderrors -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class FindErrorsTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.mod = self.project.root.create_file("mod.py") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_unresolved_variables(self): - self.mod.write("print(var)\n") - result = finderrors.find_errors(self.project, self.mod) - self.assertEqual(1, len(result)) - self.assertEqual(1, result[0].lineno) - - -def test_defined_later(self): - self.mod.write(dedent("""\ - print(var) - var = 1 - """)) - result = finderrors.find_errors(self.project, self.mod) - self.assertEqual(1, len(result)) - self.assertEqual(1, result[0].lineno) - - -def test_ignoring_builtins(self): - self.mod.write("range(2)\n") - result = finderrors.find_errors(self.project, self.mod) - self.assertEqual(0, len(result)) - - -def test_ignoring_none(self): - self.mod.write("var = None\n") - result = finderrors.find_errors(self.project, self.mod) - self.assertEqual(0, len(result)) - - -def test_bad_attributes(self): - code = dedent("""\ - class C(object): - pass - c = C() - print(c.var) - """) - self.mod.write(code) - result = finderrors.find_errors(self.project, self.mod) - self.assertEqual(1, len(result)) - self.assertEqual(4, result[0].lineno) - -def __init__(self, project, resource, offset): - self.project = project - self.name = worder.get_name_at(resource, offset) - this_pymodule = self.project.get_pymodule(resource) - self.pyname = evaluate.eval_location(this_pymodule, offset) - if not self._is_an_attribute(self.pyname): - raise exceptions.RefactoringError( - "Encapsulate field should be performed on class attributes." - ) - self.resource = self.pyname.get_definition_location()[0].get_resource() - - -@path C:/Repos/ekr-rope/ropetest/contrib/ -from textwrap import dedent - -import unittest - -from rope.base import exceptions -from rope.contrib.findit import find_occurrences, find_implementations, find_definition -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class FindItTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_finding_occurrences(self): - mod = testutils.create_module(self.project, "mod") - mod.write("a_var = 1\n") - result = find_occurrences(self.project, mod, 1) - self.assertEqual(mod, result[0].resource) - self.assertEqual(0, result[0].offset) - self.assertEqual(False, result[0].unsure) - - -def test_finding_occurrences_in_more_than_one_module(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("a_var = 1\n") - mod2.write(dedent("""\ - import mod1 - my_var = mod1.a_var""")) - result = find_occurrences(self.project, mod1, 1) - self.assertEqual(2, len(result)) - modules = (result[0].resource, result[1].resource) - self.assertTrue(mod1 in modules and mod2 in modules) - - -def test_finding_occurrences_matching_when_unsure(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - class C(object): - def a_func(self): - pass - def f(arg): - arg.a_func() - """)) - result = find_occurrences( - self.project, mod1, mod1.read().index("a_func"), unsure=True - ) - self.assertEqual(2, len(result)) - - -def test_find_occurrences_resources_parameter(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("a_var = 1\n") - mod2.write(dedent("""\ - import mod1 - my_var = mod1.a_var""")) - result = find_occurrences(self.project, mod1, 1, resources=[mod1]) - self.assertEqual(1, len(result)) - self.assertEqual((mod1, 0), (result[0].resource, result[0].offset)) - - -def test_find_occurrences_and_class_hierarchies(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - class A(object): - def f(): - pass - class B(A): - def f(): - pass - """)) - offset = mod1.read().rindex("f") - result1 = find_occurrences(self.project, mod1, offset) - result2 = find_occurrences(self.project, mod1, offset, in_hierarchy=True) - self.assertEqual(1, len(result1)) - self.assertEqual(2, len(result2)) - - -def test_trivial_find_implementations(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - class A(object): - def f(self): - pass - """)) - offset = mod1.read().rindex("f(") - result = find_implementations(self.project, mod1, offset) - self.assertEqual([], result) - - -def get_changes( - self, - getter=None, - setter=None, - resources=None, - task_handle=taskhandle.NullTaskHandle(), -): - """Get the changes this refactoring makes - - If `getter` is not `None`, that will be the name of the - getter, otherwise ``get_${field_name}`` will be used. The - same is true for `setter` and if it is None set_${field_name} is - used. - - `resources` can be a list of `rope.base.resource.File` that - the refactoring should be applied on; if `None` all python - files in the project are searched. - - """ - if resources is None: - resources = self.project.get_python_files() - changes = ChangeSet("Encapsulate field <%s>" % self.name) - job_set = task_handle.create_jobset("Collecting Changes", len(resources)) - if getter is None: - getter = "get_" + self.name - if setter is None: - setter = "set_" + self.name - renamer = GetterSetterRenameInModule( - self.project, self.name, self.pyname, getter, setter - ) - for file in resources: - job_set.started_job(file.path) - if file == self.resource: - result = self._change_holding_module(changes, renamer, getter, setter) - changes.add_change(ChangeContents(self.resource, result)) - else: - result = renamer.get_changed_module(file) - if result is not None: - changes.add_change(ChangeContents(file, result)) - job_set.finished_job() - return changes - - -def test_find_implementations_and_not_returning_parents(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - class A(object): - def f(self): - pass - class B(A): - def f(self): - pass - """)) - offset = mod1.read().rindex("f(") - result = find_implementations(self.project, mod1, offset) - self.assertEqual([], result) - - -def test_find_implementations_real_implementation(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - class A(object): - def f(self): - pass - class B(A): - def f(self): - pass - """)) - offset = mod1.read().index("f(") - result = find_implementations(self.project, mod1, offset) - self.assertEqual(1, len(result)) - self.assertEqual(mod1.read().rindex("f("), result[0].offset) - - -def test_find_implementations_real_implementation_simple(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write("class A(object):\n pass\n") - offset = mod1.read().index("A") - with self.assertRaises(exceptions.BadIdentifierError): - find_implementations(self.project, mod1, offset) - - -def test_trivial_find_definition(self): - code = dedent("""\ - def a_func(): - pass - a_func()""") - result = find_definition(self.project, code, code.rindex("a_func")) - start = code.index("a_func") - self.assertEqual(start, result.offset) - self.assertEqual(None, result.resource) - self.assertEqual(1, result.lineno) - self.assertEqual((start, start + len("a_func")), result.region) - - -def test_find_definition_in_other_modules(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write("var = 1\n") - code = dedent("""\ - import mod1 - print(mod1.var) - """) - result = find_definition(self.project, code, code.index("var")) - self.assertEqual(mod1, result.resource) - self.assertEqual(0, result.offset) - -@path C:/Repos/ekr-rope/ropetest/contrib/ -import unittest - - -from ropetest import testutils -from rope.contrib.fixmodnames import FixModuleNames -from rope.contrib.generate import create_module, create_package - - -@others -@language python -@tabwidth -4 - -# HACK: for making this test work on case-insensitive file-systems, it -# uses a name.replace('x', '_') fixer. -class FixModuleNamesTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_module_renaming(self): - mod = create_module(self.project, "xod") - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - self.assertFalse(mod.exists()) - self.assertTrue(self.project.get_resource("_od.py").exists()) - - -def get_field_name(self): - """Get the name of the field to be encapsulated""" - return self.name - - -def test_packages_module_renaming(self): - pkg = create_package(self.project, "xkg") - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - self.assertFalse(pkg.exists()) - self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) - - -def test_fixing_contents(self): - mod1 = create_module(self.project, "xod1") - mod2 = create_module(self.project, "xod2") - mod1.write("import xod2\n") - mod2.write("import xod1\n") - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - newmod1 = self.project.get_resource("_od1.py") - newmod2 = self.project.get_resource("_od2.py") - self.assertEqual("import _od2\n", newmod1.read()) - self.assertEqual("import _od1\n", newmod2.read()) - - -def test_handling_nested_modules(self): - pkg = create_package(self.project, "xkg") - mod = create_module(self.project, "xkg.xod") # noqa - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - self.assertFalse(pkg.exists()) - self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) - self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) - - - -def _fixer(name): - return name.replace("x", "_") - -@path C:/Repos/ekr-rope/ropetest/contrib/ -from textwrap import dedent - -import unittest - -from rope.base import exceptions -from rope.contrib import generate -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class GenerateTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod1") - self.mod2 = testutils.create_module(self.project, "mod2") - self.pkg = testutils.create_package(self.project, "pkg") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _get_generate(self, offset): - return generate.GenerateVariable(self.project, self.mod, offset) - - -def _get_generate_class(self, offset, goal_mod=None): - return generate.GenerateClass( - self.project, self.mod, offset, goal_resource=goal_mod - ) - - -def _is_an_attribute(self, pyname): - if pyname is not None and isinstance(pyname, pynames.AssignedName): - pymodule, lineno = self.pyname.get_definition_location() - scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - if scope.get_kind() == "Class": - return pyname in scope.get_names().values() - parent = scope.parent - if parent is not None and parent.get_kind() == "Class": - return pyname in parent.get_names().values() - return False - - -def _get_generate_module(self, offset): - return generate.GenerateModule(self.project, self.mod, offset) - - -def _get_generate_package(self, offset): - return generate.GeneratePackage(self.project, self.mod, offset) - - -def _get_generate_function(self, offset): - return generate.GenerateFunction(self.project, self.mod, offset) - - -def test_getting_location(self): - code = "a_var = name\n" - self.mod.write(code) - generator = self._get_generate(code.index("name")) - self.assertEqual((self.mod, 1), generator.get_location()) - - -def test_generating_variable(self): - code = dedent("""\ - a_var = name - """) - self.mod.write(code) - changes = self._get_generate(code.index("name")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - name = None - - - a_var = name - """), - self.mod.read(), - ) - - -def test_generating_variable_inserting_before_statement(self): - code = dedent("""\ - c = 1 - c = b - """) - self.mod.write(code) - changes = self._get_generate(code.index("b")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - c = 1 - b = None - - - c = b - """), - self.mod.read(), - ) - - -def test_generating_variable_in_local_scopes(self): - code = dedent("""\ - def f(): - c = 1 - c = b - """) - self.mod.write(code) - changes = self._get_generate(code.index("b")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - def f(): - c = 1 - b = None - c = b - """), - self.mod.read(), - ) - - -def test_generating_variable_in_other_modules(self): - code = dedent("""\ - import mod2 - c = mod2.b - """) - self.mod.write(code) - generator = self._get_generate(code.index("b")) - self.project.do(generator.get_changes()) - self.assertEqual((self.mod2, 1), generator.get_location()) - self.assertEqual("b = None\n", self.mod2.read()) - - -def test_generating_variable_in_classes(self): - code = dedent("""\ - class C(object): - def f(self): - pass - c = C() - a_var = c.attr""") - self.mod.write(code) - changes = self._get_generate(code.index("attr")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - class C(object): - def f(self): - pass - - attr = None - c = C() - a_var = c.attr"""), - self.mod.read(), - ) - - -def test_generating_variable_in_classes_removing_pass(self): - code = dedent("""\ - class C(object): - pass - c = C() - a_var = c.attr""") - self.mod.write(code) - changes = self._get_generate(code.index("attr")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - class C(object): - - attr = None - c = C() - a_var = c.attr"""), - self.mod.read(), - ) - - -def _get_defining_class_scope(self): - defining_scope = self._get_defining_scope() - if defining_scope.get_kind() == "Function": - defining_scope = defining_scope.parent - return defining_scope - - -def test_generating_variable_in_packages(self): - code = "import pkg\na = pkg.a\n" - self.mod.write(code) - generator = self._get_generate(code.rindex("a")) - self.project.do(generator.get_changes()) - init = self.pkg.get_child("__init__.py") - self.assertEqual((init, 1), generator.get_location()) - self.assertEqual("a = None\n", init.read()) - - -def test_generating_classes(self): - code = "c = C()\n" - self.mod.write(code) - changes = self._get_generate_class(code.index("C")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - class C(object): - pass - - - c = C() - """), - self.mod.read(), - ) - - -def test_generating_classes_in_other_module(self): - code = "c = C()\n" - self.mod.write(code) - changes = self._get_generate_class(code.index("C"), self.mod2).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - class C(object): - pass - """), - self.mod2.read(), - ) - self.assertEqual( - dedent("""\ - from mod2 import C - c = C() - """), - self.mod.read(), - ) - - -def test_generating_modules(self): - code = dedent("""\ - import pkg - pkg.mod - """) - self.mod.write(code) - generator = self._get_generate_module(code.rindex("mod")) - self.project.do(generator.get_changes()) - mod = self.pkg.get_child("mod.py") - self.assertEqual((mod, 1), generator.get_location()) - self.assertEqual( - dedent("""\ - import pkg.mod - pkg.mod - """), - self.mod.read(), - ) - - -def test_generating_packages(self): - code = dedent("""\ - import pkg - pkg.pkg2 - """) - self.mod.write(code) - generator = self._get_generate_package(code.rindex("pkg2")) - self.project.do(generator.get_changes()) - pkg2 = self.pkg.get_child("pkg2") - init = pkg2.get_child("__init__.py") - self.assertEqual((init, 1), generator.get_location()) - self.assertEqual( - dedent("""\ - import pkg.pkg2 - pkg.pkg2 - """), - self.mod.read(), - ) - - -def test_generating_function(self): - code = "a_func()\n" - self.mod.write(code) - changes = self._get_generate_function(code.index("a_func")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - def a_func(): - pass - - - a_func() - """), - self.mod.read(), - ) - - -def test_generating_modules_with_empty_primary(self): - code = "mod\n" - self.mod.write(code) - generator = self._get_generate_module(code.rindex("mod")) - self.project.do(generator.get_changes()) - mod = self.project.root.get_child("mod.py") - self.assertEqual((mod, 1), generator.get_location()) - self.assertEqual("import mod\nmod\n", self.mod.read()) - - -def test_generating_variable_already_exists(self): - code = dedent("""\ - b = 1 - c = b - """) - self.mod.write(code) - with self.assertRaises(exceptions.RefactoringError): - self._get_generate(code.index("b")).get_changes() - - -def test_generating_variable_primary_cannot_be_determined(self): - code = "c = can_not_be_found.b\n" - self.mod.write(code) - with self.assertRaises(exceptions.RefactoringError): - self._get_generate(code.rindex("b")).get_changes() - - -def test_generating_modules_when_already_exists(self): - code = "mod2\n" - self.mod.write(code) - generator = self._get_generate_module(code.rindex("mod")) - with self.assertRaises(exceptions.RefactoringError): - self.project.do(generator.get_changes()) - - -def _get_defining_scope(self): - pymodule, line = self.pyname.get_definition_location() - return pymodule.get_scope().get_inner_scope_for_line(line) - - -def test_generating_static_methods(self): - code = dedent("""\ - class C(object): - pass - C.a_func() - """) - self.mod.write(code) - changes = self._get_generate_function(code.index("a_func")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - class C(object): - - @staticmethod - def a_func(): - pass - C.a_func() - """), - self.mod.read(), - ) - - -def test_generating_methods(self): - code = dedent("""\ - class C(object): - pass - c = C() - c.a_func() - """) - self.mod.write(code) - changes = self._get_generate_function(code.index("a_func")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - class C(object): - - def a_func(self): - pass - c = C() - c.a_func() - """), - self.mod.read(), - ) - - -def test_generating_constructors(self): - code = dedent("""\ - class C(object): - pass - c = C() - """) - self.mod.write(code) - changes = self._get_generate_function(code.rindex("C")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - class C(object): - - def __init__(self): - pass - c = C() - """), - self.mod.read(), - ) - - -def test_generating_calls(self): - code = dedent("""\ - class C(object): - pass - c = C() - c() - """) - self.mod.write(code) - changes = self._get_generate_function(code.rindex("c")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - class C(object): - - def __call__(self): - pass - c = C() - c() - """), - self.mod.read(), - ) - - -def test_generating_calls_in_other_modules(self): - self.mod2.write(dedent("""\ - class C(object): - pass - """)) - code = dedent("""\ - import mod2 - c = mod2.C() - c() - """) - self.mod.write(code) - changes = self._get_generate_function(code.rindex("c")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - class C(object): - - def __call__(self): - pass - """), - self.mod2.read(), - ) - - -def test_generating_function_handling_arguments(self): - code = "a_func(1)\n" - self.mod.write(code) - changes = self._get_generate_function(code.index("a_func")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - def a_func(arg0): - pass - - - a_func(1) - """), - self.mod.read(), - ) - - -def test_generating_function_handling_keyword_xarguments(self): - code = "a_func(p=1)\n" - self.mod.write(code) - changes = self._get_generate_function(code.index("a_func")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - def a_func(p): - pass - - - a_func(p=1) - """), - self.mod.read(), - ) - - -def test_generating_function_handling_arguments_better_naming(self): - code = dedent("""\ - a_var = 1 - a_func(a_var) - """) - self.mod.write(code) - changes = self._get_generate_function(code.index("a_func")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - a_var = 1 - def a_func(a_var): - pass - - - a_func(a_var) - """), - self.mod.read(), - ) - - -def test_generating_variable_in_other_modules2(self): - self.mod2.write("\n\n\nprint(1)\n") - code = dedent("""\ - import mod2 - c = mod2.b - """) - self.mod.write(code) - generator = self._get_generate(code.index("b")) - self.project.do(generator.get_changes()) - self.assertEqual((self.mod2, 5), generator.get_location()) - self.assertEqual( - dedent("""\ - - - - print(1) - - - b = None - """), - self.mod2.read(), - ) - - -def test_generating_function_in_a_suite(self): - code = dedent("""\ - if True: - a_func() - """) - self.mod.write(code) - changes = self._get_generate_function(code.index("a_func")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - def a_func(): - pass - - - if True: - a_func() - """), - self.mod.read(), - ) - - -def _change_holding_module(self, changes, renamer, getter, setter): - pymodule = self.project.get_pymodule(self.resource) - class_scope = self._get_defining_class_scope() - defining_object = self._get_defining_scope().pyobject - start, end = sourceutils.get_body_region(defining_object) - - new_source = renamer.get_changed_module( - pymodule=pymodule, skip_start=start, skip_end=end - ) - if new_source is not None: - pymodule = libutils.get_string_module( - self.project, new_source, self.resource - ) - class_scope = pymodule.get_scope().get_inner_scope_for_line( - class_scope.get_start() - ) - indents = sourceutils.get_indent(self.project) * " " - getter = "def {}(self):\n{}return self.{}".format(getter, indents, self.name) - setter = "def {}(self, value):\n{}self.{} = value".format( - setter, - indents, - self.name, - ) - new_source = sourceutils.add_methods(pymodule, class_scope, [getter, setter]) - return new_source - - - -def test_generating_function_in_a_suite_in_a_function(self): - code = dedent("""\ - def f(): - a = 1 - if 1: - g() - """) - self.mod.write(code) - changes = self._get_generate_function(code.index("g()")).get_changes() - self.project.do(changes) - self.assertEqual( - dedent("""\ - def f(): - a = 1 - def g(): - pass - if 1: - g() - """), - self.mod.read(), - ) - - -def test_create_generate_class_with_goal_resource(self): - code = "c = C()\n" - self.mod.write(code) - - result = generate.create_generate( - "class", self.project, self.mod, code.index("C"), goal_resource=self.mod2 - ) - - self.assertTrue(isinstance(result, generate.GenerateClass)) - self.assertEqual(result.goal_resource, self.mod2) - - -def test_create_generate_class_without_goal_resource(self): - code = "c = C()\n" - self.mod.write(code) - - result = generate.create_generate( - "class", self.project, self.mod, code.index("C") - ) - - self.assertTrue(isinstance(result, generate.GenerateClass)) - self.assertIsNone(result.goal_resource) - -@path C:/Repos/ekr-rope/ropetest/contrib/ -import sys - -import unittest - -import ropetest.contrib.autoimporttest -import ropetest.contrib.changestacktest -import ropetest.contrib.codeassisttest -import ropetest.contrib.finderrorstest -import ropetest.contrib.findittest -import ropetest.contrib.fixmodnamestest -import ropetest.contrib.generatetest - - -@others -if __name__ == "__main__": - runner = unittest.TextTestRunner() - result = runner.run(suite()) - sys.exit(not result.wasSuccessful()) -@language python -@tabwidth -4 - -def suite(): - result = unittest.TestSuite() - result.addTests(unittest.makeSuite(ropetest.contrib.generatetest.GenerateTest)) - result.addTests(ropetest.contrib.codeassisttest.suite()) - result.addTests(ropetest.contrib.autoimporttest.suite()) - result.addTests(ropetest.contrib.findittest.suite()) - result.addTests( - unittest.makeSuite(ropetest.contrib.changestacktest.ChangeStackTest) - ) - result.addTests( - unittest.makeSuite(ropetest.contrib.fixmodnamestest.FixModuleNamesTest) - ) - result.addTests(unittest.makeSuite(ropetest.contrib.finderrorstest.FindErrorsTest)) - return result - - - - -@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ -import pathlib - -import pytest - -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -@pytest.fixture -def project(): - project = testutils.sample_project() - yield project - testutils.remove_project(project) - - - -@pytest.fixture -def mod1(project): - mod1 = testutils.create_module(project, "mod1") - yield mod1 - - - -@pytest.fixture -def mod1_path(mod1): - yield pathlib.Path(mod1.real_path) - - - -class GetterSetterRenameInModule: - @others - -@pytest.fixture -def project_path(project): - yield pathlib.Path(project.address) - - - -@pytest.fixture -def typing_path(): - import typing - - yield pathlib.Path(typing.__file__) - - - -@pytest.fixture -def build_env_path(): - from build import env - - yield pathlib.Path(env.__file__) - - - -@pytest.fixture -def build_path(): - import build - - # Uses __init__.py so we need the parent - - yield pathlib.Path(build.__file__).parent - - - -@pytest.fixture -def compiled_lib(): - import _sqlite3 - - yield "_sqlite3", pathlib.Path(_sqlite3.__file__) - -@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ -from unittest import TestCase - -from rope.contrib.autoimport import models - - -@others -@language python -@tabwidth -4 - -class QueryTest(TestCase): - def test_select_non_existent_column(self): - with self.assertRaisesRegex(ValueError, """Unknown column names passed: {['"]doesnotexist['"]}"""): - models.Name.objects.select('doesnotexist')._query - - - -class NameModelTest(TestCase): - @others - -def test_name_objects(self): - self.assertEqual( - models.Name.objects.select_star()._query, - "SELECT * FROM names", - ) - - -def test_query_strings(self): - with self.subTest("objects"): - self.assertEqual( - models.Name.objects.select_star()._query, - 'SELECT * FROM names', - ) - - with self.subTest("search_submodule_like"): - self.assertEqual( - models.Name.search_submodule_like.select_star()._query, - 'SELECT * FROM names WHERE module LIKE ("%." || ?)', - ) - - with self.subTest("search_module_like"): - self.assertEqual( - models.Name.search_module_like.select_star()._query, - 'SELECT * FROM names WHERE module LIKE (?)', - ) - - with self.subTest("import_assist"): - self.assertEqual( - models.Name.import_assist.select_star()._query, - "SELECT * FROM names WHERE name LIKE (? || '%')", - ) - - with self.subTest("search_by_name_like"): - self.assertEqual( - models.Name.search_by_name_like.select_star()._query, - 'SELECT * FROM names WHERE name LIKE (?)', - ) - - with self.subTest("delete_by_module_name"): - self.assertEqual( - models.Name.delete_by_module_name._query, - 'DELETE FROM names WHERE module = ?', - ) - - - -def __init__(self, project, name, pyname, getter, setter): - self.project = project - self.name = name - self.finder = occurrences.create_finder(project, name, pyname) - self.getter = getter - self.setter = setter - - -class PackageModelTest(TestCase): - @others - -def test_query_strings(self): - with self.subTest("objects"): - self.assertEqual( - models.Package.objects.select_star()._query, - 'SELECT * FROM packages', - ) - - with self.subTest("delete_by_package_name"): - self.assertEqual( - models.Package.delete_by_package_name._query, - 'DELETE FROM packages WHERE package = ?', - ) - -@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ -from rope.contrib.autoimport import parse -from rope.contrib.autoimport.defs import Name, NameType, PartialName, Source - - -@others -@language python -@tabwidth -4 - -def test_typing_names(typing_path): - names = list(parse.get_names_from_file(typing_path)) - assert PartialName("Text", NameType.Variable) in names - - - -def test_find_sys(): - names = list(parse.get_names_from_compiled("sys", Source.BUILTIN)) - assert Name("exit", "sys", "sys", Source.BUILTIN, NameType.Function) in names - - - -def test_find_underlined(): - names = list(parse.get_names_from_compiled("os", Source.BUILTIN, underlined=True)) - assert Name("_exit", "os", "os", Source.BUILTIN, NameType.Function) in names - -@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ -"""Tests for autoimport utility functions, written in pytest""" - -from sys import platform - -import pytest - -from rope.contrib.autoimport import utils -from rope.contrib.autoimport.defs import Package, PackageType, Source - - -@others -@language python -@tabwidth -4 - -def test_get_package_source(mod1_path, project): - assert utils.get_package_source(mod1_path, project, "") == Source.PROJECT - - - -def test_get_package_source_not_project(mod1_path): - assert utils.get_package_source(mod1_path, None, "") == Source.UNKNOWN - - - -def test_get_package_source_pytest(build_path): - # pytest is not installed as part of the standard library - # but should be installed into site_packages, - # so it should return Source.SITE_PACKAGE - assert utils.get_package_source(build_path, None, "build") == Source.SITE_PACKAGE - - - -class _Generate: - @others - -def get_changed_module( - self, resource=None, pymodule=None, skip_start=0, skip_end=0 -): - change_finder = _FindChangesForModule( - self, resource, pymodule, skip_start, skip_end - ) - return change_finder.get_changed_module() - - - -def test_get_package_source_typing(typing_path): - - assert utils.get_package_source(typing_path, None, "typing") == Source.STANDARD - - - -def test_get_modname_project_no_add(mod1_path, project_path): - - assert utils.get_modname_from_path(mod1_path, project_path, False) == "mod1" - - - -def test_get_modname_single_file(typing_path): - - assert utils.get_modname_from_path(typing_path, typing_path) == "typing" - - - -def test_get_modname_folder(build_path, build_env_path): - - assert utils.get_modname_from_path(build_env_path, build_path) == "build.env" - - - -def test_get_package_tuple_sample(project_path): - assert Package( - "sample_project", Source.UNKNOWN, project_path, PackageType.STANDARD - ) == utils.get_package_tuple(project_path) - - - -def test_get_package_tuple_typing(typing_path): - - assert Package( - "typing", Source.STANDARD, typing_path, PackageType.SINGLE_FILE - ) == utils.get_package_tuple(typing_path) - - - -def test_get_package_tuple_compiled(compiled_lib): - lib_name, lib_path = compiled_lib - assert Package( - lib_name, Source.STANDARD, lib_path, PackageType.COMPILED - ) == utils.get_package_tuple(lib_path) - - -@path C:/Repos/ekr-rope/ropetest/refactor/ -from textwrap import dedent - -import unittest - -import rope.base.exceptions -from rope.refactor import change_signature -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class ChangeSignatureTest(unittest.TestCase): - @others - -class _FindChangesForModule: - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_normalizing_parameters_for_trivial_case(self): - code = dedent("""\ - def a_func(): - pass - a_func()""") - self.mod.write(code) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) - self.assertEqual(code, self.mod.read()) - - -def test_normalizing_parameters_for_trivial_case2(self): - code = dedent("""\ - def a_func(param): - pass - a_func(2)""") - self.mod.write(code) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) - self.assertEqual(code, self.mod.read()) - - -def test_normalizing_parameters_for_unneeded_keyword(self): - self.mod.write(dedent("""\ - def a_func(param): - pass - a_func(param=1)""")) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) - self.assertEqual( - dedent("""\ - def a_func(param): - pass - a_func(1)"""), - self.mod.read(), - ) - - -def test_normalizing_parameters_for_unneeded_keyword_for_methods(self): - code = dedent("""\ - class A(object): - def a_func(self, param): - pass - a_var = A() - a_var.a_func(param=1) - """) - self.mod.write(code) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) - expected = dedent("""\ - class A(object): - def a_func(self, param): - pass - a_var = A() - a_var.a_func(1) - """) - self.assertEqual(expected, self.mod.read()) - - -def test_normalizing_parameters_for_unsorted_keyword(self): - self.mod.write(dedent("""\ - def a_func(p1, p2): - pass - a_func(p2=2, p1=1)""")) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) - self.assertEqual( - dedent("""\ - def a_func(p1, p2): - pass - a_func(1, 2)"""), - self.mod.read(), - ) - - -def test_raising_exceptions_for_non_functions(self): - self.mod.write("a_var = 10") - with self.assertRaises(rope.base.exceptions.RefactoringError): - change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_var") + 1 - ) - - -def test_normalizing_parameters_for_args_parameter(self): - self.mod.write(dedent("""\ - def a_func(*arg): - pass - a_func(1, 2) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) - self.assertEqual( - dedent("""\ - def a_func(*arg): - pass - a_func(1, 2) - """), - self.mod.read(), - ) - - -def test_normalizing_parameters_for_args_parameter_and_keywords(self): - self.mod.write(dedent("""\ - def a_func(param, *args): - pass - a_func(*[1, 2, 3]) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) - self.assertEqual( - dedent("""\ - def a_func(param, *args): - pass - a_func(*[1, 2, 3]) - """), - self.mod.read(), - ) - - -def __init__(self, finder, resource, pymodule, skip_start, skip_end): - self.project = finder.project - self.finder = finder.finder - self.getter = finder.getter - self.setter = finder.setter - self.resource = resource - self.pymodule = pymodule - self.last_modified = 0 - self.last_set = None - self.set_index = None - self.skip_start = skip_start - self.skip_end = skip_end - - -def test_normalizing_functions_from_other_modules(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - def a_func(param): - pass - """)) - self.mod.write(dedent("""\ - import mod1 - mod1.a_func(param=1) - """)) - signature = change_signature.ChangeSignature( - self.project, mod1, mod1.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) - self.assertEqual( - dedent("""\ - import mod1 - mod1.a_func(1) - """), - self.mod.read(), - ) - - -def test_normalizing_parameters_for_keyword_parameters(self): - self.mod.write(dedent("""\ - def a_func(p1, **kwds): - pass - a_func(p2=2, p1=1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) - self.assertEqual( - dedent("""\ - def a_func(p1, **kwds): - pass - a_func(1, p2=2) - """), - self.mod.read(), - ) - - -def test_removing_arguments(self): - self.mod.write(dedent("""\ - def a_func(p1): - pass - a_func(1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentRemover(0)])) - self.assertEqual( - dedent("""\ - def a_func(): - pass - a_func() - """), - self.mod.read(), - ) - - -def test_removing_arguments_with_multiple_args(self): - self.mod.write(dedent("""\ - def a_func(p1, p2): - pass - a_func(1, 2) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentRemover(0)])) - self.assertEqual( - dedent("""\ - def a_func(p2): - pass - a_func(2) - """), - self.mod.read(), - ) - - -def test_removing_arguments_passed_as_keywords(self): - self.mod.write(dedent("""\ - def a_func(p1): - pass - a_func(p1=1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentRemover(0)])) - self.assertEqual( - dedent("""\ - def a_func(): - pass - a_func() - """), - self.mod.read(), - ) - - -def test_removing_arguments_with_defaults(self): - self.mod.write(dedent("""\ - def a_func(p1=1): - pass - a_func(1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentRemover(0)])) - self.assertEqual( - dedent("""\ - def a_func(): - pass - a_func() - """), - self.mod.read(), - ) - - -def test_removing_arguments_star_args(self): - self.mod.write(dedent("""\ - def a_func(p1, *args): - pass - a_func(1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentRemover(1)])) - self.assertEqual( - dedent("""\ - def a_func(p1): - pass - a_func(1) - """), - self.mod.read(), - ) - - -def test_removing_keyword_arg(self): - self.mod.write(dedent("""\ - def a_func(p1, **kwds): - pass - a_func(1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentRemover(1)])) - self.assertEqual( - dedent("""\ - def a_func(p1): - pass - a_func(1) - """), - self.mod.read(), - ) - - -def test_removing_keyword_arg2(self): - self.mod.write(dedent("""\ - def a_func(p1, *args, **kwds): - pass - a_func(1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentRemover(2)])) - self.assertEqual( - dedent("""\ - def a_func(p1, *args): - pass - a_func(1) - """), - self.mod.read(), - ) - - -# XXX: What to do here for star args? -@unittest.skip("How to deal with start args?") -def xxx_test_removing_arguments_star_args2(self): - self.mod.write(dedent("""\ - def a_func(p1, *args): - pass - a_func(2, 3, p1=1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentRemover(1)])) - self.assertEqual( - dedent("""\ - def a_func(p1): - pass - a_func(p1=1) - """), - self.mod.read(), - ) - - -def get_changed_module(self): - result = [] - for occurrence in self.finder.find_occurrences(self.resource, self.pymodule): - start, end = occurrence.get_word_range() - if self.skip_start <= start < self.skip_end: - continue - self._manage_writes(start, result) - result.append(self.source[self.last_modified : start]) - if self._is_assigned_in_a_tuple_assignment(occurrence): - raise exceptions.RefactoringError( - "Cannot handle tuple assignments in encapsulate field." - ) - if occurrence.is_written(): - assignment_type = self.worder.get_assignment_type(start) - if assignment_type == "=": - result.append(self.setter + "(") - else: - var_name = ( - self.source[occurrence.get_primary_range()[0] : start] - + self.getter - + "()" - ) - result.append( - self.setter + "(" + var_name + " %s " % assignment_type[:-1] - ) - current_line = self.lines.get_line_number(start) - start_line, end_line = self.pymodule.logical_lines.logical_line_in( - current_line - ) - self.last_set = self.lines.get_line_end(end_line) - end = self.source.index("=", end) + 1 - self.set_index = len(result) - else: - result.append(self.getter + "()") - self.last_modified = end - if self.last_modified != 0: - self._manage_writes(len(self.source), result) - result.append(self.source[self.last_modified :]) - return "".join(result) - return None - - -# XXX: What to do here for star args? -def xxx_test_removing_arguments_star_args3(self): - self.mod.write(dedent("""\ - def a_func(p1, *args): - pass - a_func(*[1, 2, 3]) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentRemover(1)])) - self.assertEqual( - dedent("""\ - def a_func(p1): - pass - a_func(*[1, 2, 3]) - """), - self.mod.read(), - ) - - -def test_adding_arguments_for_normal_args_changing_definition(self): - self.mod.write(dedent("""\ - def a_func(): - pass - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do( - signature.get_changes([change_signature.ArgumentAdder(0, "p1")]) - ) - self.assertEqual( - dedent("""\ - def a_func(p1): - pass - """), - self.mod.read(), - ) - - -def test_adding_arguments_for_normal_args_with_defaults(self): - self.mod.write(dedent("""\ - def a_func(): - pass - a_func() - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - adder = change_signature.ArgumentAdder(0, "p1", "None") - self.project.do(signature.get_changes([adder])) - self.assertEqual( - dedent("""\ - def a_func(p1=None): - pass - a_func() - """), - self.mod.read(), - ) - - -def test_adding_arguments_for_normal_args_changing_calls(self): - self.mod.write(dedent("""\ - def a_func(): - pass - a_func() - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - adder = change_signature.ArgumentAdder(0, "p1", "None", "1") - self.project.do(signature.get_changes([adder])) - self.assertEqual( - dedent("""\ - def a_func(p1=None): - pass - a_func(1) - """), - self.mod.read(), - ) - - -def test_adding_arguments_for_norm_args_chang_calls_with_kwords(self): - self.mod.write(dedent("""\ - def a_func(p1=0): - pass - a_func() - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - adder = change_signature.ArgumentAdder(1, "p2", "0", "1") - self.project.do(signature.get_changes([adder])) - self.assertEqual( - dedent("""\ - def a_func(p1=0, p2=0): - pass - a_func(p2=1) - """), - self.mod.read(), - ) - - -def test_adding_arguments_for_norm_args_chang_calls_with_no_value(self): - self.mod.write(dedent("""\ - def a_func(p2=0): - pass - a_func(1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - adder = change_signature.ArgumentAdder(0, "p1", "0", None) - self.project.do(signature.get_changes([adder])) - self.assertEqual( - dedent("""\ - def a_func(p1=0, p2=0): - pass - a_func(p2=1) - """), - self.mod.read(), - ) - - -def test_adding_duplicate_parameter_and_raising_exceptions(self): - self.mod.write(dedent("""\ - def a_func(p1): - pass - """)) - with self.assertRaises(rope.base.exceptions.RefactoringError): - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do( - signature.get_changes([change_signature.ArgumentAdder(1, "p1")]) - ) - - -def test_inlining_default_arguments(self): - self.mod.write(dedent("""\ - def a_func(p1=0): - pass - a_func() - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do( - signature.get_changes([change_signature.ArgumentDefaultInliner(0)]) - ) - self.assertEqual( - dedent("""\ - def a_func(p1=0): - pass - a_func(0) - """), - self.mod.read(), - ) - - -def test_inlining_default_arguments2(self): - self.mod.write(dedent("""\ - def a_func(p1=0): - pass - a_func(1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do( - signature.get_changes([change_signature.ArgumentDefaultInliner(0)]) - ) - self.assertEqual( - dedent("""\ - def a_func(p1=0): - pass - a_func(1) - """), - self.mod.read(), - ) - - -def test_preserving_args_and_keywords_order(self): - self.mod.write(dedent("""\ - def a_func(*args, **kwds): - pass - a_func(3, 1, 2, a=1, c=3, b=2) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentNormalizer()])) - self.assertEqual( - dedent("""\ - def a_func(*args, **kwds): - pass - a_func(3, 1, 2, a=1, c=3, b=2) - """), - self.mod.read(), - ) - - -def _manage_writes(self, offset, result): - if self.last_set is not None and self.last_set <= offset: - result.append(self.source[self.last_modified : self.last_set]) - set_value = "".join(result[self.set_index :]).strip() - del result[self.set_index :] - result.append(set_value + ")") - self.last_modified = self.last_set - self.last_set = None - - -def test_change_order_for_only_one_parameter(self): - self.mod.write(dedent("""\ - def a_func(p1): - pass - a_func(1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do( - signature.get_changes([change_signature.ArgumentReorderer([0])]) - ) - self.assertEqual( - dedent("""\ - def a_func(p1): - pass - a_func(1) - """), - self.mod.read(), - ) - - -def test_change_order_for_two_parameter(self): - self.mod.write(dedent("""\ - def a_func(p1, p2): - pass - a_func(1, 2) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do( - signature.get_changes([change_signature.ArgumentReorderer([1, 0])]) - ) - self.assertEqual( - dedent("""\ - def a_func(p2, p1): - pass - a_func(2, 1) - """), - self.mod.read(), - ) - - -def test_reordering_multi_line_function_headers(self): - self.mod.write(dedent("""\ - def a_func(p1, - p2): - pass - a_func(1, 2) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do( - signature.get_changes([change_signature.ArgumentReorderer([1, 0])]) - ) - self.assertEqual( - dedent("""\ - def a_func(p2, p1): - pass - a_func(2, 1) - """), - self.mod.read(), - ) - - -def test_changing_order_with_static_params(self): - self.mod.write(dedent("""\ - def a_func(p1, p2=0, p3=0): - pass - a_func(1, 2) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do( - signature.get_changes([change_signature.ArgumentReorderer([0, 2, 1])]) - ) - self.assertEqual( - dedent("""\ - def a_func(p1, p3=0, p2=0): - pass - a_func(1, p2=2) - """), - self.mod.read(), - ) - - -def test_doing_multiple_changes(self): - changers = [] - self.mod.write(dedent("""\ - def a_func(p1): - pass - a_func(1) - """)) - changers.append(change_signature.ArgumentRemover(0)) - changers.append(change_signature.ArgumentAdder(0, "p2", None, None)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - signature.get_changes(changers).do() - self.assertEqual( - dedent("""\ - def a_func(p2): - pass - a_func() - """), - self.mod.read(), - ) - - -def test_doing_multiple_changes2(self): - changers = [] - self.mod.write(dedent("""\ - def a_func(p1, p2): - pass - a_func(p2=2) - """)) - changers.append(change_signature.ArgumentAdder(2, "p3", None, "3")) - changers.append(change_signature.ArgumentReorderer([1, 0, 2])) - changers.append(change_signature.ArgumentRemover(1)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - signature.get_changes(changers).do() - self.assertEqual( - dedent("""\ - def a_func(p2, p3): - pass - a_func(2, 3) - """), - self.mod.read(), - ) - - -def test_changing_signature_in_subclasses(self): - self.mod.write(dedent("""\ - class A(object): - def a_method(self): - pass - class B(A): - def a_method(self): - pass - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_method") + 1 - ) - signature.get_changes( - [change_signature.ArgumentAdder(1, "p1")], in_hierarchy=True - ).do() - self.assertEqual( - dedent("""\ - class A(object): - def a_method(self, p1): - pass - class B(A): - def a_method(self, p1): - pass - """), - self.mod.read(), - ) - - -def test_differentiating_class_accesses_from_instance_accesses(self): - self.mod.write(dedent("""\ - class A(object): - def a_func(self, param): - pass - a_var = A() - A.a_func(a_var, param=1)""")) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("a_func") + 1 - ) - self.project.do(signature.get_changes([change_signature.ArgumentRemover(1)])) - self.assertEqual( - dedent("""\ - class A(object): - def a_func(self): - pass - a_var = A() - A.a_func(a_var)"""), - self.mod.read(), - ) - - -def test_changing_signature_for_constructors(self): - self.mod.write(dedent("""\ - class C(object): - def __init__(self, p): - pass - c = C(1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("C") + 1 - ) - signature.get_changes([change_signature.ArgumentRemover(1)]).do() - self.assertEqual( - dedent("""\ - class C(object): - def __init__(self): - pass - c = C() - """), - self.mod.read(), - ) - - -def test_changing_signature_for_constructors2(self): - self.mod.write(dedent("""\ - class C(object): - def __init__(self, p): - pass - c = C(1) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("__init__") + 1 - ) - signature.get_changes([change_signature.ArgumentRemover(1)]).do() - self.assertEqual( - dedent("""\ - class C(object): - def __init__(self): - pass - c = C() - """), - self.mod.read(), - ) - - -def _is_assigned_in_a_tuple_assignment(self, occurrence): - offset = occurrence.get_word_range()[0] - return self.worder.is_assigned_in_a_tuple_assignment(offset) - - -def test_changing_signature_for_constructors_when_using_super(self): - self.mod.write(dedent("""\ - class A(object): - def __init__(self, p): - pass - class B(A): - def __init__(self, p): - super(B, self).__init__(p) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().index("__init__") + 1 - ) - signature.get_changes([change_signature.ArgumentRemover(1)]).do() - self.assertEqual( - dedent("""\ - class A(object): - def __init__(self): - pass - class B(A): - def __init__(self, p): - super(B, self).__init__() - """), - self.mod.read(), - ) - - -def test_redordering_arguments_reported_by_mft(self): - self.mod.write(dedent("""\ - def f(a, b, c): - pass - f(1, 2, 3) - """)) - signature = change_signature.ChangeSignature( - self.project, self.mod, self.mod.read().rindex("f") - ) - signature.get_changes([change_signature.ArgumentReorderer([1, 2, 0])]).do() - self.assertEqual( - dedent("""\ - def f(b, c, a): - pass - f(2, 3, 1) - """), - self.mod.read(), - ) - - -def test_resources_parameter(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write("def a_func(param):\n pass\n") - self.mod.write(dedent("""\ - import mod1 - mod1.a_func(1) - """)) - signature = change_signature.ChangeSignature( - self.project, mod1, mod1.read().index("a_func") + 1 - ) - signature.get_changes( - [change_signature.ArgumentRemover(0)], resources=[mod1] - ).do() - self.assertEqual( - dedent("""\ - import mod1 - mod1.a_func(1) - """), - self.mod.read(), - ) - self.assertEqual( - dedent("""\ - def a_func(): - pass - """), - mod1.read(), - ) - - -def test_reordering_and_automatic_defaults(self): - code = dedent("""\ - def f(p1, p2=2): - pass - f(1, 2) - """) - self.mod.write(code) - signature = change_signature.ChangeSignature( - self.project, self.mod, code.index("f(") - ) - reorder = change_signature.ArgumentReorderer([1, 0], autodef="1") - signature.get_changes([reorder]).do() - expected = dedent("""\ - def f(p2=2, p1=1): - pass - f(2, 1) - """) - self.assertEqual(expected, self.mod.read()) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -from textwrap import dedent - -import unittest - -import rope.base.codeanalyze -import rope.base.exceptions - -from rope.refactor import extract -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class ExtractMethodTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def do_extract_method(self, source_code, start, end, extracted, **kwds): - testmod = testutils.create_module(self.project, "testmod") - testmod.write(source_code) - extractor = extract.ExtractMethod(self.project, testmod, start, end) - self.project.do(extractor.get_changes(extracted, **kwds)) - return testmod.read() - - -def do_extract_variable(self, source_code, start, end, extracted, **kwds): - testmod = testutils.create_module(self.project, "testmod") - testmod.write(source_code) - extractor = extract.ExtractVariable(self.project, testmod, start, end) - self.project.do(extractor.get_changes(extracted, **kwds)) - return testmod.read() - - -@property -@utils.saveit -def source(self): - if self.resource is not None: - return self.resource.read() - else: - return self.pymodule.source_code - - -def _convert_line_range_to_offset(self, code, start, end): - lines = rope.base.codeanalyze.SourceLinesAdapter(code) - return lines.get_line_start(start), lines.get_line_end(end) - - -def test_simple_extract_function(self): - code = dedent("""\ - def a_func(): - print('one') - print('two') - """) - start, end = self._convert_line_range_to_offset(code, 2, 2) - refactored = self.do_extract_method(code, start, end, "extracted") - expected = dedent("""\ - def a_func(): - extracted() - print('two') - - def extracted(): - print('one') - """) - self.assertEqual(expected, refactored) - - -def test_simple_extract_function_one_line(self): - code = dedent("""\ - def a_func(): - resp = 'one' - print(resp) - """) - selected = "'one'" - start, end = code.index(selected), code.index(selected) + len(selected) - refactored = self.do_extract_method(code, start, end, "extracted") - expected = dedent("""\ - def a_func(): - resp = extracted() - print(resp) - - def extracted(): - return 'one' - """) - self.assertEqual(expected, refactored) - - -def test_extract_function_at_the_end_of_file(self): - code = dedent("""\ - def a_func(): - print('one')""") - start, end = self._convert_line_range_to_offset(code, 2, 2) - refactored = self.do_extract_method(code, start, end, "extracted") - expected = dedent("""\ - def a_func(): - extracted() - def extracted(): - print('one') - """) - self.assertEqual(expected, refactored) - - -def test_extract_function_after_scope(self): - code = dedent("""\ - def a_func(): - print('one') - print('two') - - print('hey') - """) - start, end = self._convert_line_range_to_offset(code, 2, 2) - refactored = self.do_extract_method(code, start, end, "extracted") - expected = dedent("""\ - def a_func(): - extracted() - print('two') - - def extracted(): - print('one') - - print('hey') - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for("3.5") -def test_extract_function_containing_dict_generalized_unpacking(self): - code = dedent("""\ - def a_func(dict1): - dict2 = {} - a_var = {a: b, **dict1, **dict2} - """) - start = code.index("{a") - end = code.index("2}") + len("2}") - refactored = self.do_extract_method(code, start, end, "extracted") - expected = dedent("""\ - def a_func(dict1): - dict2 = {} - a_var = extracted(dict1, dict2) - - def extracted(dict1, dict2): - return {a: b, **dict1, **dict2} - """) - self.assertEqual(expected, refactored) - - -def test_simple_extract_function_with_parameter(self): - code = dedent("""\ - def a_func(): - a_var = 10 - print(a_var) - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - a_var = 10 - new_func(a_var) - - def new_func(a_var): - print(a_var) - """) - self.assertEqual(expected, refactored) - - -def test_not_unread_variables_as_parameter(self): - code = dedent("""\ - def a_func(): - a_var = 10 - print('hey') - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - a_var = 10 - new_func() - - def new_func(): - print('hey') - """) - self.assertEqual(expected, refactored) - - -def test_simple_extract_function_with_two_parameter(self): - code = dedent("""\ - def a_func(): - a_var = 10 - another_var = 20 - third_var = a_var + another_var - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - a_var = 10 - another_var = 20 - new_func(a_var, another_var) - - def new_func(a_var, another_var): - third_var = a_var + another_var - """) - self.assertEqual(expected, refactored) - - -def test_simple_extract_function_with_return_value(self): - code = dedent("""\ - def a_func(): - a_var = 10 - print(a_var) - """) - start, end = self._convert_line_range_to_offset(code, 2, 2) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - a_var = new_func() - print(a_var) - - def new_func(): - a_var = 10 - return a_var - """) - self.assertEqual(expected, refactored) - - -@property -@utils.saveit -def lines(self): - if self.pymodule is None: - self.pymodule = self.project.get_pymodule(self.resource) - return self.pymodule.lines - - -def test_extract_function_with_multiple_return_values(self): - code = dedent("""\ - def a_func(): - a_var = 10 - another_var = 20 - third_var = a_var + another_var - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - a_var, another_var = new_func() - third_var = a_var + another_var - - def new_func(): - a_var = 10 - another_var = 20 - return a_var, another_var - """) - self.assertEqual(expected, refactored) - - -def test_simple_extract_method(self): - code = dedent("""\ - class AClass(object): - - def a_func(self): - print(1) - print(2) - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - class AClass(object): - - def a_func(self): - self.new_func() - print(2) - - def new_func(self): - print(1) - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_args_and_returns(self): - code = dedent("""\ - class AClass(object): - def a_func(self): - a_var = 10 - another_var = a_var * 3 - third_var = a_var + another_var - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - class AClass(object): - def a_func(self): - a_var = 10 - another_var = self.new_func(a_var) - third_var = a_var + another_var - - def new_func(self, a_var): - another_var = a_var * 3 - return another_var - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_self_as_argument(self): - code = dedent("""\ - class AClass(object): - def a_func(self): - print(self) - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - class AClass(object): - def a_func(self): - self.new_func() - - def new_func(self): - print(self) - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_no_self_as_argument(self): - code = dedent("""\ - class AClass(object): - def a_func(): - print(1) - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_extract_method_with_multiple_methods(self): - code = dedent("""\ - class AClass(object): - def a_func(self): - print(self) - - def another_func(self): - pass - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - class AClass(object): - def a_func(self): - self.new_func() - - def new_func(self): - print(self) - - def another_func(self): - pass - """) - self.assertEqual(expected, refactored) - - -def test_extract_function_with_function_returns(self): - code = dedent("""\ - def a_func(): - def inner_func(): - pass - inner_func() - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - inner_func = new_func() - inner_func() - - def new_func(): - def inner_func(): - pass - return inner_func - """) - self.assertEqual(expected, refactored) - - -def test_simple_extract_global_function(self): - code = dedent("""\ - print('one') - print('two') - print('three') - """) - start, end = self._convert_line_range_to_offset(code, 2, 2) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - print('one') - - def new_func(): - print('two') - - new_func() - print('three') - """) - self.assertEqual(expected, refactored) - - -def test_extract_global_function_inside_ifs(self): - code = dedent("""\ - if True: - a = 10 - """) - start, end = self._convert_line_range_to_offset(code, 2, 2) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - - def new_func(): - a = 10 - - if True: - new_func() - """) - self.assertEqual(expected, refactored) - - -def test_extract_function_while_inner_function_reads(self): - code = dedent("""\ - def a_func(): - a_var = 10 - def inner_func(): - print(a_var) - return inner_func - """) - start, end = self._convert_line_range_to_offset(code, 3, 4) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - a_var = 10 - inner_func = new_func(a_var) - return inner_func - - def new_func(a_var): - def inner_func(): - print(a_var) - return inner_func - """) - self.assertEqual(expected, refactored) - - -@property -@utils.saveit -def worder(self): - return worder.Worder(self.source) - -def test_extract_method_bad_range(self): - code = dedent("""\ - def a_func(): - pass - a_var = 10 - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_extract_method_bad_range2(self): - code = dedent("""\ - class AClass(object): - pass - """) - start, end = self._convert_line_range_to_offset(code, 1, 1) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_extract_method_containing_return(self): - code = dedent("""\ - def a_func(arg): - if arg: - return arg * 2 - return 1""") - start, end = self._convert_line_range_to_offset(code, 2, 4) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_extract_method_containing_yield(self): - code = dedent("""\ - def a_func(arg): - yield arg * 2 - """) - start, end = self._convert_line_range_to_offset(code, 2, 2) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_extract_method_containing_uncomplete_lines(self): - code = dedent("""\ - a_var = 20 - another_var = 30 - """) - start = code.index("20") - end = code.index("30") + 2 - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_extract_method_containing_uncomplete_lines2(self): - code = dedent("""\ - a_var = 20 - another_var = 30 - """) - start = code.index("20") - end = code.index("another") + 5 - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_extract_function_and_argument_as_paramenter(self): - code = dedent("""\ - def a_func(arg): - print(arg) - """) - start, end = self._convert_line_range_to_offset(code, 2, 2) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(arg): - new_func(arg) - - def new_func(arg): - print(arg) - """) - self.assertEqual(expected, refactored) - - -def test_extract_function_and_end_as_the_start_of_a_line(self): - code = dedent("""\ - print("hey") - if True: - pass - """) - start = 0 - end = code.index("\n") + 1 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - - def new_func(): - print("hey") - - new_func() - if True: - pass - """) - self.assertEqual(expected, refactored) - - -def test_extract_function_and_indented_blocks(self): - code = dedent("""\ - def a_func(arg): - if True: - if True: - print(arg) - """) - start, end = self._convert_line_range_to_offset(code, 3, 4) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(arg): - if True: - new_func(arg) - - def new_func(arg): - if True: - print(arg) - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_and_multi_line_headers(self): - code = dedent("""\ - def a_func( - arg): - print(arg) - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func( - arg): - new_func(arg) - - def new_func(arg): - print(arg) - """) - self.assertEqual(expected, refactored) - - -@path C:/Repos/ekr-rope/rope/refactor/ -import re -from contextlib import contextmanager -from itertools import chain - -from rope.base import ast, codeanalyze -from rope.base.change import ChangeSet, ChangeContents -from rope.base.exceptions import RefactoringError -from rope.base.utils.datastructures import OrderedSet -from rope.refactor import sourceutils, similarfinder, patchedast, suites, usefunction - - -@others -@language python -@tabwidth -4 - -def test_single_line_extract_function(self): - code = dedent("""\ - a_var = 10 + 20 - """) - start = code.index("10") - end = code.index("20") + 2 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - - def new_func(): - return 10 + 20 - - a_var = new_func() - """) - self.assertEqual(expected, refactored) - - -def test_single_line_extract_function2(self): - code = dedent("""\ - def a_func(): - a = 10 - b = a * 20 - """) - start = code.rindex("a") - end = code.index("20") + 2 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - a = 10 - b = new_func(a) - - def new_func(a): - return a * 20 - """) - self.assertEqual(expected, refactored) - - -def test_single_line_extract_method_and_logical_lines(self): - code = dedent("""\ - a_var = 10 +\\ - 20 - """) - start = code.index("10") - end = code.index("20") + 2 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - - def new_func(): - return 10 + 20 - - a_var = new_func() - """) - self.assertEqual(expected, refactored) - - -def test_single_line_extract_method_and_logical_lines2(self): - code = dedent("""\ - a_var = (10,\\ - 20) - """) - start = code.index("10") - 1 - end = code.index("20") + 3 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - - def new_func(): - return (10, 20) - - a_var = new_func() - """) - self.assertEqual(expected, refactored) - - -def test_single_line_extract_method_with_large_multiline_expression(self): - code = dedent("""\ - a_var = func( - { - "hello": 1, - "world": 2, - }, - blah=foo, - ) - """) - start = code.index("{") - 1 - end = code.index("}") + 1 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - - def new_func(): - return { - "hello": 1, - "world": 2, - } - - a_var = func( - new_func(), - blah=foo, - ) - """) - self.assertEqual(expected, refactored) - - -def test_single_line_extract_method(self): - code = dedent("""\ - class AClass(object): - - def a_func(self): - a = 10 - b = a * a - """) - start = code.rindex("=") + 2 - end = code.rindex("a") + 1 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - class AClass(object): - - def a_func(self): - a = 10 - b = self.new_func(a) - - def new_func(self, a): - return a * a - """) - self.assertEqual(expected, refactored) - - -def test_single_line_extract_function_if_condition(self): - code = dedent("""\ - if True: - pass - """) - start = code.index("True") - end = code.index("True") + 4 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - - def new_func(): - return True - - if new_func(): - pass - """) - self.assertEqual(expected, refactored) - - -def test_unneeded_params(self): - code = dedent("""\ - class A(object): - def a_func(self): - a_var = 10 - a_var += 2 - """) - start = code.rindex("2") - end = code.rindex("2") + 1 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - class A(object): - def a_func(self): - a_var = 10 - a_var += self.new_func() - - def new_func(self): - return 2 - """) - self.assertEqual(expected, refactored) - - -def test_breaks_and_continues_inside_loops(self): - code = dedent("""\ - def a_func(): - for i in range(10): - continue - """) - start = code.index("for") - end = len(code) - 1 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - new_func() - - def new_func(): - for i in range(10): - continue - """) - self.assertEqual(expected, refactored) - - -def test_breaks_and_continues_outside_loops(self): - code = dedent("""\ - def a_func(): - for i in range(10): - a = i - continue - """) - start = code.index("a = i") - end = len(code) - 1 - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def __init__(self, project, resource, offset, goal_resource=None): - self.project = project - self.resource = resource - self.goal_resource = goal_resource - self.info = self._generate_info(project, resource, offset) - self.name = self.info.get_name() - self._check_exceptional_conditions() - - -# Extract refactoring has lots of special cases. I tried to split it -# to smaller parts to make it more manageable: -# -# _ExtractInfo: holds information about the refactoring; it is passed -# to the parts that need to have information about the refactoring -# -# _ExtractCollector: merely saves all of the information necessary for -# performing the refactoring. -# -# _DefinitionLocationFinder: finds where to insert the definition. -# -# _ExceptionalConditionChecker: checks for exceptional conditions in -# which the refactoring cannot be applied. -# -# _ExtractMethodParts: generates the pieces of code (like definition) -# needed for performing extract method. -# -# _ExtractVariableParts: like _ExtractMethodParts for variables. -# -# _ExtractPerformer: Uses above classes to collect refactoring -# changes. -# -# There are a few more helper functions and classes used by above -# classes. -class _ExtractRefactoring: - - kind_prefixes = {} - - @others - -def test_for_loop_variable_scope(self): - code = dedent("""\ - def my_func(): - i = 0 - for dummy in range(10): - i += 1 - print(i) - """) - start, end = self._convert_line_range_to_offset(code, 4, 5) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def my_func(): - i = 0 - for dummy in range(10): - i = new_func(i) - - def new_func(i): - i += 1 - print(i) - return i - """) - self.assertEqual(expected, refactored) - - -def test_for_loop_variable_scope_read_then_write(self): - code = dedent("""\ - def my_func(): - i = 0 - for dummy in range(10): - a = i + 1 - i = a + 1 - """) - start, end = self._convert_line_range_to_offset(code, 4, 5) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def my_func(): - i = 0 - for dummy in range(10): - i = new_func(i) - - def new_func(i): - a = i + 1 - i = a + 1 - return i - """) - self.assertEqual(expected, refactored) - - -def test_for_loop_variable_scope_write_then_read(self): - code = dedent("""\ - def my_func(): - i = 0 - for dummy in range(10): - i = 'hello' - print(i) - """) - start, end = self._convert_line_range_to_offset(code, 4, 5) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def my_func(): - i = 0 - for dummy in range(10): - new_func() - - def new_func(): - i = 'hello' - print(i) - """) - self.assertEqual(expected, refactored) - - -def test_for_loop_variable_scope_write_only(self): - code = dedent("""\ - def my_func(): - i = 0 - for num in range(10): - i = 'hello' + num - print(i) - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def my_func(): - i = 0 - for num in range(10): - i = new_func(num) - print(i) - - def new_func(num): - i = 'hello' + num - return i - """) - self.assertEqual(expected, refactored) - - -def test_variable_writes_followed_by_variable_reads_after_extraction(self): - code = dedent("""\ - def a_func(): - a = 1 - a = 2 - b = a - """) - start = code.index("a = 1") - end = code.index("a = 2") - 1 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - new_func() - a = 2 - b = a - - def new_func(): - a = 1 - """) - self.assertEqual(expected, refactored) - - -def test_var_writes_followed_by_var_reads_inside_extraction(self): - code = dedent("""\ - def a_func(): - a = 1 - a = 2 - b = a - """) - start = code.index("a = 2") - end = len(code) - 1 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - a = 1 - new_func() - - def new_func(): - a = 2 - b = a - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable(self): - code = dedent("""\ - a_var = 10 + 20 - """) - start = code.index("10") - end = code.index("20") + 2 - refactored = self.do_extract_variable(code, start, end, "new_var") - expected = dedent("""\ - new_var = 10 + 20 - a_var = new_var - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.6") -def test_extract_variable_f_string(self): - code = dedent("""\ - foo(f"abc {a_var} def", 10) - """) - start = code.index('f"') - end = code.index('def"') + 4 - refactored = self.do_extract_variable(code, start, end, "new_var") - expected = dedent("""\ - new_var = f"abc {a_var} def" - foo(new_var, 10) - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable_multiple_lines(self): - code = dedent("""\ - a = 1 - b = 2 - """) - start = code.index("1") - end = code.index("1") + 1 - refactored = self.do_extract_variable(code, start, end, "c") - expected = dedent("""\ - c = 1 - a = c - b = 2 - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable_in_the_middle_of_statements(self): - code = dedent("""\ - a = 1 + 2 - """) - start = code.index("1") - end = code.index("1") + 1 - refactored = self.do_extract_variable(code, start, end, "c") - expected = dedent("""\ - c = 1 - a = c + 2 - """) - self.assertEqual(expected, refactored) - - -def __init__(self, project, resource, start_offset, end_offset, variable=False): - self.project = project - self.resource = resource - self.start_offset = self._fix_start(resource.read(), start_offset) - self.end_offset = self._fix_end(resource.read(), end_offset) - - -def test_extract_variable_for_a_tuple(self): - code = dedent("""\ - a = 1, 2 - """) - start = code.index("1") - end = code.index("2") + 1 - refactored = self.do_extract_variable(code, start, end, "c") - expected = dedent("""\ - c = 1, 2 - a = c - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable_for_a_string(self): - code = dedent("""\ - def a_func(): - a = "hey!" - """) - start = code.index('"') - end = code.rindex('"') + 1 - refactored = self.do_extract_variable(code, start, end, "c") - expected = dedent("""\ - def a_func(): - c = "hey!" - a = c - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable_inside_ifs(self): - code = dedent("""\ - if True: - a = 1 + 2 - """) - start = code.index("1") - end = code.rindex("2") + 1 - refactored = self.do_extract_variable(code, start, end, "b") - expected = dedent("""\ - if True: - b = 1 + 2 - a = b - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable_inside_ifs_and_logical_lines(self): - code = dedent("""\ - if True: - a = (3 + - (1 + 2)) - """) - start = code.index("1") - end = code.index("2") + 1 - refactored = self.do_extract_variable(code, start, end, "b") - expected = dedent("""\ - if True: - b = 1 + 2 - a = (3 + - (b)) - """) - self.assertEqual(expected, refactored) - - -# TODO: Handle when extracting a subexpression -def xxx_test_extract_variable_for_a_subexpression(self): - code = dedent("""\ - a = 3 + 1 + 2 - """) - start = code.index("1") - end = code.index("2") + 1 - refactored = self.do_extract_variable(code, start, end, "b") - expected = dedent("""\ - b = 1 + 2 - a = 3 + b - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable_starting_from_the_start_of_the_line(self): - code = dedent("""\ - a_dict = {1: 1} - a_dict.values().count(1) - """) - start = code.rindex("a_dict") - end = code.index("count") - 1 - refactored = self.do_extract_variable(code, start, end, "values") - expected = dedent("""\ - a_dict = {1: 1} - values = a_dict.values() - values.count(1) - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable_on_the_last_line_of_a_function(self): - code = dedent("""\ - def f(): - a_var = {} - a_var.keys() - """) - start = code.rindex("a_var") - end = code.index(".keys") - refactored = self.do_extract_variable(code, start, end, "new_var") - expected = dedent("""\ - def f(): - a_var = {} - new_var = a_var - new_var.keys() - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable_on_the_indented_function_statement(self): - code = dedent("""\ - def f(): - if True: - a_var = 1 + 2 - """) - start = code.index("1") - end = code.index("2") + 1 - refactored = self.do_extract_variable(code, start, end, "new_var") - expected = dedent("""\ - def f(): - if True: - new_var = 1 + 2 - a_var = new_var - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_on_the_last_line_of_a_function(self): - code = dedent("""\ - def f(): - a_var = {} - a_var.keys() - """) - start = code.rindex("a_var") - end = code.index(".keys") - refactored = self.do_extract_method(code, start, end, "new_f") - expected = dedent("""\ - def f(): - a_var = {} - new_f(a_var).keys() - - def new_f(a_var): - return a_var - """) - self.assertEqual(expected, refactored) - - -def test_raising_exception_when_on_incomplete_variables(self): - code = dedent("""\ - a_var = 10 + 20 - """) - start = code.index("10") + 1 - end = code.index("20") + 2 - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def _fix_start(self, source, offset): - while offset < len(source) and source[offset].isspace(): - offset += 1 - return offset - - -def test_raising_exception_when_on_incomplete_variables_on_end(self): - code = dedent("""\ - a_var = 10 + 20 - """) - start = code.index("10") - end = code.index("20") + 1 - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_raising_exception_on_bad_parens(self): - code = dedent("""\ - a_var = (10 + 20) + 30 - """) - start = code.index("20") - end = code.index("30") + 2 - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_raising_exception_on_bad_operators(self): - code = dedent("""\ - a_var = 10 + 20 + 30 - """) - start = code.index("10") - end = code.rindex("+") + 1 - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -# FIXME: Extract method should be more intelligent about bad ranges -def xxx_test_raising_exception_on_function_parens(self): - code = dedent("""\ - a = range(10)""") - start = code.index("(") - end = code.rindex(")") + 1 - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_extract_method_and_extra_blank_lines(self): - code = dedent("""\ - - print(1) - """) - refactored = self.do_extract_method(code, 0, len(code), "new_f") - expected = dedent("""\ - - - def new_f(): - print(1) - - new_f() - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.6") -def test_extract_method_f_string_extract_method(self): - code = dedent("""\ - def func(a_var): - foo(f"abc {a_var}", 10) - """) - start = code.index('f"') - end = code.index('}"') + 2 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def func(a_var): - foo(new_func(a_var), 10) - - def new_func(a_var): - return f"abc {a_var}" - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.6") -def test_extract_method_f_string_extract_method_complex_expression(self): - code = dedent("""\ - def func(a_var): - b_var = int - c_var = 10 - fill = 10 - foo(f"abc {a_var + f'{b_var(a_var)}':{fill}16}" f"{c_var}", 10) - """) - start = code.index('f"') - end = code.index('c_var}"') + 7 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def func(a_var): - b_var = int - c_var = 10 - fill = 10 - foo(new_func(a_var, b_var, c_var, fill), 10) - - def new_func(a_var, b_var, c_var, fill): - return f"abc {a_var + f'{b_var(a_var)}':{fill}16}" f"{c_var}" - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.6") -def test_extract_method_f_string_false_comment(self): - code = dedent("""\ - def func(a_var): - foo(f"abc {a_var} # ", 10) - """) - start = code.index('f"') - end = code.index('# "') + 3 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def func(a_var): - foo(new_func(a_var), 10) - - def new_func(a_var): - return f"abc {a_var} # " - """) - self.assertEqual(expected, refactored) - - -@unittest.expectedFailure -@testutils.only_for_versions_higher("3.6") -def test_extract_method_f_string_false_format_value_in_regular_string(self): - code = dedent("""\ - def func(a_var): - b_var = 1 - foo(f"abc {a_var} " "{b_var}" f"{b_var} def", 10) - """) - start = code.index('f"') - end = code.index('def"') + 4 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def func(a_var): - b_var = 1 - foo(new_func(a_var, b_var), 10) - - def new_func(a_var, b_var): - return f"abc {a_var} " "{b_var}" f"{b_var} def" - """) - self.assertEqual(expected, refactored) - - -def test_variable_writes_in_the_same_line_as_variable_read(self): - code = dedent("""\ - a = 1 - a = 1 + a - """) - start = code.index("\n") + 1 - end = len(code) - refactored = self.do_extract_method(code, start, end, "new_f", global_=True) - expected = dedent("""\ - a = 1 - - def new_f(a): - a = 1 + a - - new_f(a) - """) - self.assertEqual(expected, refactored) - - -def _fix_end(self, source, offset): - while offset > 0 and source[offset - 1].isspace(): - offset -= 1 - return offset - - -def test_variable_writes_in_the_same_line_as_variable_read2(self): - code = dedent("""\ - a = 1 - a += 1 - """) - start = code.index("\n") + 1 - end = len(code) - refactored = self.do_extract_method(code, start, end, "new_f", global_=True) - expected = dedent("""\ - a = 1 - - def new_f(a): - a += 1 - - new_f(a) - """) - self.assertEqual(expected, refactored) - - -def test_variable_writes_in_the_same_line_as_variable_read3(self): - code = dedent("""\ - a = 1 - a += 1 - print(a) - """) - start, end = self._convert_line_range_to_offset(code, 2, 2) - refactored = self.do_extract_method(code, start, end, "new_f") - expected = dedent("""\ - a = 1 - - def new_f(a): - a += 1 - return a - - a = new_f(a) - print(a) - """) - self.assertEqual(expected, refactored) - - -def test_variable_writes_only(self): - code = dedent("""\ - i = 1 - print(i) - """) - start, end = self._convert_line_range_to_offset(code, 1, 1) - refactored = self.do_extract_method(code, start, end, "new_f") - expected = dedent("""\ - - def new_f(): - i = 1 - return i - - i = new_f() - print(i) - """) - self.assertEqual(expected, refactored) - - -def test_variable_and_similar_expressions(self): - code = dedent("""\ - a = 1 - b = 1 - """) - start = code.index("1") - end = start + 1 - refactored = self.do_extract_variable(code, start, end, "one", similar=True) - expected = dedent("""\ - one = 1 - a = one - b = one - """) - self.assertEqual(expected, refactored) - - -def test_definition_should_appear_before_the_first_use(self): - code = dedent("""\ - a = 1 - b = 1 - """) - start = code.rindex("1") - end = start + 1 - refactored = self.do_extract_variable(code, start, end, "one", similar=True) - expected = dedent("""\ - one = 1 - a = one - b = one - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_and_similar_expressions(self): - code = dedent("""\ - a = 1 - b = 1 - """) - start = code.index("1") - end = start + 1 - refactored = self.do_extract_method(code, start, end, "one", similar=True) - expected = dedent("""\ - - def one(): - return 1 - - a = one() - b = one() - """) - self.assertEqual(expected, refactored) - - -def test_simple_extract_method_and_similar_statements(self): - code = dedent("""\ - class AClass(object): - - def func1(self): - a = 1 + 2 - b = a - def func2(self): - a = 1 + 2 - b = a - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "new_func", similar=True) - expected = dedent("""\ - class AClass(object): - - def func1(self): - a = self.new_func() - b = a - - def new_func(self): - a = 1 + 2 - return a - def func2(self): - a = self.new_func() - b = a - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_and_similar_statements2(self): - code = dedent("""\ - class AClass(object): - - def func1(self, p1): - a = p1 + 2 - def func2(self, p2): - a = p2 + 2 - """) - start = code.rindex("p1") - end = code.index("2\n") + 1 - refactored = self.do_extract_method(code, start, end, "new_func", similar=True) - expected = dedent("""\ - class AClass(object): - - def func1(self, p1): - a = self.new_func(p1) - - def new_func(self, p1): - return p1 + 2 - def func2(self, p2): - a = self.new_func(p2) - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_and_similar_sttemnts_return_is_different(self): - code = dedent("""\ - class AClass(object): - - def func1(self, p1): - a = p1 + 2 - def func2(self, p2): - self.attr = p2 + 2 - """) - start = code.rindex("p1") - end = code.index("2\n") + 1 - refactored = self.do_extract_method(code, start, end, "new_func", similar=True) - expected = dedent("""\ - class AClass(object): - - def func1(self, p1): - a = self.new_func(p1) - - def new_func(self, p1): - return p1 + 2 - def func2(self, p2): - self.attr = self.new_func(p2) - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_and_similar_sttemnts_overlapping_regions(self): - code = dedent("""\ - def func(p): - a = p - b = a - c = b - d = c - return d""") - start = code.index("a") - end = code.rindex("a") + 1 - refactored = self.do_extract_method(code, start, end, "new_func", similar=True) - expected = dedent("""\ - def func(p): - b = new_func(p) - d = new_func(b) - return d - def new_func(p): - a = p - b = a - return b - """) - self.assertEqual(expected, refactored) - - -def get_changes(self, extracted_name, similar=False, global_=False, kind=None): - """Get the changes this refactoring makes - - :parameters: - - `extracted_name`: target name, when starts with @ - set kind to - classmethod, $ - staticmethod - - `similar`: if `True`, similar expressions/statements are also - replaced. - - `global_`: if `True`, the extracted method/variable will - be global. - - `kind`: kind of target refactoring to (staticmethod, classmethod) - - """ - extracted_name, kind = self._get_kind_from_name(extracted_name, kind) - - info = _ExtractInfo( - self.project, - self.resource, - self.start_offset, - self.end_offset, - extracted_name, - variable=self._get_kind(kind) == "variable", - similar=similar, - make_global=global_, - ) - info.kind = self._get_kind(kind) - new_contents = _ExtractPerformer(info).extract() - changes = ChangeSet("Extract {} <{}>".format(info.kind, extracted_name)) - changes.add_change(ChangeContents(self.resource, new_contents)) - return changes - - -def test_definition_should_appear_where_it_is_visible(self): - code = dedent("""\ - if True: - a = 1 - else: - b = 1 - """) - start = code.rindex("1") - end = start + 1 - refactored = self.do_extract_variable(code, start, end, "one", similar=True) - expected = dedent("""\ - one = 1 - if True: - a = one - else: - b = one - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable_and_similar_statements_in_classes(self): - code = dedent("""\ - class AClass(object): - - def func1(self): - a = 1 - def func2(self): - b = 1 - """) - start = code.index(" 1") + 1 - refactored = self.do_extract_variable( - code, start, start + 1, "one", similar=True - ) - expected = dedent("""\ - class AClass(object): - - def func1(self): - one = 1 - a = one - def func2(self): - b = 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_in_staticmethods(self): - code = dedent("""\ - class AClass(object): - - @staticmethod - def func2(): - b = 1 - """) - start = code.index(" 1") + 1 - refactored = self.do_extract_method(code, start, start + 1, "one", similar=True) - expected = dedent("""\ - class AClass(object): - - @staticmethod - def func2(): - b = AClass.one() - - @staticmethod - def one(): - return 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_normal_method_with_staticmethods(self): - code = dedent("""\ - class AClass(object): - - @staticmethod - def func1(): - b = 1 - def func2(self): - b = 1 - """) - start = code.rindex(" 1") + 1 - refactored = self.do_extract_method(code, start, start + 1, "one", similar=True) - expected = dedent("""\ - class AClass(object): - - @staticmethod - def func1(): - b = 1 - def func2(self): - b = self.one() - - def one(self): - return 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_variable_with_no_new_lines_at_the_end(self): - code = "a_var = 10" - start = code.index("10") - end = start + 2 - refactored = self.do_extract_variable(code, start, end, "new_var") - expected = dedent("""\ - new_var = 10 - a_var = new_var""") - self.assertEqual(expected, refactored) - - -def test_extract_method_containing_return_in_functions(self): - code = dedent("""\ - def f(arg): - return arg - print(f(1)) - """) - start, end = self._convert_line_range_to_offset(code, 1, 3) - refactored = self.do_extract_method(code, start, end, "a_func") - expected = dedent("""\ - - def a_func(): - def f(arg): - return arg - print(f(1)) - - a_func() - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_and_varying_first_parameter(self): - code = dedent("""\ - class C(object): - def f1(self): - print(str(self)) - def f2(self): - print(str(1)) - """) - start = code.index("print(") + 6 - end = code.index("))\n") + 1 - refactored = self.do_extract_method(code, start, end, "to_str", similar=True) - expected = dedent("""\ - class C(object): - def f1(self): - print(self.to_str()) - - def to_str(self): - return str(self) - def f2(self): - print(str(1)) - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_when_an_attribute_exists_in_function_scope(self): - code = dedent("""\ - class A(object): - def func(self): - pass - a = A() - def f(): - func = a.func() - print(func) - """) - - start, end = self._convert_line_range_to_offset(code, 6, 6) - refactored = self.do_extract_method(code, start, end, "g") - refactored = refactored[refactored.index("A()") + 4 :] - expected = dedent("""\ - def f(): - func = g() - print(func) - - def g(): - func = a.func() - return func - """) - self.assertEqual(expected, refactored) - - -def test_global_option_for_extract_method(self): - code = dedent("""\ - def a_func(): - print(1) - """) - start, end = self._convert_line_range_to_offset(code, 2, 2) - refactored = self.do_extract_method(code, start, end, "extracted", global_=True) - expected = dedent("""\ - def a_func(): - extracted() - - def extracted(): - print(1) - """) - self.assertEqual(expected, refactored) - - -def test_global_extract_method(self): - code = dedent("""\ - class AClass(object): - - def a_func(self): - print(1) - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "new_func", global_=True) - expected = dedent("""\ - class AClass(object): - - def a_func(self): - new_func() - - def new_func(): - print(1) - """) - self.assertEqual(expected, refactored) - - -def _get_kind_from_name(self, extracted_name, kind): - for sign, selected_kind in self.kind_prefixes.items(): - if extracted_name.startswith(sign): - self._validate_kind_prefix(kind, selected_kind) - return extracted_name[1:], selected_kind - return extracted_name, kind - - -def test_global_extract_method_with_multiple_methods(self): - code = dedent("""\ - class AClass(object): - def a_func(self): - print(1) - - def another_func(self): - pass - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "new_func", global_=True) - expected = dedent("""\ - class AClass(object): - def a_func(self): - new_func() - - def another_func(self): - pass - - def new_func(): - print(1) - """) - self.assertEqual(expected, refactored) - - -def test_where_to_seach_when_extracting_global_names(self): - code = dedent("""\ - def a(): - return 1 - def b(): - return 1 - b = 1 - """) - start = code.index("1") - end = start + 1 - refactored = self.do_extract_variable( - code, start, end, "one", similar=True, global_=True - ) - expected = dedent("""\ - def a(): - return one - one = 1 - def b(): - return one - b = one - """) - self.assertEqual(expected, refactored) - - -def test_extracting_pieces_with_distinct_temp_names(self): - code = dedent("""\ - a = 1 - print(a) - b = 1 - print(b) - """) - start = code.index("a") - end = code.index("\nb") - refactored = self.do_extract_method( - code, start, end, "f", similar=True, global_=True - ) - expected = dedent("""\ - - def f(): - a = 1 - print(a) - - f() - f() - """) - self.assertEqual(expected, refactored) - - -def test_extract_methods_in_glob_funcs_should_be_glob(self): - code = dedent("""\ - def f(): - a = 1 - def g(): - b = 1 - """) - start = code.rindex("1") - refactored = self.do_extract_method( - code, start, start + 1, "one", similar=True, global_=False - ) - expected = dedent("""\ - def f(): - a = one() - def g(): - b = one() - - def one(): - return 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_methods_in_glob_funcs_should_be_glob_2(self): - code = dedent("""\ - if 1: - var = 2 - """) - start = code.rindex("2") - refactored = self.do_extract_method( - code, start, start + 1, "two", similar=True, global_=False - ) - expected = dedent("""\ - - def two(): - return 2 - - if 1: - var = two() - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_and_try_blocks(self): - code = dedent("""\ - def f(): - try: - pass - except Exception: - pass - """) - start, end = self._convert_line_range_to_offset(code, 2, 5) - refactored = self.do_extract_method(code, start, end, "g") - expected = dedent("""\ - def f(): - g() - - def g(): - try: - pass - except Exception: - pass - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_and_augmented_assignment_nested_1(self): - code = dedent("""\ - def f(): - my_var = [[0], [1], [2]] - my_var[0][0] += 1 - print(1) - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "g") - expected = dedent("""\ - def f(): - my_var = [[0], [1], [2]] - my_var[0][0] += 1 - g() - - def g(): - print(1) - """) - self.assertEqual(expected, refactored) - -def test_extract_method_and_augmented_assignment_nested_2(self): - code = dedent("""\ - def f(): - my_var = [[0], [1], [2]] - my_var[0][0] += 1 - print(my_var) - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "g") - expected = dedent("""\ - def f(): - my_var = [[0], [1], [2]] - g(my_var) - print(my_var) - - def g(my_var): - my_var[0][0] += 1 - """) - self.assertEqual(expected, refactored) - -def test_extract_method_and_augmented_assignment_var_to_read_in_lhs(self): - code = dedent("""\ - def f(): - var_to_read = 0 - my_var = [0, 1, 2] - my_var[var_to_read] += 1 - print(my_var) - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "g") - expected = dedent("""\ - def f(): - var_to_read = 0 - my_var = [0, 1, 2] - g(my_var, var_to_read) - print(my_var) - - def g(my_var, var_to_read): - my_var[var_to_read] += 1 - """) - self.assertEqual(expected, refactored) - -def test_extract_method_and_augmented_assignment_in_try_block(self): - code = dedent("""\ - def f(): - any_subscriptable = [0] - try: - any_subscriptable[0] += 1 - except Exception: - pass - """) - start, end = self._convert_line_range_to_offset(code, 2, 6) - refactored = self.do_extract_method(code, start, end, "g") - expected = dedent("""\ - def f(): - g() - - def g(): - any_subscriptable = [0] - try: - any_subscriptable[0] += 1 - except Exception: - pass - """) - self.assertEqual(expected, refactored) - - -def test_extract_and_not_passing_global_functions(self): - code = dedent("""\ - def next(p): - return p + 1 - var = next(1) - """) - start = code.rindex("next") - refactored = self.do_extract_method(code, start, len(code) - 1, "two") - expected = dedent("""\ - def next(p): - return p + 1 - - def two(): - return next(1) - - var = two() - """) - self.assertEqual(expected, refactored) - - -def test_extracting_with_only_one_return(self): - code = dedent("""\ - def f(): - var = 1 - return var - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - refactored = self.do_extract_method(code, start, end, "g") - expected = dedent("""\ - def f(): - return g() - - def g(): - var = 1 - return var - """) - self.assertEqual(expected, refactored) - - -def test_extracting_variable_and_implicit_continuations(self): - code = dedent("""\ - s = ("1" - "2") - """) - start = code.index('"') - end = code.rindex('"') + 1 - refactored = self.do_extract_variable(code, start, end, "s2") - expected = dedent("""\ - s2 = "1" "2" - s = (s2) - """) - self.assertEqual(expected, refactored) - - -@staticmethod -def _validate_kind_prefix(kind, selected_kind): - if kind and kind != selected_kind: - raise RefactoringError("Kind and shortcut in name mismatch") - - -def test_extracting_method_and_implicit_continuations(self): - code = dedent("""\ - s = ("1" - "2") - """) - start = code.index('"') - end = code.rindex('"') + 1 - refactored = self.do_extract_method(code, start, end, "f") - expected = dedent("""\ - - def f(): - return "1" "2" - - s = (f()) - """) - self.assertEqual(expected, refactored) - - -def test_passing_conditional_updated_vars_in_extracted(self): - code = dedent("""\ - def f(a): - if 0: - a = 1 - print(a) - """) - start, end = self._convert_line_range_to_offset(code, 2, 4) - refactored = self.do_extract_method(code, start, end, "g") - expected = dedent("""\ - def f(a): - g(a) - - def g(a): - if 0: - a = 1 - print(a) - """) - self.assertEqual(expected, refactored) - - -def test_returning_conditional_updated_vars_in_extracted(self): - code = dedent("""\ - def f(a): - if 0: - a = 1 - print(a) - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - refactored = self.do_extract_method(code, start, end, "g") - expected = dedent("""\ - def f(a): - a = g(a) - print(a) - - def g(a): - if 0: - a = 1 - return a - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_variables_possibly_written_to(self): - code = dedent("""\ - def a_func(b): - if b > 0: - a = 2 - print(a) - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - refactored = self.do_extract_method(code, start, end, "extracted") - expected = dedent("""\ - def a_func(b): - a = extracted(b) - print(a) - - def extracted(b): - if b > 0: - a = 2 - return a - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_list_comprehension(self): - code = dedent("""\ - def foo(): - x = [e for e in []] - f = 23 - - for e, f in []: - def bar(): - e[42] = 1 - """) - start, end = self._convert_line_range_to_offset(code, 4, 7) - refactored = self.do_extract_method(code, start, end, "baz") - expected = dedent("""\ - def foo(): - x = [e for e in []] - f = 23 - - baz() - - def baz(): - for e, f in []: - def bar(): - e[42] = 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_list_comprehension_in_class_method(self): - code = dedent("""\ - class SomeClass: - def method(self): - result = [i for i in range(1)] - print(1) - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "baz", similar=True) - expected = dedent("""\ - class SomeClass: - def method(self): - result = [i for i in range(1)] - self.baz() - - def baz(self): - print(1) - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_list_comprehension_and_iter(self): - code = dedent("""\ - def foo(): - x = [e for e in []] - f = 23 - - for x, f in x: - def bar(): - x[42] = 1 - """) - start, end = self._convert_line_range_to_offset(code, 4, 7) - refactored = self.do_extract_method(code, start, end, "baz") - expected = dedent("""\ - def foo(): - x = [e for e in []] - f = 23 - - baz(x) - - def baz(x): - for x, f in x: - def bar(): - x[42] = 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_list_comprehension_and_orelse(self): - code = dedent("""\ - def foo(): - x = [e for e in []] - f = 23 - - for e, f in []: - def bar(): - e[42] = 1 - """) - start, end = self._convert_line_range_to_offset(code, 4, 7) - refactored = self.do_extract_method(code, start, end, "baz") - expected = dedent("""\ - def foo(): - x = [e for e in []] - f = 23 - - baz() - - def baz(): - for e, f in []: - def bar(): - e[42] = 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_list_comprehension_multiple_targets(self): - code = dedent("""\ - def foo(): - x = [(a, b) for a, b in []] - f = 23 - print("hello") - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "baz") - expected = dedent("""\ - def foo(): - x = [(a, b) for a, b in []] - f = 23 - baz() - - def baz(): - print("hello") - """) - self.assertEqual(expected, refactored) - - -def test_extract_function_with_for_else_statemant(self): - code = dedent("""\ - def a_func(): - for i in range(10): - a = i - else: - a = None - """) - start = code.index("for") - end = len(code) - 1 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - new_func() - - def new_func(): - for i in range(10): - a = i - else: - a = None - """) - self.assertEqual(expected, refactored) - - -@classmethod -def _get_kind(cls, kind): - raise NotImplementedError(f"You have to sublass {cls}") - - - -def test_extract_function_with_for_else_statemant_more(self): - """TODO: fixed code to test passed""" - code = dedent("""\ - def a_func(): - for i in range(10): - a = i - else: - for i in range(5): - b = i - else: - b = None - a = None - """) - - start = code.index("for") - end = len(code) - 1 - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def a_func(): - new_func() - - def new_func(): - for i in range(10): - a = i - else: - for i in range(5): - b = i - else: - b = None - a = None - """) - self.assertEqual(expected, refactored) - - -def test_extract_function_with_for_else_statemant_outside_loops(self): - code = dedent("""\ - def a_func(): - for i in range(10): - a = i - else: - a=None - """) - start = code.index("a = i") - end = len(code) - 1 - with self.assertRaises(rope.base.exceptions.RefactoringError): - self.do_extract_method(code, start, end, "new_func") - - -def test_extract_function_with_inline_assignment_in_method(self): - code = dedent("""\ - def foo(): - i = 1 - i += 1 - print(i) - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def foo(): - i = 1 - i = new_func(i) - print(i) - - def new_func(i): - i += 1 - return i - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.8") -def test_extract_function_statement_with_inline_assignment_in_condition(self): - code = dedent("""\ - def foo(a): - if i := a == 5: - i += 1 - print(i) - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def foo(a): - i = new_func(a) - print(i) - - def new_func(a): - if i := a == 5: - i += 1 - return i - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.8") -def test_extract_function_expression_with_inline_assignment_in_condition(self): - code = dedent("""\ - def foo(a): - if i := a == 5: - i += 1 - print(i) - """) - extract_target = "i := a == 5" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def foo(a): - if i := new_func(a): - i += 1 - print(i) - - def new_func(a): - return (i := a == 5) - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.8") -def test_extract_function_expression_with_inline_assignment_complex(self): - code = dedent("""\ - def foo(a): - if i := a == (c := 5): - i += 1 - c += 1 - print(i) - """) - extract_target = "i := a == (c := 5)" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def foo(a): - if i, c := new_func(a): - i += 1 - c += 1 - print(i) - - def new_func(a): - return (i := a == (c := 5)) - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.8") -def test_extract_function_expression_with_inline_assignment_in_inner_expression( - self, -): - code = dedent("""\ - def foo(a): - if a == (c := 5): - c += 1 - print(i) - """) - extract_target = "a == (c := 5)" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - with self.assertRaisesRegex( - rope.base.exceptions.RefactoringError, - "Extracted piece cannot contain named expression \\(:= operator\\).", - ): - self.do_extract_method(code, start, end, "new_func") - - -def test_extract_exec(self): - code = dedent("""\ - exec("def f(): pass", {}) - """) - start, end = self._convert_line_range_to_offset(code, 1, 1) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - - def new_func(): - exec("def f(): pass", {}) - - new_func() - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_lower("3") -def test_extract_exec_statement(self): - code = dedent("""\ - exec "def f(): pass" in {} - """) - start, end = self._convert_line_range_to_offset(code, 1, 1) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - - def new_func(): - exec "def f(): pass" in {} - - new_func() - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.5") -def test_extract_async_function(self): - code = dedent("""\ - async def my_func(my_list): - for x in my_list: - var = x + 1 - return var - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - async def my_func(my_list): - for x in my_list: - var = new_func(x) - return var - - def new_func(x): - var = x + 1 - return var - """) - self.assertEqual(expected, refactored) - - -class ExtractMethod(_ExtractRefactoring): - kind = "method" - allowed_kinds = ("function", "method", "staticmethod", "classmethod") - kind_prefixes = {"@": "classmethod", "$": "staticmethod"} - - @others - -@testutils.only_for_versions_higher("3.5") -def test_extract_inner_async_function(self): - code = dedent("""\ - def my_func(my_list): - async def inner_func(my_list): - for x in my_list: - var = x + 1 - return inner_func - """) - start, end = self._convert_line_range_to_offset(code, 2, 4) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def my_func(my_list): - inner_func = new_func(my_list) - return inner_func - - def new_func(my_list): - async def inner_func(my_list): - for x in my_list: - var = x + 1 - return inner_func - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.5") -def test_extract_around_inner_async_function(self): - code = dedent("""\ - def my_func(lst): - async def inner_func(obj): - for x in obj: - var = x + 1 - return map(inner_func, lst) - """) - start, end = self._convert_line_range_to_offset(code, 5, 5) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - def my_func(lst): - async def inner_func(obj): - for x in obj: - var = x + 1 - return new_func(inner_func, lst) - - def new_func(inner_func, lst): - return map(inner_func, lst) - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.5") -def test_extract_refactor_around_async_for_loop(self): - code = dedent("""\ - async def my_func(my_list): - async for x in my_list: - var = x + 1 - return var - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - async def my_func(my_list): - async for x in my_list: - var = new_func(x) - return var - - def new_func(x): - var = x + 1 - return var - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.5") -@testutils.only_for_versions_lower("3.8") -def test_extract_refactor_containing_async_for_loop_should_error_before_py38(self): - """ - Refactoring async/await syntaxes is only supported in Python 3.8 and - higher because support for ast.PyCF_ALLOW_TOP_LEVEL_AWAIT was only - added to the standard library in Python 3.8. - """ - code = dedent("""\ - async def my_func(my_list): - async for x in my_list: - var = x + 1 - return var - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - with self.assertRaisesRegex( - rope.base.exceptions.RefactoringError, - "Extracted piece can only have async/await statements if Rope is running on Python 3.8 or higher", - ): - self.do_extract_method(code, start, end, "new_func") - - -@testutils.only_for_versions_higher("3.8") -def test_extract_refactor_containing_async_for_loop_is_supported_after_py38(self): - code = dedent("""\ - async def my_func(my_list): - async for x in my_list: - var = x + 1 - return var - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - async def my_func(my_list): - var = new_func(my_list) - return var - - def new_func(my_list): - async for x in my_list: - var = x + 1 - return var - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.5") -def test_extract_await_expression(self): - code = dedent("""\ - async def my_func(my_list): - for url in my_list: - resp = await request(url) - return resp - """) - selected = "request(url)" - start, end = code.index(selected), code.index(selected) + len(selected) - refactored = self.do_extract_method(code, start, end, "new_func") - expected = dedent("""\ - async def my_func(my_list): - for url in my_list: - resp = await new_func(url) - return resp - - def new_func(url): - return request(url) - """) - self.assertEqual(expected, refactored) - - -def test_extract_to_staticmethod(self): - code = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = a_var + 1 - """) - extract_target = "a_var + 1" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method( - code, start, end, "second_method", kind="staticmethod" - ) - expected = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = A.second_method(a_var) - - @staticmethod - def second_method(a_var): - return a_var + 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_to_staticmethod_when_self_in_body(self): - code = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = self.a_var + 1 - """) - extract_target = "self.a_var + 1" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method( - code, start, end, "second_method", kind="staticmethod" - ) - expected = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = A.second_method(self) - - @staticmethod - def second_method(self): - return self.a_var + 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_from_function_to_staticmethod_raises_exception(self): - code = dedent("""\ - def first_method(): - a_var = 1 - b_var = a_var + 1 - """) - extract_target = "a_var + 1" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - with self.assertRaisesRegex( - rope.base.exceptions.RefactoringError, - "Cannot extract to staticmethod/classmethod outside class", - ): - self.do_extract_method( - code, start, end, "second_method", kind="staticmethod" - ) - - -def test_extract_method_in_classmethods(self): - code = dedent("""\ - class AClass(object): - @classmethod - def func2(cls): - b = 1 - """) - start = code.index(" 1") + 1 - refactored = self.do_extract_method(code, start, start + 1, "one", similar=True) - expected = dedent("""\ - class AClass(object): - @classmethod - def func2(cls): - b = AClass.one() - - @classmethod - def one(cls): - return 1 - """) - self.assertEqual(expected, refactored) - - -@classmethod -def _get_kind(cls, kind): - return kind if kind in cls.allowed_kinds else cls.kind - - - -def test_extract_from_function_to_classmethod_raises_exception(self): - code = dedent("""\ - def first_method(): - a_var = 1 - b_var = a_var + 1 - """) - extract_target = "a_var + 1" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - with self.assertRaisesRegex( - rope.base.exceptions.RefactoringError, - "Cannot extract to staticmethod/classmethod outside class", - ): - self.do_extract_method( - code, start, end, "second_method", kind="classmethod" - ) - - -def test_extract_to_classmethod_when_self_in_body(self): - code = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = self.a_var + 1 - """) - extract_target = "self.a_var + 1" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method( - code, start, end, "second_method", kind="classmethod" - ) - expected = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = A.second_method(self) - - @classmethod - def second_method(cls, self): - return self.a_var + 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_to_classmethod(self): - code = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = a_var + 1 - """) - extract_target = "a_var + 1" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method( - code, start, end, "second_method", kind="classmethod" - ) - expected = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = A.second_method(a_var) - - @classmethod - def second_method(cls, a_var): - return a_var + 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_to_classmethod_when_name_starts_with_at_sign(self): - code = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = a_var + 1 - """) - extract_target = "a_var + 1" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "@second_method") - expected = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = A.second_method(a_var) - - @classmethod - def second_method(cls, a_var): - return a_var + 1 - """) - self.assertEqual(expected, refactored) - - -def test_extract_to_staticmethod_when_name_starts_with_dollar_sign(self): - code = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = a_var + 1 - """) - extract_target = "a_var + 1" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "$second_method") - expected = dedent("""\ - class A: - def first_method(self): - a_var = 1 - b_var = A.second_method(a_var) - - @staticmethod - def second_method(a_var): - return a_var + 1 - """) - self.assertEqual(expected, refactored) - - -def test_raises_exception_when_sign_in_name_and_kind_mismatch(self): - with self.assertRaisesRegex( - rope.base.exceptions.RefactoringError, "Kind and shortcut in name mismatch" - ): - self.do_extract_method("code", 0, 1, "$second_method", kind="classmethod") - - -def test_extracting_from_static_with_function_arg(self): - code = dedent("""\ - class A: - @staticmethod - def first_method(someargs): - b_var = someargs + 1 - """) - - extract_target = "someargs + 1" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "second_method") - expected = dedent("""\ - class A: - @staticmethod - def first_method(someargs): - b_var = A.second_method(someargs) - - @staticmethod - def second_method(someargs): - return someargs + 1 - """) - - self.assertEqual(expected, refactored) - - -def test_extract_with_list_comprehension(self): - code = dedent("""\ - def f(): - y = [1,2,3,4] - a = sum([x for x in y]) - b = sum([x for x in y]) - - print(a, b) - - f() - """) - extract_target = " a = sum([x for x in y])\n" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "_a") - expected = dedent("""\ - def f(): - y = [1,2,3,4] - a = _a(y) - b = sum([x for x in y]) - - print(a, b) - - def _a(y): - a = sum([x for x in y]) - return a - - f() - """) - self.assertEqual(expected, refactored) - - -def test_extract_with_generator(self): - code = dedent("""\ - def f(): - y = [1,2,3,4] - a = sum(x for x in y) - b = sum(x for x in y) - - print(a, b) - - f() - """) - extract_target = " a = sum(x for x in y)\n" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "_a") - expected = dedent("""\ - def f(): - y = [1,2,3,4] - a = _a(y) - b = sum(x for x in y) - - print(a, b) - - def _a(y): - a = sum(x for x in y) - return a - - f() - """) - self.assertEqual(expected, refactored) - - -def test_extract_with_generator_2(self): - code = dedent("""\ - def f(): - y = [1,2,3,4] - a = sum(x for x in y) - """) - extract_target = "x for x in y" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "_a") - expected = dedent("""\ - def f(): - y = [1,2,3,4] - a = sum(_a(y)) - - def _a(y): - return (x for x in y) - """) - self.assertEqual(expected, refactored) - - -def _generate_info(self, project, resource, offset): - return _GenerationInfo(project.pycore, resource, offset, self.goal_resource) - - -class ExtractVariable(_ExtractRefactoring): - @others - -def test_extract_with_set_comprehension(self): - code = dedent("""\ - def f(): - y = [1,2,3,4] - a = sum({x for x in y}) - b = sum({x for x in y}) - - print(a, b) - - f() - """) - extract_target = " a = sum({x for x in y})\n" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "_a") - expected = dedent("""\ - def f(): - y = [1,2,3,4] - a = _a(y) - b = sum({x for x in y}) - - print(a, b) - - def _a(y): - a = sum({x for x in y}) - return a - - f() - """) - self.assertEqual(expected, refactored) - - -def test_extract_with_dict_comprehension(self): - code = dedent("""\ - def f(): - y = [1,2,3,4] - a = sum({x: x for x in y}) - b = sum({x: x for x in y}) - - print(a, b) - - f() - """) - extract_target = " a = sum({x: x for x in y})\n" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "_a") - expected = dedent("""\ - def f(): - y = [1,2,3,4] - a = _a(y) - b = sum({x: x for x in y}) - - print(a, b) - - def _a(y): - a = sum({x: x for x in y}) - return a - - f() - """) - self.assertEqual(expected, refactored) - - -def test_extract_function_expression_with_assignment_to_attribute(self): - code = dedent("""\ - class A(object): - def func(self): - self.var_a = 1 - var_bb = self.var_a - """) - extract_target = "= self.var_a" - start, end = ( - code.index(extract_target) + 2, - code.index(extract_target) + 2 + len(extract_target) - 2, - ) - refactored = self.do_extract_method(code, start, end, "new_func", similar=True) - expected = dedent("""\ - class A(object): - def func(self): - self.var_a = 1 - var_bb = self.new_func() - - def new_func(self): - return self.var_a - """) - - self.assertEqual(expected, refactored) - - -def test_extract_function_expression_with_assignment_index(self): - code = dedent("""\ - class A(object): - def func(self, val): - self[val] = 1 - var_bb = self[val] - """) - extract_target = "= self[val]" - start, end = ( - code.index(extract_target) + 2, - code.index(extract_target) + 2 + len(extract_target) - 2, - ) - refactored = self.do_extract_method(code, start, end, "new_func", similar=True) - expected = dedent("""\ - class A(object): - def func(self, val): - self[val] = 1 - var_bb = self.new_func(val) - - def new_func(self, val): - return self[val] - """) - - self.assertEqual(expected, refactored) - - -def test_extraction_method_with_global_variable(self): - code = dedent("""\ - g = None - - def f(): - global g - - g = 2 - - f() - print(g) - """) - extract_target = "g = 2" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "_g") - expected = dedent("""\ - g = None - - def f(): - global g - - _g() - - def _g(): - global g - g = 2 - - f() - print(g) - """) - self.assertEqual(expected, refactored) - - -def test_extraction_method_with_global_variable_and_global_declaration(self): - code = dedent("""\ - g = None - - def f(): - global g - - g = 2 - - f() - print(g) - """) - start, end = 23, 42 - refactored = self.do_extract_method(code, start, end, "_g") - expected = dedent("""\ - g = None - - def f(): - _g() - - def _g(): - global g - - g = 2 - - f() - print(g) - """) - self.assertEqual(expected, refactored) - - -def test_extraction_one_line_with_global_variable_read_only(self): - code = dedent("""\ - g = None - - def f(): - global g - - a = g - - f() - print(g) - """) - extract_target = "= g" - start, end = code.index(extract_target) + 2, code.index(extract_target) + 3 - refactored = self.do_extract_method(code, start, end, "_g") - expected = dedent("""\ - g = None - - def f(): - global g - - a = _g() - - def _g(): - return g - - f() - print(g) - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.8") -def test_extraction_one_line_with_global_variable(self): - code = dedent("""\ - g = None - - def f(): - global g - - while g := 4: - pass - - f() - print(g) - """) - extract_target = "g := 4" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "_g") - expected = dedent("""\ - g = None - - def f(): - global g - - while _g(): - pass - - def _g(): - global g - return (g := 4) - - f() - print(g) - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.8") -def test_extraction_one_line_with_global_variable_has_postread(self): - code = dedent("""\ - g = None - - def f(): - global g - - while g := 4: - print(g) - - f() - print(g) - """) - extract_target = "g := 4" - start, end = code.index(extract_target), code.index(extract_target) + len( - extract_target - ) - refactored = self.do_extract_method(code, start, end, "_g") - expected = dedent("""\ - g = None - - def f(): - global g - - while g := _g(): - print(g) - - def _g(): - global g - return (g := 4) - - f() - print(g) - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_nested_double_with_as(self): - code = dedent("""\ - with open("test") as file1: - with open("test") as file2: - print(file1, file2) - """) - start, end = self._convert_line_range_to_offset(code, 3, 4) - refactored = self.do_extract_method(code, start, end, "extracted", global_=True) - expected = dedent("""\ - - def extracted(file1, file2): - print(file1, file2) - - with open("test") as file1: - with open("test") as file2: - extracted(file1, file2) - """) - self.assertEqual(expected, refactored) - - -def __init__(self, *args, **kwds): - kwds = dict(kwds) - kwds["variable"] = True - super().__init__(*args, **kwds) - - -def test_extract_method_with_double_with_as(self): - code = dedent("""\ - with open("test") as file1, open("test") as file2: - print(file1, file2) - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - refactored = self.do_extract_method(code, start, end, "extracted", global_=True) - expected = dedent("""\ - - def extracted(file1, file2): - print(file1, file2) - - with open("test") as file1, open("test") as file2: - extracted(file1, file2) - """) - self.assertEqual(expected, refactored) - - -def test_extract_method_with_nested_double_with_as_and_misleading_comment(self): - code = dedent("""\ - with open("test") as file1, open("test") as file2: - # with in comment - bar() - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "extracted", global_=True) - expected = dedent("""\ - - def extracted(): - bar() - - with open("test") as file1, open("test") as file2: - # with in comment - extracted() - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.8") -def test_extract_method_async_with_simple(self): - code = dedent("""\ - async def afunc(): - async with open("test") as file1: - print(file1) - """) - start, end = self._convert_line_range_to_offset(code, 2, 3) - refactored = self.do_extract_method(code, start, end, "extracted", global_=True) - expected = dedent("""\ - async def afunc(): - extracted() - - def extracted(): - async with open("test") as file1: - print(file1) - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.8") -def test_extract_method_containing_async_with(self): - code = dedent("""\ - async def afunc(): - async with open("test") as file1, open("test") as file2: - print(file1, file2) - """) - start, end = self._convert_line_range_to_offset(code, 3, 3) - refactored = self.do_extract_method(code, start, end, "extracted", global_=True) - expected = dedent("""\ - async def afunc(): - async with open("test") as file1, open("test") as file2: - extracted(file1, file2) - - def extracted(file1, file2): - print(file1, file2) - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.10") -def test_extract_method_containing_structural_pattern_match(self): - code = dedent("""\ - match var: - case Foo("xx"): - print(x) - case Foo(x): - print(x) - """) - start, end = self._convert_line_range_to_offset(code, 5, 5) - refactored = self.do_extract_method(code, start, end, "extracted") - expected = dedent("""\ - - def extracted(): - print(x) - - match var: - case Foo("xx"): - print(x) - case Foo(x): - extracted() - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.10") -def test_extract_method_containing_structural_pattern_match_2(self): - code = dedent("""\ - def foo(): - match var: - case Foo(x): - print(x) - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "extracted") - expected = dedent("""\ - def foo(): - match var: - case Foo(x): - extracted(x) - - def extracted(x): - print(x) - """) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.10") -def test_extract_method_containing_structural_pattern_match_3(self): - code = dedent("""\ - def foo(): - match var: - case {"hello": x} as y: - print(x) - """) - start, end = self._convert_line_range_to_offset(code, 4, 4) - refactored = self.do_extract_method(code, start, end, "extracted") - expected = dedent("""\ - def foo(): - match var: - case {"hello": x} as y: - extracted(x) - - def extracted(x): - print(x) - """) - self.assertEqual(expected, refactored) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -import unittest - -from textwrap import dedent - -from rope.refactor.importutils import ImportTools, importinfo, add_import -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class ImportUtilsTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.import_tools = ImportTools(self.project) - - self.mod = testutils.create_module(self.project, "mod") - self.pkg1 = testutils.create_package(self.project, "pkg1") - self.mod1 = testutils.create_module(self.project, "mod1", self.pkg1) - self.pkg2 = testutils.create_package(self.project, "pkg2") - self.mod2 = testutils.create_module(self.project, "mod2", self.pkg2) - self.mod3 = testutils.create_module(self.project, "mod3", self.pkg2) - p1 = testutils.create_package(self.project, "p1") - p2 = testutils.create_package(self.project, "p2", p1) - p3 = testutils.create_package(self.project, "p3", p2) - m1 = testutils.create_module(self.project, "m1", p3) # noqa - l = testutils.create_module(self.project, "l", p3) # noqa - - -kind = "variable" - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_get_import_for_module(self): - mod = self.project.find_module("mod") - import_statement = self.import_tools.get_import(mod) - self.assertEqual("import mod", import_statement.get_import_statement()) - - -def test_get_import_for_module_in_nested_modules(self): - mod = self.project.find_module("pkg1.mod1") - import_statement = self.import_tools.get_import(mod) - self.assertEqual("import pkg1.mod1", import_statement.get_import_statement()) - - -def test_get_import_for_module_in_init_dot_py(self): - init_dot_py = self.pkg1.get_child("__init__.py") - import_statement = self.import_tools.get_import(init_dot_py) - self.assertEqual("import pkg1", import_statement.get_import_statement()) - - -def test_get_from_import_for_module(self): - mod = self.project.find_module("mod") - import_statement = self.import_tools.get_from_import(mod, "a_func") - self.assertEqual( - "from mod import a_func", import_statement.get_import_statement() - ) - - -def test_get_from_import_for_module_in_nested_modules(self): - mod = self.project.find_module("pkg1.mod1") - import_statement = self.import_tools.get_from_import(mod, "a_func") - self.assertEqual( - "from pkg1.mod1 import a_func", import_statement.get_import_statement() - ) - - -def test_get_from_import_for_module_in_init_dot_py(self): - init_dot_py = self.pkg1.get_child("__init__.py") - import_statement = self.import_tools.get_from_import(init_dot_py, "a_func") - self.assertEqual( - "from pkg1 import a_func", import_statement.get_import_statement() - ) - - -def test_get_import_statements(self): - self.mod.write("import pkg1\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.imports - self.assertEqual("import pkg1", imports[0].import_info.get_import_statement()) - - -def test_get_import_statements_with_alias(self): - self.mod.write("import pkg1.mod1 as mod1\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.imports - self.assertEqual( - "import pkg1.mod1 as mod1", imports[0].import_info.get_import_statement() - ) - - -def test_get_import_statements_for_froms(self): - self.mod.write("from pkg1 import mod1\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.imports - self.assertEqual( - "from pkg1 import mod1", imports[0].import_info.get_import_statement() - ) - - -def _get_kind(cls, kind): - return cls.kind - - - -def test_get_multi_line_import_statements_for_froms(self): - self.mod.write("from pkg1 \\\n import mod1\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.imports - self.assertEqual( - "from pkg1 import mod1", imports[0].import_info.get_import_statement() - ) - - -def test_get_import_statements_for_from_star(self): - self.mod.write("from pkg1 import *\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.imports - self.assertEqual( - "from pkg1 import *", imports[0].import_info.get_import_statement() - ) - - -@testutils.only_for("2.5") -def test_get_import_statements_for_new_relatives(self): - self.mod2.write("from .mod3 import x\n") - pymod = self.project.get_module("pkg2.mod2") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.imports - self.assertEqual( - "from .mod3 import x", imports[0].import_info.get_import_statement() - ) - - -def test_ignoring_indented_imports(self): - self.mod.write(dedent("""\ - if True: - import pkg1 - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.imports - self.assertEqual(0, len(imports)) - - -def test_import_get_names(self): - self.mod.write("import pkg1 as pkg\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.imports - context = importinfo.ImportContext(self.project, self.project.root) - self.assertEqual(["pkg"], imports[0].import_info.get_imported_names(context)) - - -def test_import_get_names_with_alias(self): - self.mod.write("import pkg1.mod1\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.imports - context = importinfo.ImportContext(self.project, self.project.root) - self.assertEqual(["pkg1"], imports[0].import_info.get_imported_names(context)) - - -def test_import_get_names_with_alias2(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - """)) - self.mod.write("from pkg1.mod1 import *\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.imports - context = importinfo.ImportContext(self.project, self.project.root) - self.assertEqual(["a_func"], imports[0].import_info.get_imported_names(context)) - - -def test_empty_getting_used_imports(self): - self.mod.write("") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.get_used_imports(pymod) - self.assertEqual(0, len(imports)) - - -def test_empty_getting_used_imports2(self): - self.mod.write("import pkg\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.get_used_imports(pymod) - self.assertEqual(0, len(imports)) - - -def test_simple_getting_used_imports(self): - self.mod.write("import pkg\nprint(pkg)\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.get_used_imports(pymod) - self.assertEqual(1, len(imports)) - self.assertEqual("import pkg", imports[0].get_import_statement()) - - -class _ExtractInfo: - """Holds information about the extract to be performed""" - - @others - -def test_simple_getting_used_imports2(self): - self.mod.write(dedent("""\ - import pkg - def a_func(): - print(pkg) - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.get_used_imports(pymod) - self.assertEqual(1, len(imports)) - self.assertEqual("import pkg", imports[0].get_import_statement()) - - -def test_getting_used_imports_for_nested_scopes(self): - self.mod.write(dedent("""\ - import pkg1 - print(pkg1) - def a_func(): - pass - print(pkg1) - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.get_used_imports(pymod["a_func"].get_object()) - self.assertEqual(0, len(imports)) - - -def test_getting_used_imports_for_nested_scopes2(self): - self.mod.write(dedent("""\ - from pkg1 import mod1 - def a_func(): - print(mod1) - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.get_used_imports(pymod["a_func"].get_object()) - self.assertEqual(1, len(imports)) - self.assertEqual("from pkg1 import mod1", imports[0].get_import_statement()) - - -def test_empty_removing_unused_imports(self): - self.mod.write("import pkg1\nprint(pkg1)\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - "import pkg1\nprint(pkg1)\n", module_with_imports.get_changed_source() - ) - - -def test_simple_removing_unused_imports(self): - self.mod.write("import pkg1\n\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual("", module_with_imports.get_changed_source()) - - -def test_simple_removing_unused_imports_for_froms(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import a_func, another_func - - a_func() - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - from pkg1.mod1 import a_func - - a_func() - """), - module_with_imports.get_changed_source(), - ) - - -def test_simple_removing_unused_imports_for_from_stars(self): - self.mod.write(dedent("""\ - from pkg1.mod1 import * - - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual("", module_with_imports.get_changed_source()) - - -def test_simple_removing_unused_imports_for_nested_modules(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - """)) - self.mod.write(dedent("""\ - import pkg1.mod1 - pkg1.mod1.a_func()""")) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - "import pkg1.mod1\npkg1.mod1.a_func()", - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_and_functions_of_the_same_name(self): - self.mod.write(dedent("""\ - def a_func(): - pass - def a_func(): - pass - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - def a_func(): - pass - def a_func(): - pass - """), - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_for_from_import_with_as(self): - self.mod.write("a_var = 1\n") - self.mod1.write(dedent("""\ - from mod import a_var as myvar - a_var = myvar - """)) - pymod = self.project.get_pymodule(self.mod1) - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - from mod import a_var as myvar - a_var = myvar - """), - module_with_imports.get_changed_source(), - ) - - -def __init__( - self, project, resource, start, end, new_name, variable, similar, make_global -): - self.project = project - self.resource = resource - self.pymodule = project.get_pymodule(resource) - self.global_scope = self.pymodule.get_scope() - self.source = self.pymodule.source_code - self.lines = self.pymodule.lines - self.new_name = new_name - self.variable = variable - self.similar = similar - self._init_parts(start, end) - self.kind = None - self._init_scope() - self.make_global = make_global - - -def test_not_removing_imports_that_conflict_with_class_names(self): - code = dedent("""\ - import pkg1 - class A(object): - pkg1 = 0 - def f(self): - a_var = pkg1 - """) - self.mod.write(code) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual(code, module_with_imports.get_changed_source()) - - -def test_adding_imports(self): - self.mod.write("\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - new_import = self.import_tools.get_import(self.mod1) - module_with_imports.add_import(new_import) - self.assertEqual("import pkg1.mod1\n", module_with_imports.get_changed_source()) - - -def test_adding_imports_no_pull_to_top(self): - self.mod.write(dedent("""\ - import pkg2.mod3 - class A(object): - pass - - import pkg2.mod2 - """)) - pymod = self.project.get_module("mod") - self.project.prefs["pull_imports_to_top"] = False - module_with_imports = self.import_tools.module_imports(pymod) - new_import = self.import_tools.get_import(self.mod1) - module_with_imports.add_import(new_import) - self.assertEqual( - dedent("""\ - import pkg2.mod3 - class A(object): - pass - - import pkg2.mod2 - import pkg1.mod1 - """), - module_with_imports.get_changed_source(), - ) - - -def test_adding_from_imports(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write("from pkg1.mod1 import a_func\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - new_import = self.import_tools.get_from_import(self.mod1, "another_func") - module_with_imports.add_import(new_import) - self.assertEqual( - "from pkg1.mod1 import a_func, another_func\n", - module_with_imports.get_changed_source(), - ) - - -def test_adding_to_star_imports(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write("from pkg1.mod1 import *\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - new_import = self.import_tools.get_from_import(self.mod1, "another_func") - module_with_imports.add_import(new_import) - self.assertEqual( - "from pkg1.mod1 import *\n", module_with_imports.get_changed_source() - ) - - -def test_adding_star_imports(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write("from pkg1.mod1 import a_func\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - new_import = self.import_tools.get_from_import(self.mod1, "*") - module_with_imports.add_import(new_import) - self.assertEqual( - "from pkg1.mod1 import *\n", module_with_imports.get_changed_source() - ) - - -def test_adding_imports_and_preserving_spaces_after_imports(self): - self.mod.write(dedent("""\ - import pkg1 - - - print(pkg1) - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - new_import = self.import_tools.get_import(self.pkg2) - module_with_imports.add_import(new_import) - self.assertEqual( - dedent("""\ - import pkg1 - import pkg2 - - - print(pkg1) - """), - module_with_imports.get_changed_source(), - ) - - -def test_not_changing_the_format_of_unchanged_imports(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import (a_func, - another_func) - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - self.assertEqual( - dedent("""\ - from pkg1.mod1 import (a_func, - another_func) - """), - module_with_imports.get_changed_source(), - ) - - -def test_not_changing_the_format_of_unchanged_imports2(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import (a_func) - a_func() - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - from pkg1.mod1 import (a_func) - a_func() - """), - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_and_reoccuring_names(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import * - from pkg1.mod1 import a_func - a_func() - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - from pkg1.mod1 import * - a_func() - """), - module_with_imports.get_changed_source(), - ) - - -def _init_parts(self, start, end): - self.region = ( - self._choose_closest_line_end(start), - self._choose_closest_line_end(end, end=True), - ) - - start = self.logical_lines.logical_line_in( - self.lines.get_line_number(self.region[0]) - )[0] - end = self.logical_lines.logical_line_in( - self.lines.get_line_number(self.region[1]) - )[1] - self.region_lines = (start, end) - - self.lines_region = ( - self.lines.get_line_start(self.region_lines[0]), - self.lines.get_line_end(self.region_lines[1]), - ) - - -def test_removing_unused_imports_and_reoccuring_names2(self): - self.mod.write(dedent("""\ - import pkg2.mod2 - import pkg2.mod3 - print(pkg2.mod2, pkg2.mod3)""")) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - import pkg2.mod2 - import pkg2.mod3 - print(pkg2.mod2, pkg2.mod3)"""), - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_and_common_packages(self): - self.mod.write(dedent("""\ - import pkg1.mod1 - import pkg1 - print(pkg1, pkg1.mod1) - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - import pkg1.mod1 - print(pkg1, pkg1.mod1) - """), - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_and_common_packages_reversed(self): - self.mod.write(dedent("""\ - import pkg1 - import pkg1.mod1 - print(pkg1, pkg1.mod1) - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_duplicates() - self.assertEqual( - dedent("""\ - import pkg1.mod1 - print(pkg1, pkg1.mod1) - """), - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_and_common_packages2(self): - self.mod.write(dedent("""\ - import pkg1.mod1 - import pkg1.mod2 - print(pkg1) - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - import pkg1.mod1 - print(pkg1) - """), - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_and_froms(self): - self.mod1.write(dedent("""\ - def func1(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import func1 - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual("", module_with_imports.get_changed_source()) - - -def test_removing_unused_imports_and_froms2(self): - self.mod1.write(dedent("""\ - def func1(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import func1 - func1()""")) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - from pkg1.mod1 import func1 - func1()"""), - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_and_froms3(self): - self.mod1.write(dedent("""\ - def func1(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import func1 - def a_func(): - func1() - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - from pkg1.mod1 import func1 - def a_func(): - func1() - """), - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_and_froms4(self): - self.mod1.write(dedent("""\ - def func1(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import func1 - class A(object): - def a_func(self): - func1() - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - from pkg1.mod1 import func1 - class A(object): - def a_func(self): - func1() - """), - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_and_getting_attributes(self): - self.mod1.write(dedent("""\ - class A(object): - def f(self): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import A - var = A().f()""")) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - from pkg1.mod1 import A - var = A().f()"""), - module_with_imports.get_changed_source(), - ) - - -def test_removing_unused_imports_function_parameters(self): - self.mod1.write(dedent("""\ - def func1(): - pass - """)) - self.mod.write(dedent("""\ - import pkg1 - def a_func(pkg1): - my_var = pkg1 - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - def a_func(pkg1): - my_var = pkg1 - """), - module_with_imports.get_changed_source(), - ) - - -@property -def logical_lines(self): - return self.pymodule.logical_lines - - -def test_trivial_expanding_star_imports(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write("from pkg1.mod1 import *\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.expand_stars() - self.assertEqual("", module_with_imports.get_changed_source()) - - -def test_expanding_star_imports(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write("from pkg1.mod1 import *\na_func()\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.expand_stars() - self.assertEqual( - "from pkg1.mod1 import a_func\na_func()\n", - module_with_imports.get_changed_source(), - ) - - -def test_removing_duplicate_imports(self): - self.mod.write("import pkg1\nimport pkg1\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_duplicates() - self.assertEqual("import pkg1\n", module_with_imports.get_changed_source()) - - -def test_removing_duplicates_and_reoccuring_names(self): - self.mod.write("import pkg2.mod2\nimport pkg2.mod3\n") - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_duplicates() - self.assertEqual( - "import pkg2.mod2\nimport pkg2.mod3\n", - module_with_imports.get_changed_source(), - ) - - -def test_removing_duplicate_imports_for_froms(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1 import a_func - from pkg1 import a_func, another_func - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_duplicates() - self.assertEqual( - "from pkg1 import a_func, another_func\n", - module_with_imports.get_changed_source(), - ) - - -def test_transforming_froms_to_normal_changing_imports(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import a_func - print(a_func) - """)) - pymod = self.project.get_module("mod") - changed_module = self.import_tools.froms_to_imports(pymod) - self.assertEqual( - dedent("""\ - import pkg1.mod1 - print(pkg1.mod1.a_func) - """), - changed_module, - ) - - -def test_transforming_froms_to_normal_changing_occurrences(self): - self.mod1.write("def a_func():\n pass\n") - self.mod.write("from pkg1.mod1 import a_func\na_func()") - pymod = self.project.get_module("mod") - changed_module = self.import_tools.froms_to_imports(pymod) - self.assertEqual("import pkg1.mod1\npkg1.mod1.a_func()", changed_module) - - -def test_transforming_froms_to_normal_for_multi_imports(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import * - a_func() - another_func() - """)) - pymod = self.project.get_module("mod") - changed_module = self.import_tools.froms_to_imports(pymod) - self.assertEqual( - dedent("""\ - import pkg1.mod1 - pkg1.mod1.a_func() - pkg1.mod1.another_func() - """), - changed_module, - ) - - -def test_transform_froms_to_norm_for_multi_imports_inside_parens(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - def another_func(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import (a_func, - another_func) - a_func() - another_func() - """)) - pymod = self.project.get_module("mod") - changed_module = self.import_tools.froms_to_imports(pymod) - self.assertEqual( - dedent("""\ - import pkg1.mod1 - pkg1.mod1.a_func() - pkg1.mod1.another_func() - """), - changed_module, - ) - - -def test_transforming_froms_to_normal_from_stars(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import * - a_func() - """)) - pymod = self.project.get_module("mod") - changed_module = self.import_tools.froms_to_imports(pymod) - self.assertEqual( - dedent("""\ - import pkg1.mod1 - pkg1.mod1.a_func() - """), - changed_module, - ) - - -def _init_scope(self): - start_line = self.region_lines[0] - scope = self.global_scope.get_inner_scope_for_line(start_line) - if scope.get_kind() != "Module" and scope.get_start() == start_line: - scope = scope.parent - self.scope = scope - self.scope_region = self._get_scope_region(self.scope) - - -def test_transforming_froms_to_normal_from_stars2(self): - self.mod1.write("a_var = 10") - self.mod.write(dedent("""\ - import pkg1.mod1 - from pkg1.mod1 import a_var - def a_func(): - print(pkg1.mod1, a_var) - """)) - pymod = self.project.get_module("mod") - changed_module = self.import_tools.froms_to_imports(pymod) - self.assertEqual( - dedent("""\ - import pkg1.mod1 - def a_func(): - print(pkg1.mod1, pkg1.mod1.a_var) - """), - changed_module, - ) - - -def test_transforming_froms_to_normal_from_with_alias(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - """)) - self.mod.write(dedent("""\ - from pkg1.mod1 import a_func as another_func - another_func() - """)) - pymod = self.project.get_module("mod") - changed_module = self.import_tools.froms_to_imports(pymod) - self.assertEqual( - dedent("""\ - import pkg1.mod1 - pkg1.mod1.a_func() - """), - changed_module, - ) - - -def test_transforming_froms_to_normal_for_relatives(self): - self.mod2.write(dedent("""\ - def a_func(): - pass - """)) - self.mod3.write(dedent("""\ - from mod2 import * - a_func() - """)) - pymod = self.project.get_pymodule(self.mod3) - changed_module = self.import_tools.froms_to_imports(pymod) - self.assertEqual( - dedent("""\ - import pkg2.mod2 - pkg2.mod2.a_func() - """), - changed_module, - ) - - -def test_transforming_froms_to_normal_for_os_path(self): - self.mod.write("from os import path\npath.exists('.')\n") - pymod = self.project.get_pymodule(self.mod) - changed_module = self.import_tools.froms_to_imports(pymod) - self.assertEqual("import os\nos.path.exists('.')\n", changed_module) - - -def test_transform_relatives_imports_to_abs_imports_doing_nothing(self): - self.mod2.write("from pkg1 import mod1\nimport mod1\n") - pymod = self.project.get_pymodule(self.mod2) - self.assertEqual( - "from pkg1 import mod1\nimport mod1\n", - self.import_tools.relatives_to_absolutes(pymod), - ) - - -def test_transform_relatives_to_absolute_imports_for_normal_imports(self): - self.mod2.write("import mod3\n") - pymod = self.project.get_pymodule(self.mod2) - self.assertEqual( - "import pkg2.mod3\n", self.import_tools.relatives_to_absolutes(pymod) - ) - - -def test_transform_relatives_imports_to_absolute_imports_for_froms(self): - self.mod3.write(dedent("""\ - def a_func(): - pass - """)) - self.mod2.write("from mod3 import a_func\n") - pymod = self.project.get_pymodule(self.mod2) - self.assertEqual( - "from pkg2.mod3 import a_func\n", - self.import_tools.relatives_to_absolutes(pymod), - ) - - -@testutils.only_for("2.5") -def test_transform_rel_imports_to_abs_imports_for_new_relatives(self): - self.mod3.write(dedent("""\ - def a_func(): - pass - """)) - self.mod2.write("from .mod3 import a_func\n") - pymod = self.project.get_pymodule(self.mod2) - self.assertEqual( - "from pkg2.mod3 import a_func\n", - self.import_tools.relatives_to_absolutes(pymod), - ) - - -def test_transform_relatives_to_absolute_imports_for_normal_imports2(self): - self.mod2.write("import mod3\nprint(mod3)") - pymod = self.project.get_pymodule(self.mod2) - self.assertEqual( - "import pkg2.mod3\nprint(pkg2.mod3)", - self.import_tools.relatives_to_absolutes(pymod), - ) - - -def test_transform_relatives_to_absolute_imports_for_aliases(self): - self.mod2.write("import mod3 as mod3\nprint(mod3)") - pymod = self.project.get_pymodule(self.mod2) - self.assertEqual( - "import pkg2.mod3 as mod3\nprint(mod3)", - self.import_tools.relatives_to_absolutes(pymod), - ) - - -def _get_scope_region(self, scope): - return ( - self.lines.get_line_start(scope.get_start()), - self.lines.get_line_end(scope.get_end()) + 1, - ) - - -def test_organizing_imports(self): - self.mod1.write("import mod1\n") - pymod = self.project.get_pymodule(self.mod1) - self.assertEqual("", self.import_tools.organize_imports(pymod)) - - -def test_organizing_imports_without_deduplication(self): - contents = dedent("""\ - from pkg2 import mod2 - from pkg2 import mod3 - """) - self.mod.write(contents) - pymod = self.project.get_pymodule(self.mod) - self.project.prefs["split_imports"] = True - self.assertEqual( - contents, self.import_tools.organize_imports(pymod, unused=False) - ) - - -def test_splitting_imports(self): - self.mod.write(dedent("""\ - from pkg1 import mod1 - from pkg2 import mod2, mod3 - """)) - pymod = self.project.get_pymodule(self.mod) - self.project.prefs["split_imports"] = True - self.assertEqual( - dedent("""\ - from pkg1 import mod1 - from pkg2 import mod2 - from pkg2 import mod3 - """), - self.import_tools.organize_imports(pymod, unused=False), - ) - - -def test_splitting_imports_no_pull_to_top(self): - self.mod.write(dedent("""\ - from pkg2 import mod3, mod4 - from pkg1 import mod2 - from pkg1 import mod1 - """)) - pymod = self.project.get_pymodule(self.mod) - self.project.prefs["split_imports"] = True - self.project.prefs["pull_imports_to_top"] = False - self.assertEqual( - dedent("""\ - from pkg1 import mod2 - from pkg1 import mod1 - from pkg2 import mod3 - from pkg2 import mod4 - """), - self.import_tools.organize_imports(pymod, sort=False, unused=False), - ) - - -def test_splitting_imports_with_filter(self): - self.mod.write(dedent("""\ - from pkg1 import mod1, mod2 - from pkg2 import mod3, mod4 - """)) - pymod = self.project.get_pymodule(self.mod) - self.project.prefs["split_imports"] = True - - def import_filter(stmt): - return stmt.import_info.module_name == "pkg1" - - self.assertEqual( - dedent("""\ - from pkg1 import mod1 - from pkg1 import mod2 - from pkg2 import mod3, mod4 - """), - self.import_tools.organize_imports( - pymod, unused=False, import_filter=import_filter - ), - ) - - -def test_splitting_duplicate_imports(self): - self.mod.write(dedent("""\ - from pkg2 import mod1 - from pkg2 import mod1, mod2 - """)) - pymod = self.project.get_pymodule(self.mod) - self.project.prefs["split_imports"] = True - self.assertEqual( - dedent("""\ - from pkg2 import mod1 - from pkg2 import mod2 - """), - self.import_tools.organize_imports(pymod, unused=False), - ) - - -def test_splitting_duplicate_imports2(self): - self.mod.write(dedent("""\ - from pkg2 import mod1, mod3 - from pkg2 import mod1, mod2 - from pkg2 import mod2, mod3 - """)) - pymod = self.project.get_pymodule(self.mod) - self.project.prefs["split_imports"] = True - self.assertEqual( - dedent("""\ - from pkg2 import mod1 - from pkg2 import mod2 - from pkg2 import mod3 - """), - self.import_tools.organize_imports(pymod, unused=False), - ) - - -def test_removing_self_imports(self): - self.mod.write(dedent("""\ - import mod - mod.a_var = 1 - print(mod.a_var) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - a_var = 1 - print(a_var) - """), - self.import_tools.organize_imports(pymod), - ) - - -def test_removing_self_imports2(self): - self.mod1.write(dedent("""\ - import pkg1.mod1 - pkg1.mod1.a_var = 1 - print(pkg1.mod1.a_var) - """)) - pymod = self.project.get_pymodule(self.mod1) - self.assertEqual( - dedent("""\ - a_var = 1 - print(a_var) - """), - self.import_tools.organize_imports(pymod), - ) - - -def test_removing_self_imports_with_as(self): - self.mod.write(dedent("""\ - import mod as mymod - mymod.a_var = 1 - print(mymod.a_var) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - a_var = 1 - print(a_var) - """), - self.import_tools.organize_imports(pymod), - ) - - -def _check_exceptional_conditions(self): - if self.info.element_already_exists(): - raise exceptions.RefactoringError( - "Element <%s> already exists." % self.name - ) - if not self.info.primary_is_found(): - raise exceptions.RefactoringError( - "Cannot determine the scope <%s> should be defined in." % self.name - ) - - -def _choose_closest_line_end(self, offset, end=False): - lineno = self.lines.get_line_number(offset) - line_start = self.lines.get_line_start(lineno) - line_end = self.lines.get_line_end(lineno) - if self.source[line_start:offset].strip() == "": - if end: - return line_start - 1 - else: - return line_start - elif self.source[offset:line_end].strip() == "": - return min(line_end, len(self.source)) - return offset - - -def test_removing_self_imports_for_froms(self): - self.mod1.write(dedent("""\ - from pkg1 import mod1 - mod1.a_var = 1 - print(mod1.a_var) - """)) - pymod = self.project.get_pymodule(self.mod1) - self.assertEqual( - dedent("""\ - a_var = 1 - print(a_var) - """), - self.import_tools.organize_imports(pymod), - ) - - -def test_removing_self_imports_for_froms_with_as(self): - self.mod1.write(dedent("""\ - from pkg1 import mod1 as mymod - mymod.a_var = 1 - print(mymod.a_var) - """)) - pymod = self.project.get_pymodule(self.mod1) - self.assertEqual( - dedent("""\ - a_var = 1 - print(a_var) - """), - self.import_tools.organize_imports(pymod), - ) - - -def test_removing_self_imports_for_froms2(self): - self.mod.write(dedent("""\ - from mod import a_var - a_var = 1 - print(a_var) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - a_var = 1 - print(a_var) - """), - self.import_tools.organize_imports(pymod), - ) - - -def test_removing_self_imports_for_froms3(self): - self.mod.write(dedent("""\ - from mod import a_var - a_var = 1 - print(a_var) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - a_var = 1 - print(a_var) - """), - self.import_tools.organize_imports(pymod), - ) - - -def test_removing_self_imports_for_froms4(self): - self.mod.write(dedent("""\ - from mod import a_var as myvar - a_var = 1 - print(myvar) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - a_var = 1 - print(a_var) - """), - self.import_tools.organize_imports(pymod), - ) - - -def test_removing_self_imports_with_no_dot_after_mod(self): - self.mod.write(dedent("""\ - import mod - print(mod) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - import mod - - - print(mod) - """), - self.import_tools.organize_imports(pymod), - ) - - -def test_removing_self_imports_with_no_dot_after_mod2(self): - self.mod.write(dedent("""\ - import mod - a_var = 1 - print(mod\\ - \\ - .var) - - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - a_var = 1 - print(var) - - """), - self.import_tools.organize_imports(pymod), - ) - - -def test_removing_self_imports_for_from_import_star(self): - self.mod.write(dedent("""\ - from mod import * - a_var = 1 - print(myvar) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - a_var = 1 - print(myvar) - """), - self.import_tools.organize_imports(pymod), - ) - - -def test_not_removing_future_imports(self): - self.mod.write("from __future__ import division\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - "from __future__ import division\n", - self.import_tools.organize_imports(pymod), - ) - - -def test_sorting_empty_imports(self): - self.mod.write("") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual("", self.import_tools.sort_imports(pymod)) - - -@property -def one_line(self): - return self.region != self.lines_region and ( - self.logical_lines.logical_line_in(self.region_lines[0]) - == self.logical_lines.logical_line_in(self.region_lines[1]) - ) - - -def test_sorting_one_import(self): - self.mod.write("import pkg1.mod1\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual("import pkg1.mod1\n", self.import_tools.sort_imports(pymod)) - - -def test_sorting_imports_alphabetically(self): - self.mod.write("import pkg2.mod2\nimport pkg1.mod1\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - "import pkg1.mod1\nimport pkg2.mod2\n", - self.import_tools.sort_imports(pymod), - ) - - -def test_sorting_imports_purely_alphabetically(self): - self.mod.write(dedent("""\ - from pkg2 import mod3 as mod0 - import pkg2.mod2 - import pkg1.mod1 - """)) - pymod = self.project.get_pymodule(self.mod) - self.project.prefs["sort_imports_alphabetically"] = True - self.assertEqual( - dedent("""\ - import pkg1.mod1 - import pkg2.mod2 - from pkg2 import mod3 as mod0 - """), - self.import_tools.sort_imports(pymod), - ) - - -def test_sorting_imports_and_froms(self): - self.mod.write("import pkg2.mod2\nfrom pkg1 import mod1\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - "import pkg2.mod2\nfrom pkg1 import mod1\n", - self.import_tools.sort_imports(pymod), - ) - - -def test_sorting_imports_and_standard_modules(self): - self.mod.write(dedent("""\ - import pkg1 - import sys - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - import sys - - import pkg1 - """), - self.import_tools.sort_imports(pymod), - ) - - -def test_sorting_imports_and_standard_modules2(self): - self.mod.write(dedent("""\ - import sys - - import time - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - import sys - import time - """), - self.import_tools.sort_imports(pymod), - ) - - -def test_sorting_only_standard_modules(self): - self.mod.write("import sys\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual("import sys\n", self.import_tools.sort_imports(pymod)) - - -def test_sorting_third_party(self): - self.mod.write(dedent("""\ - import pkg1 - import a_third_party - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - import a_third_party - - import pkg1 - """), - self.import_tools.sort_imports(pymod), - ) - - -def test_sorting_only_third_parties(self): - self.mod.write(dedent("""\ - import a_third_party - a_var = 1 - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - import a_third_party - - - a_var = 1 - """), - self.import_tools.sort_imports(pymod), - ) - - -def test_simple_handling_long_imports(self): - self.mod.write(dedent("""\ - import pkg1.mod1 - - - m = pkg1.mod1 - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - import pkg1.mod1 - - - m = pkg1.mod1 - """), - self.import_tools.handle_long_imports(pymod, maxdots=2), - ) - - -@property -def global_(self): - return self.scope.parent is None - - -def test_handling_long_imports_for_many_dots(self): - self.mod.write(dedent("""\ - import p1.p2.p3.m1 - - - m = p1.p2.p3.m1 - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - from p1.p2.p3 import m1 - - - m = m1 - """), - self.import_tools.handle_long_imports(pymod, maxdots=2), - ) - - -def test_handling_long_imports_for_their_length(self): - self.mod.write(dedent("""\ - import p1.p2.p3.m1 - - - m = p1.p2.p3.m1 - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - import p1.p2.p3.m1 - - - m = p1.p2.p3.m1 - """), - self.import_tools.handle_long_imports(pymod, maxdots=3, maxlength=20), - ) - - -def test_handling_long_imports_for_many_dots2(self): - self.mod.write(dedent("""\ - import p1.p2.p3.m1 - - - m = p1.p2.p3.m1 - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - from p1.p2.p3 import m1 - - - m = m1 - """), - self.import_tools.handle_long_imports(pymod, maxdots=3, maxlength=10), - ) - - -def test_handling_long_imports_with_one_letter_last(self): - self.mod.write(dedent("""\ - import p1.p2.p3.l - - - m = p1.p2.p3.l - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - from p1.p2.p3 import l - - - m = l - """), - self.import_tools.handle_long_imports(pymod, maxdots=2), - ) - - -def test_empty_removing_unused_imports_and_eating_blank_lines(self): - self.mod.write(dedent("""\ - import pkg1 - import pkg2 - - - print(pkg1) - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - module_with_imports.remove_unused_imports() - self.assertEqual( - dedent("""\ - import pkg1 - - - print(pkg1) - """), - module_with_imports.get_changed_source(), - ) - - -def test_sorting_imports_moving_to_top(self): - self.mod.write(dedent("""\ - import mod - def f(): - print(mod, pkg1, pkg2) - import pkg1 - import pkg2 - """)) - pymod = self.project.get_module("mod") - self.assertEqual( - dedent("""\ - import mod - import pkg1 - import pkg2 - - - def f(): - print(mod, pkg1, pkg2) - """), - self.import_tools.sort_imports(pymod), - ) - - -def test_sorting_imports_moving_to_top2(self): - self.mod.write(dedent("""\ - def f(): - print(mod) - import mod - """)) - pymod = self.project.get_module("mod") - self.assertEqual( - dedent("""\ - import mod - - - def f(): - print(mod) - """), - self.import_tools.sort_imports(pymod), - ) - - -# Sort pulls imports to the top anyway -def test_sorting_imports_no_pull_to_top(self): - code = dedent("""\ - import pkg2 - def f(): - print(mod, pkg1, pkg2) - import pkg1 - import mod - """) - self.mod.write(code) - pymod = self.project.get_module("mod") - self.project.prefs["pull_imports_to_top"] = False - self.assertEqual( - dedent("""\ - import mod - import pkg1 - import pkg2 - - - def f(): - print(mod, pkg1, pkg2) - """), - self.import_tools.sort_imports(pymod), - ) - - -def test_sorting_imports_moving_to_top_and_module_docs(self): - self.mod.write(dedent('''\ - """ - docs - """ - def f(): - print(mod) - import mod - ''')) - pymod = self.project.get_module("mod") - self.assertEqual( - dedent('''\ - """ - docs - """ - import mod - - - def f(): - print(mod) - '''), - self.import_tools.sort_imports(pymod), - ) - - -def test_sorting_imports_moving_to_top_and_module_docs2(self): - self.mod.write(dedent('''\ - """ - docs - """ - - - import bbb - import aaa - def f(): - print(mod) - import mod - ''')) - pymod = self.project.get_module("mod") - self.assertEqual( - dedent('''\ - """ - docs - """ - - - import aaa - import bbb - - import mod - - - def f(): - print(mod) - '''), - self.import_tools.sort_imports(pymod), - ) - - -@property -def method(self): - return self.scope.parent is not None and self.scope.parent.get_kind() == "Class" - - -def test_get_changed_source_preserves_blank_lines(self): - self.mod.write(dedent("""\ - __author__ = "author" - - import aaa - - import bbb - - def f(): - print(mod) - """)) - pymod = self.project.get_module("mod") - module_with_imports = self.import_tools.module_imports(pymod) - self.assertEqual( - dedent("""\ - import aaa - - import bbb - - __author__ = "author" - - def f(): - print(mod) - """), - module_with_imports.get_changed_source(), - ) - - -def test_sorting_future_imports(self): - self.mod.write(dedent("""\ - import os - from __future__ import devision - """)) - pymod = self.project.get_module("mod") - self.assertEqual( - dedent("""\ - from __future__ import devision - - import os - """), - self.import_tools.sort_imports(pymod), - ) - - -def test_organizing_imports_all_star(self): - code = expected = dedent("""\ - from package import some_name - - - __all__ = ["some_name"] - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_organizing_imports_all_star_with_variables(self): - code = expected = dedent("""\ - from package import name_one, name_two - - - if something(): - foo = 'name_one' - else: - foo = 'name_two' - __all__ = [foo] - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_organizing_imports_all_star_with_inline_if(self): - code = expected = dedent("""\ - from package import name_one, name_two - - - __all__ = ['name_one' if something() else 'name_two'] - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -@testutils.only_for_versions_higher("3") -def test_organizing_imports_all_star_tolerates_non_list_of_str_1(self): - code = expected = dedent("""\ - from package import name_one, name_two - - - foo = 'name_two' - __all__ = [bar, *abc] + mylist - __all__ = [foo, 'name_one', *abc] - __all__ = [it for it in mylist] - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_organizing_imports_all_star_assigned_name_alias(self): - code = expected = dedent("""\ - from package import name_one, name_two - - - foo = ['name_one', 'name_two'] - __all__ = foo - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_organizing_imports_all_star_imported_name_alias(self): - self.mod1.write("foo = ['name_one', 'name_two']") - self.mod2.write("from pkg1.mod1 import foo") - code = expected = dedent("""\ - from package import name_one, name_two - - from pkg2.mod2 import foo - - - __all__ = foo - """) - self.mod3.write(code) - pymod = self.project.get_pymodule(self.mod3) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_organizing_imports_all_star_tolerates_non_list_of_str_2(self): - code = expected = dedent("""\ - from package import name_one, name_two - - - foo = 'name_two' - __all__ = [foo, 3, 'name_one'] - __all__ = [it for it in mylist] - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_organizing_imports_all_star_plusjoin(self): - code = expected = dedent("""\ - from package import name_one, name_two - - - foo = ['name_two'] - __all__ = ['name_one'] + foo - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -@property -def indents(self): - return sourceutils.get_indents(self.pymodule.lines, self.region_lines[0]) - - -def test_organizing_imports_all_star_starjoin(self): - code = expected = dedent("""\ - from package import name_one, name_two - - - foo = ['name_two'] - __all__ = ['name_one', *foo] - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -@testutils.time_limit(60) -def test_organizing_imports_all_star_no_infinite_loop(self): - code = expected = dedent("""\ - from package import name_one, name_two - - - foo = bar - bar = foo - __all__ = [foo, 'name_one', 'name_two'] - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_organizing_imports_all_star_resolve_imported_name(self): - self.mod1.write("foo = 'name_one'") - - code = expected = dedent("""\ - from package import name_one, name_two - - from pkg1.mod1 import foo - - - __all__ = [foo, 'name_two'] - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_organizing_imports_undefined_variable(self): - code = expected = dedent("""\ - from foo import some_name - - - __all__ = ['some_name', undefined_variable] - """) - self.mod1.write(code) - - pymod = self.project.get_pymodule(self.mod1) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_organizing_imports_undefined_variable_with_imported_name(self): - self.mod1.write("") - self.mod2.write("from pkg1.mod1 import undefined_variable") - - code = expected = dedent("""\ - from pkg2.mod2 import undefined_variable - - - __all__ = undefined_variable - """) - self.mod3.write(code) - - pymod = self.project.get_pymodule(self.mod3) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_organizing_indirect_all_star_import(self): - self.mod1.write("some_name = 1") - self.mod2.write(dedent("""\ - __all__ = ['some_name', *imported_all] - """)) - - code = expected = dedent("""\ - from mod1 import some_name - - from mod2 import __all__ - """) - self.mod3.write(code) - - pymod = self.project.get_pymodule(self.mod3) - self.assertEqual(expected, self.import_tools.organize_imports(pymod)) - - -def test_customized_import_organization(self): - self.mod.write(dedent("""\ - import sys - import sys - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - "import sys\n", self.import_tools.organize_imports(pymod, unused=False) - ) - - -def test_customized_import_organization2(self): - self.mod.write("import sys\n") - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - "import sys\n", self.import_tools.organize_imports(pymod, unused=False) - ) - - -def test_customized_import_organization3(self): - self.mod.write(dedent("""\ - import sys - import mod - - - var = 1 - print(mod.var) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - import sys - - - var = 1 - print(var) - """), - self.import_tools.organize_imports(pymod, unused=False), - ) - - -def test_trivial_filtered_expand_stars(self): - self.pkg1.get_child("__init__.py").write("var1 = 1\n") - self.pkg2.get_child("__init__.py").write("var2 = 1\n") - self.mod.write(dedent("""\ - from pkg1 import * - from pkg2 import * - - print(var1, var2) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - from pkg1 import * - from pkg2 import * - - print(var1, var2) - """), - self.import_tools.expand_stars(pymod, lambda stmt: False), - ) - - -@property -def scope_indents(self): - if self.global_: - return 0 - return sourceutils.get_indents(self.pymodule.lines, self.scope.get_start()) - - -def _line_filter(self, lineno): - def import_filter(import_stmt): - return import_stmt.start_line <= lineno < import_stmt.end_line - - return import_filter - - -def test_filtered_expand_stars(self): - self.pkg1.get_child("__init__.py").write("var1 = 1\n") - self.pkg2.get_child("__init__.py").write("var2 = 1\n") - self.mod.write(dedent("""\ - from pkg1 import * - from pkg2 import * - - print(var1, var2) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - from pkg1 import * - from pkg2 import var2 - - print(var1, var2) - """), - self.import_tools.expand_stars(pymod, self._line_filter(2)), - ) - - -def test_filtered_relative_to_absolute(self): - self.mod3.write("var = 1") - self.mod2.write("import mod3\n\nprint(mod3.var)\n") - pymod = self.project.get_pymodule(self.mod2) - self.assertEqual( - dedent("""\ - import mod3 - - print(mod3.var) - """), - self.import_tools.relatives_to_absolutes(pymod, lambda stmt: False), - ) - self.assertEqual( - dedent("""\ - import pkg2.mod3 - - print(pkg2.mod3.var) - """), - self.import_tools.relatives_to_absolutes(pymod, self._line_filter(1)), - ) - - -def test_filtered_froms_to_normals(self): - self.pkg1.get_child("__init__.py").write("var1 = 1\n") - self.pkg2.get_child("__init__.py").write("var2 = 1\n") - self.mod.write(dedent("""\ - from pkg1 import var1 - from pkg2 import var2 - - print(var1, var2) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - from pkg1 import var1 - from pkg2 import var2 - - print(var1, var2) - """), - self.import_tools.expand_stars(pymod, lambda stmt: False), - ) - self.assertEqual( - dedent("""\ - from pkg1 import var1 - import pkg2 - - print(var1, pkg2.var2) - """), - self.import_tools.froms_to_imports(pymod, self._line_filter(2)), - ) - - -def test_filtered_froms_to_normals2(self): - self.pkg1.get_child("__init__.py").write("var1 = 1\n") - self.pkg2.get_child("__init__.py").write("var2 = 1\n") - self.mod.write(dedent("""\ - from pkg1 import * - from pkg2 import * - - print(var1, var2) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - from pkg1 import * - import pkg2 - - print(var1, pkg2.var2) - """), - self.import_tools.froms_to_imports(pymod, self._line_filter(2)), - ) - - -def test_filtered_handle_long_imports(self): - self.mod.write(dedent("""\ - import p1.p2.p3.m1 - import pkg1.mod1 - - - m = p1.p2.p3.m1, pkg1.mod1 - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - import p1.p2.p3.m1 - from pkg1 import mod1 - - - m = p1.p2.p3.m1, mod1 - """), - self.import_tools.handle_long_imports( - pymod, maxlength=5, import_filter=self._line_filter(2) - ), - ) - - -def test_filtering_and_import_actions_with_more_than_one_phase(self): - self.pkg1.get_child("__init__.py").write("var1 = 1\n") - self.pkg2.get_child("__init__.py").write("var2 = 1\n") - self.mod.write(dedent("""\ - from pkg1 import * - from pkg2 import * - - print(var2) - """)) - pymod = self.project.get_pymodule(self.mod) - self.assertEqual( - dedent("""\ - from pkg2 import * - - print(var2) - """), - self.import_tools.expand_stars(pymod, self._line_filter(1)), - ) - - -def test_non_existent_module_and_used_imports(self): - self.mod.write(dedent("""\ - from does_not_exist import func - - func() - """)) - pymod = self.project.get_module("mod") - - module_with_imports = self.import_tools.module_imports(pymod) - imports = module_with_imports.get_used_imports(pymod) - self.assertEqual(1, len(imports)) - - - -class AddImportTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - self.mod1 = testutils.create_module(self.project, "mod1") - self.mod2 = testutils.create_module(self.project, "mod2") - self.pkg = testutils.create_package(self.project, "pkg") - self.mod3 = testutils.create_module(self.project, "mod3", self.pkg) - - -@property -def extracted(self): - return self.source[self.region[0] : self.region[1]] - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_normal_imports(self): - self.mod2.write("myvar = None\n") - self.mod1.write("\n") - pymod = self.project.get_module("mod1") - result, name = add_import(self.project, pymod, "mod2", "myvar") - self.assertEqual("import mod2\n", result) - self.assertEqual("mod2.myvar", name) - - -def test_not_reimporting_a_name(self): - self.mod2.write("myvar = None\n") - self.mod1.write("from mod2 import myvar\n") - pymod = self.project.get_module("mod1") - result, name = add_import(self.project, pymod, "mod2", "myvar") - self.assertEqual("from mod2 import myvar\n", result) - self.assertEqual("myvar", name) - - -def test_adding_import_when_siblings_are_imported(self): - self.mod2.write("var1 = None\nvar2 = None\n") - self.mod1.write("from mod2 import var1\n") - pymod = self.project.get_module("mod1") - result, name = add_import(self.project, pymod, "mod2", "var2") - self.assertEqual("from mod2 import var1, var2\n", result) - self.assertEqual("var2", name) - - -def test_adding_import_when_the_package_is_imported(self): - self.pkg.get_child("__init__.py").write("var1 = None\n") - self.mod3.write("var2 = None\n") - self.mod1.write("from pkg import var1\n") - pymod = self.project.get_module("mod1") - result, name = add_import(self.project, pymod, "pkg.mod3", "var2") - self.assertEqual("from pkg import var1, mod3\n", result) - self.assertEqual("mod3.var2", name) - - -def test_adding_import_for_modules_instead_of_names(self): - self.pkg.get_child("__init__.py").write("var1 = None\n") - self.mod3.write("\n") - self.mod1.write("from pkg import var1\n") - pymod = self.project.get_module("mod1") - result, name = add_import(self.project, pymod, "pkg.mod3", None) - self.assertEqual("from pkg import var1, mod3\n", result) - self.assertEqual("mod3", name) - - -def test_adding_import_for_modules_with_normal_duplicate_imports(self): - self.pkg.get_child("__init__.py").write("var1 = None\n") - self.mod3.write("\n") - self.mod1.write("import pkg.mod3\n") - pymod = self.project.get_module("mod1") - result, name = add_import(self.project, pymod, "pkg.mod3", None) - self.assertEqual("import pkg.mod3\n", result) - self.assertEqual("pkg.mod3", name) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -from textwrap import dedent - -import unittest - -import rope.base.exceptions -from rope.refactor import inline -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class InlineTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - self.mod2 = testutils.create_module(self.project, "mod2") - - -_cached_parsed_extraced = None - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _inline(self, code, offset, **kwds): - self.mod.write(code) - self._inline2(self.mod, offset, **kwds) - return self.mod.read() - - -def _inline2(self, resource, offset, **kwds): - inliner = inline.create_inline(self.project, resource, offset) - changes = inliner.get_changes(**kwds) - self.project.do(changes) - return self.mod.read() - - -def test_simple_case(self): - code = dedent("""\ - a_var = 10 - another_var = a_var - """) - refactored = self._inline(code, code.index("a_var") + 1) - self.assertEqual("another_var = 10\n", refactored) - - -def test_empty_case(self): - code = "a_var = 10\n" - refactored = self._inline(code, code.index("a_var") + 1) - self.assertEqual("", refactored) - - -def test_long_definition(self): - code = dedent("""\ - a_var = 10 + (10 + 10) - another_var = a_var - """) - refactored = self._inline(code, code.index("a_var") + 1) - self.assertEqual("another_var = 10 + (10 + 10)\n", refactored) - - -def test_explicit_continuation(self): - code = dedent("""\ - a_var = (10 + - 10) - another_var = a_var - """) - refactored = self._inline(code, code.index("a_var") + 1) - self.assertEqual( - dedent("""\ - another_var = (10 + - 10) - """), - refactored, - ) - - -def test_implicit_continuation(self): - code = dedent("""\ - a_var = 10 +\\ - 10 - another_var = a_var - """) - refactored = self._inline(code, code.index("a_var") + 1) - self.assertEqual( - dedent("""\ - another_var = 10 +\\ - 10 - """), - refactored, - ) - - -def test_inlining_at_the_end_of_input(self): - code = dedent("""\ - a = 1 - b = a""") - refactored = self._inline(code, code.index("a") + 1) - self.assertEqual("b = 1", refactored) - - -def test_on_classes(self): - code = dedent("""\ - class AClass(object): - pass - """) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self._inline(code, code.index("AClass") + 1) - - -@property -def _parsed_extracted(self): - if self._cached_parsed_extraced is None: - self._cached_parsed_extraced = _parse_text(self.extracted) - return self._cached_parsed_extraced - - -def test_multiple_assignments(self): - code = dedent("""\ - a_var = 10 - a_var = 20 - """) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self._inline(code, code.index("a_var") + 1) - - -def test_tuple_assignments(self): - code = "a_var, another_var = (20, 30)\n" - with self.assertRaises(rope.base.exceptions.RefactoringError): - self._inline(code, code.index("a_var") + 1) - - -def test_on_unknown_vars(self): - code = "a_var = another_var\n" - with self.assertRaises(rope.base.exceptions.RefactoringError): - self._inline(code, code.index("another_var") + 1) - - -def test_attribute_inlining(self): - code = dedent("""\ - class A(object): - def __init__(self): - self.an_attr = 3 - range(self.an_attr) - """) - refactored = self._inline(code, code.index("an_attr") + 1) - expected = dedent("""\ - class A(object): - def __init__(self): - range(3) - """) - self.assertEqual(expected, refactored) - - -def test_attribute_inlining2(self): - code = dedent("""\ - class A(object): - def __init__(self): - self.an_attr = 3 - range(self.an_attr) - a = A() - range(a.an_attr)""") - refactored = self._inline(code, code.index("an_attr") + 1) - expected = dedent("""\ - class A(object): - def __init__(self): - range(3) - a = A() - range(3)""") - self.assertEqual(expected, refactored) - - -def test_a_function_with_no_occurrence(self): - self.mod.write(dedent("""\ - def a_func(): - pass - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("", self.mod.read()) - - -def test_a_function_with_no_occurrence2(self): - self.mod.write(dedent("""\ - a_var = 10 - def a_func(): - pass - print(a_var) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - a_var = 10 - print(a_var) - """), - self.mod.read(), - ) - - -def test_replacing_calls_with_function_definition_in_other_modules(self): - self.mod.write(dedent("""\ - def a_func(): - print(1) - """)) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - import mod - mod.a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - import mod - print(1) - """), - mod1.read(), - ) - - -def test_replacing_calls_with_function_definition_in_other_modules2(self): - self.mod.write(dedent("""\ - def a_func(): - print(1) - """)) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - import mod - if True: - mod.a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - import mod - if True: - print(1) - """), - mod1.read(), - ) - - -def test_replacing_calls_with_method_definition_in_other_modules(self): - self.mod.write(dedent("""\ - class A(object): - var = 10 - def a_func(self): - print(1) - """)) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - import mod - mod.A().a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - import mod - print(1) - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - class A(object): - var = 10 - """), - self.mod.read(), - ) - - -_returned = None - - -def test_replacing_calls_with_function_definition_in_defining_module(self): - self.mod.write(dedent("""\ - def a_func(): - print(1) - a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("print(1)\n", self.mod.read()) - - -def test_replac_calls_with_function_definition_in_defining_module2(self): - self.mod.write(dedent("""\ - def a_func(): - for i in range(10): - print(1) - a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - for i in range(10): - print(1) - """), - self.mod.read(), - ) - - -def test_replacing_calls_with_method_definition_in_defining_modules(self): - self.mod.write(dedent("""\ - class A(object): - var = 10 - def a_func(self): - print(1) - A().a_func()""")) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - class A(object): - var = 10 - print(1) - """), - self.mod.read(), - ) - - -def test_parameters_with_the_same_name_as_passed(self): - self.mod.write(dedent("""\ - def a_func(var): - print(var) - var = 1 - a_func(var) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var = 1 - print(var) - """), - self.mod.read(), - ) - - -def test_parameters_with_the_same_name_as_passed2(self): - self.mod.write(dedent("""\ - def a_func(var): - print(var) - var = 1 - a_func(var=var) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var = 1 - print(var) - """), - self.mod.read(), - ) - - -def test_simple_parameters_renaming(self): - self.mod.write(dedent("""\ - def a_func(param): - print(param) - var = 1 - a_func(var) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var = 1 - print(var) - """), - self.mod.read(), - ) - - -def test_simple_parameters_renaming_for_multiple_params(self): - self.mod.write(dedent("""\ - def a_func(param1, param2): - p = param1 + param2 - var1 = 1 - var2 = 1 - a_func(var1, var2) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var1 = 1 - var2 = 1 - p = var1 + var2 - """), - self.mod.read(), - ) - - -def test_parameters_renaming_for_passed_constants(self): - self.mod.write(dedent("""\ - def a_func(param): - print(param) - a_func(1) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("print(1)\n", self.mod.read()) - - -def test_parameters_renaming_for_passed_statements(self): - self.mod.write(dedent("""\ - def a_func(param): - print(param) - a_func((1 + 2) / 3) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - print((1 + 2) / 3) - """), - self.mod.read(), - ) - - -def test_simple_parameters_renam_for_multiple_params_using_keywords(self): - self.mod.write(dedent("""\ - def a_func(param1, param2): - p = param1 + param2 - var1 = 1 - var2 = 1 - a_func(param2=var1, param1=var2) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var1 = 1 - var2 = 1 - p = var2 + var1 - """), - self.mod.read(), - ) - - -def get_changes(self): - changes = change.ChangeSet( - "Generate {} <{}>".format(self._get_element_kind(), self.name) - ) - indents = self.info.get_scope_indents() - blanks = self.info.get_blank_lines() - base_definition = sourceutils.fix_indentation(self._get_element(), indents) - definition = "\n" * blanks[0] + base_definition + "\n" * blanks[1] - - resource = self.info.get_insertion_resource() - start, end = self.info.get_insertion_offsets() - - collector = codeanalyze.ChangeCollector(resource.read()) - collector.add_change(start, end, definition) - changes.add_change(change.ChangeContents(resource, collector.get_changed())) - if self.goal_resource: - relative_import = _add_relative_import_to_module( - self.project, self.resource, self.goal_resource, self.name - ) - changes.add_change(relative_import) - return changes - - -@property -def returned(self): - """Does the extracted piece contain return statement""" - if self._returned is None: - self._returned = usefunction._returns_last(self._parsed_extracted) - return self._returned - - -def test_simple_params_renam_for_multi_params_using_mixed_keywords(self): - self.mod.write(dedent("""\ - def a_func(param1, param2): - p = param1 + param2 - var1 = 1 - var2 = 1 - a_func(var2, param2=var1) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var1 = 1 - var2 = 1 - p = var2 + var1 - """), - self.mod.read(), - ) - - -def test_simple_putting_in_default_arguments(self): - self.mod.write(dedent("""\ - def a_func(param=None): - print(param) - a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("print(None)\n", self.mod.read()) - - -def test_overriding_default_arguments(self): - self.mod.write(dedent("""\ - def a_func(param1=1, param2=2): - print(param1, param2) - a_func(param2=3) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("print(1, 3)\n", self.mod.read()) - - -def test_arguments_containing_comparisons(self): - self.mod.write(dedent("""\ - def a_func(param1, param2, param3): - param2.name - a_func(2 <= 1, item, True) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("item.name\n", self.mod.read()) - - -def test_badly_formatted_text(self): - self.mod.write(dedent("""\ - def a_func ( param1 = 1 ,param2 = 2 ) : - print(param1, param2) - a_func ( param2 - = 3 ) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("print(1, 3)\n", self.mod.read()) - - -def test_passing_first_arguments_for_methods(self): - a_class = dedent("""\ - class A(object): - def __init__(self): - self.var = 1 - self.a_func(self.var) - def a_func(self, param): - print(param) - """) - self.mod.write(a_class) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - expected = dedent("""\ - class A(object): - def __init__(self): - self.var = 1 - print(self.var) - """) - self.assertEqual(expected, self.mod.read()) - - -def test_passing_first_arguments_for_methods2(self): - a_class = dedent("""\ - class A(object): - def __init__(self): - self.var = 1 - def a_func(self, param): - print(param, self.var) - an_a = A() - an_a.a_func(1) - """) - self.mod.write(a_class) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - expected = dedent("""\ - class A(object): - def __init__(self): - self.var = 1 - an_a = A() - print(1, an_a.var) - """) - self.assertEqual(expected, self.mod.read()) - - -def test_passing_first_arguments_for_methods3(self): - a_class = dedent("""\ - class A(object): - def __init__(self): - self.var = 1 - def a_func(self, param): - print(param, self.var) - an_a = A() - A.a_func(an_a, 1) - """) - self.mod.write(a_class) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - expected = dedent("""\ - class A(object): - def __init__(self): - self.var = 1 - an_a = A() - print(1, an_a.var) - """) - self.assertEqual(expected, self.mod.read()) - - -def test_inlining_staticmethods(self): - a_class = dedent("""\ - class A(object): - @staticmethod - def a_func(param): - print(param) - A.a_func(1) - """) - self.mod.write(a_class) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - expected = dedent("""\ - class A(object): - pass - print(1) - """) - self.assertEqual(expected, self.mod.read()) - - -def test_static_methods2(self): - a_class = dedent("""\ - class A(object): - var = 10 - @staticmethod - def a_func(param): - print(param) - an_a = A() - an_a.a_func(1) - A.a_func(2) - """) - self.mod.write(a_class) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - expected = dedent("""\ - class A(object): - var = 10 - an_a = A() - print(1) - print(2) - """) - self.assertEqual(expected, self.mod.read()) - - -_returning_named_expr = None - - -def test_inlining_classmethods(self): - a_class = dedent("""\ - class A(object): - @classmethod - def a_func(cls, param): - print(param) - A.a_func(1) - """) - self.mod.write(a_class) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - expected = dedent("""\ - class A(object): - pass - print(1) - """) - self.assertEqual(expected, self.mod.read()) - - -def test_inlining_classmethods2(self): - a_class = dedent("""\ - class A(object): - @classmethod - def a_func(cls, param): - return cls - print(A.a_func(1)) - """) - self.mod.write(a_class) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - expected = dedent("""\ - class A(object): - pass - print(A) - """) - self.assertEqual(expected, self.mod.read()) - - -def test_simple_return_values_and_inlining_functions(self): - self.mod.write(dedent("""\ - def a_func(): - return 1 - a = a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("a = 1\n", self.mod.read()) - - -def test_simple_return_values_and_inlining_lonely_functions(self): - self.mod.write(dedent("""\ - def a_func(): - return 1 - a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("1\n", self.mod.read()) - - -def test_empty_returns_and_inlining_lonely_functions(self): - self.mod.write(dedent("""\ - def a_func(): - if True: - return - a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - if True: - pass - """), - self.mod.read(), - ) - - -def test_multiple_returns(self): - self.mod.write(dedent("""\ - def less_than_five(var): - if var < 5: - return True - return False - a = less_than_five(2) - """)) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self._inline2(self.mod, self.mod.read().index("less") + 1) - - -def test_multiple_returns_and_not_using_the_value(self): - self.mod.write(dedent("""\ - def less_than_five(var): - if var < 5: - return True - return False - less_than_five(2) - """)) - self._inline2(self.mod, self.mod.read().index("less") + 1) - self.assertEqual( - dedent("""\ - if 2 < 5: - True - False - """), - self.mod.read(), - ) - - -def test_raising_exception_for_list_arguments(self): - self.mod.write(dedent("""\ - def a_func(*args): - print(args) - a_func(1) - """)) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - - -def test_raising_exception_for_list_keywods(self): - self.mod.write(dedent("""\ - def a_func(**kwds): - print(kwds) - a_func(n=1) - """)) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - - -def test_function_parameters_and_returns_in_other_functions(self): - code = dedent("""\ - def a_func(param1, param2): - return param1 + param2 - range(a_func(20, param2=abs(10))) - """) - self.mod.write(code) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("range(20 + abs(10))\n", self.mod.read()) - - -@property -def returning_named_expr(self): - """Does the extracted piece contains named expression/:= operator)""" - if self._returning_named_expr is None: - self._returning_named_expr = usefunction._namedexpr_last( - self._parsed_extracted - ) - return self._returning_named_expr - - -def test_function_references_other_than_call(self): - self.mod.write(dedent("""\ - def a_func(param): - print(param) - f = a_func - """)) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - - -def test_function_referencing_itself(self): - self.mod.write(dedent("""\ - def a_func(var): - func = a_func - """)) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - - -def test_recursive_functions(self): - self.mod.write(dedent("""\ - def a_func(var): - a_func(var) - """)) - with self.assertRaises(rope.base.exceptions.RefactoringError): - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - - -# TODO: inlining on function parameters -def xxx_test_inlining_function_default_parameters(self): - self.mod.write(dedent("""\ - def a_func(p1=1): - pass - a_func() - """)) - self._inline2(self.mod, self.mod.read().index("p1") + 1) - self.assertEqual( - dedent("""\ - def a_func(p1=1): - pass - a_func() - """), - self.mod.read(), - ) - - -def test_simple_inlining_after_extra_indented_lines(self): - self.mod.write(dedent("""\ - def a_func(): - for i in range(10): - pass - if True: - pass - a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - if True: - pass - for i in range(10): - pass - """), - self.mod.read(), - ) - - -def test_inlining_a_function_with_pydoc(self): - self.mod.write(dedent('''\ - def a_func(): - """docs""" - a = 1 - a_func()''')) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("a = 1\n", self.mod.read()) - - -def test_inlining_methods(self): - self.mod.write(dedent("""\ - class A(object): - name = 'hey' - def get_name(self): - return self.name - a = A() - name = a.get_name() - """)) - self._inline2(self.mod, self.mod.read().rindex("get_name") + 1) - self.assertEqual( - dedent("""\ - class A(object): - name = 'hey' - a = A() - name = a.name - """), - self.mod.read(), - ) - - -def test_simple_returns_with_backslashes(self): - self.mod.write(dedent("""\ - def a_func(): - return 1\\ - + 2 - a = a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - "a = 1\\\n + 2\n", - dedent("""\ - a = 1\\ - + 2 - """), - self.mod.read(), - ) - - -def test_a_function_with_pass_body(self): - self.mod.write(dedent("""\ - def a_func(): - print(1) - a = a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - print(1) - a = None - """), - self.mod.read(), - ) - - -def test_inlining_the_last_method_of_a_class(self): - self.mod.write(dedent("""\ - class A(object): - def a_func(self): - pass - """)) - self._inline2(self.mod, self.mod.read().rindex("a_func") + 1) - self.assertEqual( - dedent("""\ - class A(object): - pass - """), - self.mod.read(), - ) - - -_returning_generator = None - - -def test_adding_needed_imports_in_the_dest_module(self): - self.mod.write(dedent("""\ - import sys - - def ver(): - print(sys.version) - """)) - self.mod2.write(dedent("""\ - import mod - - mod.ver()""")) - self._inline2(self.mod, self.mod.read().index("ver") + 1) - self.assertEqual( - dedent("""\ - import mod - import sys - - print(sys.version) - """), - self.mod2.read(), - ) - - -def test_adding_needed_imports_in_the_dest_module_removing_selfs(self): - self.mod.write(dedent("""\ - import mod2 - - def f(): - print(mod2.var) - """)) - self.mod2.write(dedent("""\ - import mod - - var = 1 - mod.f() - """)) - self._inline2(self.mod, self.mod.read().index("f(") + 1) - self.assertEqual( - dedent("""\ - import mod - - var = 1 - print(var) - """), - self.mod2.read(), - ) - - -def test_handling_relative_imports_when_inlining(self): - pkg = testutils.create_package(self.project, "pkg") - mod3 = testutils.create_module(self.project, "mod3", pkg) - mod4 = testutils.create_module(self.project, "mod4", pkg) - mod4.write("var = 1\n") - mod3.write(dedent("""\ - from . import mod4 - - def f(): - print(mod4.var) - """)) - self.mod.write(dedent("""\ - import pkg.mod3 - - pkg.mod3.f() - """)) - self._inline2(self.mod, self.mod.read().index("f(") + 1) - # Cannot determine the exact import - self.assertTrue("\n\nprint(mod4.var)\n" in self.mod.read()) - - -def test_adding_needed_imports_for_elements_in_source(self): - self.mod.write(dedent("""\ - def f1(): - return f2() - def f2(): - return 1 - """)) - self.mod2.write(dedent("""\ - import mod - - print(mod.f1()) - """)) - self._inline2(self.mod, self.mod.read().index("f1") + 1) - self.assertEqual( - dedent("""\ - import mod - from mod import f2 - - print(f2()) - """), - self.mod2.read(), - ) - - -def test_relative_imports_and_changing_inlining_body(self): - pkg = testutils.create_package(self.project, "pkg") - mod3 = testutils.create_module(self.project, "mod3", pkg) - mod4 = testutils.create_module(self.project, "mod4", pkg) - mod4.write("var = 1\n") - mod3.write(dedent("""\ - import mod4 - - def f(): - print(mod4.var) - """)) - self.mod.write(dedent("""\ - import pkg.mod3 - - pkg.mod3.f() - """)) - self._inline2(self.mod, self.mod.read().index("f(") + 1) - self.assertEqual( - dedent("""\ - import pkg.mod3 - import pkg.mod4 - - print(pkg.mod4.var) - """), - self.mod.read(), - ) - - -def test_inlining_with_different_returns(self): - self.mod.write(dedent("""\ - def f(p): - return p - print(f(1)) - print(f(2)) - print(f(1)) - """)) - self._inline2(self.mod, self.mod.read().index("f(") + 1) - self.assertEqual( - dedent("""\ - print(1) - print(2) - print(1) - """), - self.mod.read(), - ) - - -def test_not_removing_definition_for_variables(self): - code = dedent("""\ - a_var = 10 - another_var = a_var - """) - refactored = self._inline(code, code.index("a_var") + 1, remove=False) - self.assertEqual( - dedent("""\ - a_var = 10 - another_var = 10 - """), - refactored, - ) - - -def test_not_removing_definition_for_methods(self): - code = dedent("""\ - def func(): - print(1) - - func() - """) - refactored = self._inline(code, code.index("func") + 1, remove=False) - self.assertEqual( - dedent("""\ - def func(): - print(1) - - print(1) - """), - refactored, - ) - - -def test_only_current_for_methods(self): - code = dedent("""\ - def func(): - print(1) - - func() - func() - """) - refactored = self._inline( - code, code.rindex("func") + 1, remove=False, only_current=True - ) - self.assertEqual( - dedent("""\ - def func(): - print(1) - - func() - print(1) - """), - refactored, - ) - - -def test_only_current_for_variables(self): - code = dedent("""\ - one = 1 - - a = one - b = one - """) - refactored = self._inline( - code, code.rindex("one") + 1, remove=False, only_current=True - ) - self.assertEqual( - dedent("""\ - one = 1 - - a = one - b = 1 - """), - refactored, - ) - - -@property -def returning_generator_exp(self): - """Does the extracted piece contains a generator expression""" - if self._returning_generator is None: - self._returning_generator = ( - isinstance(self._parsed_extracted, ast.Module) - and isinstance(self._parsed_extracted.body[0], ast.Expr) - and isinstance(self._parsed_extracted.body[0].value, ast.GeneratorExp) - ) - - return self._returning_generator - - - -def test_inlining_one_line_functions(self): - code = dedent("""\ - def f(): return 1 - var = f() - """) - refactored = self._inline(code, code.rindex("f")) - self.assertEqual("var = 1\n", refactored) - - -def test_inlining_one_line_functions_with_breaks(self): - code = dedent("""\ - def f( - p): return p - var = f(1) - """) - refactored = self._inline(code, code.rindex("f")) - self.assertEqual("var = 1\n", refactored) - - -def test_inlining_one_line_functions_with_breaks2(self): - code = dedent("""\ - def f( - ): return 1 - var = f() - """) - refactored = self._inline(code, code.rindex("f")) - self.assertEqual("var = 1\n", refactored) - - -def test_resources_parameter(self): - self.mod.write(dedent("""\ - def a_func(): - print(1) - """)) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - import mod - mod.a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func"), resources=[self.mod]) - self.assertEqual("", self.mod.read()) - self.assertEqual( - dedent("""\ - import mod - mod.a_func() - """), - mod1.read(), - ) - - -def test_inlining_parameters(self): - code = dedent("""\ - def f(p=1): - pass - f() - """) - result = self._inline(code, code.index("p")) - self.assertEqual( - dedent("""\ - def f(p=1): - pass - f(1) - """), - result, - ) - - -def test_inlining_function_with_line_breaks_in_args(self): - code = dedent("""\ - def f(p): return p - var = f(1 + - 1) - """) - refactored = self._inline(code, code.rindex("f")) - self.assertEqual("var = 1 + 1\n", refactored) - - -def test_inlining_variables_before_comparison(self): - code = "start = 1\nprint(start <= 2)\n" - refactored = self._inline(code, code.index("start")) - self.assertEqual("print(1 <= 2)\n", refactored) - - -def test_inlining_variables_in_other_modules(self): - self.mod.write("myvar = 1\n") - self.mod2.write(dedent("""\ - import mod - print(mod.myvar) - """)) - self._inline2(self.mod, 2) - self.assertEqual( - dedent("""\ - import mod - print(1) - """), - self.mod2.read(), - ) - - -def test_inlining_variables_and_back_importing(self): - self.mod.write(dedent("""\ - mainvar = 1 - myvar = mainvar - """)) - self.mod2.write(dedent("""\ - import mod - print(mod.myvar) - """)) - self._inline2(self.mod, self.mod.read().index("myvar")) - expected = dedent("""\ - import mod - from mod import mainvar - print(mainvar) - """) - self.assertEqual(expected, self.mod2.read()) - - -def test_inlining_variables_and_importing_used_imports(self): - self.mod.write(dedent("""\ - import sys - myvar = sys.argv - """)) - self.mod2.write(dedent("""\ - import mod - print(mod.myvar) - """)) - self._inline2(self.mod, self.mod.read().index("myvar")) - expected = dedent("""\ - import mod - import sys - print(sys.argv) - """) - self.assertEqual(expected, self.mod2.read()) - - -class _ExtractCollector: - """Collects information needed for performing the extract""" - - @others - -def test_inlining_variables_and_removing_old_froms(self): - self.mod.write("var = 1\n") - self.mod2.write(dedent("""\ - from mod import var - print(var) - """)) - self._inline2(self.mod2, self.mod2.read().rindex("var")) - self.assertEqual("print(1)\n", self.mod2.read()) - - -def test_inlining_method_and_removing_old_froms(self): - self.mod.write(dedent("""\ - def f(): return 1 - """)) - self.mod2.write(dedent("""\ - from mod import f - print(f()) - """)) - self._inline2(self.mod2, self.mod2.read().rindex("f")) - self.assertEqual("print(1)\n", self.mod2.read()) - - -def test_inlining_functions_in_other_modules_and_only_current(self): - code1 = dedent("""\ - def f(): - return 1 - print(f()) - """) - code2 = dedent("""\ - import mod - print(mod.f()) - print(mod.f()) - """) - self.mod.write(code1) - self.mod2.write(code2) - self._inline2( - self.mod2, self.mod2.read().rindex("f"), remove=False, only_current=True - ) - expected2 = dedent("""\ - import mod - print(mod.f()) - print(1) - """) - self.assertEqual(code1, self.mod.read()) - self.assertEqual(expected2, self.mod2.read()) - - -def test_inlining_variables_in_other_modules_and_only_current(self): - code1 = dedent("""\ - var = 1 - print(var) - """) - code2 = dedent("""\ - import mod - print(mod.var) - print(mod.var) - """) - self.mod.write(code1) - self.mod2.write(code2) - self._inline2( - self.mod2, self.mod2.read().rindex("var"), remove=False, only_current=True - ) - expected2 = "import mod\n" "print(mod.var)\n" "print(1)\n" - self.assertEqual(code1, self.mod.read()) - self.assertEqual(expected2, self.mod2.read()) - - -def test_inlining_does_not_change_string_constants(self): - code = dedent("""\ - var = 1 - print("var\\ - ") - """) - expected = dedent("""\ - var = 1 - print("var\\ - ") - """) - refactored = self._inline( - code, code.rindex("var"), remove=False, only_current=True, docs=False - ) - self.assertEqual(expected, refactored) - - -def test_inlining_does_change_string_constants_if_docs_is_set(self): - code = dedent("""\ - var = 1 - print("var\\ - ") - """) - expected = dedent("""\ - var = 1 - print("1\\ - ") - """) - refactored = self._inline( - code, code.rindex("var"), remove=False, only_current=True, docs=True - ) - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.6") -def test_inlining_into_format_string(self): - code = dedent("""\ - var = 123 - print(f"{var}") - """) - expected = dedent("""\ - print(f"{123}") - """) - - refactored = self._inline(code, code.rindex("var")) - - self.assertEqual(expected, refactored) - - -@testutils.only_for_versions_higher("3.6") -def test_inlining_into_format_string_containing_quotes(self): - code = dedent('''\ - var = 123 - print(f" '{var}' ") - print(f""" "{var}" """) - print(f' "{var}" ') - ''') - expected = dedent('''\ - print(f" '{123}' ") - print(f""" "{123}" """) - print(f' "{123}" ') - ''') - - refactored = self._inline(code, code.rindex("var")) - - self.assertEqual(expected, refactored) - - -def test_parameters_with_the_same_name_as_passed_with_type_hints(self): - self.mod.write(dedent("""\ - def a_func(var: int): - print(var) - var = 1 - a_func(var) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var = 1 - print(var) - """), - self.mod.read(), - ) - - -def test_parameters_with_the_same_name_as_passed_as_kwargs_with_type_hints(self): - self.mod.write(dedent("""\ - def a_func(var: int): - print(var) - var = 1 - a_func(var=var) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var = 1 - print(var) - """), - self.mod.read(), - ) - - -def __init__(self, info): - self.definition = None - self.body_pattern = None - self.checks = {} - self.replacement_pattern = None - self.matches = None - self.replacements = None - self.definition_location = None - - - -def test_simple_parameters_renaming_with_type_hints(self): - self.mod.write(dedent("""\ - def a_func(param: int): - print(param) - var = 1 - a_func(var) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var = 1 - print(var) - """), - self.mod.read(), - ) - - -def test_simple_parameters_renaming_for_multiple_params_with_type_hints(self): - self.mod.write(dedent("""\ - def a_func(param1, param2: int): - p = param1 + param2 - var1 = 1 - var2 = 1 - a_func(var1, var2) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var1 = 1 - var2 = 1 - p = var1 + var2 - """), - self.mod.read(), - ) - - -def test_parameters_renaming_for_passed_constants_with_type_hints(self): - self.mod.write(dedent("""\ - def a_func(param: int): - print(param) - a_func(1) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("print(1)\n", self.mod.read()) - - -def test_parameters_renaming_for_passed_statements_with_type_hints(self): - self.mod.write(dedent("""\ - def a_func(param: int): - print(param) - a_func((1 + 2) / 3) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - print((1 + 2) / 3) - """), - self.mod.read(), - ) - - -def test_simple_parameters_renaming_for_multiple_params_using_keywords_with_type_hints( - self, -): - self.mod.write(dedent("""\ - def a_func(param1, param2: int): - p = param1 + param2 - var1 = 1 - var2 = 1 - a_func(param2=var1, param1=var2) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var1 = 1 - var2 = 1 - p = var2 + var1 - """), - self.mod.read(), - ) - - -def test_simple_params_renaming_for_multi_params_using_mixed_keywords_with_type_hints( - self, -): - self.mod.write(dedent("""\ - def a_func(param1, param2: int): - p = param1 + param2 - var1 = 1 - var2 = 1 - a_func(var2, param2=var1) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual( - dedent("""\ - var1 = 1 - var2 = 1 - p = var2 + var1 - """), - self.mod.read(), - ) - - -def test_simple_putting_in_default_arguments_with_type_hints(self): - self.mod.write(dedent("""\ - def a_func(param: Optional[int] = None): - print(param) - a_func() - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("print(None)\n", self.mod.read()) - - -def test_overriding_default_arguments_with_type_hints(self): - self.mod.write(dedent("""\ - def a_func(param1=1, param2: int = 2): - print(param1, param2) - a_func(param2=3) - """)) - self._inline2(self.mod, self.mod.read().index("a_func") + 1) - self.assertEqual("print(1, 3)\n", self.mod.read()) - -def test_dictionary_with_inline_comment(self): - code = dedent("""\ - myvar = { - "key": "value", # noqa - } - print(myvar) - """) - refactored = self._inline(code, code.index("myvar") + 1) - expected = dedent("""\ - print({ - "key": "value", # noqa - }) - """) - self.assertEqual(expected, refactored) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -from textwrap import dedent - -import unittest - -from rope.base import exceptions -from rope.refactor import move -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class MoveRefactoringTest(unittest.TestCase): - @others - -class _ExtractPerformer: - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.mod1 = testutils.create_module(self.project, "mod1") - self.mod2 = testutils.create_module(self.project, "mod2") - self.mod3 = testutils.create_module(self.project, "mod3") - self.pkg = testutils.create_package(self.project, "pkg") - self.mod4 = testutils.create_module(self.project, "mod4", self.pkg) - self.mod5 = testutils.create_module(self.project, "mod5", self.pkg) - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _move(self, resource, offset, dest_resource): - changes = move.create_move(self.project, resource, offset).get_changes( - dest_resource - ) - self.project.do(changes) - - -def test_move_constant(self): - self.mod1.write("foo = 123\n") - self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2) - self.assertEqual("", self.mod1.read()) - self.assertEqual("foo = 123\n", self.mod2.read()) - - -def test_move_constant_2(self): - self.mod1.write("bar = 321\nfoo = 123\n") - self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2) - self.assertEqual("bar = 321\n", self.mod1.read()) - self.assertEqual("foo = 123\n", self.mod2.read()) - - -def test_move_constant_multiline(self): - self.mod1.write(dedent("""\ - foo = ( - 123 - ) - """)) - self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2) - self.assertEqual("", self.mod1.read()) - self.assertEqual( - dedent("""\ - foo = ( - 123 - ) - """), - self.mod2.read(), - ) - - -def test_move_constant_multiple_statements(self): - self.mod1.write(dedent("""\ - foo = 123 - foo += 3 - foo = 4 - """)) - self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2) - self.assertEqual( - dedent("""\ - import mod2 - mod2.foo += 3 - mod2.foo = 4 - """), - self.mod1.read(), - ) - self.assertEqual("foo = 123\n", self.mod2.read()) - - -def test_simple_moving(self): - self.mod1.write(dedent("""\ - class AClass(object): - pass - """)) - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - self.assertEqual("", self.mod1.read()) - self.assertEqual( - dedent("""\ - class AClass(object): - pass - """), - self.mod2.read(), - ) - - -def test_moving_with_comment_prefix(self): - self.mod1.write(dedent("""\ - a = 1 - # 1 - # 2 - class AClass(object): - pass - """)) - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - self.assertEqual("a = 1\n", self.mod1.read()) - self.assertEqual( - dedent("""\ - # 1 - # 2 - class AClass(object): - pass - """), - self.mod2.read(), - ) - - -def test_moving_with_comment_prefix_imports(self): - self.mod1.write(dedent("""\ - import foo - a = 1 - # 1 - # 2 - class AClass(foo.FooClass): - pass - """)) - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - self.assertEqual("a = 1\n", self.mod1.read()) - self.assertEqual( - dedent("""\ - import foo - - - # 1 - # 2 - class AClass(foo.FooClass): - pass - """), - self.mod2.read(), - ) - - -def __init__(self, info): - self.info = info - _ExceptionalConditionChecker()(self.info) - - -def test_changing_other_modules_replacing_normal_imports(self): - self.mod1.write("class AClass(object):\n pass\n") - self.mod3.write("import mod1\na_var = mod1.AClass()\n") - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - self.assertEqual( - dedent("""\ - import mod2 - a_var = mod2.AClass() - """), - self.mod3.read(), - ) - - -def test_changing_other_modules_adding_normal_imports(self): - self.mod1.write(dedent("""\ - class AClass(object): - pass - def a_function(): - pass - """)) - self.mod3.write(dedent("""\ - import mod1 - a_var = mod1.AClass() - mod1.a_function()""")) - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - self.assertEqual( - dedent("""\ - import mod1 - import mod2 - a_var = mod2.AClass() - mod1.a_function()"""), - self.mod3.read(), - ) - - -def test_adding_imports_prefer_from_module(self): - self.project.prefs["prefer_module_from_imports"] = True - self.mod1.write(dedent("""\ - class AClass(object): - pass - def a_function(): - pass - """)) - self.mod3.write(dedent("""\ - import mod1 - a_var = mod1.AClass() - mod1.a_function()""")) - # Move to mod4 which is in a different package - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod4) - self.assertEqual( - dedent("""\ - import mod1 - from pkg import mod4 - a_var = mod4.AClass() - mod1.a_function()"""), - self.mod3.read(), - ) - - -def test_adding_imports_noprefer_from_module(self): - self.project.prefs["prefer_module_from_imports"] = False - self.mod1.write(dedent("""\ - class AClass(object): - pass - def a_function(): - pass - """)) - self.mod3.write(dedent("""\ - import mod1 - a_var = mod1.AClass() - mod1.a_function()""")) - # Move to mod4 which is in a different package - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod4) - self.assertEqual( - dedent("""\ - import mod1 - import pkg.mod4 - a_var = pkg.mod4.AClass() - mod1.a_function()"""), - self.mod3.read(), - ) - - -def test_adding_imports_prefer_from_module_top_level_module(self): - self.project.prefs["prefer_module_from_imports"] = True - self.mod1.write(dedent("""\ - class AClass(object): - pass - def a_function(): - pass - """)) - self.mod3.write(dedent("""\ - import mod1 - a_var = mod1.AClass() - mod1.a_function()""")) - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - self.assertEqual( - dedent("""\ - import mod1 - import mod2 - a_var = mod2.AClass() - mod1.a_function()"""), - self.mod3.read(), - ) - - -def test_changing_other_modules_removing_from_imports(self): - self.mod1.write(dedent("""\ - class AClass(object): - pass - """)) - self.mod3.write(dedent("""\ - from mod1 import AClass - a_var = AClass() - """)) - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - self.assertEqual( - dedent("""\ - import mod2 - a_var = mod2.AClass() - """), - self.mod3.read(), - ) - - -def test_changing_source_module(self): - self.mod1.write(dedent("""\ - class AClass(object): - pass - a_var = AClass() - """)) - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - self.assertEqual( - dedent("""\ - import mod2 - a_var = mod2.AClass() - """), - self.mod1.read(), - ) - - -def test_changing_destination_module(self): - self.mod1.write(dedent("""\ - class AClass(object): - pass - """)) - self.mod2.write(dedent("""\ - from mod1 import AClass - a_var = AClass() - """)) - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - self.assertEqual( - dedent("""\ - class AClass(object): - pass - a_var = AClass() - """), - self.mod2.read(), - ) - - -def test_folder_destination(self): - folder = self.project.root.create_folder("folder") - self.mod1.write(dedent("""\ - class AClass(object): - pass - """)) - with self.assertRaises(exceptions.RefactoringError): - self._move(self.mod1, self.mod1.read().index("AClass") + 1, folder) - - -def test_raising_exception_for_moving_non_global_elements(self): - self.mod1.write(dedent("""\ - def a_func(): - class AClass(object): - pass - """)) - with self.assertRaises(exceptions.RefactoringError): - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - - -def extract(self): - extract_info = self._collect_info() - content = codeanalyze.ChangeCollector(self.info.source) - definition = extract_info.definition - lineno, indents = extract_info.definition_location - offset = self.info.lines.get_line_start(lineno) - indented = sourceutils.fix_indentation(definition, indents) - content.add_change(offset, offset, indented) - self._replace_occurrences(content, extract_info) - return content.get_changed() - - -def test_raising_an_exception_for_moving_non_global_variable(self): - code = dedent("""\ - class TestClass: - CONSTANT = 5 - """) - self.mod1.write(code) - with self.assertRaises(exceptions.RefactoringError): - mover = move.create_move( - self.project, self.mod1, code.index("CONSTANT") + 1 - ) - - -def test_raising_exception_for_mov_glob_elemnts_to_the_same_module(self): - self.mod1.write("def a_func():\n pass\n") - with self.assertRaises(exceptions.RefactoringError): - self._move(self.mod1, self.mod1.read().index("a_func"), self.mod1) - - -def test_moving_used_imports_to_destination_module(self): - self.mod3.write("a_var = 10") - code = dedent("""\ - import mod3 - from mod3 import a_var - def a_func(): - print(mod3, a_var) - """) - self.mod1.write(code) - self._move(self.mod1, code.index("a_func") + 1, self.mod2) - expected = dedent("""\ - import mod3 - from mod3 import a_var - - - def a_func(): - print(mod3, a_var) - """) - self.assertEqual(expected, self.mod2.read()) - - -def test_moving_used_names_to_destination_module2(self): - code = dedent("""\ - a_var = 10 - def a_func(): - print(a_var) - """) - self.mod1.write(code) - self._move(self.mod1, code.index("a_func") + 1, self.mod2) - self.assertEqual( - dedent("""\ - a_var = 10 - """), - self.mod1.read(), - ) - expected = dedent("""\ - from mod1 import a_var - - - def a_func(): - print(a_var) - """) - self.assertEqual(expected, self.mod2.read()) - - -def test_moving_used_underlined_names_to_destination_module(self): - code = dedent("""\ - _var = 10 - def a_func(): - print(_var) - """) - self.mod1.write(code) - self._move(self.mod1, code.index("a_func") + 1, self.mod2) - expected = dedent("""\ - from mod1 import _var - - - def a_func(): - print(_var) - """) - self.assertEqual(expected, self.mod2.read()) - - -def test_moving_and_used_relative_imports(self): - code = dedent("""\ - import mod5 - def a_func(): - print(mod5) - """) - self.mod4.write(code) - self._move(self.mod4, code.index("a_func") + 1, self.mod1) - expected = dedent("""\ - import pkg.mod5 - - - def a_func(): - print(pkg.mod5) - """) - self.assertEqual(expected, self.mod1.read()) - self.assertEqual("", self.mod4.read()) - - -def test_moving_modules(self): - code = "import mod1\nprint(mod1)" - self.mod2.write(code) - self._move(self.mod2, code.index("mod1") + 1, self.pkg) - expected = "import pkg.mod1\nprint(pkg.mod1)" - self.assertEqual(expected, self.mod2.read()) - self.assertTrue( - not self.mod1.exists() and self.project.find_module("pkg.mod1") is not None - ) - - -def test_moving_modules_and_removing_out_of_date_imports(self): - code = "import pkg.mod4\nprint(pkg.mod4)" - self.mod2.write(code) - self._move(self.mod2, code.index("mod4") + 1, self.project.root) - expected = "import mod4\nprint(mod4)" - self.assertEqual(expected, self.mod2.read()) - self.assertTrue(self.project.find_module("mod4") is not None) - - -def test_moving_modules_and_removing_out_of_date_froms(self): - code = "from pkg import mod4\nprint(mod4)" - self.mod2.write(code) - self._move(self.mod2, code.index("mod4") + 1, self.project.root) - self.assertEqual("import mod4\nprint(mod4)", self.mod2.read()) - - -def test_moving_modules_and_removing_out_of_date_froms2(self): - self.mod4.write("a_var = 10") - code = "from pkg.mod4 import a_var\nprint(a_var)\n" - self.mod2.write(code) - self._move(self.mod2, code.index("mod4") + 1, self.project.root) - expected = "from mod4 import a_var\nprint(a_var)\n" - self.assertEqual(expected, self.mod2.read()) - - -def get_location(self): - return (self.info.get_insertion_resource(), self.info.get_insertion_lineno()) - - -def _replace_occurrences(self, content, extract_info): - for match in extract_info.matches: - replacement = similarfinder.CodeTemplate(extract_info.replacement_pattern) - mapping = {} - for name in replacement.get_names(): - node = match.get_ast(name) - if node: - start, end = patchedast.node_region(match.get_ast(name)) - mapping[name] = self.info.source[start:end] - else: - mapping[name] = name - region = match.get_region() - content.add_change(region[0], region[1], replacement.substitute(mapping)) - - -def test_moving_modules_and_relative_import(self): - self.mod4.write("import mod5\nprint(mod5)\n") - code = "import pkg.mod4\nprint(pkg.mod4)" - self.mod2.write(code) - self._move(self.mod2, code.index("mod4") + 1, self.project.root) - moved = self.project.find_module("mod4") - expected = "import pkg.mod5\nprint(pkg.mod5)\n" - self.assertEqual(expected, moved.read()) - - -def test_moving_module_kwarg_same_name_as_old(self): - self.mod1.write("def foo(mod1=0):\n pass") - code = "import mod1\nmod1.foo(mod1=1)" - self.mod2.write(code) - self._move(self.mod1, None, self.pkg) - moved = self.project.find_module("mod2") - expected = "import pkg.mod1\npkg.mod1.foo(mod1=1)" - self.assertEqual(expected, moved.read()) - - -def test_moving_packages(self): - pkg2 = testutils.create_package(self.project, "pkg2") - code = "import pkg.mod4\nprint(pkg.mod4)" - self.mod1.write(code) - self._move(self.mod1, code.index("pkg") + 1, pkg2) - self.assertFalse(self.pkg.exists()) - self.assertTrue(self.project.find_module("pkg2.pkg.mod4") is not None) - self.assertTrue(self.project.find_module("pkg2.pkg.mod4") is not None) - self.assertTrue(self.project.find_module("pkg2.pkg.mod5") is not None) - expected = "import pkg2.pkg.mod4\nprint(pkg2.pkg.mod4)" - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_modules_with_self_imports(self): - self.mod1.write("import mod1\nprint(mod1)\n") - self.mod2.write("import mod1\n") - self._move(self.mod2, self.mod2.read().index("mod1") + 1, self.pkg) - moved = self.project.find_module("pkg.mod1") - self.assertEqual( - dedent("""\ - import pkg.mod1 - print(pkg.mod1) - """), - moved.read(), - ) - - -def test_moving_modules_with_from_imports(self): - pkg2 = testutils.create_package(self.project, "pkg2") - code = dedent("""\ - from pkg import mod4 - print(mod4)""") - self.mod1.write(code) - self._move(self.mod1, code.index("pkg") + 1, pkg2) - self.assertFalse(self.pkg.exists()) - self.assertTrue(self.project.find_module("pkg2.pkg.mod4") is not None) - self.assertTrue(self.project.find_module("pkg2.pkg.mod5") is not None) - expected = dedent("""\ - from pkg2.pkg import mod4 - print(mod4)""") - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_modules_with_from_import(self): - pkg2 = testutils.create_package(self.project, "pkg2") - pkg3 = testutils.create_package(self.project, "pkg3", pkg2) - pkg4 = testutils.create_package(self.project, "pkg4", pkg3) - code = dedent("""\ - from pkg import mod4 - print(mod4)""") - self.mod1.write(code) - self._move(self.mod4, None, pkg4) - self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) - expected = dedent("""\ - from pkg2.pkg3.pkg4 import mod4 - print(mod4)""") - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_modules_with_multi_from_imports(self): - pkg2 = testutils.create_package(self.project, "pkg2") - pkg3 = testutils.create_package(self.project, "pkg3", pkg2) - pkg4 = testutils.create_package(self.project, "pkg4", pkg3) - code = dedent("""\ - from pkg import mod4, mod5 - print(mod4)""") - self.mod1.write(code) - self._move(self.mod4, None, pkg4) - self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) - expected = dedent("""\ - from pkg import mod5 - from pkg2.pkg3.pkg4 import mod4 - print(mod4)""") - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_modules_with_from_and_normal_imports(self): - pkg2 = testutils.create_package(self.project, "pkg2") - pkg3 = testutils.create_package(self.project, "pkg3", pkg2) - pkg4 = testutils.create_package(self.project, "pkg4", pkg3) - code = dedent("""\ - from pkg import mod4 - import pkg.mod4 - print(mod4) - print(pkg.mod4)""") - self.mod1.write(code) - self._move(self.mod4, None, pkg4) - self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) - expected = dedent("""\ - import pkg2.pkg3.pkg4.mod4 - from pkg2.pkg3.pkg4 import mod4 - print(mod4) - print(pkg2.pkg3.pkg4.mod4)""") - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_modules_with_normal_and_from_imports(self): - pkg2 = testutils.create_package(self.project, "pkg2") - pkg3 = testutils.create_package(self.project, "pkg3", pkg2) - pkg4 = testutils.create_package(self.project, "pkg4", pkg3) - code = dedent("""\ - import pkg.mod4 - from pkg import mod4 - print(mod4) - print(pkg.mod4)""") - self.mod1.write(code) - self._move(self.mod4, None, pkg4) - self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) - expected = dedent("""\ - import pkg2.pkg3.pkg4.mod4 - from pkg2.pkg3.pkg4 import mod4 - print(mod4) - print(pkg2.pkg3.pkg4.mod4)""") - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_modules_from_import_variable(self): - pkg2 = testutils.create_package(self.project, "pkg2") - pkg3 = testutils.create_package(self.project, "pkg3", pkg2) - pkg4 = testutils.create_package(self.project, "pkg4", pkg3) - code = dedent("""\ - from pkg.mod4 import foo - print(foo)""") - self.mod1.write(code) - self._move(self.mod4, None, pkg4) - self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) - expected = dedent("""\ - from pkg2.pkg3.pkg4.mod4 import foo - print(foo)""") - self.assertEqual(expected, self.mod1.read()) - - -def _collect_info(self): - extract_collector = _ExtractCollector(self.info) - self._find_definition(extract_collector) - self._find_matches(extract_collector) - self._find_definition_location(extract_collector) - return extract_collector - - -def test_moving_modules_normal_import(self): - pkg2 = testutils.create_package(self.project, "pkg2") - pkg3 = testutils.create_package(self.project, "pkg3", pkg2) - pkg4 = testutils.create_package(self.project, "pkg4", pkg3) - code = dedent("""\ - import pkg.mod4 - print(pkg.mod4)""") - self.mod1.write(code) - self._move(self.mod4, None, pkg4) - self.assertTrue(self.project.find_module("pkg2.pkg3.pkg4.mod4") is not None) - expected = dedent("""\ - import pkg2.pkg3.pkg4.mod4 - print(pkg2.pkg3.pkg4.mod4)""") - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_package_with_from_and_normal_imports(self): - pkg2 = testutils.create_package(self.project, "pkg2") - code = dedent("""\ - from pkg import mod4 - import pkg.mod4 - print(pkg.mod4) - print(mod4)""") - self.mod1.write(code) - self._move(self.mod1, code.index("pkg") + 1, pkg2) - self.assertFalse(self.pkg.exists()) - self.assertTrue(self.project.find_module("pkg2.pkg.mod4") is not None) - self.assertTrue(self.project.find_module("pkg2.pkg.mod5") is not None) - expected = dedent("""\ - from pkg2.pkg import mod4 - import pkg2.pkg.mod4 - print(pkg2.pkg.mod4) - print(mod4)""") - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_package_with_from_and_normal_imports2(self): - pkg2 = testutils.create_package(self.project, "pkg2") - code = dedent("""\ - import pkg.mod4 - from pkg import mod4 - print(pkg.mod4) - print(mod4)""") - self.mod1.write(code) - self._move(self.mod1, code.index("pkg") + 1, pkg2) - self.assertFalse(self.pkg.exists()) - self.assertTrue(self.project.find_module("pkg2.pkg.mod4") is not None) - self.assertTrue(self.project.find_module("pkg2.pkg.mod5") is not None) - expected = dedent("""\ - import pkg2.pkg.mod4 - from pkg2.pkg import mod4 - print(pkg2.pkg.mod4) - print(mod4)""") - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_package_and_retaining_blank_lines(self): - pkg2 = testutils.create_package(self.project, "pkg2", self.pkg) - code = dedent('''\ - """Docstring followed by blank lines.""" - - import pkg.mod4 - - from pkg import mod4 - from x import y - from y import z - from a import b - from b import c - print(pkg.mod4) - print(mod4)''') - self.mod1.write(code) - self._move(self.mod4, None, pkg2) - expected = dedent('''\ - """Docstring followed by blank lines.""" - - import pkg.pkg2.mod4 - - from x import y - from y import z - from a import b - from b import c - from pkg.pkg2 import mod4 - print(pkg.pkg2.mod4) - print(mod4)''') - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_functions_to_imported_module(self): - code = dedent("""\ - import mod1 - def a_func(): - var = mod1.a_var - """) - self.mod1.write("a_var = 1\n") - self.mod2.write(code) - self._move(self.mod2, code.index("a_func") + 1, self.mod1) - expected = dedent("""\ - def a_func(): - var = a_var - a_var = 1 - """) - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_resources_using_move_module_refactoring(self): - self.mod1.write("a_var = 1") - self.mod2.write(dedent("""\ - import mod1 - my_var = mod1.a_var - """)) - mover = move.create_move(self.project, self.mod1) - mover.get_changes(self.pkg).do() - expected = dedent("""\ - import pkg.mod1 - my_var = pkg.mod1.a_var - """) - self.assertEqual(expected, self.mod2.read()) - self.assertTrue(self.pkg.get_child("mod1.py") is not None) - - -def test_moving_resources_using_move_module_for_packages(self): - self.mod1.write(dedent("""\ - import pkg - my_pkg = pkg""")) - pkg2 = testutils.create_package(self.project, "pkg2") - mover = move.create_move(self.project, self.pkg) - mover.get_changes(pkg2).do() - expected = dedent("""\ - import pkg2.pkg - my_pkg = pkg2.pkg""") - self.assertEqual(expected, self.mod1.read()) - self.assertTrue(pkg2.get_child("pkg") is not None) - - -def test_moving_resources_using_move_module_for_init_dot_py(self): - self.mod1.write(dedent("""\ - import pkg - my_pkg = pkg""")) - pkg2 = testutils.create_package(self.project, "pkg2") - init = self.pkg.get_child("__init__.py") - mover = move.create_move(self.project, init) - mover.get_changes(pkg2).do() - self.assertEqual( - dedent("""\ - import pkg2.pkg - my_pkg = pkg2.pkg"""), - self.mod1.read(), - ) - self.assertTrue(pkg2.get_child("pkg") is not None) - - -def test_moving_module_and_star_imports(self): - self.mod1.write("a_var = 1") - self.mod2.write(dedent("""\ - from mod1 import * - a = a_var - """)) - mover = move.create_move(self.project, self.mod1) - mover.get_changes(self.pkg).do() - self.assertEqual( - dedent("""\ - from pkg.mod1 import * - a = a_var - """), - self.mod2.read(), - ) - - -def test_moving_module_and_not_removing_blanks_after_imports(self): - self.mod4.write("a_var = 1") - self.mod2.write(dedent("""\ - from pkg import mod4 - import os - - - print(mod4.a_var) - """)) - mover = move.create_move(self.project, self.mod4) - mover.get_changes(self.project.root).do() - self.assertEqual( - dedent("""\ - import os - import mod4 - - - print(mod4.a_var) - """), - self.mod2.read(), - ) - - -def _find_matches(self, collector): - regions = self._where_to_search() - finder = similarfinder.SimilarFinder(self.info.pymodule) - matches = [] - for start, end in regions: - region_matches = finder.get_matches( - collector.body_pattern, collector.checks, start, end - ) - # Don't extract overlapping regions - last_match_end = -1 - for region_match in region_matches: - if self.info.one_line and self._is_assignment(region_match): - continue - start, end = region_match.get_region() - if last_match_end < start: - matches.append(region_match) - last_match_end = end - collector.matches = matches - - -def test_moving_module_refactoring_and_nonexistent_destinations(self): - self.mod4.write("a_var = 1") - self.mod2.write(dedent("""\ - from pkg import mod4 - import os - - - print(mod4.a_var) - """)) - with self.assertRaises(exceptions.RefactoringError): - mover = move.create_move(self.project, self.mod4) - mover.get_changes(None).do() - - -def test_moving_methods_choosing_the_correct_class(self): - code = dedent("""\ - class A(object): - def a_method(self): - pass - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - self.assertTrue(isinstance(mover, move.MoveMethod)) - - -def test_moving_methods_getting_new_method_for_empty_methods(self): - code = dedent("""\ - class A(object): - def a_method(self): - pass - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - self.assertEqual( - dedent("""\ - def new_method(self): - pass - """), - mover.get_new_method("new_method"), - ) - - -def test_moving_methods_getting_new_method_for_constant_methods(self): - code = dedent("""\ - class A(object): - def a_method(self): - return 1 - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - self.assertEqual( - dedent("""\ - def new_method(self): - return 1 - """), - mover.get_new_method("new_method"), - ) - - -def test_moving_methods_getting_new_method_passing_simple_paremters(self): - code = dedent("""\ - class A(object): - def a_method(self, p): - return p - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - self.assertEqual( - dedent("""\ - def new_method(self, p): - return p - """), - mover.get_new_method("new_method"), - ) - - -def test_moving_methods_getting_new_method_using_main_object(self): - code = dedent("""\ - class A(object): - attr = 1 - def a_method(host): - return host.attr - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - self.assertEqual( - dedent("""\ - def new_method(self, host): - return host.attr - """), - mover.get_new_method("new_method"), - ) - - -def test_moving_methods_getting_new_method_renaming_main_object(self): - code = dedent("""\ - class A(object): - attr = 1 - def a_method(self): - return self.attr - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - self.assertEqual( - dedent("""\ - def new_method(self, host): - return host.attr - """), - mover.get_new_method("new_method"), - ) - - -def test_moving_methods_gettin_new_method_with_keyword_arguments(self): - code = dedent("""\ - class A(object): - attr = 1 - def a_method(self, p=None): - return p - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - self.assertEqual( - dedent("""\ - def new_method(self, p=None): - return p - """), - mover.get_new_method("new_method"), - ) - - -def test_moving_methods_gettin_new_method_with_many_kinds_arguments(self): - code = dedent("""\ - class A(object): - attr = 1 - def a_method(self, p1, *args, **kwds): - return self.attr - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - expected = dedent("""\ - def new_method(self, host, p1, *args, **kwds): - return host.attr - """) - self.assertEqual(expected, mover.get_new_method("new_method")) - - -def test_moving_methods_getting_new_method_for_multi_line_methods(self): - code = dedent("""\ - class A(object): - def a_method(self): - a = 2 - return a - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - self.assertEqual( - dedent("""\ - def new_method(self): - a = 2 - return a - """), - mover.get_new_method("new_method"), - ) - - -@staticmethod -def _is_assignment(region_match): - return isinstance( - region_match.ast, (ast.Attribute, ast.Subscript) - ) and isinstance(region_match.ast.ctx, ast.Store) - - -def test_moving_methods_getting_old_method_for_constant_methods(self): - self.mod2.write("class B(object):\n pass\n") - code = dedent("""\ - import mod2 - - class A(object): - attr = mod2.B() - def a_method(self): - return 1 - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - mover.get_changes("attr", "new_method").do() - expected = dedent("""\ - import mod2 - - class A(object): - attr = mod2.B() - def a_method(self): - return self.attr.new_method() - """) - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_methods_getting_getting_changes_for_goal_class(self): - self.mod2.write("class B(object):\n var = 1\n") - code = dedent("""\ - import mod2 - - class A(object): - attr = mod2.B() - def a_method(self): - return 1 - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - mover.get_changes("attr", "new_method").do() - expected = dedent("""\ - class B(object): - var = 1 - - - def new_method(self): - return 1 - """) - self.assertEqual(expected, self.mod2.read()) - - -def test_moving_methods_getting_getting_changes_for_goal_class2(self): - code = dedent("""\ - class B(object): - var = 1 - - class A(object): - attr = B() - def a_method(self): - return 1 - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - mover.get_changes("attr", "new_method").do() - self.assertEqual( - dedent("""\ - class B(object): - var = 1 - - - def new_method(self): - return 1 - - class A(object): - attr = B() - def a_method(self): - return self.attr.new_method() - """), - self.mod1.read(), - ) - - -def test_moving_methods_and_nonexistent_attributes(self): - code = dedent("""\ - class A(object): - def a_method(self): - return 1 - """) - self.mod1.write(code) - with self.assertRaises(exceptions.RefactoringError): - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - mover.get_changes("x", "new_method") - - -def test_unknown_attribute_type(self): - code = dedent("""\ - class A(object): - attr = 1 - def a_method(self): - return 1 - """) - self.mod1.write(code) - with self.assertRaises(exceptions.RefactoringError): - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - mover.get_changes("attr", "new_method") - - -def test_moving_methods_and_moving_used_imports(self): - self.mod2.write("class B(object):\n var = 1\n") - code = dedent("""\ - import sys - import mod2 - - class A(object): - attr = mod2.B() - def a_method(self): - return sys.version - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - mover.get_changes("attr", "new_method").do() - code = dedent("""\ - import sys - class B(object): - var = 1 - - - def new_method(self): - return sys.version - """) - self.assertEqual(code, self.mod2.read()) - - -def test_moving_methods_getting_getting_changes_for_goal_class3(self): - self.mod2.write(dedent("""\ - class B(object): - pass - """)) - code = dedent("""\ - import mod2 - - class A(object): - attr = mod2.B() - def a_method(self): - return 1 - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - mover.get_changes("attr", "new_method").do() - expected = dedent("""\ - class B(object): - - def new_method(self): - return 1 - """) - self.assertEqual(expected, self.mod2.read()) - - -def test_moving_methods_and_source_class_with_parameters(self): - self.mod2.write("class B(object):\n pass\n") - code = dedent("""\ - import mod2 - - class A(object): - attr = mod2.B() - def a_method(self, p): - return p - """) - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("a_method")) - mover.get_changes("attr", "new_method").do() - expected1 = dedent("""\ - import mod2 - - class A(object): - attr = mod2.B() - def a_method(self, p): - return self.attr.new_method(p) - """) - self.assertEqual(expected1, self.mod1.read()) - expected2 = dedent("""\ - class B(object): - - def new_method(self, p): - return p - """) - self.assertEqual(expected2, self.mod2.read()) - - -def test_moving_globals_to_a_module_with_only_docstrings(self): - self.mod1.write(dedent("""\ - import sys - - - def f(): - print(sys.version) - """)) - self.mod2.write(dedent('''\ - """doc - - More docs ... - - """ - ''')) - mover = move.create_move( - self.project, self.mod1, self.mod1.read().index("f()") + 1 - ) - self.project.do(mover.get_changes(self.mod2)) - self.assertEqual( - dedent('''\ - """doc - - More docs ... - - """ - import sys - - - def f(): - print(sys.version) - '''), - self.mod2.read(), - ) - - -def test_moving_globals_to_a_module_with_only_docstrings2(self): - code = dedent("""\ - import os - import sys - - - def f(): - print(sys.version, os.path) - """) - self.mod1.write(code) - self.mod2.write('"""doc\n\nMore docs ...\n\n"""\n') - mover = move.create_move( - self.project, self.mod1, self.mod1.read().index("f()") + 1 - ) - self.project.do(mover.get_changes(self.mod2)) - expected = dedent('''\ - """doc - - More docs ... - - """ - import os - import sys - - - def f(): - print(sys.version, os.path) - ''') - self.assertEqual(expected, self.mod2.read()) - - -def _where_to_search(self): - if self.info.similar: - if self.info.make_global or self.info.global_: - return [(0, len(self.info.pymodule.source_code))] - if self.info.method and not self.info.variable: - class_scope = self.info.scope.parent - regions = [] - method_kind = _get_function_kind(self.info.scope) - for scope in class_scope.get_scopes(): - if ( - method_kind == "method" - and _get_function_kind(scope) != "method" - ): - continue - start = self.info.lines.get_line_start(scope.get_start()) - end = self.info.lines.get_line_end(scope.get_end()) - regions.append((start, end)) - return regions - else: - if self.info.variable: - return [self.info.scope_region] - else: - return [self.info._get_scope_region(self.info.scope.parent)] - else: - return [self.info.region] - - -def test_moving_a_global_when_it_is_used_after_a_multiline_str(self): - code = dedent('''\ - def f(): - pass - s = """\\ - """ - r = f() - ''') - self.mod1.write(code) - mover = move.create_move(self.project, self.mod1, code.index("f()") + 1) - self.project.do(mover.get_changes(self.mod2)) - expected = dedent('''\ - import mod2 - s = """\\ - """ - r = mod2.f() - ''') - self.assertEqual(expected, self.mod1.read()) - - -def test_raising_an_exception_when_moving_non_package_folders(self): - dir = self.project.root.create_folder("dir") - with self.assertRaises(exceptions.RefactoringError): - move.create_move(self.project, dir) - - -def test_moving_to_a_module_with_encoding_cookie(self): - code1 = "# -*- coding: utf-8 -*-" - self.mod1.write(code1) - code2 = dedent("""\ - def f(): pass - """) - self.mod2.write(code2) - mover = move.create_move(self.project, self.mod2, code2.index("f()") + 1) - self.project.do(mover.get_changes(self.mod1)) - expected = "%s\n%s" % (code1, code2) - self.assertEqual(expected, self.mod1.read()) - - -def test_moving_decorated_function(self): - self.mod1.write(dedent("""\ - def hello(func): - return func - @hello - def foo(): - pass - """)) - self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2) - self.assertEqual("def hello(func):\n return func\n", self.mod1.read()) - self.assertEqual( - dedent("""\ - from mod1 import hello - - - @hello - def foo(): - pass - """), - self.mod2.read(), - ) - - -def test_moving_decorated_class(self): - self.mod1.write(dedent("""\ - from dataclasses import dataclass - @dataclass - class AClass: - pass - """)) - self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2) - self.assertEqual("", self.mod1.read()) - self.assertEqual( - dedent("""\ - from dataclasses import dataclass - - - @dataclass - class AClass: - pass - """), - self.mod2.read(), - ) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -from textwrap import dedent - -import unittest - -from rope.refactor import multiproject, rename, move -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class MultiProjectRefactoringTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project1 = testutils.sample_project(foldername="testproject1") - self.project2 = testutils.sample_project(foldername="testproject2") - self.mod1 = self.project1.root.create_file("mod1.py") - self.other = self.project1.root.create_file("other.py") - self.mod2 = self.project2.root.create_file("mod2.py") - - -def tearDown(self): - testutils.remove_project(self.project1) - testutils.remove_project(self.project2) - super().tearDown() - - -def test_trivial_rename(self): - self.mod1.write("var = 1\n") - refactoring = multiproject.MultiProjectRefactoring(rename.Rename, []) - renamer = refactoring(self.project1, self.mod1, 1) - multiproject.perform(renamer.get_all_changes("newvar")) - self.assertEqual("newvar = 1\n", self.mod1.read()) - - -def _find_definition_location(self, collector): - matched_lines = [] - for match in collector.matches: - start = self.info.lines.get_line_number(match.get_region()[0]) - start_line = self.info.logical_lines.logical_line_in(start)[0] - matched_lines.append(start_line) - location_finder = _DefinitionLocationFinder(self.info, matched_lines) - collector.definition_location = ( - location_finder.find_lineno(), - location_finder.find_indents(), - ) - - -def test_rename(self): - self.mod1.write("var = 1\n") - self.mod2.write(dedent("""\ - import mod1 - myvar = mod1.var - """)) - refactoring = multiproject.MultiProjectRefactoring( - rename.Rename, [self.project2] - ) - renamer = refactoring(self.project1, self.mod1, 1) - multiproject.perform(renamer.get_all_changes("newvar")) - self.assertEqual("newvar = 1\n", self.mod1.read()) - self.assertEqual( - dedent("""\ - import mod1 - myvar = mod1.newvar - """), - self.mod2.read(), - ) - - -def test_move(self): - self.mod1.write(dedent("""\ - def a_func(): - pass - """)) - self.mod2.write(dedent("""\ - import mod1 - myvar = mod1.a_func() - """)) - refactoring = multiproject.MultiProjectRefactoring( - move.create_move, [self.project2] - ) - renamer = refactoring(self.project1, self.mod1, self.mod1.read().index("_func")) - multiproject.perform(renamer.get_all_changes(self.other)) - self.assertEqual("", self.mod1.read()) - self.assertEqual( - dedent("""\ - def a_func(): - pass - """), - self.other.read(), - ) - self.assertEqual( - dedent("""\ - import other - myvar = other.a_func() - """), - self.mod2.read(), - ) - - -def test_rename_from_the_project_not_containing_the_change(self): - self.project2.get_prefs().add("python_path", self.project1.address) - self.mod1.write("var = 1\n") - self.mod2.write(dedent("""\ - import mod1 - myvar = mod1.var - """)) - refactoring = multiproject.MultiProjectRefactoring( - rename.Rename, [self.project1] - ) - renamer = refactoring(self.project2, self.mod2, self.mod2.read().rindex("var")) - multiproject.perform(renamer.get_all_changes("newvar")) - self.assertEqual( - dedent("""\ - newvar = 1 - """), - self.mod1.read(), - ) - self.assertEqual( - dedent("""\ - import mod1 - myvar = mod1.newvar - """), - self.mod2.read(), - ) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -import unittest -import sys -from textwrap import dedent - -from rope.base import ast -from rope.refactor import patchedast -from ropetest import testutils - -try: - basestring -except NameError: - basestring = (str, bytes) - -NameConstant = "Name" if sys.version_info <= (3, 8) else "NameConstant" -Bytes = "Bytes" if (3, 0) <= sys.version_info <= (3, 8) else "Str" - - -@others -@language python -@tabwidth -4 - -class PatchedASTTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - - -def tearDown(self): - super().tearDown() - - -def assert_single_case_match_block(self, checker, match_type): - checker.check_children("Match", [ - "match", - " ", - "Name", - "", - ":", - "\n ", - "match_case", - ]) - checker.check_children("match_case", [ - "case", - " ", - match_type, - "", - ":", - "\n ", - "Expr", - ]) - - -def test_bytes_string(self): - source = '1 + b"("\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - str_fragment = 'b"("' - start = source.index(str_fragment) - checker.check_region(Bytes, start, start + len(str_fragment)) - checker.check_children(Bytes, [str_fragment]) - - -def test_integer_literals_and_region(self): - source = "a = 10\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.index("10") - checker.check_region("Num", start, start + 2) - - -def _find_definition(self, collector): - if self.info.variable: - parts = _ExtractVariableParts(self.info) - else: - parts = _ExtractMethodParts(self.info) - collector.definition = parts.get_definition() - collector.body_pattern = parts.get_body_pattern() - collector.replacement_pattern = parts.get_replacement_pattern() - collector.checks = parts.get_checks() - - - -def test_negative_integer_literals_and_region(self): - source = "a = -10\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.index("-10") + 1 - end = start + 2 - # Python 3 parses as UnaryOp(op=USub(), operand=Num(n=10)) - checker.check_region("Num", start, end) - - -def test_scientific_integer_literals_and_region(self): - source = "a = -1.0e-3\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.index("-1.0e-3") + 1 - end = start + 6 - # Python 3 parses as UnaryOp(op=USub(), operand=Num(n=10)) - checker.check_region("Num", start, end) - - -def test_hex_integer_literals_and_region(self): - source = "a = 0x1\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.index("0x1") - checker.check_region("Num", start, start + 3) - - -@testutils.only_for_versions_lower("3") -def test_long_literals_and_region(self): - source = "a = 0x1L\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.index("0x1L") - checker.check_region("Num", start, start + 4) - - -def test_octal_integer_literals_and_region(self): - source = "a = -0125e1\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.index("-0125e1") + 1 - end = start + 6 - # Python 3 parses as UnaryOp(op=USub(), operand=Num(n=10)) - checker.check_region("Num", start, end) - - -def test_integer_literals_and_sorted_children(self): - source = "a = 10\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Num", ["10"]) - - -def test_ellipsis(self): - source = "a[...]\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.index("...") - checker.check_region("Ellipsis", start, start + len("...")) - - -def test_ass_name_node(self): - source = "a = 10\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.index("a") - checker.check_region("Name", start, start + 1) - checker.check_children("Name", ["a"]) - - -def test_assign_node(self): - source = "a = 10\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Assign", 0, len(source) - 1) - checker.check_children("Assign", ["Name", " ", "=", " ", "Num"]) - - -@testutils.only_for_versions_higher("3.6") -def test_ann_assign_node_without_target(self): - source = "a: List[int]\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("AnnAssign", 0, len(source) - 1) - checker.check_children("AnnAssign", ["Name", "", ":", " ", "Subscript"]) - - -class _DefinitionLocationFinder: - @others - -@testutils.only_for_versions_higher("3.6") -def test_ann_assign_node_with_target(self): - source = "a: int = 10\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("AnnAssign", 0, len(source) - 1) - checker.check_children( - "AnnAssign", ["Name", "", ":", " ", "Name", " ", "=", " ", "Num"] - ) - - -def test_add_node(self): - source = "1 + 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("BinOp", 0, len(source) - 1) - checker.check_children("BinOp", ["Num", " ", "+", " ", "Num"]) - - -def test_lshift_node(self): - source = "1 << 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("BinOp", 0, len(source) - 1) - checker.check_children("BinOp", ["Num", " ", "<<", " ", "Num"]) - - -def test_and_node(self): - source = "True and True\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("BoolOp", 0, len(source) - 1) - checker.check_children("BoolOp", [NameConstant, " ", "and", " ", NameConstant]) - - -def test_matmult_node(self): - source = "a @ b\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("BinOp", ["Name", " ", "@", " ", "Name"]) - - -def test_basic_closing_parens(self): - source = "1 + (2)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("BinOp", 0, len(source) - 1) - checker.check_children("BinOp", ["Num", " ", "+", " (", "Num", ")"]) - - -def test_basic_opening_parens(self): - source = "(1) + 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("BinOp", 0, len(source) - 1) - checker.check_children("BinOp", ["(", "Num", ") ", "+", " ", "Num"]) - - -def test_basic_opening_biway(self): - source = "(1) + (2)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("BinOp", 0, len(source) - 1) - checker.check_children("BinOp", ["(", "Num", ") ", "+", " (", "Num", ")"]) - - -def test_basic_opening_double(self): - source = "1 + ((2))\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("BinOp", 0, len(source) - 1) - checker.check_children("BinOp", ["Num", " ", "+", " ((", "Num", "))"]) - - -def test_handling_comments(self): - source = "(1 + #(\n2)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("BinOp", ["Num", " ", "+", " #(\n", "Num"]) - - -def __init__(self, info, matched_lines): - self.info = info - self.matched_lines = matched_lines - # This only happens when subexpressions cannot be matched - if not matched_lines: - self.matched_lines.append(self.info.region_lines[0]) - - -def test_handling_parens_with_spaces(self): - source = "1 + (2\n )\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("BinOp", ["Num", " ", "+", " (", "Num", "\n )"]) - - -def test_handling_strings(self): - source = '1 + "("\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("BinOp", ["Num", " ", "+", " ", "Str"]) - - -def test_handling_implicit_string_concatenation(self): - source = "a = '1''2'" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Assign", ["Name", " ", "=", " ", "Str"]) - checker.check_children("Str", ["'1''2'"]) - - -def test_handling_implicit_string_concatenation_line_breaks(self): - source = dedent("""\ - a = '1' \\ - '2'""") - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Assign", ["Name", " ", "=", " ", "Str"]) - checker.check_children("Str", ["'1' \\\n'2'"]) - - -def test_handling_explicit_string_concatenation_line_breaks(self): - source = "a = ('1' \n'2')" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Assign", ["Name", " ", "=", " (", "Str", ")"]) - checker.check_children("Str", ["'1' \n'2'"]) - - -def test_not_concatenating_strings_on_separate_lines(self): - source = dedent("""\ - '1' - '2' - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Module", ["", "Expr", "\n", "Expr", "\n"]) - - -def test_handling_raw_strings(self): - source = 'r"abc"\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Str", ['r"abc"']) - - -@testutils.only_for_versions_higher("3.6") -def test_handling_format_strings_basic(self): - source = '1 + f"abc{a}"\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("JoinedStr", ['f"', "abc", "FormattedValue", "", '"']) - checker.check_children("FormattedValue", ["{", "", "Name", "", "}"]) - - -@testutils.only_for_versions_higher("3.6") -def test_handling_format_strings_with_implicit_join(self): - source = '''"1" + rf'abc{a}' f"""xxx{b} """\n''' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "JoinedStr", - ["rf'", "abc", "FormattedValue", '\' f"""xxx', "FormattedValue", " ", '"""',], - ) - checker.check_children("FormattedValue", ["{", "", "Name", "", "}"]) - - -@testutils.only_for_versions_higher("3.6") -def test_handling_format_strings_with_format_spec(self): - source = 'f"abc{a:01}"\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("JoinedStr", ['f"', "abc", "FormattedValue", "", '"']) - checker.check_children( - "FormattedValue", ["{", "", "Name", "", ":", "", "01", "", "}"] - ) - - -def find_lineno(self): - if self.info.variable and not self.info.make_global: - return self._get_before_line() - if self.info.global_: - toplevel = self._find_toplevel(self.info.scope) - ast = self.info.pymodule.get_ast() - newlines = sorted(self.matched_lines + [toplevel.get_end() + 1]) - return suites.find_visible(ast, newlines) - if self.info.make_global: - toplevel = self._find_toplevel(self.info.scope) - return toplevel.get_end() + 1 - return self._get_after_scope() - - -@testutils.only_for_versions_higher("3.6") -def test_handling_format_strings_with_inner_format_spec(self): - source = 'f"abc{a:{length}01}"\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("JoinedStr", ['f"', "abc", "FormattedValue", "", '"']) - checker.check_children( - "FormattedValue", - ["{", "", "Name", "", ":", "{", "Name", "}", "01", "", "}"], - ) - - -@testutils.only_for_versions_higher("3.6") -def test_handling_format_strings_with_expression(self): - source = 'f"abc{a + b}"\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("JoinedStr", ['f"', "abc", "FormattedValue", "", '"']) - checker.check_children("FormattedValue", ["{", "", "BinOp", "", "}"]) - - -@testutils.only_for_versions_lower("3") -def test_long_integer_literals(self): - source = "0x1L + a" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("BinOp", ["Num", " ", "+", " ", "Name"]) - checker.check_children("Num", ["0x1L"]) - - -def test_complex_number_literals(self): - source = "1.0e2j + a" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("BinOp", ["Num", " ", "+", " ", "Name"]) - checker.check_children("Num", ["1.0e2j"]) - - -def test_ass_attr_node(self): - source = "a.b = 1\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Attribute", 0, source.index("=") - 1) - checker.check_children("Attribute", ["Name", "", ".", "", "b"]) - - -def test_ass_list_node(self): - source = "[a, b] = 1, 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("List", 0, source.index("]") + 1) - checker.check_children("List", ["[", "", "Name", "", ",", " ", "Name", "", "]"]) - - -def test_ass_tuple(self): - source = "a, b = range(2)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Tuple", 0, source.index("=") - 1) - checker.check_children("Tuple", ["Name", "", ",", " ", "Name"]) - - -def test_ass_tuple2(self): - source = "(a, b) = range(2)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Tuple", 0, source.index("=") - 1) - checker.check_children( - "Tuple", ["(", "", "Name", "", ",", " ", "Name", "", ")"] - ) - - -def test_assert(self): - source = "assert True\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Assert", 0, len(source) - 1) - checker.check_children("Assert", ["assert", " ", NameConstant]) - - -def test_assert2(self): - source = 'assert True, "error"\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Assert", 0, len(source) - 1) - checker.check_children( - "Assert", ["assert", " ", NameConstant, "", ",", " ", "Str"] - ) - - -def _get_element_kind(self): - raise NotImplementedError() - - -def _find_toplevel(self, scope): - toplevel = scope - if toplevel.parent is not None: - while toplevel.parent.parent is not None: - toplevel = toplevel.parent - return toplevel - - -def test_aug_assign_node(self): - source = "a += 1\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.index("a") - checker.check_region("AugAssign", 0, len(source) - 1) - checker.check_children("AugAssign", ["Name", " ", "+", "", "=", " ", "Num"]) - self.assertTrue(start is not None) - - -@testutils.only_for_versions_lower("3") -def test_back_quotenode(self): - source = "`1`\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Repr", 0, len(source) - 1) - checker.check_children("Repr", ["`", "", "Num", "", "`"]) - - -def test_bitand(self): - source = "1 & 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("BinOp", 0, len(source) - 1) - checker.check_children("BinOp", ["Num", " ", "&", " ", "Num"]) - - -def test_bitor(self): - source = "1 | 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("BinOp", ["Num", " ", "|", " ", "Num"]) - - -def test_call_func(self): - source = "f(1, 2)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Call", 0, len(source) - 1) - checker.check_children( - "Call", ["Name", "", "(", "", "Num", "", ",", " ", "Num", "", ")"] - ) - - -def test_call_func_and_keywords(self): - source = "f(1, p=2)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", ["Name", "", "(", "", "Num", "", ",", " ", "keyword", "", ")"] - ) - - -@testutils.only_for_versions_lower("3.5") -def test_call_func_and_star_args(self): - source = "f(1, *args)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", ["Name", "", "(", "", "Num", "", ",", " ", "*", "", "Name", "", ")"] - ) - - -@testutils.only_for("3.5") -def test_call_func_and_star_argspython35(self): - source = "f(1, *args)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", ["Name", "", "(", "", "Num", "", ",", " *", "Starred", "", ")"] - ) - - -@testutils.only_for_versions_lower("3.5") -def test_call_func_and_only_dstar_args(self): - source = "f(**kwds)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Call", ["Name", "", "(", "", "**", "", "Name", "", ")"]) - - -@testutils.only_for("3.5") -def test_call_func_and_only_dstar_args_python35(self): - source = "f(**kwds)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Call", ["Name", "", "(", "**", "keyword", "", ")"]) - - -def find_indents(self): - if self.info.variable and not self.info.make_global: - return sourceutils.get_indents(self.info.lines, self._get_before_line()) - else: - if self.info.global_ or self.info.make_global: - return 0 - return self.info.scope_indents - - -@testutils.only_for_versions_lower("3.5") -def test_call_func_and_both_varargs_and_kwargs(self): - source = "f(*args, **kwds)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", - ["Name", "", "(", "", "*", "", "Name", "", ",", " ", "**", "", "Name", "", ")"], - ) - - -@testutils.only_for("3.5") -def test_call_func_and_both_varargs_and_kwargs_python35(self): - source = "f(*args, **kwds)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", - ["Name", "", "(", "*", "Starred", "", ",", " **", "keyword", "", ")"], - ) - - -def test_class_node(self): - source = dedent('''\ - class A(object): - """class docs""" - pass - ''') - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Class", 0, len(source) - 1) - checker.check_children( - "Class", - ["class", " ", "A", "", "(", "", "Name", "", ")", "", ":", "\n ", "Expr", "\n ", "Pass"], - ) - - -def test_class_with_no_bases(self): - source = dedent("""\ - class A: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Class", 0, len(source) - 1) - checker.check_children("Class", ["class", " ", "A", "", ":", "\n ", "Pass"]) - - -def test_simple_compare(self): - source = "1 < 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Compare", 0, len(source) - 1) - checker.check_children("Compare", ["Num", " ", "<", " ", "Num"]) - - -def test_multiple_compare(self): - source = "1 < 2 <= 3\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Compare", 0, len(source) - 1) - checker.check_children( - "Compare", ["Num", " ", "<", " ", "Num", " ", "<=", " ", "Num"] - ) - - -def test_decorators_node(self): - source = dedent("""\ - @d - def f(): - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("FunctionDef", 0, len(source) - 1) - checker.check_children( - "FunctionDef", - ["@", "", "Name", "\n", "def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Pass"], - ) - - -@testutils.only_for("2.6") -def test_decorators_for_classes(self): - source = dedent("""\ - @d - class C(object): - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("ClassDef", 0, len(source) - 1) - checker.check_children( - "ClassDef", - ["@", "", "Name", "\n", "class", " ", "C", "", "(", "", "Name", "", ")", "", ":", "\n ", "Pass"], - ) - - -def test_both_varargs_and_kwargs(self): - source = dedent("""\ - def f(*args, **kwds): - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "arguments", ["*", "", "args", "", ",", " ", "**", "", "kwds"] - ) - - -def test_function_node(self): - source = dedent("""\ - def f(): - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Function", 0, len(source) - 1) - checker.check_children( - "Function", - ["def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Pass"], - ) - - -def _get_before_line(self): - ast = self.info.scope.pyobject.get_ast() - return suites.find_visible(ast, self.matched_lines) - - -@testutils.only_for_versions_higher("3.5") -def test_async_function_node(self): - source = dedent("""\ - async def f(): - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("AsyncFunction", 0, len(source) - 1) - checker.check_children( - "AsyncFunction", - ["async", " ", "def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Pass"], - ) - - -def test_function_node2(self): - source = dedent('''\ - def f(p1, **p2): - """docs""" - pass - ''') - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Function", 0, len(source) - 1) - checker.check_children( - "Function", - ["def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Expr", "\n ", "Pass"], - ) - expected_child = ast.arg.__name__ - checker.check_children( - "arguments", [expected_child, "", ",", " ", "**", "", "p2"] - ) - - -@testutils.only_for_versions_lower("3") -def test_function_node_and_tuple_parameters(self): - source = dedent("""\ - def f(a, (b, c)): - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Function", 0, len(source) - 1) - checker.check_children( - "Function", - ["def", " ", "f", "", "(", "", "arguments", "", ")", "", ":", "\n ", "Pass"], - ) - checker.check_children("arguments", ["Name", "", ",", " ", "Tuple"]) - - -def test_dict_node(self): - source = "{1: 2, 3: 4}\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Dict", 0, len(source) - 1) - checker.check_children( - "Dict", - ["{", "", "Num", "", ":", " ", "Num", "", ",", " ", "Num", "", ":", " ", "Num", "", "}"], - ) - - -@testutils.only_for("3.5") -def test_dict_node_with_unpacking(self): - source = "{**dict1, **dict2}\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Dict", 0, len(source) - 1) - checker.check_children( - "Dict", ["{", "", "**", "", "Name", "", ",", " ", "**", "", "Name", "", "}"] - ) - - -def test_div_node(self): - source = "1 / 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("BinOp", 0, len(source) - 1) - checker.check_children("BinOp", ["Num", " ", "/", " ", "Num"]) - - -@testutils.only_for_versions_lower("3") -def test_simple_exec_node(self): - source = 'exec ""\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Exec", 0, len(source) - 1) - checker.check_children("Exec", ["exec", "", "", " ", "Str", "", ""]) - - -@testutils.only_for_versions_lower("3") -def test_exec_node(self): - source = 'exec "" in locals(), globals()\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Exec", 0, len(source) - 1) - checker.check_children( - "Exec", - ["exec", "", "", " ", "Str", " ", "in", " ", "Call", "", ",", " ", "Call", "", ""], - ) - - -@testutils.only_for_versions_lower("3") -def test_exec_node_with_parens(self): - source = 'exec("", locals(), globals())\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Exec", 0, len(source) - 1) - checker.check_children( - "Exec", - ["exec", "", "(", "", "Str", "", ",", " ", "Call", "", ",", " ", "Call", "", ")"], - ) - - -def test_for_node(self): - source = dedent("""\ - for i in range(1): - pass - else: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("For", 0, len(source) - 1) - checker.check_children( - "For", - ["for", " ", "Name", " ", "in", " ", "Call", "", ":", "\n ", "Pass", "\n", "else", "", ":", "\n ", "Pass"], - ) - - -def _get_after_scope(self): - return self.info.scope.get_end() + 1 - - - -@testutils.only_for_versions_higher("3.5") -def test_async_for_node(self): - source = dedent("""\ - async def foo(): - async for i in range(1): - pass - else: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("AsyncFor", source.index("async for"), len(source) - 1) - checker.check_children( - "AsyncFor", - ["async", " ", "for", " ", "Name", " ", "in", " ", "Call", "", ":", "\n ", "Pass", "\n ", "else", "", ":", "\n ", "Pass"], - ) - - -@testutils.only_for_versions_higher("3.8") -def test_named_expr_node(self): - source = dedent("""\ - if a := 10 == 10: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.index("a") - checker.check_region("NamedExpr", start, start + 13) - checker.check_children("NamedExpr", ["Name", " ", ":=", " ", "Compare"]) - - -def test_normal_from_node(self): - source = "from x import y\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("ImportFrom", 0, len(source) - 1) - checker.check_children( - "ImportFrom", ["from", " ", "x", " ", "import", " ", "alias"] - ) - checker.check_children("alias", ["y"]) - - -@testutils.only_for("2.5") -def test_from_node(self): - source = "from ..x import y as z\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("ImportFrom", 0, len(source) - 1) - checker.check_children( - "ImportFrom", ["from", " ", "..", "", "x", " ", "import", " ", "alias"] - ) - checker.check_children("alias", ["y", " ", "as", " ", "z"]) - - -@testutils.only_for("2.5") -def test_from_node_relative_import(self): - source = "from . import y as z\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("ImportFrom", 0, len(source) - 1) - checker.check_children( - "ImportFrom", ["from", " ", ".", "", "", " ", "import", " ", "alias"] - ) - checker.check_children("alias", ["y", " ", "as", " ", "z"]) - - -def test_simple_gen_expr_node(self): - source = "zip(i for i in x)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("GeneratorExp", 4, len(source) - 2) - checker.check_children("GeneratorExp", ["Name", " ", "comprehension"]) - checker.check_children( - "comprehension", ["for", " ", "Name", " ", "in", " ", "Name"] - ) - - -def test_gen_expr_node_handling_surrounding_parens(self): - source = "(i for i in x)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("GeneratorExp", 0, len(source) - 1) - checker.check_children( - "GeneratorExp", ["(", "", "Name", " ", "comprehension", "", ")"] - ) - - -def test_gen_expr_node2(self): - source = "zip(i for i in range(1) if i == 1)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "comprehension", - ["for", " ", "Name", " ", "in", " ", "Call", " ", "if", " ", "Compare"], - ) - - -def test_get_attr_node(self): - source = "a.b\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Attribute", 0, len(source) - 1) - checker.check_children("Attribute", ["Name", "", ".", "", "b"]) - - -def test_global_node(self): - source = "global a, b\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Global", 0, len(source) - 1) - checker.check_children("Global", ["global", " ", "a", "", ",", " ", "b"]) - - -class _ExceptionalConditionChecker: - @others - -def test_if_node(self): - source = "if True:\n pass\nelse:\n pass\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("If", 0, len(source) - 1) - checker.check_children( - "If", - ["if", " ", NameConstant, "", ":", "\n ", "Pass", "\n", "else", "", ":", "\n ", "Pass"], - ) - - -def test_if_node2(self): - source = dedent("""\ - if True: - pass - elif False: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("If", 0, len(source) - 1) - checker.check_children( - "If", ["if", " ", NameConstant, "", ":", "\n ", "Pass", "\n", "If"] - ) - - -def test_if_node3(self): - source = dedent("""\ - if True: - pass - else: - if True: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("If", 0, len(source) - 1) - checker.check_children( - "If", - ["if", " ", NameConstant, "", ":", "\n ", "Pass", "\n", "else", "", ":", "\n ", "If"], - ) - - -def test_import_node(self): - source = "import a, b as c\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Import", 0, len(source) - 1) - checker.check_children( - "Import", ["import", " ", "alias", "", ",", " ", "alias"] - ) - - -def test_lambda_node(self): - source = "lambda a, b=1, *z: None\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Lambda", 0, len(source) - 1) - checker.check_children( - "Lambda", ["lambda", " ", "arguments", "", ":", " ", NameConstant] - ) - expected_child = ast.arg.__name__ - checker.check_children( - "arguments", - [expected_child, "", ",", " ", expected_child, "", "=", "", "Num", "", ",", " ", "*", "", "z"], - ) - - -def test_list_node(self): - source = "[1, 2]\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("List", 0, len(source) - 1) - checker.check_children("List", ["[", "", "Num", "", ",", " ", "Num", "", "]"]) - - -def test_list_comp_node(self): - source = "[i for i in range(1) if True]\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("ListComp", 0, len(source) - 1) - checker.check_children( - "ListComp", ["[", "", "Name", " ", "comprehension", "", "]"] - ) - checker.check_children( - "comprehension", - ["for", " ", "Name", " ", "in", " ", "Call", " ", "if", " ", NameConstant], - ) - - -def test_list_comp_node_with_multiple_comprehensions(self): - source = "[i for i in range(1) for j in range(1) if True]\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("ListComp", 0, len(source) - 1) - checker.check_children( - "ListComp", - ["[", "", "Name", " ", "comprehension", " ", "comprehension", "", "]"], - ) - checker.check_children( - "comprehension", - ["for", " ", "Name", " ", "in", " ", "Call", " ", "if", " ", NameConstant], - ) - - -def test_set_node(self): - # make sure we are in a python version with set literals - source = "{1, 2}\n" - - try: - eval(source) - except SyntaxError: - return - - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Set", 0, len(source) - 1) - checker.check_children("Set", ["{", "", "Num", "", ",", " ", "Num", "", "}"]) - - -def test_set_comp_node(self): - # make sure we are in a python version with set comprehensions - source = "{i for i in range(1) if True}\n" - - try: - eval(source) - except SyntaxError: - return - - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("SetComp", 0, len(source) - 1) - checker.check_children( - "SetComp", ["{", "", "Name", " ", "comprehension", "", "}"] - ) - checker.check_children( - "comprehension", - ["for", " ", "Name", " ", "in", " ", "Call", " ", "if", " ", NameConstant], - ) - - -def __call__(self, info): - self.base_conditions(info) - if info.one_line: - self.one_line_conditions(info) - else: - self.multi_line_conditions(info) - - -def test_dict_comp_node(self): - # make sure we are in a python version with dict comprehensions - source = "{i:i for i in range(1) if True}\n" - - try: - eval(source) - except SyntaxError: - return - - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("DictComp", 0, len(source) - 1) - checker.check_children( - "DictComp", - ["{", "", "Name", "", ":", "", "Name", " ", "comprehension", "", "}"], - ) - checker.check_children( - "comprehension", - ["for", " ", "Name", " ", "in", " ", "Call", " ", "if", " ", NameConstant], - ) - - -def test_ext_slice_node(self): - source = "x = xs[0,:]\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - if sys.version_info >= (3, 9): - checker.check_region("Tuple", 7, len(source) - 2) - checker.check_children("Tuple", ["Num", "", ",", "", "Slice"]) - else: - checker.check_region("ExtSlice", 7, len(source) - 2) - checker.check_children("ExtSlice", ["Index", "", ",", "", "Slice"]) - - -def test_simple_module_node(self): - source = "pass\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Module", 0, len(source)) - checker.check_children("Module", ["", "Pass", "\n"]) - - -def test_module_node(self): - source = dedent('''\ - """docs""" - pass - ''') - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Module", 0, len(source)) - checker.check_children("Module", ["", "Expr", "\n", "Pass", "\n"]) - checker.check_children("Str", ['"""docs"""']) - - -def test_not_and_or_nodes(self): - source = "not True or False\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Expr", ["BoolOp"]) - checker.check_children("BoolOp", ["UnaryOp", " ", "or", " ", NameConstant]) - - -@testutils.only_for_versions_lower("3") -def test_print_node(self): - source = "print >>out, 1,\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Print", 0, len(source) - 1) - checker.check_children( - "Print", ["print", " ", ">>", "", "Name", "", ",", " ", "Num", "", ","] - ) - - -@testutils.only_for_versions_lower("3") -def test_printnl_node(self): - source = "print 1\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Print", 0, len(source) - 1) - checker.check_children("Print", ["print", " ", "Num"]) - - -@testutils.only_for_versions_lower("3") -def test_raise_node_for_python2(self): - source = "raise x, y, z\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Raise", 0, len(source) - 1) - checker.check_children( - "Raise", ["raise", " ", "Name", "", ",", " ", "Name", "", ",", " ", "Name"] - ) - - -# @#testutils.only_for('3') -@unittest.skipIf(sys.version < "3", "This is wrong") -def test_raise_node_for_python3(self): - source = "raise x(y)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_region("Raise", 0, len(source) - 1) - checker.check_children("Raise", ["raise", " ", "Call"]) - - -def test_return_node(self): - source = dedent("""\ - def f(): - return None - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Return", ["return", " ", NameConstant]) - - -def base_conditions(self, info): - if info.region[1] > info.scope_region[1]: - raise RefactoringError("Bad region selected for extract method") - end_line = info.region_lines[1] - end_scope = info.global_scope.get_inner_scope_for_line(end_line) - if end_scope != info.scope and end_scope.get_end() != end_line: - raise RefactoringError("Bad region selected for extract method") - try: - extracted = info.extracted - if info.one_line: - extracted = "(%s)" % extracted - if _UnmatchedBreakOrContinueFinder.has_errors(extracted): - raise RefactoringError( - "A break/continue without having a matching for/while loop." - ) - except SyntaxError: - raise RefactoringError( - "Extracted piece should contain complete statements." - ) - - -def test_empty_return_node(self): - source = dedent("""\ - def f(): - return - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Return", ["return"]) - - -def test_simple_slice_node(self): - source = "a[1:2]\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Subscript", ["Name", "", "[", "", "Slice", "", "]"]) - checker.check_children("Slice", ["Num", "", ":", "", "Num"]) - - -def test_slice_node2(self): - source = "a[:]\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Subscript", ["Name", "", "[", "", "Slice", "", "]"]) - checker.check_children("Slice", [":"]) - - -def test_simple_subscript(self): - source = "a[1]\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - if sys.version_info >= (3, 9): - checker.check_children("Subscript", ["Name", "", "[", "", "Num", "", "]"]) - else: - checker.check_children("Subscript", ["Name", "", "[", "", "Index", "", "]"]) - checker.check_children("Index", ["Num"]) - - -def test_tuple_node(self): - source = "(1, 2)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Tuple", ["(", "", "Num", "", ",", " ", "Num", "", ")"]) - - -def test_tuple_node2(self): - source = "#(\n1, 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Tuple", ["Num", "", ",", " ", "Num"]) - - -def test_tuple_with_complex_parentheses1(self): - source = "a = ( # (he\n ((((), None))))\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Tuple", ["(", "", "Tuple", "", ",", " ", NameConstant, "", ")"] - ) - - -def test_tuple_with_complex_parentheses2(self): - source = "a = ( # (he\n ((((('a')), ('b')))))\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Tuple", ["(", "", "((", "Str", "))", ",", " (", "Str", ")", "", ")"] - ) - - -def test_tuple_with_complex_parentheses3(self): - source = "a = ((), (([],), []),)" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Tuple", ["(", "", "Tuple", "", ",", " ", "Tuple", ",", ")"] - ) - - -def test_one_item_tuple_node(self): - source = "(1,)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Tuple", ["(", "", "Num", ",", ")"]) - - -def one_line_conditions(self, info): - if self._is_region_on_a_word(info): - raise RefactoringError("Should extract complete statements.") - if info.variable and not info.one_line: - raise RefactoringError("Extract variable should not span multiple lines.") - if usefunction._named_expr_count( - info._parsed_extracted - ) - usefunction._namedexpr_last(info._parsed_extracted): - raise RefactoringError( - "Extracted piece cannot contain named expression (:= operator)." - ) - - -def test_empty_tuple_node(self): - source = "()\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Tuple", ["()"]) - - -def test_empty_tuple_node2(self): - source = "a = ((), None)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Tuple", ["(", "", "Tuple", "", ",", " ", NameConstant, "", ")"] - ) - - -def test_empty_tuple_node3(self): - source = "a = (), None\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Tuple", ["Tuple", "", ",", " ", NameConstant] - ) - - -def test_yield_node(self): - source = dedent("""\ - def f(): - yield None - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Yield", ["yield", " ", NameConstant]) - - -@testutils.only_for_versions_higher("3.3") -def test_yield_from_node(self): - source = dedent("""\ - def f(lst): - yield from lst - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("YieldFrom", ["yield", " ", "from", " ", "Name"]) - - -def test_while_node(self): - source = dedent("""\ - while True: - pass - else: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "While", - ["while", " ", NameConstant, "", ":", "\n ", "Pass", "\n", "else", "", ":", "\n ", "Pass"], - ) - - -@testutils.only_for("2.5") -def test_with_node(self): - source = dedent("""\ - from __future__ import with_statement - with a as b: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "With", - ["with", " ", "Name", " ", "as", " ", "Name", "", ":", "\n ", "Pass"], - ) - - -@testutils.only_for("3.5") -def test_async_with_node(self): - source = dedent("""\ - async def afunc(): - async with a as b: - pass\n - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "AsyncWith", - ["async", " ", "with", " ", "Name", " ", "as", " ", "Name", "", ":", "\n ", "Pass"], - ) - - -def test_try_finally_node(self): - source = dedent("""\ - try: - pass - finally: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - node_to_test = "Try" - expected_children = ["try", "", ":", "\n ", "Pass", "\n", "finally", "", ":", "\n ", "Pass"] - checker.check_children(node_to_test, expected_children) - - -@testutils.only_for_versions_lower("3") -def test_try_except_node(self): - source = dedent("""\ - try: - pass - except Exception, e: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "TryExcept", - ["try", "", ":", "\n ", "Pass", "\n", ("excepthandler", "ExceptHandler")], - ) - checker.check_children( - ("excepthandler", "ExceptHandler"), - ["except", " ", "Name", "", ",", " ", "Name", "", ":", "\n ", "Pass"], - ) - - -def multi_line_conditions(self, info): - node = _parse_text(info.source[info.region[0] : info.region[1]]) - count = usefunction._return_count(node) - extracted = info.extracted - if count > 1: - raise RefactoringError( - "Extracted piece can have only one return statement." - ) - if usefunction._yield_count(node): - raise RefactoringError("Extracted piece cannot have yield statements.") - if not hasattr( - ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT" - ) and _AsyncStatementFinder.has_errors(extracted): - raise RefactoringError( - "Extracted piece can only have async/await " - "statements if Rope is running on Python " - "3.8 or higher" - ) - if count == 1 and not usefunction._returns_last(node): - raise RefactoringError("Return should be the last statement.") - if info.region != info.lines_region: - raise RefactoringError( - "Extracted piece should contain complete statements." - ) - - -def test_try_except_node__with_as_syntax(self): - source = dedent("""\ - try: - pass - except Exception as e: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - node_to_test = "Try" - checker.check_children( - node_to_test, - ["try", "", ":", "\n ", "Pass", "\n", ("excepthandler", "ExceptHandler")], - ) - expected_child = "e" - checker.check_children( - ("excepthandler", "ExceptHandler"), - ["except", " ", "Name", " ", "as", " ", expected_child, "", ":", "\n ", "Pass"], - ) - - -@testutils.only_for("2.5") -def test_try_except_and_finally_node(self): - source = dedent("""\ - try: - pass - except: - pass - finally: - pass - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - node_to_test = "Try" - expected_children = ["try", "", ":", "\n ", "Pass", "\n", "ExceptHandler", "\n", "finally", "", ":", "\n ", "Pass"] - checker.check_children(node_to_test, expected_children) - - -def test_ignoring_comments(self): - source = "#1\n1\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - start = source.rindex("1") - checker.check_region("Num", start, start + 1) - - -def test_simple_sliceobj(self): - source = "a[1::3]\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Slice", ["Num", "", ":", "", ":", "", "Num"]) - - -def test_ignoring_strings_that_start_with_a_char(self): - source = 'r"""("""\n1\n' - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Module", ["", "Expr", "\n", "Expr", "\n"]) - - -@testutils.only_for_versions_lower("3") -def test_how_to_handle_old_not_equals(self): - source = "1 <> 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Compare", ["Num", " ", "<>", " ", "Num"]) - - -def test_semicolon(self): - source = "1;\n" - patchedast.get_patched_ast(source, True) - - -@testutils.only_for("2.5") -def test_if_exp_node(self): - source = "1 if True else 2\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "IfExp", ["Num", " ", "if", " ", NameConstant, " ", "else", " ", "Num"] - ) - - -def test_delete_node(self): - source = "del a, b\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Delete", ["del", " ", "Name", "", ",", " ", "Name"]) - - -@testutils.only_for_versions_lower("3.5") -def test_starargs_before_keywords_legacy(self): - source = "foo(*args, a=1)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", - ["Name", "", "(", "", "*", "", "Name", "", ",", " ", "keyword", "", ")"], - ) - - -def _is_region_on_a_word(self, info): - if ( - info.region[0] > 0 - and self._is_on_a_word(info, info.region[0] - 1) - or self._is_on_a_word(info, info.region[1] - 1) - ): - return True - - -@testutils.only_for_versions_lower("3.5") -def test_starargs_in_keywords_legacy(self): - source = "foo(a=1, *args, b=2)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", - ["Name", "", "(", "", "keyword", "", ",", " ", "*", "", "Name", "", ",", " ", "keyword", "", ")"], - ) - - -@testutils.only_for_versions_lower("3.5") -def test_starargs_after_keywords_legacy(self): - source = "foo(a=1, *args)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", - ["Name", "", "(", "", "keyword", "", ",", " ", "*", "", "Name", "", ")"], - ) - - -@testutils.only_for("3.5") -def test_starargs_before_keywords(self): - source = "foo(*args, a=1)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", ["Name", "", "(", "*", "Starred", "", ",", " ", "keyword", "", ")"] - ) - - -@testutils.only_for("3.5") -def test_starargs_in_keywords(self): - source = "foo(a=1, *args, b=2)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", - ["Name", "", "(", "", "keyword", "", ",", " *", "Starred", "", ",", " ", "keyword", "", ")"], - ) - - -@testutils.only_for("3.5") -def test_starargs_in_positional(self): - source = "foo(a, *b, c)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", - ["Name", "", "(", "", "Name", "", ",", " *", "Starred", "", ",", " ", "Name", "", ")"], - ) - - -@testutils.only_for("3.5") -def test_starargs_after_keywords(self): - source = "foo(a=1, *args)\n" - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children( - "Call", ["Name", "", "(", "", "keyword", "", ",", " *", "Starred", "", ")"] - ) - - -@testutils.only_for_versions_higher("3.5") -def test_await_node(self): - source = dedent("""\ - async def f(): - await sleep() - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Await", ["await", " ", "Call"]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_constant_match_value(self): - source = dedent("""\ - match x: - case 1: - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchValue") - checker.check_children("MatchValue", [ - "Constant" - ]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_match_case_with_guard(self): - source = dedent("""\ - match x: - case int(n) if x < 10: - print(n) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - checker.check_children("Match", [ - "match", - " ", - "Name", - "", - ":", - "\n ", - "match_case", - ]) - checker.check_children("match_case", [ - "case", - " ", - "MatchClass", - " ", - "if", - " ", - "Compare", - "", - ":", - "\n ", - "Expr", - ]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_class(self): - source = dedent("""\ - match x: - case Foo(1): - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchClass") - checker.check_children("MatchClass", [ - "Name", - "", - "(", - "", - "MatchValue", - "", - ")", - ]) - checker.check_children("MatchValue", [ - "Constant" - ]) - - -@utils.saveit -def get_pymodule(self): - """Get a `PyModule`""" - msg = None - code = self.code - tries = 0 - while True: - try: - if ( - tries == 0 - and self.resource is not None - and self.resource.read() == code - ): - return self.project.get_pymodule(self.resource, force_errors=True) - return libutils.get_string_module( - self.project, code, resource=self.resource, force_errors=True - ) - except exceptions.ModuleSyntaxError as e: - if msg is None: - msg = "{}:{} {}".format(e.filename, e.lineno, e.message_) - if tries < self.maxfixes: - tries += 1 - self.commenter.comment(e.lineno) - code = "\n".join(self.commenter.lines) - else: - raise exceptions.ModuleSyntaxError( - e.filename, e.lineno, f"Failed to fix error: {msg}" - ) - - -def _get_element(self): - raise NotImplementedError() - - - -def _is_on_a_word(self, info, offset): - prev = info.source[offset] - if not (prev.isalnum() or prev == "_") or offset + 1 == len(info.source): - return False - next = info.source[offset + 1] - return next.isalnum() or next == "_" - - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_wildcard(self): - source = dedent("""\ - match x: - case _: - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "_" - ]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_as_capture_pattern(self): - source = dedent("""\ - match x: - case myval: - print(myval) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "myval" - ]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_as_capture_pattern_with_explicit_name(self): - source = dedent("""\ - match x: - case "foo" as myval: - print(myval) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "MatchValue", - " ", - "as", - " ", - "myval", - ]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_class_simple_match_as_capture_pattern(self): - source = dedent("""\ - match x: - case Foo(x): - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchClass") - checker.check_children("MatchClass", [ - "Name", - "", - "(", - "", - "MatchAs", - "", - ")", - ]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_class_named_argument(self): - source = dedent("""\ - match x: - case Foo(x=10, y="20"): - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchClass") - checker.check_children("MatchClass", [ - "Name", - "", - "(", - "", - "x", - "", - "=", - "", - "MatchValue", - "", - ",", - " ", - "y", - "", - "=", - "", - "MatchValue", - "", - ")", - ]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name(self): - source = dedent("""\ - match x: - case Foo(x) as b: - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "MatchClass", - " ", - "as", - " ", - "b", - ]) - checker.check_children("MatchClass", [ - "Name", - "", - "(", - "", - "MatchAs", - "", - ")", - ]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_mapping_match_as(self): - source = dedent("""\ - match x: - case {"a": b} as c: - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "MatchMapping", - " ", - "as", - " ", - "c", - ]) - checker.check_children("MatchMapping", [ - "{", - "", - "Constant", - "", - ":", - " ", - "MatchAs", - "", - "}", - ]) - - - -class _ResultChecker: - @others - -def __init__(self, test_case, ast): - self.test_case = test_case - self.ast = ast - - -def check_region(self, text, start, end): - node = self._find_node(text) - if node is None: - self.test_case.fail("Node <%s> cannot be found" % text) - self.test_case.assertEqual((start, end), node.region) - - -def _find_node(self, text): - goal = text - if not isinstance(text, (tuple, list)): - goal = [text] - - class Search: - result = None - - @others - search = Search() - ast.call_for_nodes(self.ast, search, recursive=True) - return search.result - - -class _ExtractMethodParts: - @others - -def __call__(self, node): - for text in goal: - if sys.version_info >= (3, 8) and text in [ - "Num", - "Str", - "NameConstant", - "Ellipsis", - ]: - text = "Constant" - if str(node).startswith(text): - self.result = node - break - if node.__class__.__name__.startswith(text): - self.result = node - break - return self.result is not None - - -def check_children(self, text, children): - node = self._find_node(text) - if node is None: - self.test_case.fail("Node <%s> cannot be found" % text) - result = list(node.sorted_children) - self.test_case.assertEqual(len(children), len(result)) - for expected, child in zip(children, result): - goals = expected - if not isinstance(expected, (tuple, list)): - goals = [expected] - for goal in goals: - if goal == "" or isinstance(child, basestring): - self.test_case.assertEqual(goal, child) - break - else: - self.test_case.assertNotEqual("", text, "probably ignoring some node") - if sys.version_info >= (3, 8) and expected in [ - "Num", - "Str", - "NameConstant", - "Ellipsis", - ]: - expected = "Constant" - self.test_case.assertTrue( - child.__class__.__name__.startswith(expected), - msg="Expected <%s> but was <%s>" - % (expected, child.__class__.__name__), - ) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -import sys -from textwrap import dedent - -import unittest - -import rope.base.codeanalyze -import rope.refactor.occurrences -from rope.refactor import rename -from rope.refactor.rename import Rename -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class RenameRefactoringTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _local_rename(self, source_code, offset, new_name): - testmod = testutils.create_module(self.project, "testmod") - testmod.write(source_code) - changes = Rename(self.project, testmod, offset).get_changes( - new_name, resources=[testmod] - ) - self.project.do(changes) - return testmod.read() - - -def _rename(self, resource, offset, new_name, **kwds): - changes = Rename(self.project, resource, offset).get_changes(new_name, **kwds) - self.project.do(changes) - - -def test_local_variable_but_not_parameter(self): - code = dedent("""\ - a = 10 - foo = dict(a=a) - """) - - refactored = self._local_rename(code, 1, "new_a") - self.assertEqual( - dedent("""\ - new_a = 10 - foo = dict(a=new_a) - """), - refactored, - ) - - -def test_simple_global_variable_renaming(self): - refactored = self._local_rename("a_var = 20\n", 2, "new_var") - self.assertEqual("new_var = 20\n", refactored) - - -def __init__(self, info): - self.info = info - self.info_collector = self._create_info_collector() - self.info.kind = self._get_kind_by_scope() - self._check_constraints() - - -def test_variable_renaming_only_in_its_scope(self): - refactored = self._local_rename( - dedent("""\ - a_var = 20 - def a_func(): - a_var = 10 - """), - 32, - "new_var", - ) - self.assertEqual( - dedent("""\ - a_var = 20 - def a_func(): - new_var = 10 - """), - refactored, - ) - - -def test_not_renaming_dot_name(self): - refactored = self._local_rename( - dedent("""\ - replace = True - 'aaa'.replace('a', 'b') - """), - 1, - "new_var", - ) - self.assertEqual( - dedent("""\ - new_var = True - 'aaa'.replace('a', 'b') - """), - refactored, - ) - - -def test_renaming_multiple_names_in_the_same_line(self): - refactored = self._local_rename( - dedent("""\ - a_var = 10 - a_var = 10 + a_var / 2 - """), - 2, - "new_var", - ) - self.assertEqual( - dedent("""\ - new_var = 10 - new_var = 10 + new_var / 2 - """), - refactored, - ) - - -def test_renaming_names_when_getting_some_attribute(self): - refactored = self._local_rename( - dedent("""\ - a_var = 'a b c' - a_var.split('\\n') - """), - 2, - "new_var", - ) - self.assertEqual( - dedent("""\ - new_var = 'a b c' - new_var.split('\\n') - """), - refactored, - ) - - -def test_renaming_names_when_getting_some_attribute2(self): - refactored = self._local_rename( - dedent("""\ - a_var = 'a b c' - a_var.split('\\n') - """), - 20, - "new_var", - ) - self.assertEqual( - dedent("""\ - new_var = 'a b c' - new_var.split('\\n') - """), - refactored, - ) - - -def test_renaming_function_parameters1(self): - refactored = self._local_rename( - dedent("""\ - def f(a_param): - print(a_param) - """), - 8, - "new_param", - ) - self.assertEqual( - dedent("""\ - def f(new_param): - print(new_param) - """), - refactored, - ) - - -def test_renaming_function_parameters2(self): - refactored = self._local_rename( - dedent("""\ - def f(a_param): - print(a_param) - """), - 30, - "new_param", - ) - self.assertEqual( - dedent("""\ - def f(new_param): - print(new_param) - """), - refactored, - ) - - -def test_renaming_occurrences_inside_functions(self): - code = dedent("""\ - def a_func(p1): - a = p1 - a_func(1) - """) - refactored = self._local_rename(code, code.index("p1") + 1, "new_param") - self.assertEqual( - dedent("""\ - def a_func(new_param): - a = new_param - a_func(1) - """), - refactored, - ) - - -def test_renaming_comprehension_loop_variables(self): - code = "[b_var for b_var, c_var in d_var if b_var == c_var]" - refactored = self._local_rename(code, code.index("b_var") + 1, "new_var") - self.assertEqual( - "[new_var for new_var, c_var in d_var if new_var == c_var]", refactored - ) - - -def test_renaming_list_comprehension_loop_variables_in_assignment(self): - code = "a_var = [b_var for b_var, c_var in d_var if b_var == c_var]" - refactored = self._local_rename(code, code.index("b_var") + 1, "new_var") - self.assertEqual( - "a_var = [new_var for new_var, c_var in d_var if new_var == c_var]", - refactored, - ) - - -def _get_kind_by_scope(self): - if self._extacting_from_staticmethod(): - return "staticmethod" - elif self._extracting_from_classmethod(): - return "classmethod" - return self.info.kind - - -def test_renaming_generator_comprehension_loop_variables(self): - code = "a_var = (b_var for b_var, c_var in d_var if b_var == c_var)" - refactored = self._local_rename(code, code.index("b_var") + 1, "new_var") - self.assertEqual( - "a_var = (new_var for new_var, c_var in d_var if new_var == c_var)", - refactored, - ) - - -def test_renaming_comprehension_loop_variables_scope(self): - code = dedent("""\ - [b_var for b_var, c_var in d_var if b_var == c_var] - b_var = 10 - """) - refactored = self._local_rename(code, code.index("b_var") + 1, "new_var") - self.assertEqual( - dedent("""\ - [new_var for new_var, c_var in d_var if new_var == c_var] - b_var = 10 - """), - refactored, - ) - - -@testutils.only_for_versions_higher("3.8") -def test_renaming_inline_assignment(self): - code = dedent("""\ - while a_var := next(foo): - print(a_var) - """) - refactored = self._local_rename(code, code.index("a_var") + 1, "new_var") - self.assertEqual( - dedent("""\ - while new_var := next(foo): - print(new_var) - """), - refactored, - ) - - -def test_renaming_arguments_for_normal_args_changing_calls(self): - code = dedent("""\ - def a_func(p1=None, p2=None): - pass - a_func(p2=1) - """) - refactored = self._local_rename(code, code.index("p2") + 1, "p3") - self.assertEqual( - dedent("""\ - def a_func(p1=None, p3=None): - pass - a_func(p3=1) - """), - refactored, - ) - - -def test_renaming_function_parameters_of_class_init(self): - code = dedent("""\ - class A(object): - def __init__(self, a_param): - pass - a_var = A(a_param=1) - """) - refactored = self._local_rename(code, code.index("a_param") + 1, "new_param") - expected = dedent("""\ - class A(object): - def __init__(self, new_param): - pass - a_var = A(new_param=1) - """) - self.assertEqual(expected, refactored) - - -def test_rename_functions_parameters_and_occurences_in_other_modules(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write(dedent("""\ - def a_func(a_param): - print(a_param) - """)) - mod2.write(dedent("""\ - from mod1 import a_func - a_func(a_param=10) - """)) - self._rename(mod1, mod1.read().index("a_param") + 1, "new_param") - self.assertEqual( - dedent("""\ - def a_func(new_param): - print(new_param) - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - from mod1 import a_func - a_func(new_param=10) - """), - mod2.read(), - ) - - -def test_renaming_with_backslash_continued_names(self): - refactored = self._local_rename( - "replace = True\n'ali'.\\\nreplace\n", 2, "is_replace" - ) - self.assertEqual("is_replace = True\n'ali'.\\\nreplace\n", refactored) - - -@testutils.only_for("3.6") -def test_renaming_occurrence_in_f_string(self): - code = dedent("""\ - a_var = 20 - a_string=f'value: {a_var}' - """) - expected = dedent("""\ - new_var = 20 - a_string=f'value: {new_var}' - """) - refactored = self._local_rename(code, 2, "new_var") - self.assertEqual(expected, refactored) - - -@testutils.only_for("3.6") -def test_renaming_occurrence_in_nested_f_string(self): - code = dedent("""\ - a_var = 20 - a_string=f'{f"{a_var}"}' - """) - expected = dedent("""\ - new_var = 20 - a_string=f'{f"{new_var}"}' - """) - refactored = self._local_rename(code, 2, "new_var") - self.assertEqual(expected, refactored) - - -@testutils.only_for("3.6") -def test_not_renaming_string_contents_in_f_string(self): - refactored = self._local_rename( - "a_var = 20\na_string=f'{\"a_var\"}'\n", 2, "new_var" - ) - self.assertEqual( - dedent("""\ - new_var = 20 - a_string=f'{"a_var"}' - """), - refactored, - ) - - -def _check_constraints(self): - if self._extracting_staticmethod() or self._extracting_classmethod(): - if not self.info.method: - raise RefactoringError( - "Cannot extract to staticmethod/classmethod outside class" - ) - - -def test_not_renaming_string_contents(self): - refactored = self._local_rename("a_var = 20\na_string='a_var'\n", 2, "new_var") - self.assertEqual( - dedent("""\ - new_var = 20 - a_string='a_var' - """), - refactored, - ) - - -def test_not_renaming_comment_contents(self): - refactored = self._local_rename("a_var = 20\n# a_var\n", 2, "new_var") - self.assertEqual( - dedent("""\ - new_var = 20 - # a_var - """), - refactored, - ) - - -def test_renaming_all_occurrences_in_containing_scope(self): - code = dedent("""\ - if True: - a_var = 1 - else: - a_var = 20 - """) - refactored = self._local_rename(code, 16, "new_var") - self.assertEqual( - dedent("""\ - if True: - new_var = 1 - else: - new_var = 20 - """), - refactored, - ) - - -def test_renaming_a_variable_with_arguement_name(self): - code = dedent("""\ - a_var = 10 - def a_func(a_var): - print(a_var) - """) - refactored = self._local_rename(code, 1, "new_var") - self.assertEqual( - dedent("""\ - new_var = 10 - def a_func(a_var): - print(a_var) - """), - refactored, - ) - - -def test_renaming_an_arguement_with_variable_name(self): - code = dedent("""\ - a_var = 10 - def a_func(a_var): - print(a_var) - """) - refactored = self._local_rename(code, len(code) - 3, "new_var") - self.assertEqual( - dedent("""\ - a_var = 10 - def a_func(new_var): - print(new_var) - """), - refactored, - ) - - -def test_renaming_function_with_local_variable_name(self): - code = dedent("""\ - def a_func(): - a_func=20 - a_func()""") - refactored = self._local_rename(code, len(code) - 3, "new_func") - self.assertEqual( - dedent("""\ - def new_func(): - a_func=20 - new_func()"""), - refactored, - ) - - -def test_renaming_functions(self): - code = dedent("""\ - def a_func(): - pass - a_func() - """) - refactored = self._local_rename(code, len(code) - 5, "new_func") - self.assertEqual( - dedent("""\ - def new_func(): - pass - new_func() - """), - refactored, - ) - - -@testutils.only_for("3.5") -def test_renaming_async_function(self): - code = dedent("""\ - async def a_func(): - pass - a_func()""") - refactored = self._local_rename(code, len(code) - 5, "new_func") - self.assertEqual( - dedent("""\ - async def new_func(): - pass - new_func()"""), - refactored, - ) - - -@testutils.only_for("3.5") -def test_renaming_await(self): - code = dedent("""\ - async def b_func(): - pass - async def a_func(): - await b_func()""") - refactored = self._local_rename(code, len(code) - 5, "new_func") - self.assertEqual( - dedent("""\ - async def new_func(): - pass - async def a_func(): - await new_func()"""), - refactored, - ) - - -def test_renaming_functions_across_modules(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - def a_func(): - pass - a_func() - """)) - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - import mod1 - mod1.a_func() - """)) - self._rename(mod1, len(mod1.read()) - 5, "new_func") - self.assertEqual( - dedent("""\ - def new_func(): - pass - new_func() - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - import mod1 - mod1.new_func() - """), - mod2.read(), - ) - - -def _extacting_from_staticmethod(self): - return ( - self.info.method and _get_function_kind(self.info.scope) == "staticmethod" - ) - - -def test_renaming_functions_across_modules_from_import(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - def a_func(): - pass - a_func() - """)) - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - from mod1 import a_func - a_func() - """)) - self._rename(mod1, len(mod1.read()) - 5, "new_func") - self.assertEqual( - dedent("""\ - def new_func(): - pass - new_func() - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - from mod1 import new_func - new_func() - """), - mod2.read(), - ) - - -def test_renaming_functions_from_another_module(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - def a_func(): - pass - a_func() - """)) - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - import mod1 - mod1.a_func() - """)) - self._rename(mod2, len(mod2.read()) - 5, "new_func") - self.assertEqual( - dedent("""\ - def new_func(): - pass - new_func() - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - import mod1 - mod1.new_func() - """), - mod2.read(), - ) - - -def test_applying_all_changes_together(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - import mod2 - mod2.a_func() - """)) - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - def a_func(): - pass - a_func() - """)) - self._rename(mod2, len(mod2.read()) - 5, "new_func") - self.assertEqual( - dedent("""\ - import mod2 - mod2.new_func() - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - def new_func(): - pass - new_func() - """), - mod2.read(), - ) - - -def test_renaming_modules(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - def a_func(): - pass - """)) - mod2 = testutils.create_module(self.project, "mod2") - mod2.write("from mod1 import a_func\n") - self._rename(mod2, mod2.read().index("mod1") + 1, "newmod") - self.assertTrue( - not mod1.exists() and self.project.find_module("newmod") is not None - ) - self.assertEqual("from newmod import a_func\n", mod2.read()) - - -def test_renaming_modules_aliased(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - def a_func(): - pass - """)) - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - import mod1 as m - m.a_func() - """)) - self._rename(mod1, None, "newmod") - self.assertTrue( - not mod1.exists() and self.project.find_module("newmod") is not None - ) - self.assertEqual("import newmod as m\nm.a_func()\n", mod2.read()) - - -def test_renaming_packages(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod1.write(dedent("""\ - def a_func(): - pass - """)) - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod2.write("from pkg.mod1 import a_func\n") - self._rename(mod2, 6, "newpkg") - self.assertTrue(self.project.find_module("newpkg.mod1") is not None) - new_mod2 = self.project.find_module("newpkg.mod2") - self.assertEqual("from newpkg.mod1 import a_func\n", new_mod2.read()) - - -def test_module_dependencies(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - class AClass(object): - pass - """)) - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - import mod1 - a_var = mod1.AClass() - """)) - self.project.get_pymodule(mod2).get_attributes()["mod1"] - mod1.write(dedent("""\ - def AClass(): - return 0 - """)) - - self._rename(mod2, len(mod2.read()) - 3, "a_func") - self.assertEqual( - dedent("""\ - def a_func(): - return 0 - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - import mod1 - a_var = mod1.a_func() - """), - mod2.read(), - ) - - -def test_renaming_class_attributes(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - class AClass(object): - def __init__(self): - self.an_attr = 10 - """)) - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - import mod1 - a_var = mod1.AClass() - another_var = a_var.an_attr""")) - - self._rename(mod1, mod1.read().index("an_attr"), "attr") - self.assertEqual( - dedent("""\ - class AClass(object): - def __init__(self): - self.attr = 10 - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - import mod1 - a_var = mod1.AClass() - another_var = a_var.attr"""), - mod2.read(), - ) - - -def test_renaming_class_attributes2(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - class AClass(object): - def __init__(self): - an_attr = 10 - self.an_attr = 10 - """)) - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - import mod1 - a_var = mod1.AClass() - another_var = a_var.an_attr""")) - - self._rename(mod1, mod1.read().rindex("an_attr"), "attr") - self.assertEqual( - dedent("""\ - class AClass(object): - def __init__(self): - an_attr = 10 - self.attr = 10 - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - import mod1 - a_var = mod1.AClass() - another_var = a_var.attr"""), - mod2.read(), - ) - - -def test_renaming_methods_in_subclasses(self): - mod = testutils.create_module(self.project, "mod1") - mod.write(dedent("""\ - class A(object): - def a_method(self): - pass - class B(A): - def a_method(self): - pass - """)) - - self._rename( - mod, mod.read().rindex("a_method") + 1, "new_method", in_hierarchy=True - ) - self.assertEqual( - dedent("""\ - class A(object): - def new_method(self): - pass - class B(A): - def new_method(self): - pass - """), - mod.read(), - ) - - -def _extracting_from_classmethod(self): - return self.info.method and _get_function_kind(self.info.scope) == "classmethod" - - -def test_renaming_methods_in_sibling_classes(self): - mod = testutils.create_module(self.project, "mod1") - mod.write(dedent("""\ - class A(object): - def a_method(self): - pass - class B(A): - def a_method(self): - pass - class C(A): - def a_method(self): - pass - """)) - - self._rename( - mod, mod.read().rindex("a_method") + 1, "new_method", in_hierarchy=True - ) - self.assertEqual( - dedent("""\ - class A(object): - def new_method(self): - pass - class B(A): - def new_method(self): - pass - class C(A): - def new_method(self): - pass - """), - mod.read(), - ) - - -def test_not_renaming_methods_in_hierarchies(self): - mod = testutils.create_module(self.project, "mod1") - mod.write(dedent("""\ - class A(object): - def a_method(self): - pass - class B(A): - def a_method(self): - pass - """)) - - self._rename( - mod, mod.read().rindex("a_method") + 1, "new_method", in_hierarchy=False - ) - self.assertEqual( - dedent("""\ - class A(object): - def a_method(self): - pass - class B(A): - def new_method(self): - pass - """), - mod.read(), - ) - - -def test_undoing_refactorings(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - def a_func(): - pass - a_func() - """)) - self._rename(mod1, len(mod1.read()) - 5, "new_func") - self.project.history.undo() - self.assertEqual( - dedent("""\ - def a_func(): - pass - a_func() - """), - mod1.read(), - ) - - -def test_undoing_renaming_modules(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - def a_func(): - pass - """)) - mod2 = testutils.create_module(self.project, "mod2") - mod2.write("from mod1 import a_func\n") - self._rename(mod2, 6, "newmod") - self.project.history.undo() - self.assertEqual("mod1.py", mod1.path) - self.assertEqual("from mod1 import a_func\n", mod2.read()) - - -def test_rename_in_module_renaming_one_letter_names_for_expressions(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write("a = 10\nprint(1+a)\n") - pymod = self.project.get_module("mod1") - old_pyname = pymod["a"] - finder = rope.refactor.occurrences.create_finder(self.project, "a", old_pyname) - refactored = rename.rename_in_module( - finder, "new_var", pymodule=pymod, replace_primary=True - ) - self.assertEqual( - dedent("""\ - new_var = 10 - print(1+new_var) - """), - refactored, - ) - - -def test_renaming_for_loop_variable(self): - code = dedent("""\ - for var in range(10): - print(var) - """) - refactored = self._local_rename(code, code.find("var") + 1, "new_var") - self.assertEqual( - dedent("""\ - for new_var in range(10): - print(new_var) - """), - refactored, - ) - - -@testutils.only_for("3.5") -def test_renaming_async_for_loop_variable(self): - code = dedent("""\ - async def func(): - async for var in range(10): - print(var) - """) - refactored = self._local_rename(code, code.find("var") + 1, "new_var") - self.assertEqual( - dedent("""\ - async def func(): - async for new_var in range(10): - print(new_var) - """), - refactored, - ) - - -@testutils.only_for("3.5") -def test_renaming_async_with_context_manager(self): - code = dedent("""\ - def a_cm(): pass - async def a_func(): - async with a_cm() as x: pass""") - refactored = self._local_rename(code, code.find("a_cm") + 1, "another_cm") - expected = dedent("""\ - def another_cm(): pass - async def a_func(): - async with another_cm() as x: pass""") - self.assertEqual(refactored, expected) - - -@testutils.only_for("3.5") -def test_renaming_async_with_as_variable(self): - code = dedent("""\ - async def func(): - async with a_func() as var: - print(var) - """) - refactored = self._local_rename(code, code.find("var") + 1, "new_var") - self.assertEqual( - dedent("""\ - async def func(): - async with a_func() as new_var: - print(new_var) - """), - refactored, - ) - - -def test_renaming_parameters(self): - code = dedent("""\ - def a_func(param): - print(param) - a_func(param=hey) - """) - refactored = self._local_rename(code, code.find("param") + 1, "new_param") - self.assertEqual( - dedent("""\ - def a_func(new_param): - print(new_param) - a_func(new_param=hey) - """), - refactored, - ) - - -def get_definition(self): - if self.info.global_: - return "\n%s\n" % self._get_function_definition() - else: - return "\n%s" % self._get_function_definition() - - -def test_renaming_assigned_parameters(self): - code = dedent("""\ - def f(p): - p = p + 1 - return p - f(p=1) - """) - refactored = self._local_rename(code, code.find("p"), "arg") - self.assertEqual( - dedent("""\ - def f(arg): - arg = arg + 1 - return arg - f(arg=1) - """), - refactored, - ) - - -def test_renaming_parameters_not_renaming_others(self): - code = dedent("""\ - def a_func(param): - print(param) - param=10 - a_func(param) - """) - refactored = self._local_rename(code, code.find("param") + 1, "new_param") - self.assertEqual( - dedent("""\ - def a_func(new_param): - print(new_param) - param=10 - a_func(param) - """), - refactored, - ) - - -def test_renaming_parameters_not_renaming_others2(self): - code = dedent("""\ - def a_func(param): - print(param) - param=10 - a_func(param=param)""") - refactored = self._local_rename(code, code.find("param") + 1, "new_param") - self.assertEqual( - dedent("""\ - def a_func(new_param): - print(new_param) - param=10 - a_func(new_param=param)"""), - refactored, - ) - - -def test_renaming_parameters_with_multiple_params(self): - code = dedent("""\ - def a_func(param1, param2): - print(param1) - a_func(param1=1, param2=2) - """) - refactored = self._local_rename(code, code.find("param1") + 1, "new_param") - self.assertEqual( - dedent("""\ - def a_func(new_param, param2): - print(new_param) - a_func(new_param=1, param2=2) - """), - refactored, - ) - - -def test_renaming_parameters_with_multiple_params2(self): - code = dedent("""\ - def a_func(param1, param2): - print(param1) - a_func(param1=1, param2=2) - """) - refactored = self._local_rename(code, code.rfind("param2") + 1, "new_param") - self.assertEqual( - dedent("""\ - def a_func(param1, new_param): - print(param1) - a_func(param1=1, new_param=2) - """), - refactored, - ) - - -def test_renaming_parameters_on_calls(self): - code = dedent("""\ - def a_func(param): - print(param) - a_func(param = hey) - """) - refactored = self._local_rename(code, code.rfind("param") + 1, "new_param") - self.assertEqual( - dedent("""\ - def a_func(new_param): - print(new_param) - a_func(new_param = hey) - """), - refactored, - ) - - -def test_renaming_parameters_spaces_before_call(self): - code = dedent("""\ - def a_func(param): - print(param) - a_func (param=hey) - """) - refactored = self._local_rename(code, code.rfind("param") + 1, "new_param") - self.assertEqual( - dedent("""\ - def a_func(new_param): - print(new_param) - a_func (new_param=hey) - """), - refactored, - ) - - -def test_renaming_parameter_like_objects_after_keywords(self): - code = dedent("""\ - def a_func(param): - print(param) - dict(param=hey) - """) - refactored = self._local_rename(code, code.find("param") + 1, "new_param") - self.assertEqual( - dedent("""\ - def a_func(new_param): - print(new_param) - dict(param=hey) - """), - refactored, - ) - - -def test_renaming_variables_in_init_dot_pys(self): - pkg = testutils.create_package(self.project, "pkg") - init_dot_py = pkg.get_child("__init__.py") - init_dot_py.write("a_var = 10\n") - mod = testutils.create_module(self.project, "mod") - mod.write("import pkg\nprint(pkg.a_var)\n") - self._rename(mod, mod.read().index("a_var") + 1, "new_var") - self.assertEqual("new_var = 10\n", init_dot_py.read()) - self.assertEqual("import pkg\nprint(pkg.new_var)\n", mod.read()) - - -def test_renaming_variables_in_init_dot_pys2(self): - pkg = testutils.create_package(self.project, "pkg") - init_dot_py = pkg.get_child("__init__.py") - init_dot_py.write("a_var = 10\n") - mod = testutils.create_module(self.project, "mod") - mod.write("import pkg\nprint(pkg.a_var)\n") - self._rename(init_dot_py, init_dot_py.read().index("a_var") + 1, "new_var") - self.assertEqual("new_var = 10\n", init_dot_py.read()) - self.assertEqual("import pkg\nprint(pkg.new_var)\n", mod.read()) - - -def get_replacement_pattern(self): - variables = [] - variables.extend(self._find_function_arguments()) - variables.extend(self._find_function_returns()) - return similarfinder.make_pattern(self._get_call(), variables) - - -def test_renaming_variables_in_init_dot_pys3(self): - pkg = testutils.create_package(self.project, "pkg") - init_dot_py = pkg.get_child("__init__.py") - init_dot_py.write("a_var = 10\n") - mod = testutils.create_module(self.project, "mod") - mod.write("import pkg\nprint(pkg.a_var)\n") - self._rename(mod, mod.read().index("a_var") + 1, "new_var") - self.assertEqual("new_var = 10\n", init_dot_py.read()) - self.assertEqual("import pkg\nprint(pkg.new_var)\n", mod.read()) - - -def test_renaming_resources_using_rename_module_refactoring(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("a_var = 1") - mod2.write("import mod1\nmy_var = mod1.a_var\n") - renamer = rename.Rename(self.project, mod1) - renamer.get_changes("newmod").do() - self.assertEqual("import newmod\nmy_var = newmod.a_var\n", mod2.read()) - - -def test_renam_resources_using_rename_module_refactor_for_packages(self): - mod1 = testutils.create_module(self.project, "mod1") - pkg = testutils.create_package(self.project, "pkg") - mod1.write("import pkg\nmy_pkg = pkg") - renamer = rename.Rename(self.project, pkg) - renamer.get_changes("newpkg").do() - self.assertEqual("import newpkg\nmy_pkg = newpkg", mod1.read()) - - -def test_renam_resources_use_rename_module_refactor_for_init_dot_py(self): - mod1 = testutils.create_module(self.project, "mod1") - pkg = testutils.create_package(self.project, "pkg") - mod1.write("import pkg\nmy_pkg = pkg") - renamer = rename.Rename(self.project, pkg.get_child("__init__.py")) - renamer.get_changes("newpkg").do() - self.assertEqual("import newpkg\nmy_pkg = newpkg", mod1.read()) - - -def test_renaming_global_variables(self): - code = dedent("""\ - a_var = 1 - def a_func(): - global a_var - var = a_var - """) - refactored = self._local_rename(code, code.index("a_var"), "new_var") - self.assertEqual( - dedent("""\ - new_var = 1 - def a_func(): - global new_var - var = new_var - """), - refactored, - ) - - -def test_renaming_global_variables2(self): - code = dedent("""\ - a_var = 1 - def a_func(): - global a_var - var = a_var - """) - refactored = self._local_rename(code, code.rindex("a_var"), "new_var") - self.assertEqual( - dedent("""\ - new_var = 1 - def a_func(): - global new_var - var = new_var - """), - refactored, - ) - - -def test_renaming_when_unsure(self): - code = dedent("""\ - class C(object): - def a_func(self): - pass - def f(arg): - arg.a_func() - """) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(code) - self._rename(mod1, code.index("a_func"), "new_func", unsure=self._true) - self.assertEqual( - dedent("""\ - class C(object): - def new_func(self): - pass - def f(arg): - arg.new_func() - """), - mod1.read(), - ) - - -def _true(self, *args): - return True - - -def test_renaming_when_unsure_with_confirmation(self): - def confirm(occurrence): - return False - - code = dedent("""\ - class C(object): - def a_func(self): - pass - def f(arg): - arg.a_func() - """) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(code) - self._rename(mod1, code.index("a_func"), "new_func", unsure=confirm) - self.assertEqual( - dedent("""\ - class C(object): - def new_func(self): - pass - def f(arg): - arg.a_func() - """), - mod1.read(), - ) - - -def test_renaming_when_unsure_not_renaming_knowns(self): - code = dedent("""\ - class C1(object): - def a_func(self): - pass - class C2(object): - def a_func(self): - pass - c1 = C1() - c1.a_func() - c2 = C2() - c2.a_func() - """) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(code) - self._rename(mod1, code.index("a_func"), "new_func", unsure=self._true) - self.assertEqual( - dedent("""\ - class C1(object): - def new_func(self): - pass - class C2(object): - def a_func(self): - pass - c1 = C1() - c1.new_func() - c2 = C2() - c2.a_func() - """), - mod1.read(), - ) - - -def get_body_pattern(self): - variables = [] - variables.extend(self._find_function_arguments()) - variables.extend(self._find_function_returns()) - variables.extend(self._find_temps()) - return similarfinder.make_pattern(self._get_body(), variables) - - -def test_renaming_in_strings_and_comments(self): - code = dedent("""\ - a_var = 1 - # a_var - """) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(code) - self._rename(mod1, code.index("a_var"), "new_var", docs=True) - self.assertEqual( - dedent("""\ - new_var = 1 - # new_var - """), - mod1.read(), - ) - - -def test_not_renaming_in_strings_and_comments_where_not_visible(self): - code = dedent("""\ - def f(): - a_var = 1 - # a_var - """) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(code) - self._rename(mod1, code.index("a_var"), "new_var", docs=True) - self.assertEqual( - dedent("""\ - def f(): - new_var = 1 - # a_var - """), - mod1.read(), - ) - - -def test_not_renaming_all_text_occurrences_in_strings_and_comments(self): - code = dedent("""\ - a_var = 1 - # a_vard _a_var - """) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(code) - self._rename(mod1, code.index("a_var"), "new_var", docs=True) - self.assertEqual( - dedent("""\ - new_var = 1 - # a_vard _a_var - """), - mod1.read(), - ) - - -def test_renaming_occurrences_in_overwritten_scopes(self): - refactored = self._local_rename( - dedent("""\ - a_var = 20 - def f(): - print(a_var) - def f(): - print(a_var) - """), - 2, - "new_var", - ) - self.assertEqual( - dedent("""\ - new_var = 20 - def f(): - print(new_var) - def f(): - print(new_var) - """), - refactored, - ) - - -def test_renaming_occurrences_in_overwritten_scopes2(self): - code = dedent("""\ - def f(): - a_var = 1 - print(a_var) - def f(): - a_var = 1 - print(a_var) - """) - refactored = self._local_rename(code, code.index("a_var") + 1, "new_var") - self.assertEqual(code.replace("a_var", "new_var", 2), refactored) - - -@testutils.only_for_versions_higher("3.5") -def test_renaming_in_generalized_dict_unpacking(self): - code = dedent("""\ - a_var = {**{'stuff': 'can'}, **{'stuff': 'crayon'}} - - if "stuff" in a_var: - print("ya") - """) - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(code) - refactored = self._local_rename(code, code.index("a_var") + 1, "new_var") - expected = dedent("""\ - new_var = {**{'stuff': 'can'}, **{'stuff': 'crayon'}} - - if "stuff" in new_var: - print("ya") - """) - self.assertEqual(expected, refactored) - - -def test_dos_line_ending_and_renaming(self): - code = "\r\na = 1\r\n\r\nprint(2 + a + 2)\r\n" - offset = code.replace("\r\n", "\n").rindex("a") - refactored = self._local_rename(code, offset, "b") - self.assertEqual( - "\nb = 1\n\nprint(2 + b + 2)\n", refactored.replace("\r\n", "\n") - ) - - -def test_multi_byte_strs_and_renaming(self): - s = "{LATIN SMALL LETTER I WITH DIAERESIS}" * 4 - code = "# -*- coding: utf-8 -*-\n# " + s + "\na = 1\nprint(2 + a + 2)\n" - refactored = self._local_rename(code, code.rindex("a"), "b") - self.assertEqual( - "# -*- coding: utf-8 -*-\n# " + s + "\nb = 1\nprint(2 + b + 2)\n", - refactored, - ) - - -def test_resources_parameter(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write(dedent("""\ - def f(): - pass - """)) - mod2.write(dedent("""\ - import mod1 - mod1.f() - """)) - self._rename(mod1, mod1.read().rindex("f"), "g", resources=[mod1]) - self.assertEqual( - dedent("""\ - def g(): - pass - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - import mod1 - mod1.f() - """), - mod2.read(), - ) - - -def test_resources_parameter_not_changing_defining_module(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write(dedent("""\ - def f(): - pass - """)) - mod2.write(dedent("""\ - import mod1 - mod1.f() - """)) - self._rename(mod1, mod1.read().rindex("f"), "g", resources=[mod2]) - self.assertEqual( - dedent("""\ - def f(): - pass - """), - mod1.read(), - ) - self.assertEqual( - dedent("""\ - import mod1 - mod1.g() - """), - mod2.read(), - ) - - -class GenerateFunction(_Generate): - @others - -def _get_body(self): - result = sourceutils.fix_indentation(self.info.extracted, 0) - if self.info.one_line: - result = "(%s)" % result - return result - - -# XXX: with variables should not leak -@testutils.only_for("2.5") -def xxx_test_with_statement_variables_should_not_leak(self): - code = dedent("""\ - f = 1 - with open("1.txt") as f: - print(f) - """) - if sys.version_info < (2, 6, 0): - code = "from __future__ import with_statement\n" + code - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(code) - self._rename(mod1, code.rindex("f"), "file") - expected = dedent("""\ - f = 1 - with open("1.txt") as file: - print(file) - """) - self.assertEqual(expected, mod1.read()) - - -def test_rename_in_list_comprehension(self): - code = dedent("""\ - some_var = 1 - compr = [some_var for some_var in range(10)] - """) - offset = code.index("some_var") - refactored = self._local_rename(code, offset, "new_var") - expected = dedent("""\ - new_var = 1 - compr = [some_var for some_var in range(10)] - """) - self.assertEqual(refactored, expected) - - -def test_renaming_modules_aliased_with_dots(self): - pkg = testutils.create_package(self.project, "json") - mod1 = testutils.create_module(self.project, "utils", pkg) - - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - import json.utils as stdlib_json_utils - """)) - self._rename(pkg, None, "new_json") - self.assertTrue( - not mod1.exists() and self.project.find_module("new_json.utils") is not None - ) - self.assertEqual("import new_json.utils as stdlib_json_utils\n", mod2.read()) - - -def test_renaming_modules_aliased_many_dots(self): - pkg = testutils.create_package(self.project, "json") - mod1 = testutils.create_module(self.project, "utils", pkg) - - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - import json.utils.a as stdlib_json_utils - """)) - self._rename(pkg, None, "new_json") - self.assertTrue( - not mod1.exists() and self.project.find_module("new_json.utils") is not None - ) - self.assertEqual("import new_json.utils.a as stdlib_json_utils\n", mod2.read()) - - - -class ChangeOccurrencesTest(unittest.TestCase): - @others - -def setUp(self): - self.project = testutils.sample_project() - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_case(self): - self.mod.write(dedent("""\ - a_var = 1 - print(a_var) - """)) - changer = rename.ChangeOccurrences( - self.project, self.mod, self.mod.read().index("a_var") - ) - changer.get_changes("new_var").do() - self.assertEqual( - dedent("""\ - new_var = 1 - print(new_var) - """), - self.mod.read(), - ) - - -def test_only_performing_inside_scopes(self): - self.mod.write(dedent("""\ - a_var = 1 - new_var = 2 - def f(): - print(a_var) - """)) - changer = rename.ChangeOccurrences( - self.project, self.mod, self.mod.read().rindex("a_var") - ) - changer.get_changes("new_var").do() - self.assertEqual( - dedent("""\ - a_var = 1 - new_var = 2 - def f(): - print(new_var) - """), - self.mod.read(), - ) - - -def test_only_performing_on_calls(self): - self.mod.write(dedent("""\ - def f1(): - pass - def f2(): - pass - g = f1 - a = f1() - """)) - changer = rename.ChangeOccurrences( - self.project, self.mod, self.mod.read().rindex("f1") - ) - changer.get_changes("f2", only_calls=True).do() - self.assertEqual( - dedent("""\ - def f1(): - pass - def f2(): - pass - g = f1 - a = f2() - """), - self.mod.read(), - ) - - -def _find_temps(self): - return usefunction.find_temps(self.info.project, self._get_body()) - - -def test_only_performing_on_reads(self): - self.mod.write(dedent("""\ - a = 1 - b = 2 - print(a) - """)) - changer = rename.ChangeOccurrences( - self.project, self.mod, self.mod.read().rindex("a") - ) - changer.get_changes("b", writes=False).do() - self.assertEqual( - dedent("""\ - a = 1 - b = 2 - print(b) - """), - self.mod.read(), - ) - - - -class ImplicitInterfacesTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project(validate_objectdb=True) - self.pycore = self.project.pycore - self.mod1 = testutils.create_module(self.project, "mod1") - self.mod2 = testutils.create_module(self.project, "mod2") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _rename(self, resource, offset, new_name, **kwds): - changes = Rename(self.project, resource, offset).get_changes(new_name, **kwds) - self.project.do(changes) - - -def test_performing_rename_on_parameters(self): - self.mod1.write("def f(arg):\n arg.run()\n") - self.mod2.write(dedent("""\ - import mod1 - - - class A(object): - def run(self): - pass - class B(object): - def run(self): - pass - mod1.f(A()) - mod1.f(B()) - """)) - self.pycore.analyze_module(self.mod2) - self._rename(self.mod1, self.mod1.read().index("run"), "newrun") - self.assertEqual("def f(arg):\n arg.newrun()\n", self.mod1.read()) - self.assertEqual( - dedent("""\ - import mod1 - - - class A(object): - def newrun(self): - pass - class B(object): - def newrun(self): - pass - mod1.f(A()) - mod1.f(B()) - """), - self.mod2.read(), - ) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -from textwrap import dedent - -from rope.refactor import restructure -from ropetest import testutils - -import unittest - - -@others -@language python -@tabwidth -4 - -class RestructureTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def get_checks(self): - if self.info.method and not self.info.make_global: - if _get_function_kind(self.info.scope) == "method": - class_name = similarfinder._pydefined_to_str( - self.info.scope.parent.pyobject - ) - return {self._get_self_name(): "type=" + class_name} - return {} - - -def test_trivial_case(self): - refactoring = restructure.Restructure(self.project, "a = 1", "a = 0") - self.mod.write("b = 1\n") - self.project.do(refactoring.get_changes()) - self.assertEqual("b = 1\n", self.mod.read()) - - -def test_replacing_simple_patterns(self): - refactoring = restructure.Restructure(self.project, "a = 1", "a = int(1)") - self.mod.write("a = 1\nb = 1\n") - self.project.do(refactoring.get_changes()) - self.assertEqual("a = int(1)\nb = 1\n", self.mod.read()) - - -def test_replacing_patterns_with_normal_names(self): - refactoring = restructure.Restructure( - self.project, "${a} = 1", "${a} = int(1)", args={"a": "exact"} - ) - self.mod.write("a = 1\nb = 1\n") - self.project.do(refactoring.get_changes()) - self.assertEqual("a = int(1)\nb = 1\n", self.mod.read()) - - -def test_replacing_patterns_with_any_names(self): - refactoring = restructure.Restructure(self.project, "${a} = 1", "${a} = int(1)") - self.mod.write("a = 1\nb = 1\n") - self.project.do(refactoring.get_changes()) - self.assertEqual("a = int(1)\nb = int(1)\n", self.mod.read()) - - -def test_replacing_patterns_with_any_names2(self): - refactoring = restructure.Restructure(self.project, "${x} + ${x}", "${x} * 2") - self.mod.write("a = 1 + 1\n") - self.project.do(refactoring.get_changes()) - self.assertEqual("a = 1 * 2\n", self.mod.read()) - - -def test_replacing_patterns_with_checks(self): - self.mod.write(dedent("""\ - def f(p=1): - return p - g = f - g() - """)) - refactoring = restructure.Restructure( - self.project, "${f}()", "${f}(2)", args={"f": "object=mod.f"} - ) - self.project.do(refactoring.get_changes()) - self.assertEqual( - dedent("""\ - def f(p=1): - return p - g = f - g(2) - """), - self.mod.read(), - ) - - -def test_replacing_assignments_with_sets(self): - refactoring = restructure.Restructure( - self.project, "${a} = ${b}", "${a}.set(${b})" - ) - self.mod.write("a = 1\nb = 1\n") - self.project.do(refactoring.get_changes()) - self.assertEqual("a.set(1)\nb.set(1)\n", self.mod.read()) - - -def test_replacing_sets_with_assignments(self): - refactoring = restructure.Restructure( - self.project, "${a}.set(${b})", "${a} = ${b}" - ) - self.mod.write("a.set(1)\nb.set(1)\n") - self.project.do(refactoring.get_changes()) - self.assertEqual( - dedent("""\ - a = 1 - b = 1 - """), - self.mod.read(), - ) - - -def test_using_make_checks(self): - self.mod.write(dedent("""\ - def f(p=1): - return p - g = f - g() - """)) - refactoring = restructure.Restructure( - self.project, "${f}()", "${f}(2)", args={"f": "object=mod.f"} - ) - self.project.do(refactoring.get_changes()) - self.assertEqual( - dedent("""\ - def f(p=1): - return p - g = f - g(2) - """), - self.mod.read(), - ) - - -def test_using_make_checking_builtin_types(self): - self.mod.write("a = 1 + 1\n") - refactoring = restructure.Restructure( - self.project, "${i} + ${i}", "${i} * 2", args={"i": "type=__builtin__.int"} - ) - self.project.do(refactoring.get_changes()) - self.assertEqual("a = 1 * 2\n", self.mod.read()) - - -def _create_info_collector(self): - zero = self.info.scope.get_start() - 1 - start_line = self.info.region_lines[0] - zero - end_line = self.info.region_lines[1] - zero - info_collector = _FunctionInformationCollector( - start_line, end_line, self.info.global_ - ) - body = self.info.source[self.info.scope_region[0] : self.info.scope_region[1]] - node = _parse_text(body) - ast.walk(node, info_collector) - return info_collector - - -def test_auto_indentation_when_no_indentation(self): - self.mod.write("a = 2\n") - refactoring = restructure.Restructure( - self.project, "${a} = 2", "${a} = 1\n${a} += 1" - ) - self.project.do(refactoring.get_changes()) - self.assertEqual( - dedent("""\ - a = 1 - a += 1 - """), - self.mod.read(), - ) - - -def test_auto_indentation(self): - self.mod.write(dedent("""\ - def f(): - a = 2 - """)) - refactoring = restructure.Restructure( - self.project, "${a} = 2", "${a} = 1\n${a} += 1" - ) - self.project.do(refactoring.get_changes()) - self.assertEqual( - dedent("""\ - def f(): - a = 1 - a += 1 - """), - self.mod.read(), - ) - - -def test_auto_indentation_and_not_indenting_blanks(self): - self.mod.write("def f():\n a = 2\n") - refactoring = restructure.Restructure( - self.project, "${a} = 2", "${a} = 1\n\n${a} += 1" - ) - self.project.do(refactoring.get_changes()) - self.assertEqual("def f():\n a = 1\n\n a += 1\n", self.mod.read()) - - -def test_importing_names(self): - self.mod.write("a = 2\n") - refactoring = restructure.Restructure( - self.project, "${a} = 2", "${a} = myconsts.two", imports=["import myconsts"] - ) - self.project.do(refactoring.get_changes()) - self.assertEqual( - dedent("""\ - import myconsts - a = myconsts.two - """), - self.mod.read(), - ) - - -def test_not_importing_names_when_there_are_no_changes(self): - self.mod.write("a = True\n") - refactoring = restructure.Restructure( - self.project, "${a} = 2", "${a} = myconsts.two", imports=["import myconsts"] - ) - self.project.do(refactoring.get_changes()) - self.assertEqual("a = True\n", self.mod.read()) - - -def test_handling_containing_matches(self): - self.mod.write("a = 1 / 2 / 3\n") - refactoring = restructure.Restructure( - self.project, "${a} / ${b}", "${a} // ${b}" - ) - self.project.do(refactoring.get_changes()) - self.assertEqual("a = 1 // 2 // 3\n", self.mod.read()) - - -def test_handling_overlapping_matches(self): - self.mod.write("a = 1\na = 1\na = 1\n") - refactoring = restructure.Restructure(self.project, "a = 1\na = 1\n", "b = 1") - self.project.do(refactoring.get_changes()) - self.assertEqual("b = 1\na = 1\n", self.mod.read()) - - -def test_preventing_stack_overflow_when_matching(self): - self.mod.write("1\n") - refactoring = restructure.Restructure(self.project, "${a}", "${a}") - self.project.do(refactoring.get_changes()) - self.assertEqual("1\n", self.mod.read()) - - -def test_performing_a_restructuring_to_all_modules(self): - mod2 = testutils.create_module(self.project, "mod2") - self.mod.write("a = 1\n") - mod2.write("b = 1\n") - refactoring = restructure.Restructure(self.project, "1", "2 / 1") - self.project.do(refactoring.get_changes()) - self.assertEqual("a = 2 / 1\n", self.mod.read()) - self.assertEqual("b = 2 / 1\n", mod2.read()) - - -def test_performing_a_restructuring_to_selected_modules(self): - mod2 = testutils.create_module(self.project, "mod2") - self.mod.write("a = 1\n") - mod2.write("b = 1\n") - refactoring = restructure.Restructure(self.project, "1", "2 / 1") - self.project.do(refactoring.get_changes(resources=[mod2])) - self.assertEqual("a = 1\n", self.mod.read()) - self.assertEqual("b = 2 / 1\n", mod2.read()) - - -def _get_function_definition(self): - args = self._find_function_arguments() - returns = self._find_function_returns() - - result = [] - self._append_decorators(result) - result.append("def %s:\n" % self._get_function_signature(args)) - unindented_body = self._get_unindented_function_body(returns) - indents = sourceutils.get_indent(self.info.project) - function_body = sourceutils.indent_lines(unindented_body, indents) - result.append(function_body) - definition = "".join(result) - - return definition + "\n" - - -def test_unsure_argument_of_default_wildcard(self): - self.mod.write(dedent("""\ - def f(p): - return p * 2 - x = "" * 2 - i = 1 * 2 - """)) - refactoring = restructure.Restructure( - self.project, - "${s} * 2", - "dup(${s})", - args={"s": {"type": "__builtins__.str", "unsure": True}}, - ) - self.project.do(refactoring.get_changes()) - self.assertEqual( - dedent("""\ - def f(p): - return dup(p) - x = dup("") - i = 1 * 2 - """), - self.mod.read(), - ) - - -def test_statement_after_string_and_column(self): - mod_text = dedent("""\ - def f(x): - if a == "a": raise Exception("test") - """) - self.mod.write(mod_text) - refactoring = restructure.Restructure(self.project, "${a}", "${a}") - self.project.do(refactoring.get_changes()) - self.assertEqual(mod_text, self.mod.read()) - - -@testutils.only_for_versions_higher("3.3") -def test_yield_from(self): - mod_text = dedent("""\ - def f(lst): - yield from lst - """) - self.mod.write(mod_text) - refactoring = restructure.Restructure( - self.project, - "yield from ${a}", - dedent("""\ - for it in ${a}: - yield it"""), - ) - self.project.do(refactoring.get_changes()) - self.assertEqual( - dedent("""\ - def f(lst): - for it in lst: - yield it - """), - self.mod.read(), - ) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -from textwrap import dedent - -import unittest - -from rope.refactor import similarfinder -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class SimilarFinderTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _create_finder(self, source, **kwds): - self.mod.write(source) - pymodule = self.project.get_pymodule(self.mod) - return similarfinder.SimilarFinder(pymodule, **kwds) - - -def test_trivial_case(self): - finder = self._create_finder("") - self.assertEqual([], list(finder.get_match_regions("10"))) - - -def test_constant_integer(self): - source = "a = 10\n" - finder = self._create_finder(source) - result = [(source.index("10"), source.index("10") + 2)] - self.assertEqual(result, list(finder.get_match_regions("10"))) - - -def _append_decorators(self, result): - if self._extracting_staticmethod(): - result.append("@staticmethod\n") - elif self._extracting_classmethod(): - result.append("@classmethod\n") - - -def test_bool_is_not_similar_to_integer(self): - source = dedent("""\ - a = False - b = 0""") - finder = self._create_finder(source) - result = [(source.index("False"), source.index("False") + len("False"))] - self.assertEqual(result, list(finder.get_match_regions("False"))) - - -def test_simple_addition(self): - source = "a = 1 + 2\n" - finder = self._create_finder(source) - result = [(source.index("1"), source.index("2") + 1)] - self.assertEqual(result, list(finder.get_match_regions("1 + 2"))) - - -def test_simple_addition2(self): - source = "a = 1 +2\n" - finder = self._create_finder(source) - result = [(source.index("1"), source.index("2") + 1)] - self.assertEqual(result, list(finder.get_match_regions("1 + 2"))) - - -def test_simple_assign_statements(self): - source = "a = 1 + 2\n" - finder = self._create_finder(source) - self.assertEqual( - [(0, len(source) - 1)], list(finder.get_match_regions("a = 1 + 2")) - ) - - -def test_simple_multiline_statements(self): - source = dedent("""\ - a = 1 - b = 2 - """) - finder = self._create_finder(source) - self.assertEqual( - [(0, len(source) - 1)], list(finder.get_match_regions("a = 1\nb = 2")) - ) - - -def test_multiple_matches(self): - source = "a = 1 + 1\n" - finder = self._create_finder(source) - result = list(finder.get_match_regions("1")) - self.assertEqual(2, len(result)) - start1 = source.index("1") - self.assertEqual((start1, start1 + 1), result[0]) - start2 = source.rindex("1") - self.assertEqual((start2, start2 + 1), result[1]) - - -def test_multiple_matches2(self): - source = dedent("""\ - a = 1 - b = 2 - - a = 1 - b = 2 - """) - finder = self._create_finder(source) - self.assertEqual(2, len(list(finder.get_match_regions("a = 1\nb = 2")))) - - -def test_restricting_the_region_to_search(self): - source = "1\n\n1\n" - finder = self._create_finder(source) - result = list(finder.get_match_regions("1", start=2)) - start = source.rfind("1") - self.assertEqual([(start, start + 1)], result) - - -def test_matching_basic_patterns(self): - source = "b = a\n" - finder = self._create_finder(source) - result = list(finder.get_match_regions("${a}", args={"a": "exact"})) - start = source.rfind("a") - self.assertEqual([(start, start + 1)], result) - - -def test_match_get_ast(self): - source = "b = a\n" - finder = self._create_finder(source) - result = list(finder.get_matches("${a}", args={"a": "exact"})) - self.assertEqual("a", result[0].get_ast("a").id) - - -def _extracting_classmethod(self): - return self.info.kind == "classmethod" - - -def test_match_get_ast_for_statements(self): - source = "b = a\n" - finder = self._create_finder(source) - result = list(finder.get_matches("b = ${a}")) - self.assertEqual("a", result[0].get_ast("a").id) - - -def test_matching_multiple_patterns(self): - source = "c = a + b\n" - finder = self._create_finder(source) - result = list(finder.get_matches("${a} + ${b}")) - self.assertEqual("a", result[0].get_ast("a").id) - self.assertEqual("b", result[0].get_ast("b").id) - - -def test_matching_any_patterns(self): - source = "b = a\n" - finder = self._create_finder(source) - result = list(finder.get_matches("b = ${x}")) - self.assertEqual("a", result[0].get_ast("x").id) - - -def test_matching_any_patterns_repeating(self): - source = "b = 1 + 1\n" - finder = self._create_finder(source) - result = list(finder.get_matches("b = ${x} + ${x}")) - self.assertEqual(1, result[0].get_ast("x").n) - - -def test_matching_any_patterns_not_matching_different_nodes(self): - source = "b = 1 + 2\n" - finder = self._create_finder(source) - result = list(finder.get_matches("b = ${x} + ${x}")) - self.assertEqual(0, len(result)) - - -def test_matching_normal_names_and_assname(self): - source = "a = 1\n" - finder = self._create_finder(source) - result = list(finder.get_matches("${a} = 1")) - self.assertEqual("a", result[0].get_ast("a").id) - - -def test_matching_normal_names_and_assname2(self): - source = "a = 1\n" - finder = self._create_finder(source) - result = list(finder.get_matches("${a}", args={"a": "exact"})) - self.assertEqual(1, len(result)) - - -def test_matching_normal_names_and_attributes(self): - source = "x.a = 1\n" - finder = self._create_finder(source) - result = list(finder.get_matches("${a} = 1", args={"a": "exact"})) - self.assertEqual(0, len(result)) - - -def test_functions_not_matching_when_only_first_parameters(self): - source = "f(1, 2)\n" - finder = self._create_finder(source) - self.assertEqual(0, len(list(finder.get_matches("f(1)")))) - - -def test_matching_nested_try_finally(self): - source = dedent("""\ - if 1: - try: - pass - except: - pass - """) - pattern = dedent("""\ - try: - pass - except: - pass - """) - finder = self._create_finder(source) - self.assertEqual(1, len(list(finder.get_matches(pattern)))) - - -def _extracting_staticmethod(self): - return self.info.kind == "staticmethod" - - -def test_matching_dicts_inside_functions(self): - source = dedent("""\ - def f(p): - d = {1: p.x} - """) - pattern = "{1: ${a}.x}" - finder = self._create_finder(source) - self.assertEqual(1, len(list(finder.get_matches(pattern)))) - - - -class CheckingFinderTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.mod1 = testutils.create_module(self.project, "mod1") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_trivial_case(self): - self.mod1.write("") - pymodule = self.project.get_pymodule(self.mod1) - finder = similarfinder.SimilarFinder(pymodule) - self.assertEqual([], list(finder.get_matches("10", {}))) - - -def test_simple_finding(self): - self.mod1.write(dedent("""\ - class A(object): - pass - a = A() - """)) - pymodule = self.project.get_pymodule(self.mod1) - finder = similarfinder.SimilarFinder(pymodule) - result = list(finder.get_matches("${anything} = ${A}()", {})) - self.assertEqual(1, len(result)) - - -def test_not_matching_when_the_name_does_not_match(self): - self.mod1.write(dedent("""\ - class A(object): - pass - a = list() - """)) - pymodule = self.project.get_pymodule(self.mod1) - finder = similarfinder.SimilarFinder(pymodule) - result = list(finder.get_matches("${anything} = ${C}()", {"C": "name=mod1.A"})) - self.assertEqual(0, len(result)) - - -def test_not_matching_unknowns_finding(self): - self.mod1.write(dedent("""\ - class A(object): - pass - a = unknown() - """)) - pymodule = self.project.get_pymodule(self.mod1) - finder = similarfinder.SimilarFinder(pymodule) - result = list(finder.get_matches("${anything} = ${C}()", {"C": "name=mod1.A"})) - self.assertEqual(0, len(result)) - - -def test_finding_and_matching_pyobjects(self): - source = dedent("""\ - class A(object): - pass - NewA = A - a = NewA() - """) - self.mod1.write(source) - pymodule = self.project.get_pymodule(self.mod1) - finder = similarfinder.SimilarFinder(pymodule) - result = list( - finder.get_matches("${anything} = ${A}()", {"A": "object=mod1.A"}) - ) - self.assertEqual(1, len(result)) - start = source.rindex("a =") - self.assertEqual((start, len(source) - 1), result[0].get_region()) - - -def test_finding_and_matching_types(self): - source = dedent("""\ - class A(object): - def f(self): - pass - a = A() - b = a.f() - """) - self.mod1.write(source) - pymodule = self.project.get_pymodule(self.mod1) - finder = similarfinder.SimilarFinder(pymodule) - result = list( - finder.get_matches("${anything} = ${inst}.f()", {"inst": "type=mod1.A"}) - ) - self.assertEqual(1, len(result)) - start = source.rindex("b") - self.assertEqual((start, len(source) - 1), result[0].get_region()) - - -def _get_function_signature(self, args): - args = list(args) - prefix = "" - if self._extracting_method() or self._extracting_classmethod(): - self_name = self._get_self_name() - if self_name is None: - raise RefactoringError( - "Extracting a method from a function with no self argument." - ) - if self_name in args: - args.remove(self_name) - args.insert(0, self_name) - return prefix + self.info.new_name + "(%s)" % self._get_comma_form(args) - - -def test_checking_the_type_of_an_ass_name_node(self): - self.mod1.write(dedent("""\ - class A(object): - pass - an_a = A() - """)) - pymodule = self.project.get_pymodule(self.mod1) - finder = similarfinder.SimilarFinder(pymodule) - result = list(finder.get_matches("${a} = ${assigned}", {"a": "type=mod1.A"})) - self.assertEqual(1, len(result)) - - -def test_checking_instance_of_an_ass_name_node(self): - self.mod1.write(dedent("""\ - class A(object): - pass - class B(A): - pass - b = B() - """)) - pymodule = self.project.get_pymodule(self.mod1) - finder = similarfinder.SimilarFinder(pymodule) - result = list( - finder.get_matches("${a} = ${assigned}", {"a": "instance=mod1.A"}) - ) - self.assertEqual(1, len(result)) - - -def test_checking_equality_of_imported_pynames(self): - mod2 = testutils.create_module(self.project, "mod2") - mod2.write(dedent("""\ - class A(object): - pass - """)) - self.mod1.write(dedent("""\ - from mod2 import A - an_a = A() - """)) - pymod1 = self.project.get_pymodule(self.mod1) - finder = similarfinder.SimilarFinder(pymod1) - result = list(finder.get_matches("${a_class}()", {"a_class": "name=mod2.A"})) - self.assertEqual(1, len(result)) - - - -class TemplateTest(unittest.TestCase): - @others - -def test_simple_templates(self): - template = similarfinder.CodeTemplate("${a}\n") - self.assertEqual({"a"}, set(template.get_names())) - - -def test_ignoring_matches_in_comments(self): - template = similarfinder.CodeTemplate("#${a}\n") - self.assertEqual({}.keys(), template.get_names()) - - -def test_ignoring_matches_in_strings(self): - template = similarfinder.CodeTemplate("'${a}'\n") - self.assertEqual({}.keys(), template.get_names()) - - -def test_simple_substitution(self): - template = similarfinder.CodeTemplate("${a}\n") - self.assertEqual("b\n", template.substitute({"a": "b"})) - - -def test_substituting_multiple_names(self): - template = similarfinder.CodeTemplate("${a}, ${b}\n") - self.assertEqual("1, 2\n", template.substitute({"a": "1", "b": "2"})) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -from textwrap import dedent - -import unittest - -from rope.base import ast -from rope.refactor import suites -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -def _extracting_method(self): - return not self._extracting_staticmethod() and ( - self.info.method - and not self.info.make_global - and _get_function_kind(self.info.scope) == "method" - ) - - -class SuiteTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - - -def tearDown(self): - super().tearDown() - - -def test_trivial_case(self): - root = source_suite_tree("") - self.assertEqual(1, root.get_start()) - self.assertEqual(0, len(root.get_children())) - - -def test_simple_ifs(self): - root = source_suite_tree(dedent("""\ - if True: - pass""")) - self.assertEqual(1, len(root.get_children())) - - -def test_simple_else(self): - root = source_suite_tree(dedent("""\ - if True: - pass - else: - pass - """)) - self.assertEqual(2, len(root.get_children())) - self.assertEqual(1, root.get_children()[1].get_start()) - - -def test_for(self): - root = source_suite_tree(dedent("""\ - - for i in range(10): - pass - else: - pass - """)) - self.assertEqual(2, len(root.get_children())) - self.assertEqual(2, root.get_children()[1].get_start()) - - -def test_while(self): - root = source_suite_tree(dedent("""\ - while True: - pass - """)) - self.assertEqual(1, len(root.get_children())) - self.assertEqual(1, root.get_children()[0].get_start()) - - -def test_with(self): - root = source_suite_tree(dedent("""\ - from __future__ import with_statement - with file(x): pass - """)) - self.assertEqual(1, len(root.get_children())) - self.assertEqual(2, root.get_children()[0].get_start()) - - -def test_try_finally(self): - root = source_suite_tree(dedent("""\ - try: - pass - finally: - pass - """)) - self.assertEqual(2, len(root.get_children())) - self.assertEqual(1, root.get_children()[0].get_start()) - - -def _generate_info(self, project, resource, offset): - return _FunctionGenerationInfo(project.pycore, resource, offset) - - -def _get_self_name(self): - if self._extracting_classmethod(): - return "cls" - return self._get_scope_self_name() - - -def test_try_except(self): - root = source_suite_tree(dedent("""\ - try: - pass - except: - pass - else: - pass - """)) - self.assertEqual(3, len(root.get_children())) - self.assertEqual(1, root.get_children()[2].get_start()) - - -def test_try_except_finally(self): - root = source_suite_tree(dedent("""\ - try: - pass - except: - pass - finally: - pass - """)) - self.assertEqual(3, len(root.get_children())) - self.assertEqual(1, root.get_children()[2].get_start()) - - -def test_local_start_and_end(self): - root = source_suite_tree(dedent("""\ - if True: - pass - else: - pass - """)) - self.assertEqual(1, root.local_start()) - self.assertEqual(4, root.local_end()) - if_suite = root.get_children()[0] - self.assertEqual(2, if_suite.local_start()) - self.assertEqual(2, if_suite.local_end()) - else_suite = root.get_children()[1] - self.assertEqual(4, else_suite.local_start()) - self.assertEqual(4, else_suite.local_end()) - - -def test_find_suite(self): - root = source_suite_tree("\n") - self.assertEqual(root, root.find_suite(1)) - - -def test_find_suite_for_ifs(self): - root = source_suite_tree(dedent("""\ - if True: - pass - """)) - if_suite = root.get_children()[0] - self.assertEqual(if_suite, root.find_suite(2)) - - -def test_find_suite_for_between_suites(self): - root = source_suite_tree(dedent("""\ - if True: - pass - print(1) - if True: - pass - """)) - if_suite1 = root.get_children()[0] - if_suite2 = root.get_children()[1] - self.assertEqual(if_suite1, root.find_suite(2)) - self.assertEqual(if_suite2, root.find_suite(5)) - self.assertEqual(root, root.find_suite(3)) - - -def test_simple_find_visible(self): - root = source_suite_tree("a = 1\n") - self.assertEqual(1, suites.find_visible_for_suite(root, [1])) - - -def test_simple_find_visible_ifs(self): - root = source_suite_tree(dedent("""\ - - if True: - a = 1 - b = 2 - """)) - self.assertEqual(root.find_suite(3), root.find_suite(4)) - self.assertEqual(3, suites.find_visible_for_suite(root, [3, 4])) - - -def test_simple_find_visible_for_else(self): - root = source_suite_tree(dedent("""\ - - if True: - pass - else: pass - """)) - self.assertEqual(2, suites.find_visible_for_suite(root, [2, 4])) - - -def test_simple_find_visible_for_different_suites(self): - root = source_suite_tree(dedent("""\ - if True: - pass - a = 1 - if False: - pass - """)) - self.assertEqual(1, suites.find_visible_for_suite(root, [2, 3])) - self.assertEqual(5, suites.find_visible_for_suite(root, [5])) - self.assertEqual(1, suites.find_visible_for_suite(root, [2, 5])) - - -def _get_scope_self_name(self): - if self.info.scope.pyobject.get_kind() == "staticmethod": - return - param_names = self.info.scope.pyobject.get_param_names() - if param_names: - return param_names[0] - - -def test_not_always_selecting_scope_start(self): - root = source_suite_tree(dedent("""\ - if True: - a = 1 - if True: - pass - else: - pass - """)) - self.assertEqual(3, suites.find_visible_for_suite(root, [4, 6])) - self.assertEqual(3, suites.find_visible_for_suite(root, [3, 5])) - self.assertEqual(3, suites.find_visible_for_suite(root, [4, 5])) - - -def test_ignoring_functions(self): - root = source_suite_tree(dedent("""\ - def f(): - pass - a = 1 - """)) - self.assertEqual(3, suites.find_visible_for_suite(root, [2, 3])) - - -def test_ignoring_classes(self): - root = source_suite_tree(dedent("""\ - a = 1 - class C(): - pass - """)) - self.assertEqual(1, suites.find_visible_for_suite(root, [1, 3])) - - -@testutils.only_for_versions_higher("3.10") -def test_match_case(self): - root = source_suite_tree(dedent("""\ - a = 1 - match var: - case Foo("xx"): - print(x) - case Foo(x): - print(x) - """)) - self.assertEqual(root.find_suite(4), root.find_suite(6)) - self.assertEqual(root.find_suite(3), root.find_suite(6)) - self.assertEqual(2, suites.find_visible_for_suite(root, [2, 4])) - - - -def source_suite_tree(source): - return suites.ast_suite_tree(ast.parse(source)) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -from textwrap import dedent - -import unittest - -from rope.base import exceptions -from ropetest import testutils -from rope.refactor.usefunction import UseFunction - - -@others -@language python -@tabwidth -4 - -class UseFunctionTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.mod1 = testutils.create_module(self.project, "mod1") - self.mod2 = testutils.create_module(self.project, "mod2") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_case(self): - code = dedent("""\ - def f(): - pass - """) - self.mod1.write(code) - user = UseFunction(self.project, self.mod1, code.rindex("f")) - self.project.do(user.get_changes()) - self.assertEqual(code, self.mod1.read()) - - -def _get_function_call(self, args): - return "{prefix}{name}({args})".format( - prefix=self._get_function_call_prefix(args), - name=self.info.new_name, - args=self._get_comma_form(args), - ) - - -def test_simple_function(self): - code = dedent("""\ - def f(p): - print(p) - print(1) - """) - self.mod1.write(code) - user = UseFunction(self.project, self.mod1, code.rindex("f")) - self.project.do(user.get_changes()) - self.assertEqual( - dedent("""\ - def f(p): - print(p) - f(1) - """), - self.mod1.read(), - ) - - -def test_simple_function2(self): - code = dedent("""\ - def f(p): - print(p + 1) - print(1 + 1) - """) - self.mod1.write(code) - user = UseFunction(self.project, self.mod1, code.rindex("f")) - self.project.do(user.get_changes()) - self.assertEqual( - dedent("""\ - def f(p): - print(p + 1) - f(1) - """), - self.mod1.read(), - ) - - -def test_functions_with_multiple_statements(self): - code = dedent("""\ - def f(p): - r = p + 1 - print(r) - r = 2 + 1 - print(r) - """) - self.mod1.write(code) - user = UseFunction(self.project, self.mod1, code.rindex("f")) - self.project.do(user.get_changes()) - self.assertEqual( - dedent("""\ - def f(p): - r = p + 1 - print(r) - f(2) - """), - self.mod1.read(), - ) - - -def test_returning(self): - code = dedent("""\ - def f(p): - return p + 1 - r = 2 + 1 - print(r) - """) - self.mod1.write(code) - user = UseFunction(self.project, self.mod1, code.rindex("f")) - self.project.do(user.get_changes()) - self.assertEqual( - dedent("""\ - def f(p): - return p + 1 - r = f(2) - print(r) - """), - self.mod1.read(), - ) - - -def test_returning_a_single_expression(self): - code = dedent("""\ - def f(p): - return p + 1 - print(2 + 1) - """) - self.mod1.write(code) - user = UseFunction(self.project, self.mod1, code.rindex("f")) - self.project.do(user.get_changes()) - self.assertEqual( - dedent("""\ - def f(p): - return p + 1 - print(f(2)) - """), - self.mod1.read(), - ) - - -def test_occurrences_in_other_modules(self): - code = dedent("""\ - def f(p): - return p + 1 - """) - self.mod1.write(code) - user = UseFunction(self.project, self.mod1, code.rindex("f")) - self.mod2.write("print(2 + 1)\n") - self.project.do(user.get_changes()) - self.assertEqual( - dedent("""\ - import mod1 - print(mod1.f(2)) - """), - self.mod2.read(), - ) - - -def test_when_performing_on_non_functions(self): - code = "var = 1\n" - self.mod1.write(code) - with self.assertRaises(exceptions.RefactoringError): - UseFunction(self.project, self.mod1, code.rindex("var")) - - -def test_differing_in_the_inner_temp_names(self): - code = dedent("""\ - def f(p): - a = p + 1 - print(a) - b = 2 + 1 - print(b) - """) - self.mod1.write(code) - user = UseFunction(self.project, self.mod1, code.rindex("f")) - self.project.do(user.get_changes()) - self.assertEqual( - dedent("""\ - def f(p): - a = p + 1 - print(a) - f(2) - """), - self.mod1.read(), - ) - - -# TODO: probably new options should be added to restructure -def xxx_test_being_a_bit_more_intelligent_when_returning_assigneds(self): - code = dedent("""\ - def f(p): - a = p + 1 - return a - var = 2 + 1 - print(var) - """) - self.mod1.write(code) - user = UseFunction(self.project, self.mod1, code.rindex("f")) - self.project.do(user.get_changes()) - self.assertEqual( - dedent("""\ - def f(p): - a = p + 1 - return a - var = f(p) - print(var) - """), - self.mod1.read(), - ) - - -def test_exception_when_performing_a_function_with_yield(self): - code = dedent("""\ - def func(): - yield 1 - """) - self.mod1.write(code) - with self.assertRaises(exceptions.RefactoringError): - UseFunction(self.project, self.mod1, code.index("func")) - - -def _get_function_call_prefix(self, args): - prefix = "" - if self.info.method and not self.info.make_global: - if self._extracting_staticmethod() or self._extracting_classmethod(): - prefix = self.info.scope.parent.pyobject.get_name() + "." - else: - self_name = self._get_self_name() - if self_name in args: - args.remove(self_name) - prefix = self_name + "." - return prefix - - -def test_exception_when_performing_a_function_two_returns(self): - code = dedent("""\ - def func(): - return 1 - return 2 - """) - self.mod1.write(code) - with self.assertRaises(exceptions.RefactoringError): - UseFunction(self.project, self.mod1, code.index("func")) - - -def test_exception_when_returns_is_not_the_last_statement(self): - code = dedent("""\ - def func(): - return 2 - a = 1 - """) - self.mod1.write(code) - with self.assertRaises(exceptions.RefactoringError): - UseFunction(self.project, self.mod1, code.index("func")) - -@path C:/Repos/ekr-rope/ropetest/refactor/ -from textwrap import dedent - -import unittest - -import rope.base.taskhandle -import rope.refactor.introduce_parameter -import ropetest.refactor.extracttest -import ropetest.refactor.importutilstest -import ropetest.refactor.inlinetest -import ropetest.refactor.movetest -import ropetest.refactor.multiprojecttest -import ropetest.refactor.patchedasttest -import ropetest.refactor.renametest -import ropetest.refactor.restructuretest -import ropetest.refactor.suitestest -import ropetest.refactor.usefunctiontest -from rope.base.exceptions import RefactoringError, InterruptedTaskError -from rope.refactor.encapsulate_field import EncapsulateField -from rope.refactor.introduce_factory import IntroduceFactory -from rope.refactor.localtofield import LocalToField -from rope.refactor.method_object import MethodObject -from ropetest import testutils -from ropetest.refactor import change_signature_test, similarfindertest - - -@others -@language python -@tabwidth -4 - -class MethodObjectTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_empty_method(self): - code = dedent("""\ - def func(): - pass - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __call__(self): - pass - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - -def test_trivial_return(self): - code = dedent("""\ - def func(): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - -def test_multi_line_header(self): - code = dedent("""\ - def func( - ): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - -def test_a_single_parameter(self): - code = dedent("""\ - def func(param): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, param): - self.param = param - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - -def _get_comma_form(self, names): - return ", ".join(names) - - -def test_self_parameter(self): - code = dedent("""\ - def func(self): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, host): - self.self = host - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - -def test_simple_using_passed_parameters(self): - code = dedent("""\ - def func(param): - return param - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, param): - self.param = param - - def __call__(self): - return self.param - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - -def test_self_keywords_and_args_parameters(self): - code = dedent("""\ - def func(arg, *args, **kwds): - result = arg + args[0] + kwds[arg] - return result - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, arg, args, kwds): - self.arg = arg - self.args = args - self.kwds = kwds - - def __call__(self): - result = self.arg + self.args[0] + self.kwds[self.arg] - return result - """) - self.assertEqual(expected, replacer.get_new_class("_New")) - - -def test_performing_on_not_a_function(self): - code = dedent("""\ - my_var = 10 - """) - self.mod.write(code) - with self.assertRaises(RefactoringError): - MethodObject(self.project, self.mod, code.index("my_var")) - - -def test_changing_the_module(self): - code = dedent("""\ - def func(): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - self.project.do(replacer.get_changes("_New")) - expected = dedent("""\ - def func(): - return _New()() - - - class _New(object): - - def __call__(self): - return 1 - """) - self.assertEqual(expected, self.mod.read()) - - -def test_changing_the_module_and_class_methods(self): - code = dedent("""\ - class C(object): - - def a_func(self): - return 1 - - def another_func(self): - pass - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - self.project.do(replacer.get_changes("_New")) - expected = dedent("""\ - class C(object): - - def a_func(self): - return _New(self)() - - def another_func(self): - pass - - - class _New(object): - - def __init__(self, host): - self.self = host - - def __call__(self): - return 1 - """) - self.assertEqual(expected, self.mod.read()) - - - -class IntroduceFactoryTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _introduce_factory(self, resource, offset, *args, **kwds): - factory_introducer = IntroduceFactory(self.project, resource, offset) - changes = factory_introducer.get_changes(*args, **kwds) - self.project.do(changes) - - -def _get_call(self): - args = self._find_function_arguments() - returns = self._find_function_returns() - call_prefix = "" - if returns and (not self.info.one_line or self.info.returning_named_expr): - assignment_operator = " := " if self.info.one_line else " = " - call_prefix = self._get_comma_form(returns) + assignment_operator - if self.info.returned: - call_prefix = "return " - return call_prefix + self._get_function_call(args) - - -def test_adding_the_method(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - -def test_changing_occurrences_in_the_main_module(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - a_var = AClass()""") - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - a_var = AClass.create()""") - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - -def test_changing_occurrences_with_arguments(self): - code = dedent("""\ - class AClass(object): - def __init__(self, arg): - pass - a_var = AClass(10) - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - def __init__(self, arg): - pass - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - a_var = AClass.create(10) - """) - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - -def test_changing_occurrences_in_other_modules(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("import mod1\na_var = mod1.AClass()\n") - self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = dedent("""\ - import mod1 - a_var = mod1.AClass.create() - """) - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - -def test_raising_exception_for_non_classes(self): - mod = testutils.create_module(self.project, "mod") - mod.write("def a_func():\n pass\n") - with self.assertRaises(RefactoringError): - self._introduce_factory(mod, mod.read().index("a_func") + 1, "create") - - -def test_undoing_introduce_factory(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - code1 = dedent("""\ - class AClass(object): - an_attr = 10 - """) - mod1.write(code1) - code2 = dedent("""\ - from mod1 import AClass - a_var = AClass() - """) - mod2.write(code2) - self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") - self.project.history.undo() - self.assertEqual(code1, mod1.read()) - self.assertEqual(code2, mod2.read()) - - -def test_using_on_an_occurrence_outside_the_main_module(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("import mod1\na_var = mod1.AClass()\n") - self._introduce_factory(mod2, mod2.read().index("AClass") + 1, "create") - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = "import mod1\n" "a_var = mod1.AClass.create()\n" - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - -def test_introduce_factory_in_nested_scopes(self): - code = dedent("""\ - def create_var(): - class AClass(object): - an_attr = 10 - return AClass() - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - def create_var(): - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - return AClass.create() - """) - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - -def test_adding_factory_for_global_factories(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - self._introduce_factory( - mod, mod.read().index("AClass") + 1, "create", global_factory=True - ) - self.assertEqual(expected, mod.read()) - - -def test_get_name_for_factories(self): - code = dedent("""\ - class C(object): - pass - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - factory = IntroduceFactory(self.project, mod, mod.read().index("C") + 1) - self.assertEqual("C", factory.get_name()) - - -def _find_function_arguments(self): - # if not make_global, do not pass any global names; they are - # all visible. - if self.info.global_ and not self.info.make_global: - return list( - self.info_collector.read - & self.info_collector.postread - & self.info_collector.written - ) - if not self.info.one_line: - result = self.info_collector.prewritten & self.info_collector.read - result |= ( - self.info_collector.prewritten - & self.info_collector.postread - & (self.info_collector.maybe_written - self.info_collector.written) - ) - return list(result) - start = self.info.region[0] - if start == self.info.lines_region[0]: - start = start + re.search("\\S", self.info.extracted).start() - function_definition = self.info.source[start : self.info.region[1]] - read = _VariableReadsAndWritesFinder.find_reads_for_one_liners( - function_definition - ) - return list(self.info_collector.prewritten.intersection(read)) - - -def test_raising_exception_for_global_factory_for_nested_classes(self): - code = dedent("""\ - def create_var(): - class AClass(object): - an_attr = 10 - return AClass() - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - with self.assertRaises(RefactoringError): - self._introduce_factory( - mod, mod.read().index("AClass") + 1, "create", global_factory=True - ) - - -def test_changing_occurrences_in_the_main_module_for_global_factories(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - a_var = AClass()""") - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - a_var = create()""") - self._introduce_factory( - mod, mod.read().index("AClass") + 1, "create", global_factory=True - ) - self.assertEqual(expected, mod.read()) - - -def test_changing_occurrences_in_other_modules_for_global_factories(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("import mod1\na_var = mod1.AClass()\n") - self._introduce_factory( - mod1, mod1.read().index("AClass") + 1, "create", global_factory=True - ) - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = "import mod1\n" "a_var = mod1.create()\n" - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - -def test_import_if_necessary_in_other_mods_for_global_factories(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("from mod1 import AClass\npair = AClass(), AClass\n") - self._introduce_factory( - mod1, mod1.read().index("AClass") + 1, "create", global_factory=True - ) - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = dedent("""\ - from mod1 import AClass, create - pair = create(), AClass - """) - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - -def test_changing_occurrences_for_renamed_classes(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - a_class = AClass - a_var = a_class()""") - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - a_class = AClass - a_var = a_class()""") - self._introduce_factory(mod, mod.read().index("a_class") + 1, "create") - self.assertEqual(expected, mod.read()) - - -def test_changing_occurrs_in_the_same_module_with_conflict_ranges(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - def create(self): - return C() - """) - mod.write(code) - self._introduce_factory(mod, mod.read().index("C"), "create_c", True) - expected = dedent("""\ - class C(object): - def create(self): - return create_c() - """) - self.assertTrue(mod.read().startswith(expected)) - - -def _transform_module_to_package(self, resource): - self.project.do( - rope.refactor.ModuleToPackage(self.project, resource).get_changes() - ) - - -def test_transform_module_to_package(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write("import mod2\nfrom mod2 import AClass\n") - mod2 = testutils.create_module(self.project, "mod2") - mod2.write("class AClass(object):\n pass\n") - self._transform_module_to_package(mod2) - mod2 = self.project.get_resource("mod2") - root_folder = self.project.root - self.assertFalse(root_folder.has_child("mod2.py")) - self.assertEqual( - "class AClass(object):\n pass\n", - root_folder.get_child("mod2").get_child("__init__.py").read(), - ) - - -def test_transform_module_to_package_undoing(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) - self._transform_module_to_package(mod) - self.assertFalse(pkg.has_child("mod.py")) - self.assertTrue(pkg.get_child("mod").has_child("__init__.py")) - self.project.history.undo() - self.assertTrue(pkg.has_child("mod.py")) - self.assertFalse(pkg.has_child("mod")) - - -def test_transform_module_to_package_with_relative_imports(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod1.write("import mod2\nfrom mod2 import AClass\n") - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod2.write("class AClass(object):\n pass\n") - self._transform_module_to_package(mod1) - new_init = self.project.get_resource("pkg/mod1/__init__.py") - self.assertEqual( - "import pkg.mod2\nfrom pkg.mod2 import AClass\n", new_init.read() - ) - - -def _find_function_returns(self): - if self.info.one_line: - written = self.info_collector.written | self.info_collector.maybe_written - return list(written & self.info_collector.postread) - - if self.info.returned: - return [] - written = self.info_collector.written | self.info_collector.maybe_written - return list(written & self.info_collector.postread) - - -def test_resources_parameter(self): - code = dedent("""\ - class A(object): - an_attr = 10 - """) - code1 = dedent("""\ - import mod - a = mod.A() - """) - mod = testutils.create_module(self.project, "mod") - mod1 = testutils.create_module(self.project, "mod1") - mod.write(code) - mod1.write(code1) - expected = dedent("""\ - class A(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return A(*args, **kwds) - """) - self._introduce_factory( - mod, mod.read().index("A") + 1, "create", resources=[mod] - ) - self.assertEqual(expected, mod.read()) - self.assertEqual(code1, mod1.read()) - - - -class EncapsulateFieldTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - self.mod1 = testutils.create_module(self.project, "mod1") - self.a_class = dedent("""\ - class A(object): - def __init__(self): - self.attr = 1 - """) - self.added_methods = ( - "\n" - " def get_attr(self):\n" - " return self.attr\n\n" - " def set_attr(self, value):\n" - " self.attr = value\n" - ) - self.encapsulated = self.a_class + self.added_methods - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _encapsulate(self, resource, offset, **args): - changes = EncapsulateField(self.project, resource, offset).get_changes(**args) - self.project.do(changes) - - -def test_adding_getters_and_setters(self): - code = self.a_class - self.mod.write(code) - self._encapsulate(self.mod, code.index("attr") + 1) - self.assertEqual(self.encapsulated, self.mod.read()) - - -def test_changing_getters_in_other_modules(self): - code = dedent("""\ - import mod - a_var = mod.A() - range(a_var.attr) - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - range(a_var.get_attr()) - """) - self.assertEqual(expected, self.mod1.read()) - - -def test_changing_setters_in_other_modules(self): - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(1) - """) - self.assertEqual(expected, self.mod1.read()) - - -def test_changing_getters_in_setters(self): - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 + a_var.attr - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(1 + a_var.get_attr()) - """) - self.assertEqual(expected, self.mod1.read()) - - -def test_appending_to_class_end(self): - self.mod1.write(self.a_class + "a_var = A()\n") - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - self.assertEqual(self.encapsulated + "a_var = A()\n", self.mod1.read()) - - -def _get_unindented_function_body(self, returns): - if self.info.one_line: - return self._get_single_expression_function_body() - return self._get_multiline_function_body(returns) - - -def test_performing_in_other_modules(self): - code = dedent("""\ - import mod - a_var = mod.A() - range(a_var.attr) - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - self.assertEqual(self.encapsulated, self.mod.read()) - expected = dedent("""\ - import mod - a_var = mod.A() - range(a_var.get_attr()) - """) - self.assertEqual(expected, self.mod1.read()) - - -def test_changing_main_module_occurrences(self): - code = self.a_class + "a_var = A()\n" "a_var.attr = a_var.attr * 2\n" - self.mod1.write(code) - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - expected = ( - self.encapsulated + "a_var = A()\n" "a_var.set_attr(a_var.get_attr() * 2)\n" - ) - self.assertEqual(expected, self.mod1.read()) - - -def test_raising_exception_when_performed_on_non_attributes(self): - self.mod1.write("attr = 10") - with self.assertRaises(RefactoringError): - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - - -def test_raising_exception_on_tuple_assignments(self): - self.mod.write(self.a_class) - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 - a_var.attr, b = 1, 2 - """) - self.mod1.write(code) - with self.assertRaises(RefactoringError): - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - - -def test_raising_exception_on_tuple_assignments2(self): - self.mod.write(self.a_class) - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 - b, a_var.attr = 1, 2 - """) - self.mod1.write(code) - with self.assertRaises(RefactoringError): - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - - -def test_tuple_assignments_and_function_calls(self): - code = dedent("""\ - import mod - def func(a1=0, a2=0): - pass - a_var = mod.A() - func(a_var.attr, a2=2) - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - def func(a1=0, a2=0): - pass - a_var = mod.A() - func(a_var.get_attr(), a2=2) - """) - self.assertEqual(expected, self.mod1.read()) - - -def test_tuple_assignments(self): - code = dedent("""\ - import mod - a_var = mod.A() - a, b = a_var.attr, 1 - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a, b = a_var.get_attr(), 1 - """) - self.assertEqual(expected, self.mod1.read()) - - -def test_changing_augmented_assignments(self): - code = "import mod\n" "a_var = mod.A()\n" "a_var.attr += 1\n" - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(a_var.get_attr() + 1) - """) - self.assertEqual(expected, self.mod1.read()) - - -def test_changing_augmented_assignments2(self): - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr <<= 1 - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(a_var.get_attr() << 1) - """) - self.assertEqual(expected, self.mod1.read()) - - -def test_changing_occurrences_inside_the_class(self): - new_class = ( - self.a_class + "\n" " def a_func(self):\n" " self.attr = 1\n" - ) - self.mod.write(new_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = ( - self.a_class + "\n" - " def a_func(self):\n" - " self.set_attr(1)\n" + self.added_methods - ) - self.assertEqual(expected, self.mod.read()) - - -def _get_multiline_function_body(self, returns): - unindented_body = sourceutils.fix_indentation(self.info.extracted, 0) - unindented_body = self._insert_globals(unindented_body) - if returns: - unindented_body += "\nreturn %s" % self._get_comma_form(returns) - return unindented_body - - -def test_getter_and_setter_parameters(self): - self.mod.write(self.a_class) - self._encapsulate( - self.mod, - self.mod.read().index("attr") + 1, - getter="getAttr", - setter="setAttr", - ) - new_methods = self.added_methods.replace("get_attr", "getAttr").replace( - "set_attr", "setAttr" - ) - expected = self.a_class + new_methods - self.assertEqual(expected, self.mod.read()) - - -def test_using_resources_parameter(self): - self.mod1.write("import mod\na = mod.A()\nvar = a.attr\n") - self.mod.write(self.a_class) - self._encapsulate( - self.mod, self.mod.read().index("attr") + 1, resources=[self.mod] - ) - self.assertEqual("import mod\na = mod.A()\nvar = a.attr\n", self.mod1.read()) - expected = self.a_class + self.added_methods - self.assertEqual(expected, self.mod.read()) - - - -class LocalToFieldTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _perform_convert_local_variable_to_field(self, resource, offset): - changes = LocalToField(self.project, resource, offset).get_changes() - self.project.do(changes) - - -def test_simple_local_to_field(self): - code = dedent("""\ - class A(object): - def a_func(self): - var = 10 - """) - self.mod.write(code) - self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) - expected = dedent("""\ - class A(object): - def a_func(self): - self.var = 10 - """) - self.assertEqual(expected, self.mod.read()) - - -def test_raising_exception_when_performed_on_a_global_var(self): - self.mod.write("var = 10\n") - with self.assertRaises(RefactoringError): - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().index("var") + 1 - ) - - -def test_raising_exception_when_performed_on_field(self): - code = dedent("""\ - class A(object): - def a_func(self): - self.var = 10 - """) - self.mod.write(code) - with self.assertRaises(RefactoringError): - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().index("var") + 1 - ) - - -def test_raising_exception_when_performed_on_a_parameter(self): - code = dedent("""\ - class A(object): - def a_func(self, var): - a = var - """) - self.mod.write(code) - with self.assertRaises(RefactoringError): - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().index("var") + 1 - ) - - -def _get_element(self): - decorator = "" - args = [] - if self.info.is_static_method(): - decorator = "@staticmethod\n" - if ( - self.info.is_method() - or self.info.is_constructor() - or self.info.is_instance() - ): - args.append("self") - args.extend(self.info.get_passed_args()) - definition = "{}def {}({}):\n pass\n".format( - decorator, - self.name, - ", ".join(args), - ) - return definition - - -def _get_single_expression_function_body(self): - extracted = _get_single_expression_body(self.info.extracted, info=self.info) - body = "return " + extracted - return self._insert_globals(body) - - -# NOTE: This situation happens alot and is normally not an error -# @testutils.assert_raises(RefactoringError) -def test_not_rais_exception_when_there_is_a_field_with_the_same_name(self): - code = dedent("""\ - class A(object): - def __init__(self): - self.var = 1 - def a_func(self): - var = 10 - """) - self.mod.write(code) - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().rindex("var") + 1 - ) - - -def test_local_to_field_with_self_renamed(self): - code = dedent("""\ - class A(object): - def a_func(myself): - var = 10 - """) - self.mod.write(code) - self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) - expected = dedent("""\ - class A(object): - def a_func(myself): - myself.var = 10 - """) - self.assertEqual(expected, self.mod.read()) - - - -class IntroduceParameterTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def _introduce_parameter(self, offset, name): - rope.refactor.introduce_parameter.IntroduceParameter( - self.project, self.mod, offset - ).get_changes(name).do() - - -def test_simple_case(self): - code = dedent("""\ - var = 1 - def f(): - b = var - """) - self.mod.write(code) - offset = self.mod.read().rindex("var") - self._introduce_parameter(offset, "var") - expected = dedent("""\ - var = 1 - def f(var=var): - b = var - """) - self.assertEqual(expected, self.mod.read()) - - -def test_changing_function_body(self): - code = dedent("""\ - var = 1 - def f(): - b = var - """) - self.mod.write(code) - offset = self.mod.read().rindex("var") - self._introduce_parameter(offset, "p1") - expected = dedent("""\ - var = 1 - def f(p1=var): - b = p1 - """) - self.assertEqual(expected, self.mod.read()) - - -def test_unknown_variables(self): - self.mod.write("def f():\n b = var + c\n") - offset = self.mod.read().rindex("var") - with self.assertRaises(RefactoringError): - self._introduce_parameter(offset, "p1") - self.assertEqual("def f(p1=var):\n b = p1 + c\n", self.mod.read()) - - -def test_failing_when_not_inside(self): - self.mod.write("var = 10\nb = var\n") - offset = self.mod.read().rindex("var") - with self.assertRaises(RefactoringError): - self._introduce_parameter(offset, "p1") - - -def _insert_globals(self, unindented_body): - globals_in_body = self._get_globals_in_body(unindented_body) - globals_ = self.info_collector.globals_ & ( - self.info_collector.written | self.info_collector.maybe_written - ) - globals_ = globals_ - globals_in_body - - if globals_: - unindented_body = "global {}\n{}".format( - ", ".join(globals_), unindented_body - ) - return unindented_body - - -def test_attribute_accesses(self): - code = dedent("""\ - class C(object): - a = 10 - c = C() - def f(): - b = c.a - """) - self.mod.write(code) - offset = self.mod.read().rindex("a") - self._introduce_parameter(offset, "p1") - expected = dedent("""\ - class C(object): - a = 10 - c = C() - def f(p1=c.a): - b = p1 - """) - self.assertEqual(expected, self.mod.read()) - - -def test_introducing_parameters_for_methods(self): - code = dedent("""\ - var = 1 - class C(object): - def f(self): - b = var - """) - self.mod.write(code) - offset = self.mod.read().rindex("var") - self._introduce_parameter(offset, "p1") - expected = dedent("""\ - var = 1 - class C(object): - def f(self, p1=var): - b = p1 - """) - self.assertEqual(expected, self.mod.read()) - - - -class _MockTaskObserver: - def __init__(self): - self.called = 0 - - def __call__(self): - self.called += 1 - - - -class TaskHandleTest(unittest.TestCase): - @others - -def test_trivial_case(self): - handle = rope.base.taskhandle.TaskHandle() - self.assertFalse(handle.is_stopped()) - - -def test_stopping(self): - handle = rope.base.taskhandle.TaskHandle() - handle.stop() - self.assertTrue(handle.is_stopped()) - - -def test_job_sets(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset() - self.assertEqual([jobs], handle.get_jobsets()) - - -def test_starting_and_finishing_jobs(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset(name="test job set", count=1) - jobs.started_job("job1") - jobs.finished_job() - - -def test_test_checking_status(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset() - handle.stop() - with self.assertRaises(InterruptedTaskError): - jobs.check_status() - - -def test_test_checking_status_when_starting(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset() - handle.stop() - with self.assertRaises(InterruptedTaskError): - jobs.started_job("job1") - - -@staticmethod -def _get_globals_in_body(unindented_body): - node = _parse_text(unindented_body) - visitor = _GlobalFinder() - ast.walk(node, visitor) - return visitor.globals_ - - - -def test_calling_the_observer_after_stopping(self): - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) - handle.stop() - self.assertEqual(1, observer.called) - - -def test_calling_the_observer_after_creating_job_sets(self): - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) - jobs = handle.create_jobset() # noqa - self.assertEqual(1, observer.called) - - -def test_calling_the_observer_when_starting_and_finishing_jobs(self): - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) - jobs = handle.create_jobset(name="test job set", count=1) - jobs.started_job("job1") - jobs.finished_job() - self.assertEqual(3, observer.called) - - -def test_job_set_get_percent_done(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset(name="test job set", count=2) - self.assertEqual(0, jobs.get_percent_done()) - jobs.started_job("job1") - jobs.finished_job() - self.assertEqual(50, jobs.get_percent_done()) - jobs.started_job("job2") - jobs.finished_job() - self.assertEqual(100, jobs.get_percent_done()) - - -def test_getting_job_name(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset(name="test job set", count=1) - # recommended name/job_name attribute - self.assertEqual("test job set", jobs.name) - self.assertEqual(None, jobs.job_name) - # deprecated getters - self.assertEqual("test job set", jobs.get_name()) - self.assertEqual(None, jobs.get_active_job_name()) - jobs.started_job("job1") - # recommended name/job_name attribute - self.assertEqual("test job set", jobs.get_name()) - # deprecated getters - self.assertEqual("job1", jobs.get_active_job_name()) - -class _ExtractVariableParts: - @others - -def __init__(self, info): - self.info = info - - -def get_definition(self): - extracted = _get_single_expression_body(self.info.extracted, info=self.info) - return self.info.new_name + " = " + extracted + "\n" - - -def get_body_pattern(self): - return "(%s)" % self.info.extracted.strip() - - -def get_replacement_pattern(self): - return self.info.new_name - - -def get_checks(self): - return {} - - - -class _FunctionInformationCollector: - @others - -def _get_element_kind(self): - return "Function" - - - -def __init__(self, start, end, is_global): - self.start = start - self.end = end - self.is_global = is_global - self.prewritten = OrderedSet() - self.maybe_written = OrderedSet() - self.written = OrderedSet() - self.read = OrderedSet() - self.postread = OrderedSet() - self.postwritten = OrderedSet() - self.host_function = True - self.conditional = False - self.globals_ = OrderedSet() - self.surrounded_by_loop = 0 - self.loop_depth = 0 - - -def _read_variable(self, name, lineno): - if self.start <= lineno <= self.end: - if name not in self.written: - if not self.conditional or name not in self.maybe_written: - self.read.add(name) - if self.end < lineno: - if name not in self.postwritten: - self.postread.add(name) - - -def _written_variable(self, name, lineno): - if self.start <= lineno <= self.end: - if self.conditional: - self.maybe_written.add(name) - else: - self.written.add(name) - if self.loop_depth > 0 and name in self.read: - self.postread.add(name) - if self.start > lineno: - self.prewritten.add(name) - if self.end < lineno: - self.postwritten.add(name) - - -def _FunctionDef(self, node): - if not self.is_global and self.host_function: - self.host_function = False - for name in _get_argnames(node.args): - self._written_variable(name, node.lineno) - for child in node.body: - ast.walk(child, self) - else: - self._written_variable(node.name, node.lineno) - visitor = _VariableReadsAndWritesFinder() - for child in node.body: - ast.walk(child, visitor) - for name in visitor.read - visitor.written: - self._read_variable(name, node.lineno) - - -def _Global(self, node): - self.globals_.add(*node.names) - - -def _AsyncFunctionDef(self, node): - self._FunctionDef(node) - - -def _Name(self, node): - if isinstance(node.ctx, (ast.Store, ast.AugStore)): - self._written_variable(node.id, node.lineno) - if not isinstance(node.ctx, ast.Store): - self._read_variable(node.id, node.lineno) - - -def _MatchAs(self, node): - self._written_variable(node.name, node.lineno) - if node.pattern: - ast.walk(node.pattern, self) - - -def _Assign(self, node): - ast.walk(node.value, self) - for child in node.targets: - ast.walk(child, self) - - -def _AugAssign(self, node): - ast.walk(node.value, self) - if isinstance(node.target, ast.Name): - target_id = node.target.id - self._read_variable(target_id, node.target.lineno) - self._written_variable(target_id, node.target.lineno) - else: - ast.walk(node.target, self) - - -class GenerateVariable(_Generate): - def _get_element(self): - return "%s = None\n" % self.name - - def _get_element_kind(self): - return "Variable" - - - -def _ClassDef(self, node): - self._written_variable(node.name, node.lineno) - - -def _ListComp(self, node): - self._comp_exp(node) - - -def _GeneratorExp(self, node): - self._comp_exp(node) - - -def _SetComp(self, node): - self._comp_exp(node) - - -def _DictComp(self, node): - self._comp_exp(node) - - -def _comp_exp(self, node): - read = OrderedSet(self.read) - written = OrderedSet(self.written) - maybe_written = OrderedSet(self.maybe_written) - - for child in ast.get_child_nodes(node): - ast.walk(child, self) - - comp_names = list( - chain.from_iterable( - self._flatten_nested_tuple_of_names(generator.target) - for generator in node.generators - ) - ) - self.read = self.read - comp_names | read - self.written = self.written - comp_names | written - self.maybe_written = self.maybe_written - comp_names | maybe_written - - -def _flatten_nested_tuple_of_names(self, node): - if isinstance(node, ast.Tuple): - for elt in node.elts: - yield self._flatten_nested_tuple_of_names(elt) - elif isinstance(node, ast.Name): - yield node.id - else: - assert False, "Unexpected node type in list comprehension target: %s" % node - - -def _If(self, node): - self._handle_conditional_node(node) - - -def _While(self, node): - with self._handle_loop_context(node): - self._handle_conditional_node(node) - - -def _For(self, node): - with self._handle_loop_context(node), self._handle_conditional_context(node): - # iter has to be checked before the target variables - ast.walk(node.iter, self) - ast.walk(node.target, self) - - for child in node.body: - ast.walk(child, self) - for child in node.orelse: - ast.walk(child, self) - - -class GenerateClass(_Generate): - def _get_element(self): - return "class %s(object):\n pass\n" % self.name - - def _get_element_kind(self): - return "Class" - - - -def _handle_conditional_node(self, node): - with self._handle_conditional_context(node): - for child in ast.get_child_nodes(node): - ast.walk(child, self) - - -@contextmanager -def _handle_conditional_context(self, node): - if self.start <= node.lineno <= self.end: - self.conditional = True - try: - yield - finally: - self.conditional = False - - -@contextmanager -def _handle_loop_context(self, node): - if node.lineno < self.start: - self.loop_depth += 1 - try: - yield - finally: - self.loop_depth -= 1 - - - -def _get_argnames(arguments): - result = [ - node.arg for node in arguments.args if isinstance(node, ast.arg) - ] - if arguments.vararg: - result.append(vararg.arg) - if arguments.kwarg: - result.append(arguments.kwarg.arg) - return result - - - -class _VariableReadsAndWritesFinder: - @others - -def __init__(self): - self.written = set() - self.read = set() - - -def _Name(self, node): - if isinstance(node.ctx, (ast.Store, ast.AugStore)): - self.written.add(node.id) - if not isinstance(node, ast.Store): - self.read.add(node.id) - - -def _FunctionDef(self, node): - self.written.add(node.name) - visitor = _VariableReadsAndWritesFinder() - for child in ast.get_child_nodes(node): - ast.walk(child, visitor) - self.read.update(visitor.read - visitor.written) - - -def _Class(self, node): - self.written.add(node.name) - - -@staticmethod -def find_reads_and_writes(code): - if code.strip() == "": - return set(), set() - node = _parse_text(code) - visitor = _VariableReadsAndWritesFinder() - ast.walk(node, visitor) - return visitor.read, visitor.written - - -class GenerateModule(_Generate): - @others - -@staticmethod -def find_reads_for_one_liners(code): - if code.strip() == "": - return set(), set() - node = _parse_text(code) - visitor = _VariableReadsAndWritesFinder() - ast.walk(node, visitor) - return visitor.read - - - -class _BaseErrorFinder: - @others - -@classmethod -def has_errors(cls, code): - if code.strip() == "": - return False - node = _parse_text(code) - visitor = cls() - ast.walk(node, visitor) - return visitor.error - - - -class _UnmatchedBreakOrContinueFinder(_BaseErrorFinder): - @others - -def __init__(self): - self.error = False - self.loop_count = 0 - - -def _For(self, node): - self.loop_encountered(node) - - -def _While(self, node): - self.loop_encountered(node) - - -def loop_encountered(self, node): - self.loop_count += 1 - for child in node.body: - ast.walk(child, self) - self.loop_count -= 1 - if node.orelse: - if isinstance(node.orelse, (list, tuple)): - for node_ in node.orelse: - ast.walk(node_, self) - else: - ast.walk(node.orelse, self) - - -def _Break(self, node): - self.check_loop() - - -def _Continue(self, node): - self.check_loop() - - -def get_changes(self): - package = self.info.get_package() - changes = change.ChangeSet("Generate Module <%s>" % self.name) - new_resource = self.project.get_file("{}/{}.py".format(package.path, self.name)) - if new_resource.exists(): - raise exceptions.RefactoringError( - "Module <%s> already exists" % new_resource.path - ) - changes.add_change(change.CreateResource(new_resource)) - changes.add_change( - _add_import_to_module(self.project, self.resource, new_resource) - ) - return changes - - -def check_loop(self): - if self.loop_count < 1: - self.error = True - - -def _FunctionDef(self, node): - pass - - -def _ClassDef(self, node): - pass - - - -class _AsyncStatementFinder(_BaseErrorFinder): - @others - -def __init__(self): - self.error = False - - -def _AsyncFor(self, node): - self.error = True - - -def _AsyncWith(self, node): - self.error = True - - -def _FunctionDef(self, node): - pass - - -def _ClassDef(self, node): - pass - - - -class _GlobalFinder: - def __init__(self): - self.globals_ = OrderedSet() - - def _Global(self, node): - self.globals_.add(*node.names) - - - -def get_location(self): - package = self.info.get_package() - return (package.get_child("%s.py" % self.name), 1) - - - -def _get_function_kind(scope): - return scope.pyobject.get_kind() - - - -def _parse_text(body): - body = sourceutils.fix_indentation(body, 0) - try: - node = ast.parse(body) - except SyntaxError: - # needed to parse expression containing := operator - try: - node = ast.parse("(" + body + ")") - except SyntaxError: - node = ast.parse( - "async def __rope_placeholder__():\n" - + sourceutils.fix_indentation(body, 4) - ) - node.body = node.body[0].body - return node - - - -def _join_lines(code): - lines = [] - for line in code.splitlines(): - if line.endswith("\\"): - lines.append(line[:-1].strip()) - else: - lines.append(line.strip()) - return " ".join(lines) - - - -def _get_single_expression_body(extracted, info): - extracted = sourceutils.fix_indentation(extracted, 0) - already_parenthesized = ( - extracted.lstrip()[0] in "({[" and extracted.rstrip()[-1] in ")}]" - ) - large_multiline = extracted.count("\n") >= 2 and already_parenthesized - if not large_multiline: - extracted = _join_lines(extracted) - multiline_expression = "\n" in extracted - if ( - info.returning_named_expr - or info.returning_generator_exp - or (multiline_expression and not large_multiline) - ): - extracted = "(" + extracted + ")" - return extracted - -@path C:/Repos/ekr-rope/rope/refactor/ -import rope.base.exceptions -import rope.base.pyobjects -from rope.base.builtins import Lambda -from rope.base import worder - - -@others -@language python -@tabwidth -4 - -class DefinitionInfo: - @others - -def __init__( - self, function_name, is_method, args_with_defaults, args_arg, keywords_arg -): - self.function_name = function_name - self.is_method = is_method - self.args_with_defaults = args_with_defaults - self.args_arg = args_arg - self.keywords_arg = keywords_arg - - -def to_string(self): - return "{}({})".format(self.function_name, self.arguments_to_string()) - - -def arguments_to_string(self, from_index=0): - params = [] - for arg, default in self.args_with_defaults: - if default is not None: - params.append("{}={}".format(arg, default)) - else: - params.append(arg) - if self.args_arg is not None: - params.append("*" + self.args_arg) - if self.keywords_arg: - params.append("**" + self.keywords_arg) - return ", ".join(params[from_index:]) - - -@staticmethod -def _read(pyfunction, code): - kind = pyfunction.get_kind() - is_method = kind == "method" - is_lambda = kind == "lambda" - info = _FunctionParser(code, is_method, is_lambda) - args, keywords = info.get_parameters() - args_arg = None - keywords_arg = None - if args and args[-1].startswith("**"): - keywords_arg = args[-1][2:] - del args[-1] - if args and args[-1].startswith("*"): - args_arg = args[-1][1:] - del args[-1] - args_with_defaults = [(name, None) for name in args] - args_with_defaults.extend(keywords) - return DefinitionInfo( - info.get_function_name(), - is_method, - args_with_defaults, - args_arg, - keywords_arg, - ) - - -@property -@utils.saveit -def commenter(self): - return _Commenter(self.code) - - -class GeneratePackage(_Generate): - @others - -@staticmethod -def read(pyfunction): - pymodule = pyfunction.get_module() - word_finder = worder.Worder(pymodule.source_code) - lineno = pyfunction.get_ast().lineno - start = pymodule.lines.get_line_start(lineno) - if isinstance(pyfunction, Lambda): - call = word_finder.get_lambda_and_args(start) - else: - call = word_finder.get_function_and_args_in_header(start) - return DefinitionInfo._read(pyfunction, call) - - - -class CallInfo: - @others - -def __init__( - self, - function_name, - args, - keywords, - args_arg, - keywords_arg, - implicit_arg, - constructor, -): - self.function_name = function_name - self.args = args - self.keywords = keywords - self.args_arg = args_arg - self.keywords_arg = keywords_arg - self.implicit_arg = implicit_arg - self.constructor = constructor - - -def to_string(self): - function = self.function_name - if self.implicit_arg: - function = self.args[0] + "." + self.function_name - params = [] - start = 0 - if self.implicit_arg or self.constructor: - start = 1 - if self.args[start:]: - params.extend(self.args[start:]) - if self.keywords: - params.extend( - ["{}={}".format(name, value) for name, value in self.keywords] - ) - if self.args_arg is not None: - params.append("*" + self.args_arg) - if self.keywords_arg: - params.append("**" + self.keywords_arg) - return "{}({})".format(function, ", ".join(params)) - - -@staticmethod -def read(primary, pyname, definition_info, code): - is_method_call = CallInfo._is_method_call(primary, pyname) - is_constructor = CallInfo._is_class(pyname) - is_classmethod = CallInfo._is_classmethod(pyname) - info = _FunctionParser(code, is_method_call or is_classmethod) - args, keywords = info.get_parameters() - args_arg = None - keywords_arg = None - if args and args[-1].startswith("**"): - keywords_arg = args[-1][2:] - del args[-1] - if args and args[-1].startswith("*"): - args_arg = args[-1][1:] - del args[-1] - if is_constructor: - args.insert(0, definition_info.args_with_defaults[0][0]) - return CallInfo( - info.get_function_name(), - args, - keywords, - args_arg, - keywords_arg, - is_method_call or is_classmethod, - is_constructor, - ) - - -@staticmethod -def _is_method_call(primary, pyname): - return ( - primary is not None - and isinstance(primary.get_object().get_type(), rope.base.pyobjects.PyClass) - and CallInfo._is_method(pyname) - ) - - -@staticmethod -def _is_class(pyname): - return pyname is not None and isinstance( - pyname.get_object(), rope.base.pyobjects.PyClass - ) - - -@staticmethod -def _is_method(pyname): - if pyname is not None and isinstance( - pyname.get_object(), rope.base.pyobjects.PyFunction - ): - return pyname.get_object().get_kind() == "method" - return False - - -@staticmethod -def _is_classmethod(pyname): - if pyname is not None and isinstance( - pyname.get_object(), rope.base.pyobjects.PyFunction - ): - return pyname.get_object().get_kind() == "classmethod" - return False - - - -class ArgumentMapping: - @others - -def get_changes(self): - package = self.info.get_package() - changes = change.ChangeSet("Generate Package <%s>" % self.name) - new_resource = self.project.get_folder("{}/{}".format(package.path, self.name)) - if new_resource.exists(): - raise exceptions.RefactoringError( - "Package <%s> already exists" % new_resource.path - ) - changes.add_change(change.CreateResource(new_resource)) - changes.add_change( - _add_import_to_module(self.project, self.resource, new_resource) - ) - child = self.project.get_folder(package.path + "/" + self.name) - changes.add_change(change.CreateFile(child, "__init__.py")) - return changes - - -def __init__(self, definition_info, call_info): - self.call_info = call_info - self.param_dict = {} - self.keyword_args = [] - self.args_arg = [] - for index, value in enumerate(call_info.args): - if index < len(definition_info.args_with_defaults): - name = definition_info.args_with_defaults[index][0] - self.param_dict[name] = value - else: - self.args_arg.append(value) - for name, value in call_info.keywords: - index = -1 - for pair in definition_info.args_with_defaults: - if pair[0] == name: - self.param_dict[name] = value - break - else: - self.keyword_args.append((name, value)) - - -def to_call_info(self, definition_info): - args = [] - keywords = [] - for index in range(len(definition_info.args_with_defaults)): - name = definition_info.args_with_defaults[index][0] - if name in self.param_dict: - args.append(self.param_dict[name]) - else: - for i in range(index, len(definition_info.args_with_defaults)): - name = definition_info.args_with_defaults[i][0] - if name in self.param_dict: - keywords.append((name, self.param_dict[name])) - break - args.extend(self.args_arg) - keywords.extend(self.keyword_args) - return CallInfo( - self.call_info.function_name, - args, - keywords, - self.call_info.args_arg, - self.call_info.keywords_arg, - self.call_info.implicit_arg, - self.call_info.constructor, - ) - - - -class _FunctionParser: - @others - -def __init__(self, call, implicit_arg, is_lambda=False): - self.call = call - self.implicit_arg = implicit_arg - self.word_finder = worder.Worder(self.call) - if is_lambda: - self.last_parens = self.call.rindex(":") - else: - self.last_parens = self.call.rindex(")") - self.first_parens = self.word_finder._find_parens_start(self.last_parens) - - -def get_parameters(self): - args, keywords = self.word_finder.get_parameters( - self.first_parens, self.last_parens - ) - if self.is_called_as_a_method(): - instance = self.call[: self.call.rindex(".", 0, self.first_parens)] - args.insert(0, instance.strip()) - return args, keywords - - -def get_instance(self): - if self.is_called_as_a_method(): - return self.word_finder.get_primary_at( - self.call.rindex(".", 0, self.first_parens) - 1 - ) - - -def get_function_name(self): - if self.is_called_as_a_method(): - return self.word_finder.get_word_at(self.first_parens - 1) - else: - return self.word_finder.get_primary_at(self.first_parens - 1) - - -def is_called_as_a_method(self): - return self.implicit_arg and "." in self.call[: self.first_parens] - -@path C:/Repos/ekr-rope/rope/refactor/ -# Known Bugs when inlining a function/method -# The values passed to function are inlined using _inlined_variable. -# This may cause two problems, illustrated in the examples below -# -# def foo(var1): -# var1 = var1*10 -# return var1 -# -# If a call to foo(20) is inlined, the result of inlined function is 20, -# but it should be 200. -# -# def foo(var1): -# var2 = var1*10 -# return var2 -# -# 2- If a call to foo(10+10) is inlined the result of inlined function is 110 -# but it should be 200. - -import re -from typing import List - -import rope.base.exceptions -import rope.refactor.functionutils -from rope.base import ( - ast, - pynames, - pyobjects, - codeanalyze, - taskhandle, - evaluate, - worder, - utils, - libutils, -) -from rope.base.change import ChangeSet, ChangeContents -from rope.refactor import ( - occurrences, - rename, - sourceutils, - importutils, - move, - change_signature, -) - - -@others -@language python -@tabwidth -4 - -def unique_prefix(): - n = 0 - while True: - yield "__" + str(n) + "__" - n += 1 - - - -def get_location(self): - package = self.info.get_package() - child = package.get_child(self.name) - return (child.get_child("__init__.py"), 1) - - - -def create_inline(project, resource, offset): - """Create a refactoring object for inlining - - Based on `resource` and `offset` it returns an instance of - `InlineMethod`, `InlineVariable` or `InlineParameter`. - - """ - pyname = _get_pyname(project, resource, offset) - message = ( - "Inline refactoring should be performed on " - "a method, local variable or parameter." - ) - if pyname is None: - raise rope.base.exceptions.RefactoringError(message) - if isinstance(pyname, pynames.ImportedName): - pyname = pyname._get_imported_pyname() - if isinstance(pyname, pynames.AssignedName): - return InlineVariable(project, resource, offset) - if isinstance(pyname, pynames.ParameterName): - return InlineParameter(project, resource, offset) - if isinstance(pyname.get_object(), pyobjects.PyFunction): - return InlineMethod(project, resource, offset) - else: - raise rope.base.exceptions.RefactoringError(message) - - - -class _Inliner: - @others - -def __init__(self, project, resource, offset): - self.project = project - self.pyname = _get_pyname(project, resource, offset) - range_finder = worder.Worder(resource.read(), True) - self.region = range_finder.get_primary_range(offset) - self.name = range_finder.get_word_at(offset) - self.offset = offset - self.original = resource - - -def get_changes(self, *args, **kwds): - pass - - -def get_kind(self): - """Return either 'variable', 'method' or 'parameter'""" - - - -class InlineMethod(_Inliner): - @others - -def __init__(self, *args, **kwds): - super().__init__(*args, **kwds) - self.pyfunction = self.pyname.get_object() - self.pymodule = self.pyfunction.get_module() - self.resource = self.pyfunction.get_module().get_resource() - self.occurrence_finder = occurrences.create_finder( - self.project, self.name, self.pyname - ) - self.normal_generator = _DefinitionGenerator(self.project, self.pyfunction) - self._init_imports() - - -def _init_imports(self): - body = sourceutils.get_body(self.pyfunction) - body, imports = move.moving_code_with_imports(self.project, self.resource, body) - self.imports = imports - self.others_generator = _DefinitionGenerator( - self.project, self.pyfunction, body=body - ) - - -def _get_scope_range(self): - scope = self.pyfunction.get_scope() - lines = self.pymodule.lines - start_line = scope.get_start() - if self.pyfunction.decorators: - decorators = self.pyfunction.decorators - if hasattr(decorators[0], "lineno"): - start_line = decorators[0].lineno - start_offset = lines.get_line_start(start_line) - end_offset = min( - lines.get_line_end(scope.end) + 1, len(self.pymodule.source_code) - ) - return (start_offset, end_offset) - - -def get_changes( - self, - remove=True, - only_current=False, - resources=None, - task_handle=taskhandle.NullTaskHandle(), -): - """Get the changes this refactoring makes - - If `remove` is `False` the definition will not be removed. If - `only_current` is `True`, the the current occurrence will be - inlined, only. - """ - changes = ChangeSet("Inline method <%s>" % self.name) - if resources is None: - resources = self.project.get_python_files() - if only_current: - resources = [self.original] - if remove: - resources.append(self.resource) - job_set = task_handle.create_jobset("Collecting Changes", len(resources)) - for file in resources: - job_set.started_job(file.path) - if file == self.resource: - changes.add_change( - self._defining_file_changes( - changes, remove=remove, only_current=only_current - ) - ) - else: - aim = None - if only_current and self.original == file: - aim = self.offset - handle = _InlineFunctionCallsForModuleHandle( - self.project, file, self.others_generator, aim - ) - result = move.ModuleSkipRenamer( - self.occurrence_finder, file, handle - ).get_changed_module() - if result is not None: - result = _add_imports(self.project, result, file, self.imports) - if remove: - result = _remove_from(self.project, self.pyname, result, file) - changes.add_change(ChangeContents(file, result)) - job_set.finished_job() - return changes - - -def _add_import_to_module(project, resource, imported): - pymodule = project.get_pymodule(resource) - import_tools = importutils.ImportTools(project) - module_imports = import_tools.module_imports(pymodule) - module_name = libutils.modname(imported) - new_import = importutils.NormalImport(((module_name, None),)) - module_imports.add_import(new_import) - return change.ChangeContents(resource, module_imports.get_changed_source()) - - - -def _get_removed_range(self): - scope = self.pyfunction.get_scope() - lines = self.pymodule.lines - start, end = self._get_scope_range() - end_line = scope.get_end() - for i in range(end_line + 1, lines.length()): - if lines.get_line(i).strip() == "": - end_line = i - else: - break - end = min(lines.get_line_end(end_line) + 1, len(self.pymodule.source_code)) - return (start, end) - - -def _defining_file_changes(self, changes, remove, only_current): - start_offset, end_offset = self._get_removed_range() - aim = None - if only_current: - if self.resource == self.original: - aim = self.offset - else: - # we don't want to change any of them - aim = len(self.resource.read()) + 100 - handle = _InlineFunctionCallsForModuleHandle( - self.project, self.resource, self.normal_generator, aim_offset=aim - ) - replacement = None - if remove: - replacement = self._get_method_replacement() - result = move.ModuleSkipRenamer( - self.occurrence_finder, - self.resource, - handle, - start_offset, - end_offset, - replacement, - ).get_changed_module() - return ChangeContents(self.resource, result) - - -def _get_method_replacement(self): - if self._is_the_last_method_of_a_class(): - indents = sourceutils.get_indents( - self.pymodule.lines, self.pyfunction.get_scope().get_start() - ) - return " " * indents + "pass\n" - return "" - - -def _is_the_last_method_of_a_class(self): - pyclass = self.pyfunction.parent - if not isinstance(pyclass, pyobjects.PyClass): - return False - class_start, class_end = sourceutils.get_body_region(pyclass) - source = self.pymodule.source_code - func_start, func_end = self._get_scope_range() - return ( - source[class_start:func_start].strip() == "" - and source[func_end:class_end].strip() == "" - ) - - -def get_kind(self): - return "method" - - - -class InlineVariable(_Inliner): - @others - -def __init__(self, *args, **kwds): - super().__init__(*args, **kwds) - self.pymodule = self.pyname.get_definition_location()[0] - self.resource = self.pymodule.get_resource() - self._check_exceptional_conditions() - self._init_imports() - - -def _check_exceptional_conditions(self): - if len(self.pyname.assignments) != 1: - raise rope.base.exceptions.RefactoringError( - "Local variable should be assigned once for inlining." - ) - - -def get_changes( - self, - remove=True, - only_current=False, - resources=None, - docs=False, - task_handle=taskhandle.NullTaskHandle(), -): - if resources is None: - if rename._is_local(self.pyname): - resources = [self.resource] - else: - resources = self.project.get_python_files() - if only_current: - resources = [self.original] - if remove and self.original != self.resource: - resources.append(self.resource) - changes = ChangeSet("Inline variable <%s>" % self.name) - jobset = task_handle.create_jobset("Calculating changes", len(resources)) - - for resource in resources: - jobset.started_job(resource.path) - if resource == self.resource: - source = self._change_main_module(remove, only_current, docs) - changes.add_change(ChangeContents(self.resource, source)) - else: - result = self._change_module(resource, remove, only_current) - if result is not None: - result = _add_imports(self.project, result, resource, self.imports) - changes.add_change(ChangeContents(resource, result)) - jobset.finished_job() - return changes - - -def _change_main_module(self, remove, only_current, docs): - region = None - if only_current and self.original == self.resource: - region = self.region - return _inline_variable( - self.project, - self.pymodule, - self.pyname, - self.name, - remove=remove, - region=region, - docs=docs, - ) - - -def _add_relative_import_to_module(project, resource, imported, name): - pymodule = project.get_pymodule(resource) - import_tools = importutils.ImportTools(project) - module_imports = import_tools.module_imports(pymodule) - new_import = import_tools.get_from_import(imported, name) - module_imports.add_import(new_import) - return change.ChangeContents(resource, module_imports.get_changed_source()) - - - -def _init_imports(self): - vardef = _getvardef(self.pymodule, self.pyname) - self.imported, self.imports = move.moving_code_with_imports( - self.project, self.resource, vardef - ) - - -def _change_module(self, resource, remove, only_current): - filters = [occurrences.NoImportsFilter(), occurrences.PyNameFilter(self.pyname)] - if only_current and resource == self.original: - - @others - filters.insert(0, check_aim) - finder = occurrences.Finder(self.project, self.name, filters=filters) - changed = rename.rename_in_module( - finder, self.imported, resource=resource, replace_primary=True - ) - if changed and remove: - changed = _remove_from(self.project, self.pyname, changed, resource) - return changed - - -def check_aim(occurrence): - start, end = occurrence.get_primary_range() - if self.offset < start or end < self.offset: - return False - - -def get_kind(self): - return "variable" - - - -class InlineParameter(_Inliner): - @others - -def __init__(self, *args, **kwds): - super().__init__(*args, **kwds) - resource, offset = self._function_location() - index = self.pyname.index - self.changers = [change_signature.ArgumentDefaultInliner(index)] - self.signature = change_signature.ChangeSignature( - self.project, resource, offset - ) - - -def _function_location(self): - pymodule, lineno = self.pyname.get_definition_location() - resource = pymodule.get_resource() - start = pymodule.lines.get_line_start(lineno) - word_finder = worder.Worder(pymodule.source_code) - offset = word_finder.find_function_offset(start) - return resource, offset - - -def get_changes(self, **kwds): - """Get the changes needed by this refactoring - - See `rope.refactor.change_signature.ChangeSignature.get_changes()` - for arguments. - """ - return self.signature.get_changes(self.changers, **kwds) - - -def get_kind(self): - return "parameter" - - - -def _join_lines(lines: List[str]) -> str: - return "\n".join(lines) - - -class _ComplexExpressionVisitor: - def __init__(self): - self.is_complex_expression = False - - def _Set(self, node): - self.is_complex_expression = True - - def _List(self, node): - self.is_complex_expression = True - - def _Tuple(self, node): - self.is_complex_expression = True - - def _Dict(self, node): - self.is_complex_expression = True - - - -class _GenerationInfo: - @others - -class _DefinitionGenerator: - unique_prefix = unique_prefix() - - @others - -def __init__(self, project, pyfunction, body=None): - self.project = project - self.pyfunction = pyfunction - self.pymodule = pyfunction.get_module() - self.resource = self.pymodule.get_resource() - self.definition_info = self._get_definition_info() - self.definition_params = self._get_definition_params() - self._calculated_definitions = {} - if body is not None: - self.body = body - else: - self.body = sourceutils.get_body(self.pyfunction) - - -def _get_definition_info(self): - return rope.refactor.functionutils.DefinitionInfo.read(self.pyfunction) - - -def _get_definition_params(self): - definition_info = self.definition_info - paramdict = dict([pair for pair in definition_info.args_with_defaults]) - if ( - definition_info.args_arg is not None - or definition_info.keywords_arg is not None - ): - raise rope.base.exceptions.RefactoringError( - "Cannot inline functions with list and keyword arguements." - ) - if self.pyfunction.get_kind() == "classmethod": - paramdict[ - definition_info.args_with_defaults[0][0] - ] = self.pyfunction.parent.get_name() - return paramdict - - -def get_function_name(self): - return self.pyfunction.get_name() - - -def get_definition(self, primary, pyname, call, host_vars=[], returns=False): - # caching already calculated definitions - return self._calculate_definition(primary, pyname, call, host_vars, returns) - - -def _calculate_header(self, primary, pyname, call): - # A header is created which initializes parameters - # to the values passed to the function. - call_info = rope.refactor.functionutils.CallInfo.read( - primary, pyname, self.definition_info, call - ) - paramdict = self.definition_params - mapping = rope.refactor.functionutils.ArgumentMapping( - self.definition_info, call_info - ) - for param_name, value in mapping.param_dict.items(): - paramdict[param_name] = value - header = "" - to_be_inlined = [] - for name, value in paramdict.items(): - if name != value and value is not None: - header += name + " = " + value.replace("\n", " ") + "\n" - to_be_inlined.append(name) - return header, to_be_inlined - - -def _calculate_definition(self, primary, pyname, call, host_vars, returns): - - header, to_be_inlined = self._calculate_header(primary, pyname, call) - - source = header + self.body - mod = libutils.get_string_module(self.project, source) - name_dict = mod.get_scope().get_names() - all_names = [ - x - for x in name_dict - if not isinstance(name_dict[x], rope.base.builtins.BuiltinName) - ] - - # If there is a name conflict, all variable names - # inside the inlined function are renamed - if len(set(all_names).intersection(set(host_vars))) > 0: - - prefix = next(_DefinitionGenerator.unique_prefix) - guest = libutils.get_string_module(self.project, source, self.resource) - - to_be_inlined = [prefix + item for item in to_be_inlined] - for item in all_names: - pyname = guest[item] - occurrence_finder = occurrences.create_finder( - self.project, item, pyname - ) - source = rename.rename_in_module( - occurrence_finder, prefix + item, pymodule=guest - ) - guest = libutils.get_string_module(self.project, source, self.resource) - - # parameters not reassigned inside the functions are now inlined. - for name in to_be_inlined: - pymodule = libutils.get_string_module(self.project, source, self.resource) - pyname = pymodule[name] - source = _inline_variable(self.project, pymodule, pyname, name) - - return self._replace_returns_with(source, returns) - - -def _replace_returns_with(self, source, returns): - result = [] - returned = None - last_changed = 0 - for match in _DefinitionGenerator._get_return_pattern().finditer(source): - for key, value in match.groupdict().items(): - if value and key == "return": - result.append(source[last_changed : match.start("return")]) - if returns: - self._check_nothing_after_return(source, match.end("return")) - beg_idx = match.end("return") - returned = _join_lines( - source[beg_idx : len(source)].lstrip().splitlines(), - ) - last_changed = len(source) - else: - current = match.end("return") - while current < len(source) and source[current] in " \t": - current += 1 - last_changed = current - if current == len(source) or source[current] == "\n": - result.append("pass") - result.append(source[last_changed:]) - return "".join(result), returned - - -def _check_nothing_after_return(self, source, offset): - lines = codeanalyze.SourceLinesAdapter(source) - lineno = lines.get_line_number(offset) - logical_lines = codeanalyze.LogicalLineFinder(lines) - lineno = logical_lines.logical_line_in(lineno)[1] - if source[lines.get_line_end(lineno) : len(source)].strip() != "": - raise rope.base.exceptions.RefactoringError( - "Cannot inline functions with statements " + "after return statement." - ) - - -def __init__(self, pycore, resource, offset, goal_resource=None): - self.pycore = pycore - self.resource = resource - self.offset = offset - self.goal_resource = goal_resource - self.source_pymodule = self.pycore.project.get_pymodule(resource) - finder = rope.base.evaluate.ScopeNameFinder(self.source_pymodule) - self.primary, self.pyname = finder.get_primary_and_pyname_at(offset) - self._init_fields() - - -@classmethod -def _get_return_pattern(cls): - if not hasattr(cls, "_return_pattern"): - - @others - comment_pattern = named_pattern("comment", [r"#[^\n]*"]) - string_pattern = named_pattern("string", [codeanalyze.get_string_pattern()]) - return_pattern = r"\b(?P<return>return)\b" - cls._return_pattern = re.compile( - comment_pattern + "|" + string_pattern + "|" + return_pattern - ) - return cls._return_pattern - - - -def named_pattern(name, list_): - return "(?P<%s>" % name + "|".join(list_) + ")" - - -class _InlineFunctionCallsForModuleHandle: - @others - -def __init__(self, project, resource, definition_generator, aim_offset=None): - """Inlines occurrences - - If `aim` is not `None` only the occurrences that intersect - `aim` offset will be inlined. - - """ - self.project = project - self.generator = definition_generator - self.resource = resource - self.aim = aim_offset - - -def occurred_inside_skip(self, change_collector, occurrence): - if not occurrence.is_defined(): - raise rope.base.exceptions.RefactoringError( - "Cannot inline functions that reference themselves" - ) - - -def occurred_outside_skip(self, change_collector, occurrence): - start, end = occurrence.get_primary_range() - # we remove out of date imports later - if occurrence.is_in_import_statement(): - return - # the function is referenced outside an import statement - if not occurrence.is_called(): - raise rope.base.exceptions.RefactoringError( - "Reference to inlining function other than function call" - " in <file: %s, offset: %d>" % (self.resource.path, start) - ) - if self.aim is not None and (self.aim < start or self.aim > end): - return - end_parens = self._find_end_parens(self.source, end - 1) - lineno = self.lines.get_line_number(start) - start_line, end_line = self.pymodule.logical_lines.logical_line_in(lineno) - line_start = self.lines.get_line_start(start_line) - line_end = self.lines.get_line_end(end_line) - - returns = ( - self.source[line_start:start].strip() != "" - or self.source[end_parens:line_end].strip() != "" - ) - indents = sourceutils.get_indents(self.lines, start_line) - primary, pyname = occurrence.get_primary_and_pyname() - - host = self.pymodule - scope = host.scope.get_inner_scope_for_line(lineno) - definition, returned = self.generator.get_definition( - primary, - pyname, - self.source[start:end_parens], - scope.get_names(), - returns=returns, - ) - - end = min(line_end + 1, len(self.source)) - change_collector.add_change( - line_start, end, sourceutils.fix_indentation(definition, indents) - ) - if returns: - name = returned - if name is None: - name = "None" - change_collector.add_change( - line_end, - end, - self.source[line_start:start] + name + self.source[end_parens:end], - ) - - -def _find_end_parens(self, source, offset): - finder = worder.Worder(source) - return finder.get_word_parens_range(offset)[1] - - -@property -@utils.saveit -def pymodule(self): - return self.project.get_pymodule(self.resource) - - -@property -@utils.saveit -def source(self): - if self.resource is not None: - return self.resource.read() - else: - return self.pymodule.source_code - - -@property -@utils.saveit -def lines(self): - return self.pymodule.lines - - - -def _init_fields(self): - self.source_scope = self._get_source_scope() - self.goal_scope = self._get_goal_scope() - self.goal_pymodule = self._get_goal_module(self.goal_scope) - - -def _inline_variable( - project, pymodule, pyname, name, remove=True, region=None, docs=False -): - definition = _getvardef(pymodule, pyname) - start, end = _assigned_lineno(pymodule, pyname) - - occurrence_finder = occurrences.create_finder(project, name, pyname, docs=docs) - changed_source = rename.rename_in_module( - occurrence_finder, - definition, - pymodule=pymodule, - replace_primary=True, - writes=False, - region=region, - ) - if changed_source is None: - changed_source = pymodule.source_code - if remove: - lines = codeanalyze.SourceLinesAdapter(changed_source) - source = ( - changed_source[: lines.get_line_start(start)] - + changed_source[lines.get_line_end(end) + 1 :] - ) - else: - source = changed_source - return source - - - -def _getvardef(pymodule, pyname): - assignment = pyname.assignments[0] - lines = pymodule.lines - start, end = _assigned_lineno(pymodule, pyname) - definition_with_assignment = _join_lines( - [lines.get_line(n) for n in range(start, end + 1)], - ) - if assignment.levels: - raise rope.base.exceptions.RefactoringError("Cannot inline tuple assignments.") - definition = definition_with_assignment[ - definition_with_assignment.index("=") + 1 : - ].strip() - return definition - - - -def _assigned_lineno(pymodule, pyname): - definition_line = pyname.assignments[0].ast_node.lineno - return pymodule.logical_lines.logical_line_in(definition_line) - - - -def _add_imports(project, source, resource, imports): - if not imports: - return source - pymodule = libutils.get_string_module(project, source, resource) - module_import = importutils.get_module_imports(project, pymodule) - for import_info in imports: - module_import.add_import(import_info) - source = module_import.get_changed_source() - pymodule = libutils.get_string_module(project, source, resource) - import_tools = importutils.ImportTools(project) - return import_tools.organize_imports(pymodule, unused=False, sort=False) - - - -def _get_pyname(project, resource, offset): - pymodule = project.get_pymodule(resource) - pyname = evaluate.eval_location(pymodule, offset) - if isinstance(pyname, pynames.ImportedName): - pyname = pyname._get_imported_pyname() - return pyname - - - -def _remove_from(project, pyname, source, resource): - pymodule = libutils.get_string_module(project, source, resource) - module_import = importutils.get_module_imports(project, pymodule) - module_import.remove_pyname(pyname) - return module_import.get_changed_source() - -@path C:/Repos/ekr-rope/rope/refactor/ -import rope.base.exceptions -import rope.base.pyobjects -from rope.base import libutils -from rope.base import taskhandle, evaluate -from rope.base.change import ChangeSet, ChangeContents -from rope.refactor import rename, occurrences, sourceutils, importutils - - -@others -IntroduceFactoryRefactoring = IntroduceFactory -@language python -@tabwidth -4 - -class IntroduceFactory: - @others - -def __init__(self, project, resource, offset): - self.project = project - self.offset = offset - - this_pymodule = self.project.get_pymodule(resource) - self.old_pyname = evaluate.eval_location(this_pymodule, offset) - if self.old_pyname is None or not isinstance( - self.old_pyname.get_object(), rope.base.pyobjects.PyClass - ): - raise rope.base.exceptions.RefactoringError( - "Introduce factory should be performed on a class." - ) - self.old_name = self.old_pyname.get_object().get_name() - self.pymodule = self.old_pyname.get_object().get_module() - self.resource = self.pymodule.get_resource() - - -def get_changes( - self, - factory_name, - global_factory=False, - resources=None, - task_handle=taskhandle.NullTaskHandle(), -): - """Get the changes this refactoring makes - - `factory_name` indicates the name of the factory function to - be added. If `global_factory` is `True` the factory will be - global otherwise a static method is added to the class. - - `resources` can be a list of `rope.base.resource.File` that - this refactoring should be applied on; if `None` all python - files in the project are searched. - - """ - if resources is None: - resources = self.project.get_python_files() - changes = ChangeSet("Introduce factory method <%s>" % factory_name) - job_set = task_handle.create_jobset("Collecting Changes", len(resources)) - self._change_module(resources, changes, factory_name, global_factory, job_set) - return changes - - -def _get_goal_scope(self): - if self.primary is None: - if self.goal_resource: - return self.pycore.project.get_pymodule(self.goal_resource).get_scope() - else: - return self._get_source_scope() - pyobject = self.primary.get_object() - if isinstance(pyobject, pyobjects.PyDefinedObject): - return pyobject.get_scope() - elif isinstance(pyobject.get_type(), pyobjects.PyClass): - return pyobject.get_type().get_scope() - - -def get_name(self): - """Return the name of the class""" - return self.old_name - - -def _change_module(self, resources, changes, factory_name, global_, job_set): - if global_: - replacement = "__rope_factory_%s_" % factory_name - else: - replacement = self._new_function_name(factory_name, global_) - - for file_ in resources: - job_set.started_job(file_.path) - if file_ == self.resource: - self._change_resource(changes, factory_name, global_) - job_set.finished_job() - continue - changed_code = self._rename_occurrences(file_, replacement, global_) - if changed_code is not None: - if global_: - new_pymodule = libutils.get_string_module( - self.project, changed_code, self.resource - ) - modname = libutils.modname(self.resource) - changed_code, imported = importutils.add_import( - self.project, new_pymodule, modname, factory_name - ) - changed_code = changed_code.replace(replacement, imported) - changes.add_change(ChangeContents(file_, changed_code)) - job_set.finished_job() - - -def _change_resource(self, changes, factory_name, global_): - class_scope = self.old_pyname.get_object().get_scope() - source_code = self._rename_occurrences( - self.resource, self._new_function_name(factory_name, global_), global_ - ) - if source_code is None: - source_code = self.pymodule.source_code - else: - self.pymodule = libutils.get_string_module( - self.project, source_code, resource=self.resource - ) - lines = self.pymodule.lines - start = self._get_insertion_offset(class_scope, lines) - result = source_code[:start] - result += self._get_factory_method(lines, class_scope, factory_name, global_) - result += source_code[start:] - changes.add_change(ChangeContents(self.resource, result)) - - -def _get_insertion_offset(self, class_scope, lines): - start_line = class_scope.get_end() - if class_scope.get_scopes(): - start_line = class_scope.get_scopes()[-1].get_end() - start = lines.get_line_end(start_line) + 1 - return start - - -def _get_factory_method(self, lines, class_scope, factory_name, global_): - unit_indents = " " * sourceutils.get_indent(self.project) - if global_: - if self._get_scope_indents(lines, class_scope) > 0: - raise rope.base.exceptions.RefactoringError( - "Cannot make global factory method for nested classes." - ) - return "\ndef {}(*args, **kwds):\n{}return {}(*args, **kwds)\n".format( - factory_name, - unit_indents, - self.old_name, - ) - unindented_factory = ( - "@staticmethod\ndef %s(*args, **kwds):\n" % factory_name - + "{}return {}(*args, **kwds)\n".format(unit_indents, self.old_name) - ) - indents = self._get_scope_indents(lines, class_scope) + sourceutils.get_indent( - self.project - ) - return "\n" + sourceutils.indent_lines(unindented_factory, indents) - - -def _get_scope_indents(self, lines, scope): - return sourceutils.get_indents(lines, scope.get_start()) - - -def _new_function_name(self, factory_name, global_): - if global_: - return factory_name - else: - return self.old_name + "." + factory_name - - -def _rename_occurrences(self, file_, changed_name, global_factory): - finder = occurrences.create_finder( - self.project, self.old_name, self.old_pyname, only_calls=True - ) - return rename.rename_in_module( - finder, changed_name, resource=file_, replace_primary=global_factory - ) - - - -@path C:/Repos/ekr-rope/rope/refactor/ -import rope.base.change -from rope.base import exceptions, evaluate, worder, codeanalyze -from rope.refactor import functionutils, sourceutils, occurrences - - -@others -@language python -@tabwidth -4 - -class IntroduceParameter: - """Introduce parameter refactoring - - This refactoring adds a new parameter to a function and replaces - references to an expression in it with the new parameter. - - The parameter finding part is different from finding similar - pieces in extract refactorings. In this refactoring parameters - are found based on the object they reference to. For instance - in:: - - class A(object): - var = None - - class B(object): - a = A() - - b = B() - a = b.a - - def f(a): - x = b.a.var + a.var - - using this refactoring on ``a.var`` with ``p`` as the new - parameter name, will result in:: - - def f(p=a.var): - x = p + p - - """ - - @others - -def _get_goal_module(self, scope): - if scope is None: - return - while scope.parent is not None: - scope = scope.parent - return scope.pyobject - - -def __init__(self, project, resource, offset): - self.project = project - self.resource = resource - self.offset = offset - self.pymodule = self.project.get_pymodule(self.resource) - scope = self.pymodule.get_scope().get_inner_scope_for_offset(offset) - if scope.get_kind() != "Function": - raise exceptions.RefactoringError( - "Introduce parameter should be performed inside functions" - ) - self.pyfunction = scope.pyobject - self.name, self.pyname = self._get_name_and_pyname() - if self.pyname is None: - raise exceptions.RefactoringError( - "Cannot find the definition of <%s>" % self.name - ) - - -def _get_primary(self): - word_finder = worder.Worder(self.resource.read()) - return word_finder.get_primary_at(self.offset) - - -def _get_name_and_pyname(self): - return ( - worder.get_name_at(self.resource, self.offset), - evaluate.eval_location(self.pymodule, self.offset), - ) - - -def get_changes(self, new_parameter): - definition_info = functionutils.DefinitionInfo.read(self.pyfunction) - definition_info.args_with_defaults.append((new_parameter, self._get_primary())) - collector = codeanalyze.ChangeCollector(self.resource.read()) - header_start, header_end = self._get_header_offsets() - body_start, body_end = sourceutils.get_body_region(self.pyfunction) - collector.add_change(header_start, header_end, definition_info.to_string()) - self._change_function_occurrences( - collector, body_start, body_end, new_parameter - ) - changes = rope.base.change.ChangeSet("Introduce parameter <%s>" % new_parameter) - change = rope.base.change.ChangeContents(self.resource, collector.get_changed()) - changes.add_change(change) - return changes - - -def _get_header_offsets(self): - lines = self.pymodule.lines - start_line = self.pyfunction.get_scope().get_start() - end_line = self.pymodule.logical_lines.logical_line_in(start_line)[1] - start = lines.get_line_start(start_line) - end = lines.get_line_end(end_line) - start = self.pymodule.source_code.find("def", start) + 4 - end = self.pymodule.source_code.rfind(":", start, end) - return start, end - - -def _change_function_occurrences( - self, collector, function_start, function_end, new_name -): - finder = occurrences.create_finder(self.project, self.name, self.pyname) - for occurrence in finder.find_occurrences(resource=self.resource): - start, end = occurrence.get_primary_range() - if function_start <= start < function_end: - collector.add_change(start, end, new_name) - -@path C:/Repos/ekr-rope/rope/refactor/ -from rope.base import pynames, evaluate, exceptions, worder -from rope.refactor.rename import Rename - - -@others -@language python -@tabwidth -4 - -class LocalToField: - @others - -def __init__(self, project, resource, offset): - self.project = project - self.resource = resource - self.offset = offset - - -def get_changes(self): - name = worder.get_name_at(self.resource, self.offset) - this_pymodule = self.project.get_pymodule(self.resource) - pyname = evaluate.eval_location(this_pymodule, self.offset) - if not self._is_a_method_local(pyname): - raise exceptions.RefactoringError( - "Convert local variable to field should be performed on \n" - "a local variable of a method." - ) - - pymodule, lineno = pyname.get_definition_location() - function_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - # Not checking redefinition - # self._check_redefinition(name, function_scope) - - new_name = self._get_field_name(function_scope.pyobject, name) - changes = Rename(self.project, self.resource, self.offset).get_changes( - new_name, resources=[self.resource] - ) - return changes - - -def pyname_at(self, offset): - pymodule = self.get_pymodule() - - def old_pyname(): - word_finder = worder.Worder(self.code, True) - expression = word_finder.get_primary_at(offset) - expression = expression.replace("\\\n", " ").replace("\n", " ") - lineno = self.code.count("\n", 0, offset) - scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - return rope.base.evaluate.eval_str(scope, expression) - - new_code = pymodule.source_code - - def new_pyname(): - newoffset = self.commenter.transfered_offset(offset) - return rope.base.evaluate.eval_location(pymodule, newoffset) - - if new_code.startswith(self.code[: offset + 1]): - return new_pyname() - result = old_pyname() - if result is None: - return new_pyname() - return result - - - -def _get_source_scope(self): - module_scope = self.source_pymodule.get_scope() - lineno = self.source_pymodule.lines.get_line_number(self.offset) - return module_scope.get_inner_scope_for_line(lineno) - - -def _check_redefinition(self, name, function_scope): - class_scope = function_scope.parent - if name in class_scope.pyobject: - raise exceptions.RefactoringError("The field %s already exists" % name) - - -def _get_field_name(self, pyfunction, name): - self_name = pyfunction.get_param_names()[0] - new_name = self_name + "." + name - return new_name - - -def _is_a_method_local(self, pyname): - pymodule, lineno = pyname.get_definition_location() - holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - parent = holding_scope.parent - return ( - isinstance(pyname, pynames.AssignedName) - and pyname in holding_scope.get_names().values() - and holding_scope.get_kind() == "Function" - and parent is not None - and parent.get_kind() == "Class" - ) - -@path C:/Repos/ekr-rope/rope/refactor/ -import warnings - -from rope.base import libutils -from rope.base import pyobjects, exceptions, change, evaluate, codeanalyze -from rope.refactor import sourceutils, occurrences, rename - - -@others -@language python -@tabwidth -4 - -class MethodObject: - @others - -def __init__(self, project, resource, offset): - self.project = project - this_pymodule = self.project.get_pymodule(resource) - pyname = evaluate.eval_location(this_pymodule, offset) - if pyname is None or not isinstance(pyname.get_object(), pyobjects.PyFunction): - raise exceptions.RefactoringError( - "Replace method with method object refactoring should be " - "performed on a function." - ) - self.pyfunction = pyname.get_object() - self.pymodule = self.pyfunction.get_module() - self.resource = self.pymodule.get_resource() - - -def get_new_class(self, name): - body = sourceutils.fix_indentation( - self._get_body(), sourceutils.get_indent(self.project) * 2 - ) - return "class {}(object):\n\n{}{}def __call__(self):\n{}".format( - name, - self._get_init(), - " " * sourceutils.get_indent(self.project), - body, - ) - - -def get_changes(self, classname=None, new_class_name=None): - if new_class_name is not None: - warnings.warn( - "new_class_name parameter is deprecated; use classname", - DeprecationWarning, - stacklevel=2, - ) - classname = new_class_name - collector = codeanalyze.ChangeCollector(self.pymodule.source_code) - start, end = sourceutils.get_body_region(self.pyfunction) - indents = sourceutils.get_indents( - self.pymodule.lines, self.pyfunction.get_scope().get_start() - ) + sourceutils.get_indent(self.project) - new_contents = " " * indents + "return {}({})()\n".format( - classname, - ", ".join(self._get_parameter_names()), - ) - collector.add_change(start, end, new_contents) - insertion = self._get_class_insertion_point() - collector.add_change( - insertion, insertion, "\n\n" + self.get_new_class(classname) - ) - changes = change.ChangeSet("Replace method with method object refactoring") - changes.add_change( - change.ChangeContents(self.resource, collector.get_changed()) - ) - return changes - - -def _get_class_insertion_point(self): - current = self.pyfunction - while current.parent != self.pymodule: - current = current.parent - end = self.pymodule.lines.get_line_end(current.get_scope().get_end()) - return min(end + 1, len(self.pymodule.source_code)) - - -def _get_body(self): - body = sourceutils.get_body(self.pyfunction) - for param in self._get_parameter_names(): - body = param + " = None\n" + body - pymod = libutils.get_string_module(self.project, body, self.resource) - pyname = pymod[param] - finder = occurrences.create_finder(self.project, param, pyname) - result = rename.rename_in_module(finder, "self." + param, pymodule=pymod) - body = result[result.index("\n") + 1 :] - return body - - -def get_insertion_lineno(self): - lines = self.goal_pymodule.lines - if self.goal_scope == self.source_scope: - line_finder = self.goal_pymodule.logical_lines - lineno = lines.get_line_number(self.offset) - lineno = line_finder.logical_line_in(lineno)[0] - root = suites.ast_suite_tree(self.goal_scope.pyobject.get_ast()) - suite = root.find_suite(lineno) - indents = sourceutils.get_indents(lines, lineno) - while self.get_scope_indents() < indents: - lineno = suite.get_start() - indents = sourceutils.get_indents(lines, lineno) - suite = suite.parent - return lineno - else: - return min(self.goal_scope.get_end() + 1, lines.length()) - - -def _get_init(self): - params = self._get_parameter_names() - indents = " " * sourceutils.get_indent(self.project) - if not params: - return "" - header = indents + "def __init__(self" - body = "" - for arg in params: - new_name = arg - if arg == "self": - new_name = "host" - header += ", %s" % new_name - body += indents * 2 + "self.{} = {}\n".format(arg, new_name) - header += "):" - return "{}\n{}\n".format(header, body) - - -def _get_parameter_names(self): - return self.pyfunction.get_param_names() - -@path C:/Repos/ekr-rope/rope/refactor/ -"""A module containing classes for move refactoring - -`create_move()` is a factory for creating move refactoring objects -based on inputs. - -""" -from rope.base import ( - pyobjects, - codeanalyze, - exceptions, - pynames, - taskhandle, - evaluate, - worder, - libutils, -) -from rope.base.change import ChangeSet, ChangeContents, MoveResource -from rope.refactor import importutils, rename, occurrences, sourceutils, functionutils -from rope.refactor.importutils.module_imports import ( - get_first_decorator_or_function_start_line, -) - - -@others -@language python -@tabwidth -4 - -def create_move(project, resource, offset=None): - """A factory for creating Move objects - - Based on `resource` and `offset`, return one of `MoveModule`, - `MoveGlobal` or `MoveMethod` for performing move refactoring. - - """ - if offset is None: - return MoveModule(project, resource) - this_pymodule = project.get_pymodule(resource) - pyname = evaluate.eval_location(this_pymodule, offset) - if pyname is not None: - pyobject = pyname.get_object() - if isinstance(pyobject, pyobjects.PyModule) or isinstance( - pyobject, pyobjects.PyPackage - ): - return MoveModule(project, pyobject.get_resource()) - if isinstance(pyobject, pyobjects.PyFunction) and isinstance( - pyobject.parent, pyobjects.PyClass - ): - return MoveMethod(project, resource, offset) - if ( - isinstance(pyobject, pyobjects.PyDefinedObject) - and isinstance(pyobject.parent, pyobjects.PyModule) - or isinstance(pyname, pynames.AssignedName) - ): - return MoveGlobal(project, resource, offset) - raise exceptions.RefactoringError( - "Move only works on global classes/functions/variables, modules and methods." - ) - - - -class MoveMethod: - """For moving methods - - It makes a new method in the destination class and changes - the body of the old method to call the new method. You can - inline the old method to change all of its occurrences. - - """ - - @others - -def __init__(self, project, resource, offset): - self.project = project - this_pymodule = self.project.get_pymodule(resource) - pyname = evaluate.eval_location(this_pymodule, offset) - self.method_name = worder.get_name_at(resource, offset) - self.pyfunction = pyname.get_object() - if self.pyfunction.get_kind() != "method": - raise exceptions.RefactoringError("Only normal methods can be moved.") - - -def get_changes( - self, - dest_attr, - new_name=None, - resources=None, - task_handle=taskhandle.NullTaskHandle(), -): - """Return the changes needed for this refactoring - - Parameters: - - - `dest_attr`: the name of the destination attribute - - `new_name`: the name of the new method; if `None` uses - the old name - - `resources` can be a list of `rope.base.resources.File` to - apply this refactoring on. If `None`, the restructuring - will be applied to all python files. - - """ - changes = ChangeSet("Moving method <%s>" % self.method_name) - if resources is None: - resources = self.project.get_python_files() - if new_name is None: - new_name = self.get_method_name() - resource1, start1, end1, new_content1 = self._get_changes_made_by_old_class( - dest_attr, new_name - ) - collector1 = codeanalyze.ChangeCollector(resource1.read()) - collector1.add_change(start1, end1, new_content1) - - resource2, start2, end2, new_content2 = self._get_changes_made_by_new_class( - dest_attr, new_name - ) - if resource1 == resource2: - collector1.add_change(start2, end2, new_content2) - else: - collector2 = codeanalyze.ChangeCollector(resource2.read()) - collector2.add_change(start2, end2, new_content2) - result = collector2.get_changed() - import_tools = importutils.ImportTools(self.project) - new_imports = self._get_used_imports(import_tools) - if new_imports: - goal_pymodule = libutils.get_string_module( - self.project, result, resource2 - ) - result = _add_imports_to_module( - import_tools, goal_pymodule, new_imports - ) - if resource2 in resources: - changes.add_change(ChangeContents(resource2, result)) - - if resource1 in resources: - changes.add_change(ChangeContents(resource1, collector1.get_changed())) - return changes - - -def get_method_name(self): - return self.method_name - - -def _get_used_imports(self, import_tools): - return importutils.get_imports(self.project, self.pyfunction) - - -def _get_changes_made_by_old_class(self, dest_attr, new_name): - pymodule = self.pyfunction.get_module() - indents = self._get_scope_indents(self.pyfunction) - body = "return self.{}.{}({})\n".format( - dest_attr, - new_name, - self._get_passed_arguments_string(), - ) - region = sourceutils.get_body_region(self.pyfunction) - return ( - pymodule.get_resource(), - region[0], - region[1], - sourceutils.fix_indentation(body, indents), - ) - - -def get_insertion_resource(self): - return self.goal_pymodule.get_resource() - - -def _get_scope_indents(self, pyobject): - pymodule = pyobject.get_module() - return sourceutils.get_indents( - pymodule.lines, pyobject.get_scope().get_start() - ) + sourceutils.get_indent(self.project) - - -def _get_changes_made_by_new_class(self, dest_attr, new_name): - old_pyclass = self.pyfunction.parent - if dest_attr not in old_pyclass: - raise exceptions.RefactoringError( - "Destination attribute <%s> not found" % dest_attr - ) - pyclass = old_pyclass[dest_attr].get_object().get_type() - if not isinstance(pyclass, pyobjects.PyClass): - raise exceptions.RefactoringError( - "Unknown class type for attribute <%s>" % dest_attr - ) - pymodule = pyclass.get_module() - resource = pyclass.get_module().get_resource() - start, end = sourceutils.get_body_region(pyclass) - pre_blanks = "\n" - if pymodule.source_code[start:end].strip() != "pass": - pre_blanks = "\n\n" - start = end - indents = self._get_scope_indents(pyclass) - body = pre_blanks + sourceutils.fix_indentation( - self.get_new_method(new_name), indents - ) - return resource, start, end, body - - -def get_new_method(self, name): - return "{}\n{}".format( - self._get_new_header(name), - sourceutils.fix_indentation( - self._get_body(), sourceutils.get_indent(self.project) - ), - ) - - -def _get_unchanged_body(self): - return sourceutils.get_body(self.pyfunction) - - -def _get_body(self, host="host"): - self_name = self._get_self_name() - body = self_name + " = None\n" + self._get_unchanged_body() - pymodule = libutils.get_string_module(self.project, body) - finder = occurrences.create_finder(self.project, self_name, pymodule[self_name]) - result = rename.rename_in_module(finder, host, pymodule=pymodule) - if result is None: - result = body - return result[result.index("\n") + 1 :] - - -def _get_self_name(self): - return self.pyfunction.get_param_names()[0] - - -def _get_new_header(self, name): - header = "def %s(self" % name - if self._is_host_used(): - header += ", host" - definition_info = functionutils.DefinitionInfo.read(self.pyfunction) - others = definition_info.arguments_to_string(1) - if others: - header += ", " + others - return header + "):" - - -def _get_passed_arguments_string(self): - result = "" - if self._is_host_used(): - result = "self" - definition_info = functionutils.DefinitionInfo.read(self.pyfunction) - others = definition_info.arguments_to_string(1) - if others: - if result: - result += ", " - result += others - return result - - -def _is_host_used(self): - return self._get_body("__old_self") != self._get_unchanged_body() - - - -class MoveGlobal: - """For moving global function and classes""" - - @others - -def get_insertion_offsets(self): - if self.goal_scope.get_kind() == "Class": - start, end = sourceutils.get_body_region(self.goal_scope.pyobject) - if self.goal_pymodule.source_code[start:end].strip() == "pass": - return start, end - lines = self.goal_pymodule.lines - start = lines.get_line_start(self.get_insertion_lineno()) - return (start, start) - - -def __init__(self, project, resource, offset): - self.project = project - this_pymodule = self.project.get_pymodule(resource) - self.old_pyname = evaluate.eval_location(this_pymodule, offset) - if self.old_pyname is None: - raise exceptions.RefactoringError( - "Move refactoring should be performed on a class/function/variable." - ) - if self._is_variable(self.old_pyname): - self.old_name = worder.get_name_at(resource, offset) - pymodule = this_pymodule - else: - self.old_name = self.old_pyname.get_object().get_name() - pymodule = self.old_pyname.get_object().get_module() - self._check_exceptional_conditions() - self.source = pymodule.get_resource() - self.tools = _MoveTools( - self.project, self.source, self.old_pyname, self.old_name - ) - self.import_tools = self.tools.import_tools - - -def _import_filter(self, stmt): - module_name = libutils.modname(self.source) - - if isinstance(stmt.import_info, importutils.NormalImport): - # Affect any statement that imports the source module - return any( - module_name == name - for name, alias in stmt.import_info.names_and_aliases - ) - elif isinstance(stmt.import_info, importutils.FromImport): - # Affect statements importing from the source package - if "." in module_name: - package_name, basename = module_name.rsplit(".", 1) - if stmt.import_info.module_name == package_name and any( - basename == name - for name, alias in stmt.import_info.names_and_aliases - ): - return True - return stmt.import_info.module_name == module_name - return False - - -def _check_exceptional_conditions(self): - if self._is_variable(self.old_pyname): - pymodule = self.old_pyname.get_definition_location()[0] - try: - pymodule.get_scope().get_name(self.old_name) - except exceptions.NameNotFoundError: - self._raise_refactoring_error() - elif not ( - isinstance(self.old_pyname.get_object(), pyobjects.PyDefinedObject) - and self._is_global(self.old_pyname.get_object()) - ): - self._raise_refactoring_error() - - -def _raise_refactoring_error(self): - raise exceptions.RefactoringError( - "Move refactoring should be performed on a global class, function " - "or variable." - ) - - -def _is_global(self, pyobject): - return pyobject.get_scope().parent == pyobject.get_module().get_scope() - - -def _is_variable(self, pyname): - return isinstance(pyname, pynames.AssignedName) - - -def get_changes( - self, dest, resources=None, task_handle=taskhandle.NullTaskHandle() -): - if resources is None: - resources = self.project.get_python_files() - if dest is None or not dest.exists(): - raise exceptions.RefactoringError("Move destination does not exist.") - if dest.is_folder() and dest.has_child("__init__.py"): - dest = dest.get_child("__init__.py") - if dest.is_folder(): - raise exceptions.RefactoringError( - "Move destination for non-modules should not be folders." - ) - if self.source == dest: - raise exceptions.RefactoringError( - "Moving global elements to the same module." - ) - return self._calculate_changes(dest, resources, task_handle) - - -def _calculate_changes(self, dest, resources, task_handle): - changes = ChangeSet("Moving global <%s>" % self.old_name) - job_set = task_handle.create_jobset("Collecting Changes", len(resources)) - for file_ in resources: - job_set.started_job(file_.path) - if file_ == self.source: - changes.add_change(self._source_module_changes(dest)) - elif file_ == dest: - changes.add_change(self._dest_module_changes(dest)) - elif self.tools.occurs_in_module(resource=file_): - pymodule = self.project.get_pymodule(file_) - # Changing occurrences - placeholder = "__rope_renaming_%s_" % self.old_name - source = self.tools.rename_in_module(placeholder, resource=file_) - should_import = source is not None - # Removing out of date imports - pymodule = self.tools.new_pymodule(pymodule, source) - source = self.import_tools.organize_imports( - pymodule, sort=False, import_filter=self._import_filter - ) - # Adding new import - if should_import: - pymodule = self.tools.new_pymodule(pymodule, source) - source, imported = importutils.add_import( - self.project, pymodule, self._new_modname(dest), self.old_name - ) - source = source.replace(placeholder, imported) - source = self.tools.new_source(pymodule, source) - if source != file_.read(): - changes.add_change(ChangeContents(file_, source)) - job_set.finished_job() - return changes - - -def _source_module_changes(self, dest): - placeholder = "__rope_moving_%s_" % self.old_name - handle = _ChangeMoveOccurrencesHandle(placeholder) - occurrence_finder = occurrences.create_finder( - self.project, self.old_name, self.old_pyname - ) - start, end = self._get_moving_region() - renamer = ModuleSkipRenamer(occurrence_finder, self.source, handle, start, end) - source = renamer.get_changed_module() - pymodule = libutils.get_string_module(self.project, source, self.source) - source = self.import_tools.organize_imports(pymodule, sort=False) - if handle.occurred: - pymodule = libutils.get_string_module(self.project, source, self.source) - # Adding new import - source, imported = importutils.add_import( - self.project, pymodule, self._new_modname(dest), self.old_name - ) - source = source.replace(placeholder, imported) - return ChangeContents(self.source, source) - - -def _new_modname(self, dest): - return libutils.modname(dest) - - -def get_scope_indents(self): - if self.goal_scope.get_kind() == "Module": - return 0 - return ( - sourceutils.get_indents( - self.goal_pymodule.lines, self.goal_scope.get_start() - ) - + 4 - ) - - -def _dest_module_changes(self, dest): - # Changing occurrences - pymodule = self.project.get_pymodule(dest) - source = self.tools.rename_in_module(self.old_name, pymodule) - pymodule = self.tools.new_pymodule(pymodule, source) - - moving, imports = self._get_moving_element_with_imports() - pymodule, has_changed = self._add_imports2(pymodule, imports) - - module_with_imports = self.import_tools.module_imports(pymodule) - source = pymodule.source_code - lineno = 0 - if module_with_imports.imports: - lineno = module_with_imports.imports[-1].end_line - 1 - else: - while lineno < pymodule.lines.length() and pymodule.lines.get_line( - lineno + 1 - ).lstrip().startswith("#"): - lineno += 1 - if lineno > 0: - cut = pymodule.lines.get_line_end(lineno) + 1 - result = source[:cut] + "\n\n" + moving + source[cut:] - else: - result = moving + source - - # Organizing imports - source = result - pymodule = libutils.get_string_module(self.project, source, dest) - source = self.import_tools.organize_imports(pymodule, sort=False, unused=False) - # Remove unused imports of the old module - pymodule = libutils.get_string_module(self.project, source, dest) - source = self.import_tools.organize_imports( - pymodule, - sort=False, - selfs=False, - unused=True, - import_filter=self._import_filter, - ) - return ChangeContents(dest, source) - - -def _get_moving_element_with_imports(self): - return moving_code_with_imports( - self.project, self.source, self._get_moving_element() - ) - - -def _get_module_with_imports(self, source_code, resource): - pymodule = libutils.get_string_module(self.project, source_code, resource) - return self.import_tools.module_imports(pymodule) - - -def _get_moving_element(self): - start, end = self._get_moving_region() - moving = self.source.read()[start:end] - return moving.rstrip() + "\n" - - -def _get_moving_region(self): - pymodule = self.project.get_pymodule(self.source) - lines = pymodule.lines - if self._is_variable(self.old_pyname): - logical_lines = pymodule.logical_lines - lineno = logical_lines.logical_line_in( - self.old_pyname.get_definition_location()[1] - )[0] - start = lines.get_line_start(lineno) - end_line = logical_lines.logical_line_in(lineno)[1] - else: - node = self.old_pyname.get_object().ast_node - start = lines.get_line_start( - get_first_decorator_or_function_start_line(node) - ) - end_line = self.old_pyname.get_object().get_scope().get_end() - - # Include comment lines before the definition - start_line = lines.get_line_number(start) - while start_line > 1 and lines.get_line(start_line - 1).startswith("#"): - start_line -= 1 - start = lines.get_line_start(start_line) - - while end_line < lines.length() and lines.get_line(end_line + 1).strip() == "": - end_line += 1 - end = min(lines.get_line_end(end_line) + 1, len(pymodule.source_code)) - return start, end - - -def _add_imports2(self, pymodule, new_imports): - source = self.tools.add_imports(pymodule, new_imports) - if source is None: - return pymodule, False - else: - resource = pymodule.get_resource() - pymodule = libutils.get_string_module(self.project, source, resource) - return pymodule, True - - - -class MoveModule: - """For moving modules and packages""" - - @others - -def __init__(self, project, resource): - self.project = project - if not resource.is_folder() and resource.name == "__init__.py": - resource = resource.parent - if resource.is_folder() and not resource.has_child("__init__.py"): - raise exceptions.RefactoringError("Cannot move non-package folder.") - dummy_pymodule = libutils.get_string_module(self.project, "") - self.old_pyname = pynames.ImportedModule(dummy_pymodule, resource=resource) - self.source = self.old_pyname.get_object().get_resource() - if self.source.is_folder(): - self.old_name = self.source.name - else: - self.old_name = self.source.name[:-3] - self.tools = _MoveTools( - self.project, self.source, self.old_pyname, self.old_name - ) - self.import_tools = self.tools.import_tools - - -def get_changes( - self, dest, resources=None, task_handle=taskhandle.NullTaskHandle() -): - if resources is None: - resources = self.project.get_python_files() - if dest is None or not dest.is_folder(): - raise exceptions.RefactoringError( - "Move destination for modules should be packages." - ) - return self._calculate_changes(dest, resources, task_handle) - - -def _calculate_changes(self, dest, resources, task_handle): - changes = ChangeSet("Moving module <%s>" % self.old_name) - job_set = task_handle.create_jobset("Collecting changes", len(resources)) - for module in resources: - job_set.started_job(module.path) - if module == self.source: - self._change_moving_module(changes, dest) - else: - source = self._change_occurrences_in_module(dest, resource=module) - if source is not None: - changes.add_change(ChangeContents(module, source)) - job_set.finished_job() - if self.project == self.source.project: - changes.add_change(MoveResource(self.source, dest.path)) - return changes - - -def get_blank_lines(self): - if self.goal_scope.get_kind() == "Module": - base_blanks = 2 - if self.goal_pymodule.source_code.strip() == "": - base_blanks = 0 - if self.goal_scope.get_kind() == "Class": - base_blanks = 1 - if self.goal_scope.get_kind() == "Function": - base_blanks = 0 - if self.goal_scope == self.source_scope: - return (0, base_blanks) - return (base_blanks, 0) - - -def _new_modname(self, dest): - destname = libutils.modname(dest) - if destname: - return destname + "." + self.old_name - return self.old_name - - -def _new_import(self, dest): - return importutils.NormalImport([(self._new_modname(dest), None)]) - - -def _change_moving_module(self, changes, dest): - if not self.source.is_folder(): - pymodule = self.project.get_pymodule(self.source) - source = self.import_tools.relatives_to_absolutes(pymodule) - pymodule = self.tools.new_pymodule(pymodule, source) - source = self._change_occurrences_in_module(dest, pymodule) - source = self.tools.new_source(pymodule, source) - if source != self.source.read(): - changes.add_change(ChangeContents(self.source, source)) - - -def _change_occurrences_in_module(self, dest, pymodule=None, resource=None): - if not self.tools.occurs_in_module(pymodule=pymodule, resource=resource): - return - if pymodule is None: - pymodule = self.project.get_pymodule(resource) - new_name = self._new_modname(dest) - module_imports = importutils.get_module_imports(self.project, pymodule) - changed = False - source = None - if libutils.modname(dest): - changed = self._change_import_statements(dest, new_name, module_imports) - if changed: - source = module_imports.get_changed_source() - source = self.tools.new_source(pymodule, source) - pymodule = self.tools.new_pymodule(pymodule, source) - - new_import = self._new_import(dest) - source = self.tools.rename_in_module( - new_name, - imports=True, - pymodule=pymodule, - resource=resource if not changed else None, - ) - should_import = self.tools.occurs_in_module( - pymodule=pymodule, resource=resource, imports=False - ) - pymodule = self.tools.new_pymodule(pymodule, source) - source = self.tools.remove_old_imports(pymodule) - if should_import: - pymodule = self.tools.new_pymodule(pymodule, source) - source = self.tools.add_imports(pymodule, [new_import]) - source = self.tools.new_source(pymodule, source) - if source is not None and source != pymodule.resource.read(): - return source - return None - - -def _change_import_statements(self, dest, new_name, module_imports): - moving_module = self.source - parent_module = moving_module.parent - - changed = False - for import_stmt in module_imports.imports: - if not any( - name_and_alias[0] == self.old_name - for name_and_alias in import_stmt.import_info.names_and_aliases - ) and not any( - name_and_alias[0] == libutils.modname(self.source) - for name_and_alias in import_stmt.import_info.names_and_aliases - ): - continue - - # Case 1: Look for normal imports of the moving module. - if isinstance(import_stmt.import_info, importutils.NormalImport): - continue - - # Case 2: The moving module is from-imported. - changed = ( - self._handle_moving_in_from_import_stmt( - dest, import_stmt, module_imports, parent_module - ) - or changed - ) - - # Case 3: Names are imported from the moving module. - context = importutils.importinfo.ImportContext(self.project, None) - if ( - not import_stmt.import_info.is_empty() - and import_stmt.import_info.get_imported_resource(context) - == moving_module - ): - import_stmt.import_info = importutils.FromImport( - new_name, - import_stmt.import_info.level, - import_stmt.import_info.names_and_aliases, - ) - changed = True - - return changed - - -def _handle_moving_in_from_import_stmt( - self, dest, import_stmt, module_imports, parent_module -): - changed = False - context = importutils.importinfo.ImportContext(self.project, None) - if import_stmt.import_info.get_imported_resource(context) == parent_module: - imports = import_stmt.import_info.names_and_aliases - new_imports = [] - for name, alias in imports: - # The moving module was imported. - if name == self.old_name: - changed = True - new_import = importutils.FromImport( - libutils.modname(dest), 0, [(self.old_name, alias)] - ) - module_imports.add_import(new_import) - else: - new_imports.append((name, alias)) - - # Update the imports if the imported names were changed. - if new_imports != imports: - changed = True - if new_imports: - import_stmt.import_info = importutils.FromImport( - import_stmt.import_info.module_name, - import_stmt.import_info.level, - new_imports, - ) - else: - import_stmt.empty_import() - return changed - - - -class _ChangeMoveOccurrencesHandle: - @others - -def __init__(self, new_name): - self.new_name = new_name - self.occurred = False - - -def occurred_inside_skip(self, change_collector, occurrence): - pass - - -def occurred_outside_skip(self, change_collector, occurrence): - start, end = occurrence.get_primary_range() - change_collector.add_change(start, end, self.new_name) - self.occurred = True - - - -def get_package(self): - primary = self.primary - if self.primary is None: - return self.pycore.project.get_source_folders()[0] - if isinstance(primary.get_object(), pyobjects.PyPackage): - return primary.get_object().get_resource() - raise exceptions.RefactoringError( - "A module/package can be only created in a package." - ) - - -class _MoveTools: - @others - -def __init__(self, project, source, pyname, old_name): - self.project = project - self.source = source - self.old_pyname = pyname - self.old_name = old_name - self.import_tools = importutils.ImportTools(self.project) - - -def remove_old_imports(self, pymodule): - old_source = pymodule.source_code - module_with_imports = self.import_tools.module_imports(pymodule) - - class CanSelect: - changed = False - old_name = self.old_name - old_pyname = self.old_pyname - - @others - can_select = CanSelect() - module_with_imports.filter_names(can_select) - new_source = module_with_imports.get_changed_source() - if old_source != new_source: - return new_source - - -def __call__(self, name): - try: - if ( - name == self.old_name - and pymodule[name].get_object() == self.old_pyname.get_object() - ): - self.changed = True - return False - except exceptions.AttributeNotFoundError: - pass - return True - - -def rename_in_module(self, new_name, pymodule=None, imports=False, resource=None): - occurrence_finder = self._create_finder(imports) - source = rename.rename_in_module( - occurrence_finder, - new_name, - replace_primary=True, - pymodule=pymodule, - resource=resource, - ) - return source - - -def occurs_in_module(self, pymodule=None, resource=None, imports=True): - finder = self._create_finder(imports) - for occurrence in finder.find_occurrences(pymodule=pymodule, resource=resource): - return True - return False - - -def _create_finder(self, imports): - return occurrences.create_finder( - self.project, - self.old_name, - self.old_pyname, - imports=imports, - keywords=False, - ) - - -def new_pymodule(self, pymodule, source): - if source is not None: - return libutils.get_string_module( - self.project, source, pymodule.get_resource() - ) - return pymodule - - -def new_source(self, pymodule, source): - if source is None: - return pymodule.source_code - return source - - -def add_imports(self, pymodule, new_imports): - return _add_imports_to_module(self.import_tools, pymodule, new_imports) - - - -def primary_is_found(self): - return self.goal_scope is not None - - -def _add_imports_to_module(import_tools, pymodule, new_imports): - module_with_imports = import_tools.module_imports(pymodule) - for new_import in new_imports: - module_with_imports.add_import(new_import) - return module_with_imports.get_changed_source() - - - -def moving_code_with_imports(project, resource, source): - import_tools = importutils.ImportTools(project) - pymodule = libutils.get_string_module(project, source, resource) - - # Strip comment prefix, if any. These need to stay before the moving - # section, but imports would be added between them. - lines = codeanalyze.SourceLinesAdapter(source) - start = 1 - while start < lines.length() and lines.get_line(start).startswith("#"): - start += 1 - moving_prefix = source[: lines.get_line_start(start)] - pymodule = libutils.get_string_module( - project, source[lines.get_line_start(start) :], resource - ) - - origin = project.get_pymodule(resource) - - imports = [stmt.import_info for stmt in import_tools.module_imports(origin).imports] - - back_names = [name for name in origin if name not in pymodule] - imports.append(import_tools.get_from_import(resource, back_names)) - - source = _add_imports_to_module(import_tools, pymodule, imports) - pymodule = libutils.get_string_module(project, source, resource) - - source = import_tools.relatives_to_absolutes(pymodule) - pymodule = libutils.get_string_module(project, source, resource) - source = import_tools.organize_imports(pymodule, selfs=False) - pymodule = libutils.get_string_module(project, source, resource) - - # extracting imports after changes - module_imports = import_tools.module_imports(pymodule) - imports = [import_stmt.import_info for import_stmt in module_imports.imports] - start = 1 - if module_imports.imports: - start = module_imports.imports[-1].end_line - lines = codeanalyze.SourceLinesAdapter(source) - while start < lines.length() and not lines.get_line(start).strip(): - start += 1 - - # Reinsert the prefix which was removed at the beginning - moving = moving_prefix + source[lines.get_line_start(start) :] - return moving, imports - - - -class ModuleSkipRenamerHandle: - def occurred_outside_skip(self, change_collector, occurrence): - pass - - def occurred_inside_skip(self, change_collector, occurrence): - pass - - - -class ModuleSkipRenamer: - """Rename occurrences in a module - - This class can be used when you want to treat a region in a file - separately from other parts when renaming. - - """ - - @others - -def __init__( - self, - occurrence_finder, - resource, - handle=None, - skip_start=0, - skip_end=0, - replacement="", -): - """Constructor - - if replacement is `None` the region is not changed. Otherwise - it is replaced with `replacement`. - - """ - self.occurrence_finder = occurrence_finder - self.resource = resource - self.skip_start = skip_start - self.skip_end = skip_end - self.replacement = replacement - self.handle = handle - if self.handle is None: - self.handle = ModuleSkipRenamerHandle() - - -def get_changed_module(self): - source = self.resource.read() - change_collector = codeanalyze.ChangeCollector(source) - if self.replacement is not None: - change_collector.add_change( - self.skip_start, self.skip_end, self.replacement - ) - for occurrence in self.occurrence_finder.find_occurrences(self.resource): - start, end = occurrence.get_primary_range() - if self.skip_start <= start < self.skip_end: - self.handle.occurred_inside_skip(change_collector, occurrence) - else: - self.handle.occurred_outside_skip(change_collector, occurrence) - result = change_collector.get_changed() - if result is not None and result != source: - return result - -@path C:/Repos/ekr-rope/rope/refactor/ -"""This module can be used for performing cross-project refactorings - -See the "cross-project refactorings" section of ``docs/library.rst`` -file. - -""" - -from rope.base import resources, libutils - - -@others -@language python -@tabwidth -4 - -class MultiProjectRefactoring: - @others - -def __init__(self, refactoring, projects, addpath=True): - """Create a multiproject proxy for the main refactoring - - `projects` are other project. - - """ - self.refactoring = refactoring - self.projects = projects - self.addpath = addpath - - -def __call__(self, project, *args, **kwds): - """Create the refactoring""" - return _MultiRefactoring( - self.refactoring, self.projects, self.addpath, project, *args, **kwds - ) - - - -def element_already_exists(self): - if self.pyname is None or isinstance(self.pyname, pynames.UnboundName): - return False - return self.get_name() in self.goal_scope.get_defined_names() - - -class _MultiRefactoring: - @others - -def __init__(self, refactoring, other_projects, addpath, project, *args, **kwds): - self.refactoring = refactoring - self.projects = [project] + other_projects - for other_project in other_projects: - for folder in self.project.get_source_folders(): - other_project.get_prefs().add("python_path", folder.real_path) - self.refactorings = [] - for other in self.projects: - args, kwds = self._resources_for_args(other, args, kwds) - self.refactorings.append(self.refactoring(other, *args, **kwds)) - - -def get_all_changes(self, *args, **kwds): - """Get a project to changes dict""" - result = [] - for project, refactoring in zip(self.projects, self.refactorings): - args, kwds = self._resources_for_args(project, args, kwds) - result.append((project, refactoring.get_changes(*args, **kwds))) - return result - - -def __getattr__(self, name): - return getattr(self.main_refactoring, name) - - -def _resources_for_args(self, project, args, kwds): - newargs = [self._change_project_resource(project, arg) for arg in args] - newkwds = { - name: self._change_project_resource(project, value) - for name, value in kwds.items() - } - return newargs, newkwds - - -def _change_project_resource(self, project, obj): - if isinstance(obj, resources.Resource) and obj.project != project: - return libutils.path_to_resource(project, obj.real_path) - return obj - - -@property -def project(self): - return self.projects[0] - - -@property -def main_refactoring(self): - return self.refactorings[0] - - - -def perform(project_changes): - for project, changes in project_changes: - project.do(changes) - -@path C:/Repos/ekr-rope/rope/refactor/ -"""Find occurrences of a name in a project. - -This module consists of a `Finder` that finds all occurrences of a name -in a project. The `Finder.find_occurrences()` method is a generator that -yields `Occurrence` instances for each occurrence of the name. To create -a `Finder` object, use the `create_finder()` function: - - finder = occurrences.create_finder(project, 'foo', pyname) - for occurrence in finder.find_occurrences(): - pass - -It's possible to filter the occurrences. They can be specified when -calling the `create_finder()` function. - - * `only_calls`: If True, return only those instances where the name is - a function that's being called. - - * `imports`: If False, don't return instances that are in import - statements. - - * `unsure`: If a predicate function, return instances where we don't - know what the name references. It also filters based on the - predicate function. - - * `docs`: If True, it will search for occurrences in regions normally - ignored. E.g., strings and comments. - - * `in_hierarchy`: If True, it will find occurrences if the name is in - the class's hierarchy. - - * `instance`: Used only when you want implicit interfaces to be - considered. - - * `keywords`: If False, don't return instances that are the names of keyword - arguments -""" - -import ast -import re - -from rope.base import codeanalyze -from rope.base import evaluate -from rope.base import exceptions -from rope.base import pynames -from rope.base import pyobjects -from rope.base import utils -from rope.base import worder - - -@others -@language python -@tabwidth -4 - -def get_name(self): - return worder.get_name_at(self.resource, self.offset) - - - -class Finder: - """For finding occurrences of a name - - The constructor takes a `filters` argument. It should be a list - of functions that take a single argument. For each possible - occurrence, these functions are called in order with the an - instance of `Occurrence`: - - * If it returns `None` other filters are tried. - * If it returns `True`, the occurrence will be a match. - * If it returns `False`, the occurrence will be skipped. - * If all of the filters return `None`, it is skipped also. - - """ - - @others - -def __init__(self, project, name, filters=[lambda o: True], docs=False): - self.project = project - self.name = name - self.docs = docs - self.filters = filters - self._textual_finder = _TextualFinder(name, docs=docs) - - -def find_occurrences(self, resource=None, pymodule=None): - """Generate `Occurrence` instances""" - tools = _OccurrenceToolsCreator( - self.project, resource=resource, pymodule=pymodule, docs=self.docs - ) - for offset in self._textual_finder.find_offsets(tools.source_code): - occurrence = Occurrence(tools, offset) - for filter in self.filters: - result = filter(occurrence) - if result is None: - continue - if result: - yield occurrence - break - - - -def create_finder( - project, - name, - pyname, - only_calls=False, - imports=True, - unsure=None, - docs=False, - instance=None, - in_hierarchy=False, - keywords=True, -): - """A factory for `Finder` - - Based on the arguments it creates a list of filters. `instance` - argument is needed only when you want implicit interfaces to be - considered. - - """ - pynames_ = {pyname} - filters = [] - if only_calls: - filters.append(CallsFilter()) - if not imports: - filters.append(NoImportsFilter()) - if not keywords: - filters.append(NoKeywordsFilter()) - if isinstance(instance, pynames.ParameterName): - for pyobject in instance.get_objects(): - try: - pynames_.add(pyobject[name]) - except exceptions.AttributeNotFoundError: - pass - for pyname in pynames_: - filters.append(PyNameFilter(pyname)) - if in_hierarchy: - filters.append(InHierarchyFilter(pyname)) - if unsure: - filters.append(UnsureFilter(unsure)) - return Finder(project, name, filters=filters, docs=docs) - - - -class Occurrence: - @others - -def __init__(self, tools, offset): - self.tools = tools - self.offset = offset - self.resource = tools.resource - - -@utils.saveit -def get_word_range(self): - return self.tools.word_finder.get_word_range(self.offset) - - -@utils.saveit -def get_primary_range(self): - return self.tools.word_finder.get_primary_range(self.offset) - - -@utils.saveit -def get_pyname(self): - try: - return self.tools.name_finder.get_pyname_at(self.offset) - except exceptions.BadIdentifierError: - pass - - -@utils.saveit -def get_primary_and_pyname(self): - try: - return self.tools.name_finder.get_primary_and_pyname_at(self.offset) - except exceptions.BadIdentifierError: - pass - - -class _Commenter: - @others - -class _FunctionGenerationInfo(_GenerationInfo): - @others - -@utils.saveit -def is_in_import_statement(self): - return self.tools.word_finder.is_from_statement( - self.offset - ) or self.tools.word_finder.is_import_statement(self.offset) - - -def is_called(self): - return self.tools.word_finder.is_a_function_being_called(self.offset) - - -def is_defined(self): - return self.tools.word_finder.is_a_class_or_function_name_in_header(self.offset) - - -def is_a_fixed_primary(self): - return self.tools.word_finder.is_a_class_or_function_name_in_header( - self.offset - ) or self.tools.word_finder.is_a_name_after_from_import(self.offset) - - -def is_written(self): - return self.tools.word_finder.is_assigned_here(self.offset) - - -def is_unsure(self): - return unsure_pyname(self.get_pyname()) - - -def is_function_keyword_parameter(self): - return self.tools.word_finder.is_function_keyword_parameter(self.offset) - - -@property -@utils.saveit -def lineno(self): - offset = self.get_word_range()[0] - return self.tools.pymodule.lines.get_line_number(offset) - - - -def same_pyname(expected, pyname): - """Check whether `expected` and `pyname` are the same""" - if expected is None or pyname is None: - return False - if expected == pyname: - return True - if type(expected) not in (pynames.ImportedModule, pynames.ImportedName) and type( - pyname - ) not in (pynames.ImportedModule, pynames.ImportedName): - return False - return ( - expected.get_definition_location() == pyname.get_definition_location() - and expected.get_object() == pyname.get_object() - ) - - - -def unsure_pyname(pyname, unbound=True): - """Return `True` if we don't know what this name references""" - if pyname is None: - return True - if unbound and not isinstance(pyname, pynames.UnboundName): - return False - if pyname.get_object() == pyobjects.get_unknown(): - return True - - - -def _get_goal_scope(self): - if self.is_constructor(): - return self.pyname.get_object().get_scope() - if self.is_instance(): - return self.pyname.get_object().get_type().get_scope() - if self.primary is None: - return self._get_source_scope() - pyobject = self.primary.get_object() - if isinstance(pyobject, pyobjects.PyDefinedObject): - return pyobject.get_scope() - elif isinstance(pyobject.get_type(), pyobjects.PyClass): - return pyobject.get_type().get_scope() - - -class PyNameFilter: - """For finding occurrences of a name.""" - - @others - -def __init__(self, pyname): - self.pyname = pyname - - -def __call__(self, occurrence): - if same_pyname(self.pyname, occurrence.get_pyname()): - return True - - - -class InHierarchyFilter: - """Finds the occurrence if the name is in the class's hierarchy.""" - - @others - -def __init__(self, pyname, implementations_only=False): - self.pyname = pyname - self.impl_only = implementations_only - self.pyclass = self._get_containing_class(pyname) - if self.pyclass is not None: - self.name = pyname.get_object().get_name() - self.roots = self._get_root_classes(self.pyclass, self.name) - else: - self.roots = None - - -def __call__(self, occurrence): - if self.roots is None: - return - pyclass = self._get_containing_class(occurrence.get_pyname()) - if pyclass is not None: - roots = self._get_root_classes(pyclass, self.name) - if self.roots.intersection(roots): - return True - - -def _get_containing_class(self, pyname): - if isinstance(pyname, pynames.DefinedName): - scope = pyname.get_object().get_scope() - parent = scope.parent - if parent is not None and parent.get_kind() == "Class": - return parent.pyobject - - -def _get_root_classes(self, pyclass, name): - if self.impl_only and pyclass == self.pyclass: - return {pyclass} - result = set() - for superclass in pyclass.get_superclasses(): - if name in superclass: - result.update(self._get_root_classes(superclass, name)) - if not result: - return {pyclass} - return result - - - -class UnsureFilter: - """Occurrences where we don't knoow what the name references.""" - - @others - -def __init__(self, unsure): - self.unsure = unsure - - -def element_already_exists(self): - if self.pyname is None or isinstance(self.pyname, pynames.UnboundName): - return False - return self.get_name() in self.goal_scope.get_defined_names() - - -def __call__(self, occurrence): - if occurrence.is_unsure() and self.unsure(occurrence): - return True - - - -class NoImportsFilter: - """Don't include import statements as occurrences.""" - - def __call__(self, occurrence): - if occurrence.is_in_import_statement(): - return False - - - -class CallsFilter: - """Filter out non-call occurrences.""" - - def __call__(self, occurrence): - if not occurrence.is_called(): - return False - - - -class NoKeywordsFilter: - """Filter out keyword parameters.""" - - def __call__(self, occurrence): - if occurrence.is_function_keyword_parameter(): - return False - - - -class _TextualFinder: - @others - -def __init__(self, name, docs=False): - self.name = name - self.docs = docs - self.comment_pattern = _TextualFinder.any("comment", [r"#[^\n]*"]) - self.string_pattern = _TextualFinder.any( - "string", [codeanalyze.get_string_pattern()] - ) - self.f_string_pattern = _TextualFinder.any( - "fstring", [codeanalyze.get_formatted_string_pattern()] - ) - self.pattern = self._get_occurrence_pattern(self.name) - - -def find_offsets(self, source): - if not self._fast_file_query(source): - return - if self.docs: - searcher = self._normal_search - else: - searcher = self._re_search - yield from searcher(source) - - -def _re_search(self, source): - for match in self.pattern.finditer(source): - if match.groupdict()["occurrence"]: - yield match.start("occurrence") - elif match.groupdict()["fstring"]: - f_string = match.groupdict()["fstring"] - for occurrence_node in self._search_in_f_string(f_string): - yield match.start("fstring") + occurrence_node.col_offset - - -def _search_in_f_string(self, f_string): - tree = ast.parse(f_string) - for node in ast.walk(tree): - if isinstance(node, ast.Name) and node.id == self.name: - yield node - - -def _normal_search(self, source): - current = 0 - while True: - try: - found = source.index(self.name, current) - current = found + len(self.name) - if (found == 0 or not self._is_id_char(source[found - 1])) and ( - current == len(source) or not self._is_id_char(source[current]) - ): - yield found - except ValueError: - break - - -def is_static_method(self): - return self.primary is not None and isinstance( - self.primary.get_object(), pyobjects.PyClass - ) - - -def _is_id_char(self, c): - return c.isalnum() or c == "_" - - -def _fast_file_query(self, source): - try: - source.index(self.name) - return True - except ValueError: - return False - - -def _get_source(self, resource, pymodule): - if resource is not None: - return resource.read() - else: - return pymodule.source_code - - -def _get_occurrence_pattern(self, name): - occurrence_pattern = _TextualFinder.any("occurrence", ["\\b" + name + "\\b"]) - pattern = re.compile( - occurrence_pattern - + "|" - + self.comment_pattern - + "|" - + self.string_pattern - + "|" - + self.f_string_pattern - ) - return pattern - - -@staticmethod -def any(name, list_): - return "(?P<%s>" % name + "|".join(list_) + ")" - - - -class _OccurrenceToolsCreator: - @others - -def __init__(self, project, resource=None, pymodule=None, docs=False): - self.project = project - self.__resource = resource - self.__pymodule = pymodule - self.docs = docs - - -@property -@utils.saveit -def name_finder(self): - return evaluate.ScopeNameFinder(self.pymodule) - - -@property -@utils.saveit -def source_code(self): - return self.pymodule.source_code - - -@property -@utils.saveit -def word_finder(self): - return worder.Worder(self.source_code, self.docs) - - -def is_method(self): - return self.primary is not None and isinstance( - self.primary.get_object().get_type(), pyobjects.PyClass - ) - - -@property -@utils.saveit -def resource(self): - if self.__resource is not None: - return self.__resource - if self.__pymodule is not None: - return self.__pymodule.resource - - -@property -@utils.saveit -def pymodule(self): - if self.__pymodule is not None: - return self.__pymodule - return self.project.get_pymodule(self.resource) - -@path C:/Repos/ekr-rope/rope/refactor/ -import collections -import numbers -import re -import warnings -from itertools import chain - -from rope.base import ast, codeanalyze, exceptions - -### -try: - basestring -except NameError: - basestring = (str, bytes) - -COMMA_IN_WITH_PATTERN = re.compile(r"\(.*?\)|(,)") - - -@others -@language python -@tabwidth -4 - -def get_patched_ast(source, sorted_children=False): - """Adds ``region`` and ``sorted_children`` fields to nodes - - Adds ``sorted_children`` field only if `sorted_children` is True. - - """ - return patch_ast(ast.parse(source), source, sorted_children) - - - -def patch_ast(node, source, sorted_children=False): - """Patches the given node - - After calling, each node in `node` will have a new field named - `region` that is a tuple containing the start and end offsets - of the code that generated it. - - If `sorted_children` is true, a `sorted_children` field will - be created for each node, too. It is a list containing child - nodes as well as whitespaces and comments that occur between - them. - - """ - if hasattr(node, "region"): - return node - walker = _PatchingASTWalker(source, children=sorted_children) - ast.call_for_nodes(node, walker) - return node - - - -def node_region(patched_ast_node): - """Get the region of a patched ast node""" - return patched_ast_node.region - - - -def write_ast(patched_ast_node): - """Extract source form a patched AST node with `sorted_children` field - - If the node is patched with sorted_children turned off you can use - `node_region` function for obtaining code using module source code. - """ - result = [] - for child in patched_ast_node.sorted_children: - if isinstance(child, ast.AST): - result.append(write_ast(child)) - else: - result.append(child) - return "".join(result) - - - -class MismatchedTokenError(exceptions.RopeError): - pass - - - -class _PatchingASTWalker: - @others - -def __init__(self, source, children=False): - self.source = _Source(source) - self.children = children - self.lines = codeanalyze.SourceLinesAdapter(source) - self.children_stack = [] - - -def is_constructor(self): - return self.pyname is not None and isinstance( - self.pyname.get_object(), pyobjects.PyClass - ) - - -Number = object() -String = object() -semicolon_or_as_in_except = object() -exec_open_paren_or_space = object() -exec_close_paren_or_space = object() -exec_in_or_comma = object() -with_or_comma_context_manager = object() -empty_tuple = object() - - -def __call__(self, node): - method = getattr(self, "_" + node.__class__.__name__, None) - if method is not None: - return method(node) - # ???: Unknown node; what should we do here? - warnings.warn( - "Unknown node type <%s>; please report!" % node.__class__.__name__, - RuntimeWarning, - ) - node.region = (self.source.offset, self.source.offset) - if self.children: - node.sorted_children = ast.get_children(node) - - -def _handle(self, node, base_children, eat_parens=False, eat_spaces=False): - if hasattr(node, "region"): - # ???: The same node was seen twice; what should we do? - warnings.warn( - "Node <%s> has been already patched; please report!" - % node.__class__.__name__, - RuntimeWarning, - ) - return - - base_children = collections.deque(base_children) - self.children_stack.append(base_children) - children = collections.deque() - formats = [] - suspected_start = self.source.offset - start = suspected_start - first_token = True - while base_children: - child = base_children.popleft() - if child is None: - continue - offset = self.source.offset - if isinstance(child, ast.AST): - ast.call_for_nodes(child, self) - token_start = child.region[0] - else: - if child is self.String: - region = self.source.consume_string( - end=self._find_next_statement_start() - ) - elif child is self.Number: - region = self.source.consume_number() - elif child == self.empty_tuple: - region = self.source.consume_empty_tuple() - elif child == "!=": - # INFO: This has been added to handle deprecated ``<>`` - region = self.source.consume_not_equal() - elif child == self.semicolon_or_as_in_except: - # INFO: This has been added to handle deprecated - # semicolon in except - region = self.source.consume_except_as_or_semicolon() - elif child == self.exec_open_paren_or_space: - # These three cases handle the differences between - # the deprecated exec statement and the exec - # function. - region = self.source.consume_exec_open_paren_or_space() - elif child == self.exec_in_or_comma: - region = self.source.consume_exec_in_or_comma() - elif child == self.exec_close_paren_or_space: - region = self.source.consume_exec_close_paren_or_space() - elif child == self.with_or_comma_context_manager: - region = self.source.consume_with_or_comma_context_manager() - else: - if hasattr(ast, "JoinedStr") and isinstance( - node, (ast.JoinedStr, ast.FormattedValue) - ): - region = self.source.consume_joined_string(child) - else: - region = self.source.consume(child) - child = self.source[region[0] : region[1]] - token_start = region[0] - if not first_token: - formats.append(self.source[offset:token_start]) - if self.children: - children.append(self.source[offset:token_start]) - else: - first_token = False - start = token_start - if self.children: - children.append(child) - start = self._handle_parens(children, start, formats) - if eat_parens: - start = self._eat_surrounding_parens(children, suspected_start, start) - if eat_spaces: - if self.children: - children.appendleft(self.source[0:start]) - end_spaces = self.source[self.source.offset :] - self.source.consume(end_spaces) - if self.children: - children.append(end_spaces) - start = 0 - if self.children: - node.sorted_children = children - node.region = (start, self.source.offset) - self.children_stack.pop() - - -def _handle_parens(self, children, start, formats): - """Changes `children` and returns new start""" - opens, closes = self._count_needed_parens(formats) - old_end = self.source.offset - new_end = None - for i in range(closes): - new_end = self.source.consume(")")[1] - if new_end is not None: - if self.children: - children.append(self.source[old_end:new_end]) - new_start = start - for i in range(opens): - new_start = self.source.rfind_token("(", 0, new_start) - if new_start != start: - if self.children: - children.appendleft(self.source[new_start:start]) - start = new_start - return start - - -def _eat_surrounding_parens(self, children, suspected_start, start): - index = self.source.rfind_token("(", suspected_start, start) - if index is not None: - old_start = start - old_offset = self.source.offset - start = index - if self.children: - children.appendleft(self.source[start + 1 : old_start]) - children.appendleft("(") - token_start, token_end = self.source.consume(")") - if self.children: - children.append(self.source[old_offset:token_start]) - children.append(")") - return start - - -def _count_needed_parens(self, children): - start = 0 - opens = 0 - for child in children: - if not isinstance(child, basestring): - continue - if child == "" or child[0] in "'\"": - continue - index = 0 - while index < len(child): - if child[index] == ")": - if opens > 0: - opens -= 1 - else: - start += 1 - if child[index] == "(": - opens += 1 - if child[index] == "#": - try: - index = child.index("\n", index) - except ValueError: - break - index += 1 - return start, opens - - -def _find_next_statement_start(self): - for children in reversed(self.children_stack): - for child in children: - if isinstance(child, ast.stmt): - return child.col_offset + self.lines.get_line_start(child.lineno) - return len(self.source.source) - - -def _join(self, iterable, separator): - iterable = iter(iterable) - try: - yield next(iterable) - except StopIteration: - return - for child in iterable: - yield separator - yield child - - -def _flatten_keywords(self, iterable): - iterable = ([attr, "=", pattern] for attr, pattern in iterable) - iterable = self._join(iterable, separator=[","]) - return chain.from_iterable(iterable) - - -def _child_nodes(self, nodes, separator): - return list(self._join(nodes, separator=separator)) - - -def is_instance(self): - if self.pyname is None: - return False - pyobject = self.pyname.get_object() - return isinstance(pyobject.get_type(), pyobjects.PyClass) - - -_operators = { - "And": "and", - "Or": "or", - "Add": "+", - "Sub": "-", - "Mult": "*", - "Div": "/", - "Mod": "%", - "Pow": "**", - "MatMult": "@", - "LShift": "<<", - "RShift": ">>", - "BitOr": "|", - "BitAnd": "&", - "BitXor": "^", - "FloorDiv": "//", - "Invert": "~", - "Not": "not", - "UAdd": "+", - "USub": "-", - "Eq": "==", - "NotEq": "!=", - "Lt": "<", - "LtE": "<=", - "Gt": ">", - "GtE": ">=", - "Is": "is", - "IsNot": "is not", - "In": "in", - "NotIn": "not in", -} - - -def _get_op(self, node): - return self._operators[node.__class__.__name__].split(" ") - - -def _Attribute(self, node): - self._handle(node, [node.value, ".", node.attr]) - - -def _Assert(self, node): - children = ["assert", node.test] - if node.msg: - children.append(",") - children.append(node.msg) - self._handle(node, children) - - -def _Assign(self, node): - children = self._child_nodes(node.targets, "=") - children.append("=") - children.append(node.value) - self._handle(node, children) - - -def _AugAssign(self, node): - children = [node.target] - children.extend(self._get_op(node.op)) - children.extend(["=", node.value]) - self._handle(node, children) - - -def _AnnAssign(self, node): - children = [node.target, ":", node.annotation] - if node.value is not None: - children.append("=") - children.append(node.value) - self._handle(node, children) - - -def _Repr(self, node): - self._handle(node, ["`", node.value, "`"]) - - -def _BinOp(self, node): - children = [node.left] + self._get_op(node.op) + [node.right] - self._handle(node, children) - - -def _BoolOp(self, node): - self._handle(node, self._child_nodes(node.values, self._get_op(node.op)[0])) - - -def get_name(self): - if self.is_constructor(): - return "__init__" - if self.is_instance(): - return "__call__" - return worder.get_name_at(self.resource, self.offset) - - -def _Break(self, node): - self._handle(node, ["break"]) - - -def _Call(self, node): - def _arg_sort_key(node): - if isinstance(node, ast.keyword): - return (node.value.lineno, node.value.col_offset) - return (node.lineno, node.col_offset) - - children = [node.func, "("] - args = sorted([*node.args, *node.keywords], key=_arg_sort_key) - children.extend(self._child_nodes(args, ",")) - children.append(")") - self._handle(node, children) - - -def _ClassDef(self, node): - children = [] - if getattr(node, "decorator_list", None): - for decorator in node.decorator_list: - children.append("@") - children.append(decorator) - children.extend(["class", node.name]) - if node.bases: - children.append("(") - children.extend(self._child_nodes(node.bases, ",")) - children.append(")") - children.append(":") - children.extend(node.body) - self._handle(node, children) - - -def _Compare(self, node): - children = [] - children.append(node.left) - for op, expr in zip(node.ops, node.comparators): - children.extend(self._get_op(op)) - children.append(expr) - self._handle(node, children) - - -def _Delete(self, node): - self._handle(node, ["del"] + self._child_nodes(node.targets, ",")) - - -def _Constant(self, node): - if isinstance(node.value, basestring): - self._handle(node, [self.String]) - return - - if any(node.value is v for v in [True, False, None]): - self._handle(node, [str(node.value)]) - return - - if isinstance(node.value, numbers.Number): - self._handle(node, [self.Number]) - return - - if node.value is Ellipsis: - self._handle(node, ["..."]) - return - - assert False - - -def _Num(self, node): - self._handle(node, [self.Number]) - - -def _Str(self, node): - self._handle(node, [self.String]) - - -def _Bytes(self, node): - self._handle(node, [self.String]) - - -def _JoinedStr(self, node): - def start_quote_char(): - possible_quotes = [ - (self.source.source.find(q, start, end), q) for q in QUOTE_CHARS - ] - quote_pos, quote_char = min( - (pos, q) for pos, q in possible_quotes if pos != -1 - ) - return self.source[start : quote_pos + len(quote_char)] - - def end_quote_char(): - possible_quotes = [ - (self.source.source.rfind(q, start, end), q) - for q in reversed(QUOTE_CHARS) - ] - _, quote_pos, quote_char = max( - (len(q), pos, q) for pos, q in possible_quotes if pos != -1 - ) - return self.source[end - len(quote_char) : end] - - QUOTE_CHARS = ['"""', "'''", '"', "'"] - offset = self.source.offset - start, end = self.source.consume_string( - end=self._find_next_statement_start(), - ) - self.source.offset = offset - - children = [] - children.append(start_quote_char()) - for part in node.values: - if isinstance(part, ast.FormattedValue): - children.append(part) - children.append(end_quote_char()) - self._handle(node, children) - - -def get_passed_args(self): - result = [] - source = self.source_pymodule.source_code - finder = worder.Worder(source) - if finder.is_a_function_being_called(self.offset): - start, end = finder.get_primary_range(self.offset) - parens_start, parens_end = finder.get_word_parens_range(end - 1) - call = source[start:parens_end] - parser = functionutils._FunctionParser(call, False) - args, keywords = parser.get_parameters() - for arg in args: - if self._is_id(arg): - result.append(arg) - else: - result.append("arg%d" % len(result)) - for name, value in keywords: - result.append(name) - return result - - -def _FormattedValue(self, node): - children = [] - children.append("{") - children.append(node.value) - if node.format_spec: - children.append(":") - for val in node.format_spec.values: - if isinstance(val, ast.FormattedValue): - children.append(val.value) - else: - children.append(val.s) - children.append("}") - self._handle(node, children) - - -def _Continue(self, node): - self._handle(node, ["continue"]) - - -def _Dict(self, node): - children = [] - children.append("{") - if node.keys: - for index, (key, value) in enumerate(zip(node.keys, node.values)): - if key is None: - # PEP-448 dict unpacking: {a: b, **unpack} - children.extend(["**", value]) - else: - children.extend([key, ":", value]) - if index < len(node.keys) - 1: - children.append(",") - children.append("}") - self._handle(node, children) - - -def _Ellipsis(self, node): - self._handle(node, ["..."]) - - -def _Expr(self, node): - self._handle(node, [node.value]) - - -def _NamedExpr(self, node): - children = [node.target, ":=", node.value] - self._handle(node, children) - - -def _Exec(self, node): - children = ["exec", self.exec_open_paren_or_space, node.body] - if node.globals: - children.extend([self.exec_in_or_comma, node.globals]) - if node.locals: - children.extend([",", node.locals]) - children.append(self.exec_close_paren_or_space) - self._handle(node, children) - - -def _ExtSlice(self, node): - children = [] - for index, dim in enumerate(node.dims): - if index > 0: - children.append(",") - children.append(dim) - self._handle(node, children) - - -def _handle_for_loop_node(self, node, is_async): - if is_async: - children = ["async", "for"] - else: - children = ["for"] - children.extend([node.target, "in", node.iter, ":"]) - children.extend(node.body) - if node.orelse: - children.extend(["else", ":"]) - children.extend(node.orelse) - self._handle(node, children) - - -def _For(self, node): - self._handle_for_loop_node(node, is_async=False) - - -def _is_id(self, arg): - def id_or_underline(c): - return c.isalpha() or c == "_" - - for c in arg: - if not id_or_underline(c) and not c.isdigit(): - return False - return id_or_underline(arg[0]) - -def _AsyncFor(self, node): - self._handle_for_loop_node(node, is_async=True) - - -def _ImportFrom(self, node): - children = ["from"] - if node.level: - children.append("." * node.level) - # see comment at rope.base.ast.walk - children.extend([node.module or "", "import"]) - children.extend(self._child_nodes(node.names, ",")) - self._handle(node, children) - - -def _alias(self, node): - children = [node.name] - if node.asname: - children.extend(["as", node.asname]) - self._handle(node, children) - - -def _handle_function_def_node(self, node, is_async): - children = [] - try: - decorators = getattr(node, "decorator_list") - except AttributeError: - decorators = getattr(node, "decorators", None) - if decorators: - for decorator in decorators: - children.append("@") - children.append(decorator) - if is_async: - children.extend(["async", "def"]) - else: - children.extend(["def"]) - children.extend([node.name, "(", node.args]) - children.extend([")", ":"]) - children.extend(node.body) - self._handle(node, children) - - -def _FunctionDef(self, node): - self._handle_function_def_node(node, is_async=False) - - -def _AsyncFunctionDef(self, node): - self._handle_function_def_node(node, is_async=True) - - -def _arguments(self, node): - children = [] - args = list(node.args) - defaults = [None] * (len(args) - len(node.defaults)) + list(node.defaults) - for index, (arg, default) in enumerate(zip(args, defaults)): - if index > 0: - children.append(",") - self._add_args_to_children(children, arg, default) - if node.vararg is not None: - if args: - children.append(",") - children.extend(["*", node.vararg.arg]) - if node.kwarg is not None: - if args or node.vararg is not None: - children.append(",") - children.extend(["**", node.kwarg.arg]) - self._handle(node, children) - - -def _add_args_to_children(self, children, arg, default): - if isinstance(arg, (list, tuple)): - self._add_tuple_parameter(children, arg) - else: - children.append(arg) - if default is not None: - children.append("=") - children.append(default) - - -def _add_tuple_parameter(self, children, arg): - children.append("(") - for index, token in enumerate(arg): - if index > 0: - children.append(",") - if isinstance(token, (list, tuple)): - self._add_tuple_parameter(children, token) - else: - children.append(token) - children.append(")") - - -def _GeneratorExp(self, node): - children = [node.elt] - children.extend(node.generators) - self._handle(node, children, eat_parens=True) - - -def __init__(self, code): - self.code = code - self.lines = self.code.split("\n") - self.lines.append("\n") - self.origs = list(range(len(self.lines) + 1)) - self.diffs = [0] * (len(self.lines) + 1) - - -@path C:/Repos/ekr-rope/rope/contrib/ -"""rope IDE tools package - -This package contains modules that can be used in IDEs -but do not depend on the UI. So these modules will be used -by `rope.ui` modules. - -""" -@language python -@tabwidth -4 - -def _comprehension(self, node): - children = ["for", node.target, "in", node.iter] - if node.ifs: - for if_ in node.ifs: - children.append("if") - children.append(if_) - self._handle(node, children) - - -def _Global(self, node): - children = self._child_nodes(node.names, ",") - children.insert(0, "global") - self._handle(node, children) - - -def _If(self, node): - if self._is_elif(node): - children = ["elif"] - else: - children = ["if"] - children.extend([node.test, ":"]) - children.extend(node.body) - if node.orelse: - if len(node.orelse) == 1 and self._is_elif(node.orelse[0]): - pass - else: - children.extend(["else", ":"]) - children.extend(node.orelse) - self._handle(node, children) - - -def _is_elif(self, node): - if not isinstance(node, ast.If): - return False - offset = self.lines.get_line_start(node.lineno) + node.col_offset - word = self.source[offset : offset + 4] - # XXX: This is a bug; the offset does not point to the first - alt_word = self.source[offset - 5 : offset - 1] - return "elif" in (word, alt_word) - - -def _IfExp(self, node): - return self._handle(node, [node.body, "if", node.test, "else", node.orelse]) - - -def _Import(self, node): - children = ["import"] - children.extend(self._child_nodes(node.names, ",")) - self._handle(node, children) - - -def _keyword(self, node): - children = [] - if node.arg is None: - children.append(node.value) - else: - children.extend([node.arg, "=", node.value]) - self._handle(node, children) - - -def _Lambda(self, node): - self._handle(node, ["lambda", node.args, ":", node.body]) - - -def _List(self, node): - self._handle(node, ["["] + self._child_nodes(node.elts, ",") + ["]"]) - - -def _ListComp(self, node): - children = ["[", node.elt] - children.extend(node.generators) - children.append("]") - self._handle(node, children) - - - -def _Set(self, node): - if node.elts: - self._handle(node, ["{"] + self._child_nodes(node.elts, ",") + ["}"]) - return - # Python doesn't have empty set literals - warnings.warn( - "Tried to handle empty <Set> literal; please report!", RuntimeWarning - ) - self._handle(node, ["set(", ")"]) - - -def _SetComp(self, node): - children = ["{", node.elt] - children.extend(node.generators) - children.append("}") - self._handle(node, children) - - -def _DictComp(self, node): - children = ["{"] - children.extend([node.key, ":", node.value]) - children.extend(node.generators) - children.append("}") - self._handle(node, children) - - -def _Module(self, node): - self._handle(node, list(node.body), eat_spaces=True) - - -def _Name(self, node): - self._handle(node, [node.id]) - - -def _NameConstant(self, node): - self._handle(node, [str(node.value)]) - - -def _arg(self, node): - self._handle(node, [node.arg]) - - -def _Pass(self, node): - self._handle(node, ["pass"]) - - -def _Print(self, node): - children = ["print"] - if node.dest: - children.extend([">>", node.dest]) - if node.values: - children.append(",") - children.extend(self._child_nodes(node.values, ",")) - if not node.nl: - children.append(",") - self._handle(node, children) - - -def _Raise(self, node): - children = ["raise"] - if node.exc: - children.append(node.exc) - if node.cause: - children.append(node.cause) - self._handle(node, children) - - -@path C:/Repos/ekr-rope/rope/contrib/autoimport/ -"""Definitions of types for the Autoimport program.""" -import pathlib -from enum import Enum -from typing import NamedTuple, Optional - - -@others -@language python -@tabwidth -4 - -def _Return(self, node): - children = ["return"] - if node.value: - children.append(node.value) - self._handle(node, children) - - -def _Sliceobj(self, node): - children = [] - for index, slice in enumerate(node.nodes): - if index > 0: - children.append(":") - if slice: - children.append(slice) - self._handle(node, children) - - -def _Index(self, node): - self._handle(node, [node.value]) - - -def _Subscript(self, node): - self._handle(node, [node.value, "[", node.slice, "]"]) - - -def _Slice(self, node): - children = [] - if node.lower: - children.append(node.lower) - children.append(":") - if node.upper: - children.append(node.upper) - if node.step: - children.append(":") - children.append(node.step) - self._handle(node, children) - - -def _TryFinally(self, node): - # @todo fixme - is_there_except_handler = False - not_empty_body = True - if len(node.finalbody) == 1: - try: - is_there_except_handler = isinstance( - node.handlers[0], ast.ExceptHandler - ) - not_empty_body = True - except IndexError: - pass - children = [] - if not_empty_body or not is_there_except_handler: - children.extend(["try", ":"]) - children.extend(node.body) - children.extend(node.handlers) - children.extend(["finally", ":"]) - children.extend(node.finalbody) - self._handle(node, children) - - -def _TryExcept(self, node): - children = ["try", ":"] - children.extend(node.body) - children.extend(node.handlers) - if node.orelse: - children.extend(["else", ":"]) - children.extend(node.orelse) - self._handle(node, children) - - -def _Try(self, node): - if len(node.finalbody): - self._TryFinally(node) - else: - self._TryExcept(node) - - -def _ExceptHandler(self, node): - self._excepthandler(node) - - -def _excepthandler(self, node): - # self._handle(node, [self.semicolon_or_as_in_except]) - children = ["except"] - if node.type: - children.append(node.type) - if node.name: - children.append(self.semicolon_or_as_in_except) - children.append(node.name) - children.append(":") - children.extend(node.body) - - self._handle(node, children) - - -class Source(Enum): - """Describes the source of the package, for sorting purposes.""" - - PROJECT = 0 # Obviously any project packages come first - MANUAL = 1 # Placeholder since Autoimport classifies manually added modules - BUILTIN = 2 - STANDARD = 3 # We want to favor standard library items - SITE_PACKAGE = 4 - UNKNOWN = 5 - - # modified_time - - - -def _Tuple(self, node): - if node.elts: - self._handle(node, self._child_nodes(node.elts, ","), eat_parens=True) - else: - self._handle(node, [self.empty_tuple]) - - -def _UnaryOp(self, node): - children = self._get_op(node.op) - children.append(node.operand) - self._handle(node, children) - - -def _Await(self, node): - children = ["await"] - if node.value: - children.append(node.value) - self._handle(node, children) - - -def _Yield(self, node): - children = ["yield"] - if node.value: - children.append(node.value) - self._handle(node, children) - - -def _YieldFrom(self, node): - children = ["yield", "from", node.value] - self._handle(node, children) - - -def _While(self, node): - children = ["while", node.test, ":"] - children.extend(node.body) - if node.orelse: - children.extend(["else", ":"]) - children.extend(node.orelse) - self._handle(node, children) - - -def _handle_with_node(self, node, is_async): - children = [] - - if is_async: - children.extend(["async"]) - for item in node.items: - children.extend([self.with_or_comma_context_manager, item.context_expr]) - if item.optional_vars: - children.extend(["as", item.optional_vars]) - children.append(":") - children.extend(node.body) - self._handle(node, children) - - -def _With(self, node): - self._handle_with_node(node, is_async=False) - - -def _AsyncWith(self, node): - self._handle_with_node(node, is_async=True) - - -def _Starred(self, node): - self._handle(node, [node.value]) - - -class ModuleInfo(NamedTuple): - """Descriptor of information to get names from a module.""" - - filepath: Optional[pathlib.Path] - modname: str - underlined: bool - process_imports: bool - - - -def _Match(self, node): - children = ["match", node.subject, ":"] - children.extend(node.cases) - self._handle(node, children) - - -def _match_case(self, node): - children = ["case", node.pattern] - if node.guard: - children.extend(["if", node.guard]) - children.append(":") - children.extend(node.body) - self._handle(node, children) - - -def _MatchAs(self, node): - if node.pattern: - children = [node.pattern, "as", node.name] - elif node.name is None: - children = ["_"] - else: - children = [node.name] - self._handle(node, children) - - -def _MatchClass(self, node): - children = [] - children.extend([node.cls, "("]) - children.extend(self._child_nodes(node.patterns, ",")) - children.extend(self._flatten_keywords(zip(node.kwd_attrs, node.kwd_patterns))) - children.append(")") - self._handle(node, children) - - -def _MatchValue(self, node): - self._handle(node, [node.value]) - -def _MatchMapping(self, node): - children = [] - children.append("{") - for index, (key, value) in enumerate(zip(node.keys, node.patterns)): - children.extend([key, ":", value]) - if index < len(node.keys) - 1: - children.append(",") - children.append("}") - self._handle(node, children) - - - -class _Source: - @others - _string_pattern = None - _number_pattern = None - _not_equals_pattern = None - -def __init__(self, source): - self.source = source - self.offset = 0 - - -def consume(self, token, skip_comment=True): - try: - while True: - new_offset = self.source.index(token, self.offset) - if self._good_token(token, new_offset) or not skip_comment: - break - else: - self._skip_comment() - except (ValueError, TypeError) as e: - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) - self.offset = new_offset + len(token) - return (new_offset, self.offset) - - -def consume_joined_string(self, token): - new_offset = self.source.index(token, self.offset) - self.offset = new_offset + len(token) - return (new_offset, self.offset) - - -def consume_string(self, end=None): - if _Source._string_pattern is None: - string_pattern = codeanalyze.get_string_pattern() - formatted_string_pattern = codeanalyze.get_formatted_string_pattern() - original = r"(?:{})|(?:{})".format(string_pattern, formatted_string_pattern) - pattern = r"({})((\s|\\\n|#[^\n]*\n)*({}))*".format(original, original) - _Source._string_pattern = re.compile(pattern) - repattern = _Source._string_pattern - return self._consume_pattern(repattern, end) - - -class ModuleFile(ModuleInfo): - """Descriptor of information to get names from a file using ast.""" - - filepath: pathlib.Path - modname: str - underlined: bool - process_imports: bool - - - -def consume_number(self): - if _Source._number_pattern is None: - _Source._number_pattern = re.compile(self._get_number_pattern()) - repattern = _Source._number_pattern - return self._consume_pattern(repattern) - - -def consume_empty_tuple(self): - return self._consume_pattern(re.compile(r"\(\s*\)")) - - -def consume_not_equal(self): - if _Source._not_equals_pattern is None: - _Source._not_equals_pattern = re.compile(r"<>|!=") - repattern = _Source._not_equals_pattern - return self._consume_pattern(repattern) - - -def consume_except_as_or_semicolon(self): - repattern = re.compile(r"as|,") - return self._consume_pattern(repattern) - - -def consume_exec_open_paren_or_space(self): - repattern = re.compile(r"\(|") - return self._consume_pattern(repattern) - - -def consume_exec_in_or_comma(self): - repattern = re.compile(r"in|,") - return self._consume_pattern(repattern) - - -def consume_exec_close_paren_or_space(self): - repattern = re.compile(r"\)|") - return self._consume_pattern(repattern) - - -def consume_with_or_comma_context_manager(self): - repattern = re.compile(r"with|,") - return self._consume_pattern(repattern) - - -def _good_token(self, token, offset, start=None): - """Checks whether consumed token is in comments""" - if start is None: - start = self.offset - try: - comment_index = self.source.rindex("#", start, offset) - except ValueError: - return True - try: - new_line_index = self.source.rindex("\n", start, offset) - except ValueError: - return False - return comment_index < new_line_index - - -def _skip_comment(self): - self.offset = self.source.index("\n", self.offset + 1) - - -class ModuleCompiled(ModuleInfo): - """Descriptor of information to get names using imports.""" - - filepath = None - modname: str - underlined: bool - process_imports: bool - - - -def _get_location(self): - lines = self.source[: self.offset].split("\n") - return (len(lines), len(lines[-1])) - - -def _consume_pattern(self, repattern, end=None): - while True: - if end is None: - end = len(self.source) - match = repattern.search(self.source, self.offset, end) - if self._good_token(match.group(), match.start()): - break - else: - self._skip_comment() - self.offset = match.end() - return match.start(), match.end() - - -def till_token(self, token): - new_offset = self.source.index(token, self.offset) - return self[self.offset : new_offset] - - -def rfind_token(self, token, start, end): - index = start - while True: - try: - index = self.source.rindex(token, start, end) - if self._good_token(token, index, start=start): - return index - else: - end = index - except ValueError: - return None - - -def from_offset(self, offset): - return self[offset : self.offset] - - -def find_backwards(self, pattern, offset): - return self.source.rindex(pattern, 0, offset) - - -def __getitem__(self, index): - return self.source[index] - - -def __getslice__(self, i, j): - return self.source[i:j] - - -def _get_number_pattern(self): - # HACK: It is merely an approaximation and does the job - integer = r"\-?(0x[\da-fA-F]+|\d+)[lL]?" - return r"(%s(\.\d*)?|(\.\d+))([eE][-+]?\d+)?[jJ]?" % integer - - -@path C:/Repos/ekr-rope/rope/refactor/ -import warnings - -from rope.base import ( - exceptions, - pyobjects, - pynames, - taskhandle, - evaluate, - worder, - codeanalyze, - libutils, -) -from rope.base.change import ChangeSet, ChangeContents, MoveResource -from rope.refactor import occurrences - - -@others -@language python -@tabwidth -4 - -class PackageType(Enum): - """Describes the type of package, to determine how to get the names from it.""" - - BUILTIN = 0 # No file exists, compiled into python. IE: Sys - STANDARD = 1 # Just a folder - COMPILED = 2 # .so module - SINGLE_FILE = 3 # a .py file - - - -class Rename: - """A class for performing rename refactoring - - It can rename everything: classes, functions, modules, packages, - methods, variables and keyword arguments. - - """ - - @others - -def __init__(self, project, resource, offset=None): - """If `offset` is None, the `resource` itself will be renamed""" - self.project = project - self.resource = resource - if offset is not None: - self.old_name = worder.get_name_at(self.resource, offset) - this_pymodule = self.project.get_pymodule(self.resource) - self.old_instance, self.old_pyname = evaluate.eval_location2( - this_pymodule, offset - ) - if self.old_pyname is None: - raise exceptions.RefactoringError( - "Rename refactoring should be performed" - " on resolvable python identifiers." - ) - else: - if not resource.is_folder() and resource.name == "__init__.py": - resource = resource.parent - dummy_pymodule = libutils.get_string_module(self.project, "") - self.old_instance = None - self.old_pyname = pynames.ImportedModule(dummy_pymodule, resource=resource) - if resource.is_folder(): - self.old_name = resource.name - else: - self.old_name = resource.name[:-3] - - -def get_old_name(self): - return self.old_name - - -def get_changes( - self, - new_name, - in_file=None, - in_hierarchy=False, - unsure=None, - docs=False, - resources=None, - task_handle=taskhandle.NullTaskHandle(), -): - """Get the changes needed for this refactoring - - Parameters: - - - `in_hierarchy`: when renaming a method this keyword forces - to rename all matching methods in the hierarchy - - `docs`: when `True` rename refactoring will rename - occurrences in comments and strings where the name is - visible. Setting it will make renames faster, too. - - `unsure`: decides what to do about unsure occurrences. - If `None`, they are ignored. Otherwise `unsure` is - called with an instance of `occurrence.Occurrence` as - parameter. If it returns `True`, the occurrence is - considered to be a match. - - `resources` can be a list of `rope.base.resources.File` to - apply this refactoring on. If `None`, the restructuring - will be applied to all python files. - - `in_file`: this argument has been deprecated; use - `resources` instead. - - """ - if unsure in (True, False): - warnings.warn( - "unsure parameter should be a function that returns " "True or False", - DeprecationWarning, - stacklevel=2, - ) - - @others - unsure = unsure_func - if in_file is not None: - warnings.warn( - "`in_file` argument has been deprecated; use `resources` " "instead. ", - DeprecationWarning, - stacklevel=2, - ) - if in_file: - resources = [self.resource] - if _is_local(self.old_pyname): - resources = [self.resource] - if resources is None: - resources = self.project.get_python_files() - changes = ChangeSet("Renaming <{}> to <{}>".format(self.old_name, new_name)) - finder = occurrences.create_finder( - self.project, - self.old_name, - self.old_pyname, - unsure=unsure, - docs=docs, - instance=self.old_instance, - in_hierarchy=in_hierarchy and self.is_method(), - ) - job_set = task_handle.create_jobset("Collecting Changes", len(resources)) - for file_ in resources: - job_set.started_job(file_.path) - new_content = rename_in_module(finder, new_name, resource=file_) - if new_content is not None: - changes.add_change(ChangeContents(file_, new_content)) - job_set.finished_job() - if self._is_renaming_a_module(): - resource = self.old_pyname.get_object().get_resource() - if self._is_allowed_to_move(resources, resource): - self._rename_module(resource, new_name, changes) - return changes - - -def unsure_func(value=unsure): - return value - - -def _is_allowed_to_move(self, resources, resource): - if resource.is_folder(): - try: - return resource.get_child("__init__.py") in resources - except exceptions.ResourceNotFoundError: - return False - else: - return resource in resources - - -def _is_renaming_a_module(self): - return isinstance(self.old_pyname.get_object(), pyobjects.AbstractModule) - - -def is_method(self): - pyname = self.old_pyname - return ( - isinstance(pyname, pynames.DefinedName) - and isinstance(pyname.get_object(), pyobjects.PyFunction) - and isinstance(pyname.get_object().parent, pyobjects.PyClass) - ) - - -def _rename_module(self, resource, new_name, changes): - if not resource.is_folder(): - new_name = new_name + ".py" - parent_path = resource.parent.path - if parent_path == "": - new_location = new_name - else: - new_location = parent_path + "/" + new_name - changes.add_change(MoveResource(resource, new_location)) - - - -class ChangeOccurrences: - """A class for changing the occurrences of a name in a scope - - This class replaces the occurrences of a name. Note that it only - changes the scope containing the offset passed to the constructor. - What's more it does not have any side-effects. That is for - example changing occurrences of a module does not rename the - module; it merely replaces the occurrences of that module in a - scope with the given expression. This class is useful for - performing many custom refactorings. - - """ - - @others - -class NameType(Enum): - """Describes the type of Name for lsp completions. Taken from python lsp server.""" - - Text = 1 - Method = 2 - Function = 3 - Constructor = 4 - Field = 5 - Variable = 6 - Class = 7 - Interface = 8 - Module = 9 - Property = 10 - Unit = 11 - Value = 12 - Enum = 13 - Keyword = 14 - Snippet = 15 - Color = 16 - File = 17 - Reference = 18 - Folder = 19 - EnumMember = 20 - Constant = 21 - Struct = 22 - Event = 23 - Operator = 24 - TypeParameter = 25 - - - -def __init__(self, project, resource, offset): - self.project = project - self.resource = resource - self.offset = offset - self.old_name = worder.get_name_at(resource, offset) - self.pymodule = project.get_pymodule(self.resource) - self.old_pyname = evaluate.eval_location(self.pymodule, offset) - - -def get_old_name(self): - word_finder = worder.Worder(self.resource.read()) - return word_finder.get_primary_at(self.offset) - - -def _get_scope_offset(self): - scope = self.pymodule.get_scope().get_inner_scope_for_offset(self.offset) - return scope.get_region() - - -def get_changes(self, new_name, only_calls=False, reads=True, writes=True): - changes = ChangeSet( - "Changing <{}> occurrences to <{}>".format(self.old_name, new_name) - ) - scope_start, scope_end = self._get_scope_offset() - finder = occurrences.create_finder( - self.project, - self.old_name, - self.old_pyname, - imports=False, - only_calls=only_calls, - ) - new_contents = rename_in_module( - finder, - new_name, - pymodule=self.pymodule, - replace_primary=True, - region=(scope_start, scope_end), - reads=reads, - writes=writes, - ) - if new_contents is not None: - changes.add_change(ChangeContents(self.resource, new_contents)) - return changes - - - -def rename_in_module( - occurrences_finder, - new_name, - resource=None, - pymodule=None, - replace_primary=False, - region=None, - reads=True, - writes=True, -): - """Returns the changed source or `None` if there is no changes""" - if resource is not None: - source_code = resource.read() - else: - source_code = pymodule.source_code - change_collector = codeanalyze.ChangeCollector(source_code) - for occurrence in occurrences_finder.find_occurrences(resource, pymodule): - if replace_primary and occurrence.is_a_fixed_primary(): - continue - if replace_primary: - start, end = occurrence.get_primary_range() - else: - start, end = occurrence.get_word_range() - if (not reads and not occurrence.is_written()) or ( - not writes and occurrence.is_written() - ): - continue - if region is None or region[0] <= start < region[1]: - change_collector.add_change(start, end, new_name) - return change_collector.get_changed() - - - -def _is_local(pyname): - module, lineno = pyname.get_definition_location() - if lineno is None: - return False - scope = module.get_scope().get_inner_scope_for_line(lineno) - if isinstance(pyname, pynames.DefinedName) and scope.get_kind() in ( - "Function", - "Class", - ): - scope = scope.parent - return ( - scope.get_kind() == "Function" - and pyname in scope.get_names().values() - and isinstance(pyname, pynames.AssignedName) - ) - -@path C:/Repos/ekr-rope/rope/refactor/ -import warnings - -from rope.base import change, taskhandle, builtins, ast, codeanalyze -from rope.base import libutils -from rope.refactor import patchedast, similarfinder, sourceutils -from rope.refactor.importutils import module_imports - - -@others -@language python -@tabwidth -4 - -class Restructure: - """A class to perform python restructurings - - A restructuring transforms pieces of code matching `pattern` to - `goal`. In the `pattern` wildcards can appear. Wildcards match - some piece of code based on their kind and arguments that are - passed to them through `args`. - - `args` is a dictionary of wildcard names to wildcard arguments. - If the argument is a tuple, the first item of the tuple is - considered to be the name of the wildcard to use; otherwise the - "default" wildcard is used. For getting the list arguments a - wildcard supports, see the pydoc of the wildcard. (see - `rope.refactor.wildcard.DefaultWildcard` for the default - wildcard.) - - `wildcards` is the list of wildcard types that can appear in - `pattern`. See `rope.refactor.wildcards`. If a wildcard does not - specify its kind (by using a tuple in args), the wildcard named - "default" is used. So there should be a wildcard with "default" - name in `wildcards`. - - `imports` is the list of imports that changed modules should - import. Note that rope handles duplicate imports and does not add - the import if it already appears. - - Example #1:: - - pattern ${pyobject}.get_attribute(${name}) - goal ${pyobject}[${name}] - args pyobject: instance=rope.base.pyobjects.PyObject - - Example #2:: - - pattern ${name} in ${pyobject}.get_attributes() - goal ${name} in {pyobject} - args pyobject: instance=rope.base.pyobjects.PyObject - - Example #3:: - - pattern ${pycore}.create_module(${project}.root, ${name}) - goal generate.create_module(${project}, ${name}) - - imports - from rope.contrib import generate - - args - project: type=rope.base.project.Project - - Example #4:: - - pattern ${pow}(${param1}, ${param2}) - goal ${param1} ** ${param2} - args pow: name=mod.pow, exact - - Example #5:: - - pattern ${inst}.longtask(${p1}, ${p2}) - goal - ${inst}.subtask1(${p1}) - ${inst}.subtask2(${p2}) - args - inst: type=mod.A,unsure - - """ - - @others - -def __init__(self, project, pattern, goal, args=None, imports=None, wildcards=None): - """Construct a restructuring - - See class pydoc for more info about the arguments. - - """ - self.project = project - self.pattern = pattern - self.goal = goal - self.args = args - if self.args is None: - self.args = {} - self.imports = imports - if self.imports is None: - self.imports = [] - self.wildcards = wildcards - self.template = similarfinder.CodeTemplate(self.goal) - - -def get_changes( - self, - checks=None, - imports=None, - resources=None, - task_handle=taskhandle.NullTaskHandle(), -): - """Get the changes needed by this restructuring - - `resources` can be a list of `rope.base.resources.File` to - apply the restructuring on. If `None`, the restructuring will - be applied to all python files. - - `checks` argument has been deprecated. Use the `args` argument - of the constructor. The usage of:: - - strchecks = {'obj1.type': 'mod.A', 'obj2': 'mod.B', - 'obj3.object': 'mod.C'} - checks = restructuring.make_checks(strchecks) - - can be replaced with:: - - args = {'obj1': 'type=mod.A', 'obj2': 'name=mod.B', - 'obj3': 'object=mod.C'} - - where obj1, obj2 and obj3 are wildcard names that appear - in restructuring pattern. - - """ - if checks is not None: - warnings.warn( - "The use of checks parameter is deprecated; " - "use the args parameter of the constructor instead.", - DeprecationWarning, - stacklevel=2, - ) - for name, value in checks.items(): - self.args[name] = similarfinder._pydefined_to_str(value) - if imports is not None: - warnings.warn( - "The use of imports parameter is deprecated; " - "use imports parameter of the constructor, instead.", - DeprecationWarning, - stacklevel=2, - ) - self.imports = imports - changes = change.ChangeSet( - "Restructuring <{}> to <{}>".format(self.pattern, self.goal) - ) - if resources is not None: - files = [ - resource - for resource in resources - if libutils.is_python_file(self.project, resource) - ] - else: - files = self.project.get_python_files() - job_set = task_handle.create_jobset("Collecting Changes", len(files)) - for resource in files: - job_set.started_job(resource.path) - pymodule = self.project.get_pymodule(resource) - finder = similarfinder.SimilarFinder(pymodule, wildcards=self.wildcards) - matches = list(finder.get_matches(self.pattern, self.args)) - computer = self._compute_changes(matches, pymodule) - result = computer.get_changed() - if result is not None: - imported_source = self._add_imports(resource, result, self.imports) - changes.add_change(change.ChangeContents(resource, imported_source)) - job_set.finished_job() - return changes - - -class Package(NamedTuple): - """Attributes of a package.""" - - name: str - source: Source - path: Optional[pathlib.Path] - type: PackageType - - - -def _compute_changes(self, matches, pymodule): - return _ChangeComputer( - pymodule.source_code, - pymodule.get_ast(), - pymodule.lines, - self.template, - matches, - ) - - -def _add_imports(self, resource, source, imports): - if not imports: - return source - import_infos = self._get_import_infos(resource, imports) - pymodule = libutils.get_string_module(self.project, source, resource) - imports = module_imports.ModuleImports(self.project, pymodule) - for import_info in import_infos: - imports.add_import(import_info) - return imports.get_changed_source() - - -def _get_import_infos(self, resource, imports): - pymodule = libutils.get_string_module( - self.project, "\n".join(imports), resource - ) - imports = module_imports.ModuleImports(self.project, pymodule) - return [imports.import_info for imports in imports.imports] - - -def make_checks(self, string_checks): - """Convert str to str dicts to str to PyObject dicts - - This function is here to ease writing a UI. - - """ - checks = {} - for key, value in string_checks.items(): - is_pyname = not key.endswith(".object") and not key.endswith(".type") - evaluated = self._evaluate(value, is_pyname=is_pyname) - if evaluated is not None: - checks[key] = evaluated - return checks - - -def _evaluate(self, code, is_pyname=True): - attributes = code.split(".") - pyname = None - if attributes[0] in ("__builtin__", "__builtins__"): - - @others - pyobject = _BuiltinsStub() - else: - pyobject = self.project.get_module(attributes[0]) - for attribute in attributes[1:]: - pyname = pyobject[attribute] - if pyname is None: - return None - pyobject = pyname.get_object() - return pyname if is_pyname else pyobject - - - -class _BuiltinsStub: - def get_attribute(self, name): - return builtins.builtins[name] - - -def replace(code, pattern, goal): - """used by other refactorings""" - finder = similarfinder.RawSimilarFinder(code) - matches = list(finder.get_matches(pattern)) - ast = patchedast.get_patched_ast(code) - lines = codeanalyze.SourceLinesAdapter(code) - template = similarfinder.CodeTemplate(goal) - computer = _ChangeComputer(code, ast, lines, template, matches) - result = computer.get_changed() - if result is None: - return code - return result - - - -class _ChangeComputer: - @others - -def __init__(self, code, ast, lines, goal, matches): - self.source = code - self.goal = goal - self.matches = matches - self.ast = ast - self.lines = lines - self.matched_asts = {} - self._nearest_roots = {} - if self._is_expression(): - for match in self.matches: - self.matched_asts[match.ast] = match - - -def get_changed(self): - if self._is_expression(): - result = self._get_node_text(self.ast) - if result == self.source: - return None - return result - else: - collector = codeanalyze.ChangeCollector(self.source) - last_end = -1 - for match in self.matches: - start, end = match.get_region() - if start < last_end: - if not self._is_expression(): - continue - last_end = end - replacement = self._get_matched_text(match) - collector.add_change(start, end, replacement) - return collector.get_changed() - - -def comment(self, lineno): - start = _logical_start(self.lines, lineno, check_prev=True) - 1 - # using self._get_stmt_end() instead of self._get_block_end() - # to lower commented lines - end = self._get_stmt_end(start) - indents = _get_line_indents(self.lines[start]) - if 0 < start: - last_lineno = self._last_non_blank(start - 1) - last_line = self.lines[last_lineno] - if last_line.rstrip().endswith(":"): - indents = _get_line_indents(last_line) + 4 - self._set(start, " " * indents + "pass") - for line in range(start + 1, end + 1): - self._set(line, self.lines[start]) - self._fix_incomplete_try_blocks(lineno, indents) - - -class Name(NamedTuple): - """A Name to be added to the database.""" - - name: str - modname: str - package: str - source: Source - name_type: NameType - - - -def _is_expression(self): - return self.matches and isinstance( - self.matches[0], similarfinder.ExpressionMatch - ) - - -def _get_matched_text(self, match): - mapping = {} - for name in self.goal.get_names(): - node = match.get_ast(name) - if node is None: - raise similarfinder.BadNameInCheckError("Unknown name <%s>" % name) - force = self._is_expression() and match.ast == node - mapping[name] = self._get_node_text(node, force) - unindented = self.goal.substitute(mapping) - return self._auto_indent(match.get_region()[0], unindented) - - -def _get_node_text(self, node, force=False): - if not force and node in self.matched_asts: - return self._get_matched_text(self.matched_asts[node]) - start, end = patchedast.node_region(node) - main_text = self.source[start:end] - collector = codeanalyze.ChangeCollector(main_text) - for node in self._get_nearest_roots(node): - sub_start, sub_end = patchedast.node_region(node) - collector.add_change( - sub_start - start, sub_end - start, self._get_node_text(node) - ) - result = collector.get_changed() - if result is None: - return main_text - return result - - -def _auto_indent(self, offset, text): - lineno = self.lines.get_line_number(offset) - indents = sourceutils.get_indents(self.lines, lineno) - result = [] - for index, line in enumerate(text.splitlines(True)): - if index != 0 and line.strip(): - result.append(" " * indents) - result.append(line) - return "".join(result) - - -def _get_nearest_roots(self, node): - if node not in self._nearest_roots: - result = [] - for child in ast.get_child_nodes(node): - if child in self.matched_asts: - result.append(child) - else: - result.extend(self._get_nearest_roots(child)) - self._nearest_roots[node] = result - return self._nearest_roots[node] - -@path C:/Repos/ekr-rope/rope/refactor/ -"""This module can be used for finding similar code""" -import re - -import rope.refactor.wildcards -from rope.base import libutils -from rope.base import codeanalyze, exceptions, ast, builtins -from rope.refactor import patchedast, wildcards - -from rope.refactor.patchedast import MismatchedTokenError - - -@others -@language python -@tabwidth -4 - -class BadNameInCheckError(exceptions.RefactoringError): - pass - - - -class SimilarFinder: - """`SimilarFinder` can be used to find similar pieces of code - - See the notes in the `rope.refactor.restructure` module for more - info. - - """ - - @others - -def __init__(self, pymodule, wildcards=None): - """Construct a SimilarFinder""" - self.source = pymodule.source_code - try: - self.raw_finder = RawSimilarFinder( - pymodule.source_code, pymodule.get_ast(), self._does_match - ) - except MismatchedTokenError: - print("in file %s" % pymodule.resource.path) - raise - self.pymodule = pymodule - if wildcards is None: - self.wildcards = {} - for wildcard in [ - rope.refactor.wildcards.DefaultWildcard(pymodule.pycore.project) - ]: - self.wildcards[wildcard.get_name()] = wildcard - else: - self.wildcards = wildcards - - -def get_matches(self, code, args={}, start=0, end=None): - self.args = args - if end is None: - end = len(self.source) - skip_region = None - if "skip" in args.get("", {}): - resource, region = args[""]["skip"] - if resource == self.pymodule.get_resource(): - skip_region = region - return self.raw_finder.get_matches(code, start=start, end=end, skip=skip_region) - - -class PartialName(NamedTuple): - """Partial information of a Name.""" - - name: str - name_type: NameType - - - -def get_match_regions(self, *args, **kwds): - for match in self.get_matches(*args, **kwds): - yield match.get_region() - - -def _does_match(self, node, name): - arg = self.args.get(name, "") - kind = "default" - if isinstance(arg, (tuple, list)): - kind = arg[0] - arg = arg[1] - suspect = wildcards.Suspect(self.pymodule, node, name) - return self.wildcards[kind].matches(suspect, arg) - - - -class RawSimilarFinder: - """A class for finding similar expressions and statements""" - - @others - -def __init__(self, source, node=None, does_match=None): - if node is None: - try: - node = ast.parse(source) - except SyntaxError: - # needed to parse expression containing := operator - node = ast.parse("(" + source + ")") - if does_match is None: - self.does_match = self._simple_does_match - else: - self.does_match = does_match - self._init_using_ast(node, source) - - -def _simple_does_match(self, node, name): - return isinstance(node, (ast.expr, ast.Name)) - - -def _init_using_ast(self, node, source): - self.source = source - self._matched_asts = {} - if not hasattr(node, "region"): - patchedast.patch_ast(node, source) - self.ast = node - - -def get_matches(self, code, start=0, end=None, skip=None): - """Search for `code` in source and return a list of `Match`-es - - `code` can contain wildcards. ``${name}`` matches normal - names and ``${?name} can match any expression. You can use - `Match.get_ast()` for getting the node that has matched a - given pattern. - - """ - if end is None: - end = len(self.source) - for match in self._get_matched_asts(code): - match_start, match_end = match.get_region() - if start <= match_start and match_end <= end: - if skip is not None and (skip[0] < match_end and skip[1] > match_start): - continue - yield match - - -def _get_matched_asts(self, code): - if code not in self._matched_asts: - wanted = self._create_pattern(code) - matches = _ASTMatcher(self.ast, wanted, self.does_match).find_matches() - self._matched_asts[code] = matches - return self._matched_asts[code] - - -def _create_pattern(self, expression): - expression = self._replace_wildcards(expression) - node = ast.parse(expression) - # Getting Module.Stmt.nodes - nodes = node.body - if len(nodes) == 1 and isinstance(nodes[0], ast.Expr): - # Getting Discard.expr - wanted = nodes[0].value - else: - wanted = nodes - return wanted - - -def _replace_wildcards(self, expression): - ropevar = _RopeVariable() - template = CodeTemplate(expression) - mapping = {} - for name in template.get_names(): - mapping[name] = ropevar.get_var(name) - return template.substitute(mapping) - - - -class SearchResult(NamedTuple): - """Search Result.""" - - import_statement: str - name: str - source: int - itemkind: int - -class _ASTMatcher: - @others - -def __init__(self, body, pattern, does_match): - """Searches the given pattern in the body AST. - - body is an AST node and pattern can be either an AST node or - a list of ASTs nodes - """ - self.body = body - self.pattern = pattern - self.matches = None - self.ropevar = _RopeVariable() - self.matches_callback = does_match - - -def find_matches(self): - if self.matches is None: - self.matches = [] - ast.call_for_nodes(self.body, self._check_node, recursive=True) - return self.matches - - -def _check_node(self, node): - if isinstance(self.pattern, list): - self._check_statements(node) - else: - self._check_expression(node) - - -def _check_expression(self, node): - mapping = {} - if self._match_nodes(self.pattern, node, mapping): - self.matches.append(ExpressionMatch(node, mapping)) - - -def _check_statements(self, node): - for child in ast.get_children(node): - if isinstance(child, (list, tuple)): - self.__check_stmt_list(child) - - -def __check_stmt_list(self, nodes): - for index in range(len(nodes)): - if len(nodes) - index >= len(self.pattern): - current_stmts = nodes[index : index + len(self.pattern)] - mapping = {} - if self._match_stmts(current_stmts, mapping): - self.matches.append(StatementMatch(current_stmts, mapping)) - - -def _match_nodes(self, expected, node, mapping): - if isinstance(expected, ast.Name): - if self.ropevar.is_var(expected.id): - return self._match_wildcard(expected, node, mapping) - if not isinstance(expected, ast.AST): - return expected == node - if expected.__class__ != node.__class__: - return False - - children1 = self._get_children(expected) - children2 = self._get_children(node) - if len(children1) != len(children2): - return False - for child1, child2 in zip(children1, children2): - if isinstance(child1, ast.AST): - if not self._match_nodes(child1, child2, mapping): - return False - elif isinstance(child1, (list, tuple)): - if not isinstance(child2, (list, tuple)) or len(child1) != len(child2): - return False - for c1, c2 in zip(child1, child2): - if not self._match_nodes(c1, c2, mapping): - return False - else: - if type(child1) is not type(child2) or child1 != child2: - return False - return True - - -def _get_children(self, node): - """Return not `ast.expr_context` children of `node`""" - children = ast.get_children(node) - return [child for child in children if not isinstance(child, ast.expr_context)] - - -def _match_stmts(self, current_stmts, mapping): - if len(current_stmts) != len(self.pattern): - return False - for stmt, expected in zip(current_stmts, self.pattern): - if not self._match_nodes(expected, stmt, mapping): - return False - return True - - -@path C:/Repos/ekr-rope/rope/contrib/autoimport/ -from typing import List - - -@others -@language python -@tabwidth -4 - -def _match_wildcard(self, node1, node2, mapping): - name = self.ropevar.get_base(node1.id) - if name not in mapping: - if self.matches_callback(node2, name): - mapping[name] = node2 - return True - return False - else: - return self._match_nodes(mapping[name], node2, {}) - - - -class Match: - @others - -def __init__(self, mapping): - self.mapping = mapping - - -def get_region(self): - """Returns match region""" - - -def get_ast(self, name): - """Return the ast node that has matched rope variables""" - return self.mapping.get(name, None) - - - -class ExpressionMatch(Match): - def __init__(self, ast, mapping): - super().__init__(mapping) - self.ast = ast - - def get_region(self): - return self.ast.region - - - -class StatementMatch(Match): - def __init__(self, ast_list, mapping): - super().__init__(mapping) - self.ast_list = ast_list - - def get_region(self): - return self.ast_list[0].region[0], self.ast_list[-1].region[1] - - - -class CodeTemplate: - @others - -def __init__(self, template): - self.template = template - self._find_names() - - -def _find_names(self): - self.names = {} - for match in CodeTemplate._get_pattern().finditer(self.template): - if "name" in match.groupdict() and match.group("name") is not None: - start, end = match.span("name") - name = self.template[start + 2 : end - 1] - if name not in self.names: - self.names[name] = [] - self.names[name].append((start, end)) - - -class FinalQuery: - def __init__(self, query): - self._query = query - - - -def get_names(self): - return self.names.keys() - - -def substitute(self, mapping): - collector = codeanalyze.ChangeCollector(self.template) - for name, occurrences in self.names.items(): - for region in occurrences: - collector.add_change(region[0], region[1], mapping[name]) - result = collector.get_changed() - if result is None: - return self.template - return result - - -_match_pattern = None - - -@classmethod -def _get_pattern(cls): - if cls._match_pattern is None: - pattern = ( - codeanalyze.get_comment_pattern() - + "|" - + codeanalyze.get_string_pattern() - + "|" - + r"(?P<name>\$\{[^\s\$\}]*\})" - ) - cls._match_pattern = re.compile(pattern) - return cls._match_pattern - - - -class _RopeVariable: - """Transform and identify rope inserted wildcards""" - - _normal_prefix = "__rope__variable_normal_" - _any_prefix = "__rope__variable_any_" - - @others - -def get_var(self, name): - if name.startswith("?"): - return self._get_any(name) - else: - return self._get_normal(name) - - -def is_var(self, name): - return self._is_normal(name) or self._is_var(name) - - -def get_base(self, name): - if self._is_normal(name): - return name[len(self._normal_prefix) :] - if self._is_var(name): - return "?" + name[len(self._any_prefix) :] - - -def _get_normal(self, name): - return self._normal_prefix + name - - -def _get_any(self, name): - return self._any_prefix + name[1:] - - -class Query: - @others - -def _is_normal(self, name): - return name.startswith(self._normal_prefix) - - -def _is_var(self, name): - return name.startswith(self._any_prefix) - - - -def make_pattern(code, variables): - variables = set(variables) - collector = codeanalyze.ChangeCollector(code) - - @others - finder = RawSimilarFinder(code, does_match=does_match) - for variable in variables: - for match in finder.get_matches("${%s}" % variable): - start, end = match.get_region() - collector.add_change(start, end, "${%s}" % variable) - result = collector.get_changed() - return result if result is not None else code - - - -def does_match(node, name): - return isinstance(node, ast.Name) and node.id == name - - -def _pydefined_to_str(pydefined): - address = [] - if isinstance(pydefined, (builtins.BuiltinClass, builtins.BuiltinFunction)): - return "__builtins__." + pydefined.get_name() - else: - while pydefined.parent is not None: - address.insert(0, pydefined.get_name()) - pydefined = pydefined.parent - module_name = libutils.modname(pydefined.resource) - return ".".join(module_name.split(".") + address) - -@path C:/Repos/ekr-rope/rope/refactor/ -from rope.base import codeanalyze - - -@others -@language python -@tabwidth -4 - -def get_indents(lines, lineno): - return codeanalyze.count_line_indents(lines.get_line(lineno)) - - - -def find_minimum_indents(source_code): - result = 80 - lines = source_code.split("\n") - for line in lines: - if line.strip() == "": - continue - result = min(result, codeanalyze.count_line_indents(line)) - return result - - - -def indent_lines(source_code, amount): - if amount == 0: - return source_code - lines = source_code.splitlines(True) - result = [] - for l in lines: - if l.strip() == "": - result.append("\n") - continue - if amount < 0: - indents = codeanalyze.count_line_indents(l) - result.append(max(0, indents + amount) * " " + l.lstrip()) - else: - result.append(" " * amount + l) - return "".join(result) - - - -def fix_indentation(code: str, new_indents: int) -> str: - """Change the indentation of `code` to `new_indents`""" - min_indents = find_minimum_indents(code) - return indent_lines(code, new_indents - min_indents) - - - -def __init__(self, query: str, columns: List[str]): - self.query = query - self.columns = columns - - -def add_methods(pymodule, class_scope, methods_sources): - source_code = pymodule.source_code - lines = pymodule.lines - insertion_line = class_scope.get_end() - if class_scope.get_scopes(): - insertion_line = class_scope.get_scopes()[-1].get_end() - insertion_offset = lines.get_line_end(insertion_line) - methods = "\n\n" + "\n\n".join(methods_sources) - indented_methods = fix_indentation( - methods, - get_indents(lines, class_scope.get_start()) - + get_indent(pymodule.pycore.project), - ) - result = [] - result.append(source_code[:insertion_offset]) - result.append(indented_methods) - result.append(source_code[insertion_offset:]) - return "".join(result) - - - -def get_body(pyfunction): - """Return unindented function body""" - # FIXME scope = pyfunction.get_scope() - pymodule = pyfunction.get_module() - start, end = get_body_region(pyfunction) - return fix_indentation(pymodule.source_code[start:end], 0) - - - -def get_body_region(defined): - """Return the start and end offsets of function body""" - scope = defined.get_scope() - pymodule = defined.get_module() - lines = pymodule.lines - node = defined.get_ast() - start_line = node.lineno - if defined.get_doc() is None: - start_line = node.body[0].lineno - elif len(node.body) > 1: - start_line = node.body[1].lineno - start = lines.get_line_start(start_line) - scope_start = pymodule.logical_lines.logical_line_in(scope.start) - if scope_start[1] >= start_line: - # a one-liner! - # XXX: what if colon appears in a string - start = pymodule.source_code.index(":", start) + 1 - while pymodule.source_code[start].isspace(): - start += 1 - end = min(lines.get_line_end(scope.end) + 1, len(pymodule.source_code)) - return start, end - - - -def get_indent(project): - return project.prefs.get("indent_size", 4) - -@path C:/Repos/ekr-rope/rope/refactor/ -from itertools import chain - -from rope.base import ast - - -@others -@language python -@tabwidth -4 - -def find_visible(node, lines): - """Return the line which is visible from all `lines`""" - root = ast_suite_tree(node) - return find_visible_for_suite(root, lines) - - - -def find_visible_for_suite(root, lines): - if len(lines) == 1: - return lines[0] - line1 = lines[0] - line2 = find_visible_for_suite(root, lines[1:]) - suite1 = root.find_suite(line1) - suite2 = root.find_suite(line2) - - @others - if valid(suite1) and not valid(suite2): - return line1 - if not valid(suite1) and valid(suite2): - return line2 - if not valid(suite1) and not valid(suite2): - return None - while suite1 != suite2 and suite1.parent != suite2.parent: - if suite1._get_level() < suite2._get_level(): - line2 = suite2.get_start() - suite2 = suite2.parent - elif suite1._get_level() > suite2._get_level(): - line1 = suite1.get_start() - suite1 = suite1.parent - else: - line1 = suite1.get_start() - line2 = suite2.get_start() - suite1 = suite1.parent - suite2 = suite2.parent - if suite1 == suite2: - return min(line1, line2) - return min(suite1.get_start(), suite2.get_start()) - - - -def valid(suite): - return suite is not None and not suite.ignored - - -def ast_suite_tree(node): - if hasattr(node, "lineno"): - lineno = node.lineno - else: - lineno = 1 - return Suite(node.body, lineno) - - - -class Suite: - @others - -def select(self, *columns: str): - if not (set(columns) <= set(self.columns)): - raise ValueError( - f"Unknown column names passed: {set(columns) - set(self.columns)}" - ) - - selected_columns = ", ".join(columns) - return FinalQuery(f"SELECT {selected_columns} FROM {self.query}") - - -def __init__(self, child_nodes, lineno, parent=None, ignored=False): - self.parent = parent - self.lineno = lineno - self.child_nodes = child_nodes - self._children = None - self.ignored = ignored - - -def get_start(self): - if self.parent is None: - if self.child_nodes: - return self.local_start() - else: - return 1 - return self.lineno - - -def get_children(self): - if self._children is None: - walker = _SuiteWalker(self) - for child in self.child_nodes: - ast.walk(child, walker) - self._children = walker.suites - return self._children - - -def local_start(self): - return self.child_nodes[0].lineno - - -def local_end(self): - end = self.child_nodes[-1].lineno - if self.get_children(): - end = max(end, self.get_children()[-1].local_end()) - return end - - -def find_suite(self, line): - if line is None: - return None - for child in self.get_children(): - if child.local_start() <= line <= child.local_end(): - return child.find_suite(line) - return self - - -def _get_level(self): - if self.parent is None: - return 0 - return self.parent._get_level() + 1 - - - -class _SuiteWalker: - @others - -def __init__(self, suite): - self.suite = suite - self.suites = [] - - -def _If(self, node): - self._add_if_like_node(node) - - -def select_star(self): - return FinalQuery(f"SELECT * FROM {self.query}") - - -def _For(self, node): - self._add_if_like_node(node) - - -def _While(self, node): - self._add_if_like_node(node) - - -def _With(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - - -def _AsyncWith(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - - -def _Match(self, node): - case_bodies = list( - chain.from_iterable([[case.pattern] + case.body for case in node.cases]) - ) - self.suites.append(Suite(case_bodies, node.lineno, self.suite)) - - -def _TryFinally(self, node): - proceed_to_except_handler = False - if len(node.finalbody) == 1: - try: - proceed_to_except_handler = isinstance( - node.handlers[0], ast.ExceptHandler - ) - except IndexError: - pass - if proceed_to_except_handler: - self._TryExcept(node) - else: - self.suites.append(Suite(node.body, node.lineno, self.suite)) - self.suites.append(Suite(node.finalbody, node.lineno, self.suite)) - - -def _Try(self, node): - if len(node.finalbody) == 1: - self._TryFinally(node) - else: - self._TryExcept(node) - - -def _TryExcept(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - for handler in node.handlers: - self.suites.append(Suite(handler.body, node.lineno, self.suite)) - if node.orelse: - self.suites.append(Suite(node.orelse, node.lineno, self.suite)) - - -def _add_if_like_node(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - if node.orelse: - self.suites.append(Suite(node.orelse, node.lineno, self.suite)) - - -def _FunctionDef(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) - - -def where(self, where_clause: str): - return Query( - f"{self.query} WHERE {where_clause}", - columns=self.columns, - ) - - -def _AsyncFunctionDef(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) - - -def _ClassDef(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) - -@path C:/Repos/ekr-rope/rope/refactor/ -import rope.refactor.importutils -from rope.base.change import ChangeSet, ChangeContents, MoveResource, CreateFolder - - -@others -@language python -@tabwidth -4 - -class ModuleToPackage: - @others - -def __init__(self, project, resource): - self.project = project - self.resource = resource - - -def get_changes(self): - changes = ChangeSet("Transform <%s> module to package" % self.resource.path) - new_content = self._transform_relatives_to_absolute(self.resource) - if new_content is not None: - changes.add_change(ChangeContents(self.resource, new_content)) - parent = self.resource.parent - name = self.resource.name[:-3] - changes.add_change(CreateFolder(parent, name)) - parent_path = parent.path + "/" - if not parent.path: - parent_path = "" - new_path = parent_path + "%s/__init__.py" % name - if self.resource.project == self.project: - changes.add_change(MoveResource(self.resource, new_path)) - return changes - - -def _transform_relatives_to_absolute(self, resource): - pymodule = self.project.get_pymodule(resource) - import_tools = rope.refactor.importutils.ImportTools(self.project) - return import_tools.relatives_to_absolutes(pymodule) - -@path C:/Repos/ekr-rope/rope/refactor/ -from rope.base import change, taskhandle, evaluate, exceptions, pyobjects, pynames, ast -from rope.base import libutils -from rope.refactor import restructure, sourceutils, similarfinder - - -@others -@language python -@tabwidth -4 - -class UseFunction: - """Try to use a function wherever possible""" - - @others - _rope_result = "_rope__result" - _rope_returned = "_rope__returned" - - - -def __init__(self, project, resource, offset): - self.project = project - self.offset = offset - this_pymodule = project.get_pymodule(resource) - pyname = evaluate.eval_location(this_pymodule, offset) - if pyname is None: - raise exceptions.RefactoringError("Unresolvable name selected") - self.pyfunction = pyname.get_object() - if not isinstance(self.pyfunction, pyobjects.PyFunction) or not isinstance( - self.pyfunction.parent, pyobjects.PyModule - ): - raise exceptions.RefactoringError( - "Use function works for global functions, only." - ) - self.resource = self.pyfunction.get_module().get_resource() - self._check_returns() - - -def transfered_offset(self, offset): - lineno = self.code.count("\n", 0, offset) - diff = sum(self.diffs[:lineno]) - return offset + diff - - -def insert_into(self) -> FinalQuery: - columns = ", ".join(self.columns) - placeholders = ", ".join(["?"] * len(self.columns)) - return FinalQuery( - f"INSERT INTO {self.query}({columns}) VALUES ({placeholders})" - ) - - -def _check_returns(self): - node = self.pyfunction.get_ast() - if _yield_count(node): - raise exceptions.RefactoringError( - "Use function should not be used on generatorS." - ) - returns = _return_count(node) - if returns > 1: - raise exceptions.RefactoringError( - "usefunction: Function has more than one return statement." - ) - if returns == 1 and not _returns_last(node): - raise exceptions.RefactoringError( - "usefunction: return should be the last statement." - ) - - -def get_changes(self, resources=None, task_handle=taskhandle.NullTaskHandle()): - if resources is None: - resources = self.project.get_python_files() - changes = change.ChangeSet("Using function <%s>" % self.pyfunction.get_name()) - if self.resource in resources: - newresources = list(resources) - newresources.remove(self.resource) - for c in self._restructure(newresources, task_handle).changes: - changes.add_change(c) - if self.resource in resources: - for c in self._restructure( - [self.resource], task_handle, others=False - ).changes: - changes.add_change(c) - return changes - - -def get_function_name(self): - return self.pyfunction.get_name() - - -def _restructure(self, resources, task_handle, others=True): - pattern = self._make_pattern() - goal = self._make_goal(import_=others) - imports = None - if others: - imports = ["import %s" % self._module_name()] - - body_region = sourceutils.get_body_region(self.pyfunction) - args_value = {"skip": (self.resource, body_region)} - args = {"": args_value} - - restructuring = restructure.Restructure( - self.project, pattern, goal, args=args, imports=imports - ) - return restructuring.get_changes(resources=resources, task_handle=task_handle) - - -def _find_temps(self): - return find_temps(self.project, self._get_body()) - - -def _module_name(self): - return libutils.modname(self.resource) - - -def _make_pattern(self): - params = self.pyfunction.get_param_names() - body = self._get_body() - body = restructure.replace(body, "return", "pass") - wildcards = list(params) - wildcards.extend(self._find_temps()) - if self._does_return(): - if self._is_expression(): - replacement = "${%s}" % self._rope_returned - else: - replacement = "{} = ${{{}}}".format( - self._rope_result, self._rope_returned - ) - body = restructure.replace( - body, "return ${%s}" % self._rope_returned, replacement - ) - wildcards.append(self._rope_result) - return similarfinder.make_pattern(body, wildcards) - - -def _get_body(self): - return sourceutils.get_body(self.pyfunction) - - -def _make_goal(self, import_=False): - params = self.pyfunction.get_param_names() - function_name = self.pyfunction.get_name() - if import_: - function_name = self._module_name() + "." + function_name - goal = "{}({})".format(function_name, ", ".join(("${%s}" % p) for p in params)) - if self._does_return() and not self._is_expression(): - goal = "${{{}}} = {}".format(self._rope_result, goal) - return goal - - -def _does_return(self): - body = self._get_body() - removed_return = restructure.replace(body, "return ${result}", "") - return removed_return != body - - -def drop_table(self) -> FinalQuery: - return FinalQuery(f"DROP TABLE {self.query}") - - -def _is_expression(self): - return len(self.pyfunction.get_ast().body) == 1 - - -def find_temps(project, code): - code = "def f():\n" + sourceutils.indent_lines(code, 4) - pymodule = libutils.get_string_module(project, code) - result = [] - function_scope = pymodule.get_scope().get_scopes()[0] - for name, pyname in function_scope.get_names().items(): - if isinstance(pyname, pynames.AssignedName): - result.append(name) - return result - - - -def _returns_last(node): - return node.body and isinstance(node.body[-1], ast.Return) - - - -def _namedexpr_last(node): - if not hasattr(ast, "NamedExpr"): # python<3.8 - return False - return ( - bool(node.body) - and len(node.body) == 1 - and isinstance(node.body[-1].value, ast.NamedExpr) - ) - - - -def _yield_count(node): - visitor = _ReturnOrYieldFinder() - visitor.start_walking(node) - return visitor.yields - - - -def _return_count(node): - visitor = _ReturnOrYieldFinder() - visitor.start_walking(node) - return visitor.returns - - - -def _named_expr_count(node): - visitor = _ReturnOrYieldFinder() - visitor.start_walking(node) - return visitor.named_expression - - - -class _ReturnOrYieldFinder: - @others - -def __init__(self): - self.returns = 0 - self.named_expression = 0 - self.yields = 0 - - -def _Return(self, node): - self.returns += 1 - - -def delete_from(self) -> FinalQuery: - return FinalQuery(f"DELETE FROM {self.query}") - - - -def _NamedExpr(self, node): - self.named_expression += 1 - - -def _Yield(self, node): - self.yields += 1 - - -def _FunctionDef(self, node): - pass - - -def _ClassDef(self, node): - pass - - -def start_walking(self, node): - nodes = [node] - if isinstance(node, ast.FunctionDef): - nodes = ast.get_child_nodes(node) - for child in nodes: - ast.walk(child, self) - -@path C:/Repos/ekr-rope/rope/refactor/ -from rope.base import ast, evaluate, builtins, pyobjects -from rope.refactor import patchedast, occurrences - - -@others -@language python -@tabwidth -4 - -class Wildcard: - def get_name(self): - """Return the name of this wildcard""" - - def matches(self, suspect, arg): - """Return `True` if `suspect` matches this wildcard""" - - - -class Suspect: - def __init__(self, pymodule, node, name): - self.name = name - self.pymodule = pymodule - self.node = node - - - -class DefaultWildcard: - """The default restructuring wildcard - - The argument passed to this wildcard is in the - ``key1=value1,key2=value2,...`` format. Possible keys are: - - * name - for checking the reference - * type - for checking the type - * object - for checking the object - * instance - for checking types but similar to builtin isinstance - * exact - matching only occurrences with the same name as the wildcard - * unsure - matching unsure occurrences - - """ - - @others - -def __init__(self, project): - self.project = project - - -class Name: - table_name = "names" - columns = [ - "name", - "module", - "package", - "source", - "type", - ] - - @others - objects = Query(table_name, columns) - - search_submodule_like = objects.where('module LIKE ("%." || ?)') - search_module_like = objects.where("module LIKE (?)") - - import_assist = objects.where("name LIKE (? || '%')") - - search_by_name_like = objects.where("name LIKE (?)") - - delete_by_module_name = objects.where("module = ?").delete_from() - - - -def get_name(self): - return "default" - - -def matches(self, suspect, arg=""): - args = parse_arg(arg) - - if not self._check_exact(args, suspect): - return False - if not self._check_object(args, suspect): - return False - return True - - -def _check_object(self, args, suspect): - kind = None - expected = None - unsure = args.get("unsure", False) - for check in ["name", "object", "type", "instance"]: - if check in args: - kind = check - expected = args[check] - if expected is not None: - checker = _CheckObject(self.project, expected, kind, unsure=unsure) - return checker(suspect.pymodule, suspect.node) - return True - - -def _check_exact(self, args, suspect): - node = suspect.node - if args.get("exact"): - if not isinstance(node, ast.Name) or not node.id == suspect.name: - return False - else: - if not isinstance(node, ast.expr): - return False - return True - - - -def parse_arg(arg): - if isinstance(arg, dict): - return arg - result = {} - tokens = arg.split(",") - for token in tokens: - if "=" in token: - parts = token.split("=", 1) - result[parts[0].strip()] = parts[1].strip() - else: - result[token.strip()] = True - return result - - - -class _CheckObject: - @others - -def __init__(self, project, expected, kind="object", unsure=False): - self.project = project - self.kind = kind - self.unsure = unsure - self.expected = self._evaluate(expected) - - -def __call__(self, pymodule, node): - pyname = self._evaluate_node(pymodule, node) - if pyname is None or self.expected is None: - return self.unsure - if self._unsure_pyname(pyname, unbound=self.kind == "name"): - return True - if self.kind == "name": - return self._same_pyname(self.expected, pyname) - else: - pyobject = pyname.get_object() - if self.kind == "object": - objects = [pyobject] - if self.kind == "type": - objects = [pyobject.get_type()] - if self.kind == "instance": - objects = [pyobject] - objects.extend(self._get_super_classes(pyobject)) - objects.extend(self._get_super_classes(pyobject.get_type())) - for pyobject in objects: - if self._same_pyobject(self.expected.get_object(), pyobject): - return True - return False - - -def _get_super_classes(self, pyobject): - result = [] - if isinstance(pyobject, pyobjects.AbstractClass): - for superclass in pyobject.get_superclasses(): - result.append(superclass) - result.extend(self._get_super_classes(superclass)) - return result - - -def _same_pyobject(self, expected, pyobject): - return expected == pyobject - - -@classmethod -def create_table(self, connection): - names_table = ( - "(name TEXT, module TEXT, package TEXT, source INTEGER, type INTEGER)" - ) - connection.execute(f"CREATE TABLE IF NOT EXISTS names{names_table}") - connection.execute("CREATE INDEX IF NOT EXISTS name ON names(name)") - connection.execute("CREATE INDEX IF NOT EXISTS module ON names(module)") - connection.execute("CREATE INDEX IF NOT EXISTS package ON names(package)") - - -def _same_pyname(self, expected, pyname): - return occurrences.same_pyname(expected, pyname) - - -def _unsure_pyname(self, pyname, unbound=True): - return self.unsure and occurrences.unsure_pyname(pyname, unbound) - - -def _split_name(self, name): - parts = name.split(".") - expression, kind = parts[0], parts[-1] - if len(parts) == 1: - kind = "name" - return expression, kind - - -def _evaluate_node(self, pymodule, node): - scope = pymodule.get_scope().get_inner_scope_for_line(node.lineno) - expression = node - if isinstance(expression, ast.Name) and isinstance(expression.ctx, ast.Store): - start, end = patchedast.node_region(expression) - text = pymodule.source_code[start:end] - return evaluate.eval_str(scope, text) - else: - return evaluate.eval_node(scope, expression) - - -def _evaluate(self, code): - attributes = code.split(".") - pyname = None - if attributes[0] in ("__builtin__", "__builtins__"): - - @others - pyobject = _BuiltinsStub() - else: - pyobject = self.project.get_module(attributes[0]) - for attribute in attributes[1:]: - pyname = pyobject[attribute] - if pyname is None: - return None - pyobject = pyname.get_object() - return pyname - -class _BuiltinsStub: - def get_attribute(self, name): - return builtins.builtins[name] - - def __getitem__(self, name): - return builtins.builtins[name] - - def __contains__(self, name): - return name in builtins.builtins - - -@path C:/Repos/ekr-rope/rope/refactor/ -"""rope refactor package - -This package contains modules that perform python refactorings. -Refactoring classes perform refactorings in 4 steps: - -1. Collect some data for performing the refactoring and use them - to construct a refactoring class. Like:: - - renamer = Rename(project, resource, offset) - -2. Some refactorings give you useful information about the - refactoring after their construction. Like:: - - print(renamer.get_old_name()) - -3. Give the refactoring class more information about how to - perform the refactoring and get the changes this refactoring is - going to make. This is done by calling `get_changes` method of the - refactoring class. Like:: - - changes = renamer.get_changes(new_name) - -4. You can commit the changes. Like:: - - project.do(changes) - -These steps are like the steps IDEs usually do for performing a -refactoring. These are the things an IDE does in each step: - -1. Construct a refactoring object by giving it information like - resource, offset and ... . Some of the refactoring problems (like - performing rename refactoring on language keywords) can be reported - here. -2. Print some information about the refactoring and ask the user - about the information that are necessary for completing the - refactoring (like new name). -3. Call the `get_changes` by passing it information asked from - the user (if necessary) and get and preview the changes returned by - it. -4. perform the refactoring. - -From ``0.5m5`` release the `get_changes()` method of some time- -consuming refactorings take an optional `rope.base.taskhandle. -TaskHandle` parameter. You can use this object for stopping or -monitoring the progress of refactorings. - -""" -from rope.refactor.importutils import ImportOrganizer # noqa -from rope.refactor.topackage import ModuleToPackage # noqa - - -__all__ = [ - "rename", - "move", - "inline", - "extract", - "restructure", - "topackage", - "importutils", - "usefunction", - "change_signature", - "encapsulate_field", - "introduce_factory", - "introduce_parameter", - "localtofield", - "method_object", - "multiproject", -] -@language python -@tabwidth -4 - - -@path C:/Repos/ekr-rope/rope/refactor/importutils/ -from rope.base import libutils -from rope.base import pyobjects, exceptions, stdmods -from rope.refactor import occurrences -from rope.refactor.importutils import importinfo - - -@others -@language python -@tabwidth -4 - -class ImportInfoVisitor: - @others - -class Package: - table_name = "packages" - columns = [ - "package", - "path", - ] - - @others - objects = Query(table_name, columns) - - delete_by_package_name = objects.where("package = ?").delete_from() - -def dispatch(self, import_): - try: - method_name = "visit" + import_.import_info.__class__.__name__ - method = getattr(self, method_name) - return method(import_, import_.import_info) - except exceptions.ModuleNotFoundError: - pass - - -def visitEmptyImport(self, import_stmt, import_info): - pass - - -def visitNormalImport(self, import_stmt, import_info): - pass - - -def visitFromImport(self, import_stmt, import_info): - pass - - - -class RelativeToAbsoluteVisitor(ImportInfoVisitor): - @others - -def __init__(self, project, current_folder): - self.to_be_absolute = [] - self.project = project - self.folder = current_folder - self.context = importinfo.ImportContext(project, current_folder) - - -def visitNormalImport(self, import_stmt, import_info): - self.to_be_absolute.extend(self._get_relative_to_absolute_list(import_info)) - new_pairs = [] - for name, alias in import_info.names_and_aliases: - resource = self.project.find_module(name, folder=self.folder) - if resource is None: - new_pairs.append((name, alias)) - continue - absolute_name = libutils.modname(resource) - new_pairs.append((absolute_name, alias)) - if not import_info._are_name_and_alias_lists_equal( - new_pairs, import_info.names_and_aliases - ): - import_stmt.import_info = importinfo.NormalImport(new_pairs) - - -def _get_relative_to_absolute_list(self, import_info): - result = [] - for name, alias in import_info.names_and_aliases: - if alias is not None: - continue - resource = self.project.find_module(name, folder=self.folder) - if resource is None: - continue - absolute_name = libutils.modname(resource) - if absolute_name != name: - result.append((name, absolute_name)) - return result - - -def visitFromImport(self, import_stmt, import_info): - resource = import_info.get_imported_resource(self.context) - if resource is None: - return None - absolute_name = libutils.modname(resource) - if import_info.module_name != absolute_name: - import_stmt.import_info = importinfo.FromImport( - absolute_name, 0, import_info.names_and_aliases - ) - - - -class FilteringVisitor(ImportInfoVisitor): - @others - -@classmethod -def create_table(self, connection): - packages_table = "(package TEXT, path TEXT)" - connection.execute(f"CREATE TABLE IF NOT EXISTS packages{packages_table}") - - -def __init__(self, project, folder, can_select): - self.to_be_absolute = [] - self.project = project - self.can_select = self._transform_can_select(can_select) - self.context = importinfo.ImportContext(project, folder) - - -def _transform_can_select(self, can_select): - def can_select_name_and_alias(name, alias): - imported = name - if alias is not None: - imported = alias - return can_select(imported) - - return can_select_name_and_alias - - -def visitNormalImport(self, import_stmt, import_info): - new_pairs = [ - (name, alias) - for name, alias in import_info.names_and_aliases - if self.can_select(name, alias) - ] - return importinfo.NormalImport(new_pairs) - - -def visitFromImport(self, import_stmt, import_info): - if _is_future(import_info): - return import_info - new_pairs = [] - if import_info.is_star_import(): - for name in import_info.get_imported_names(self.context): - if self.can_select(name, None): - new_pairs.append(import_info.names_and_aliases[0]) - break - else: - for name, alias in import_info.names_and_aliases: - if self.can_select(name, alias): - new_pairs.append((name, alias)) - return importinfo.FromImport( - import_info.module_name, import_info.level, new_pairs - ) - - - -class RemovingVisitor(ImportInfoVisitor): - @others - -def __init__(self, project, folder, can_select): - self.to_be_absolute = [] - self.project = project - self.filtering = FilteringVisitor(project, folder, can_select) - - -def dispatch(self, import_): - result = self.filtering.dispatch(import_) - if result is not None: - import_.import_info = result - - - -class AddingVisitor(ImportInfoVisitor): - """A class for adding imports - - Given a list of `ImportInfo`, it tries to add each import to the - module and returns `True` and gives up when an import can be added - to older ones. - - """ - - @others - -def __init__(self, project, import_list): - self.project = project - self.import_list = import_list - self.import_info = None - - -def dispatch(self, import_): - for import_info in self.import_list: - self.import_info = import_info - if ImportInfoVisitor.dispatch(self, import_): - return True - - -@path C:/Repos/ekr-rope/rope/contrib/autoimport/ -""" -Functions to find importable names. - -Can extract names from source code of a python file, .so object, or builtin module. -""" - -import ast -import inspect -import logging -import pathlib -from importlib import import_module -from typing import Generator, List - -from .defs import ( - ModuleCompiled, - ModuleFile, - ModuleInfo, - Name, - NameType, - Package, - PartialName, - Source, -) - -logger = logging.getLogger(__name__) - - -@others -@language python -@tabwidth -4 - -# TODO: Handle adding relative and absolute imports -def visitNormalImport(self, import_stmt, import_info): - if not isinstance(self.import_info, import_info.__class__): - return False - # Adding ``import x`` and ``import x.y`` that results ``import x.y`` - if ( - len(import_info.names_and_aliases) - == len(self.import_info.names_and_aliases) - == 1 - ): - imported1 = import_info.names_and_aliases[0] - imported2 = self.import_info.names_and_aliases[0] - if imported1[1] == imported2[1] is None: - if imported1[0].startswith(imported2[0] + "."): - return True - if imported2[0].startswith(imported1[0] + "."): - import_stmt.import_info = self.import_info - return True - # Multiple imports using a single import statement is discouraged - # so we won't bother adding them. - if self.import_info._are_name_and_alias_lists_equal( - import_info.names_and_aliases, self.import_info.names_and_aliases - ): - return True - - -def visitFromImport(self, import_stmt, import_info): - if ( - isinstance(self.import_info, import_info.__class__) - and import_info.module_name == self.import_info.module_name - and import_info.level == self.import_info.level - ): - if import_info.is_star_import(): - return True - if self.import_info.is_star_import(): - import_stmt.import_info = self.import_info - return True - if self.project.prefs.get("split_imports"): - return ( - self.import_info.names_and_aliases == import_info.names_and_aliases - ) - new_pairs = list(import_info.names_and_aliases) - for pair in self.import_info.names_and_aliases: - if pair not in new_pairs: - new_pairs.append(pair) - import_stmt.import_info = importinfo.FromImport( - import_info.module_name, import_info.level, new_pairs - ) - return True - - - -class ExpandStarsVisitor(ImportInfoVisitor): - @others - -def __init__(self, project, folder, can_select): - self.project = project - self.filtering = FilteringVisitor(project, folder, can_select) - self.context = importinfo.ImportContext(project, folder) - - -def visitNormalImport(self, import_stmt, import_info): - self.filtering.dispatch(import_stmt) - - -def visitFromImport(self, import_stmt, import_info): - if import_info.is_star_import(): - new_pairs = [ - (name, None) for name in import_info.get_imported_names(self.context) - ] - new_import = importinfo.FromImport( - import_info.module_name, import_info.level, new_pairs - ) - import_stmt.import_info = self.filtering.visitFromImport(None, new_import) - else: - self.filtering.dispatch(import_stmt) - - - -class SelfImportVisitor(ImportInfoVisitor): - @others - -def __init__(self, project, current_folder, resource): - self.project = project - self.folder = current_folder - self.resource = resource - self.to_be_fixed = set() - self.to_be_renamed = set() - self.context = importinfo.ImportContext(project, current_folder) - - -def visitNormalImport(self, import_stmt, import_info): - new_pairs = [] - for name, alias in import_info.names_and_aliases: - resource = self.project.find_module(name, folder=self.folder) - if resource is not None and resource == self.resource: - imported = name - if alias is not None: - imported = alias - self.to_be_fixed.add(imported) - else: - new_pairs.append((name, alias)) - if not import_info._are_name_and_alias_lists_equal( - new_pairs, import_info.names_and_aliases - ): - import_stmt.import_info = importinfo.NormalImport(new_pairs) - - -def visitFromImport(self, import_stmt, import_info): - resource = import_info.get_imported_resource(self.context) - if resource is None: - return - if resource == self.resource: - self._importing_names_from_self(import_info, import_stmt) - return - pymodule = self.project.get_pymodule(resource) - new_pairs = [] - for name, alias in import_info.names_and_aliases: - try: - result = pymodule[name].get_object() - if ( - isinstance(result, pyobjects.PyModule) - and result.get_resource() == self.resource - ): - imported = name - if alias is not None: - imported = alias - self.to_be_fixed.add(imported) - else: - new_pairs.append((name, alias)) - except exceptions.AttributeNotFoundError: - new_pairs.append((name, alias)) - if not import_info._are_name_and_alias_lists_equal( - new_pairs, import_info.names_and_aliases - ): - import_stmt.import_info = importinfo.FromImport( - import_info.module_name, import_info.level, new_pairs - ) - - -def get_type_ast(node: ast.AST) -> NameType: - """Get the lsp type of a node.""" - if isinstance(node, ast.ClassDef): - return NameType.Class - if isinstance(node, ast.FunctionDef): - return NameType.Function - if isinstance(node, ast.Assign): - return NameType.Variable - return NameType.Variable # default value - - - -def _importing_names_from_self(self, import_info, import_stmt): - if not import_info.is_star_import(): - for name, alias in import_info.names_and_aliases: - if alias is not None: - self.to_be_renamed.add((alias, name)) - import_stmt.empty_import() - - - -class SortingVisitor(ImportInfoVisitor): - @others - -def __init__(self, project, current_folder): - self.project = project - self.folder = current_folder - self.standard = set() - self.third_party = set() - self.in_project = set() - self.future = set() - self.context = importinfo.ImportContext(project, current_folder) - - -def visitNormalImport(self, import_stmt, import_info): - if import_info.names_and_aliases: - name, alias = import_info.names_and_aliases[0] - resource = self.project.find_module(name, folder=self.folder) - self._check_imported_resource(import_stmt, resource, name) - - -def visitFromImport(self, import_stmt, import_info): - resource = import_info.get_imported_resource(self.context) - self._check_imported_resource(import_stmt, resource, import_info.module_name) - - -def _check_imported_resource(self, import_stmt, resource, imported_name): - info = import_stmt.import_info - if resource is not None and resource.project == self.project: - self.in_project.add(import_stmt) - elif _is_future(info): - self.future.add(import_stmt) - elif imported_name.split(".")[0] in stdmods.standard_modules(): - self.standard.add(import_stmt) - else: - self.third_party.add(import_stmt) - - - -class LongImportVisitor(ImportInfoVisitor): - @others - -def __init__(self, current_folder, project, maxdots, maxlength): - self.maxdots = maxdots - self.maxlength = maxlength - self.to_be_renamed = set() - self.current_folder = current_folder - self.project = project - self.new_imports = [] - - -def visitNormalImport(self, import_stmt, import_info): - for name, alias in import_info.names_and_aliases: - if alias is None and self._is_long(name): - self.to_be_renamed.add(name) - last_dot = name.rindex(".") - from_ = name[:last_dot] - imported = name[last_dot + 1 :] - self.new_imports.append( - importinfo.FromImport(from_, 0, ((imported, None),)) - ) - - -def _is_long(self, name): - return name.count(".") > self.maxdots or ( - "." in name and len(name) > self.maxlength - ) - - - -def get_names_from_file( - module: pathlib.Path, - package_name: str = "", - underlined: bool = False, - process_imports: bool = False, -) -> Generator[PartialName, None, None]: - """Get all the names from a given file using ast.""" - try: - root_node = ast.parse(module.read_bytes()) - except SyntaxError as error: - print(error) - return - for node in ast.iter_child_nodes(root_node): - if isinstance(node, ast.Assign): - for target in node.targets: - try: - assert isinstance(target, ast.Name) - if underlined or not target.id.startswith("_"): - yield PartialName( - target.id, - get_type_ast(node), - ) - except (AttributeError, AssertionError): - # TODO handle tuple assignment - pass - elif isinstance(node, (ast.FunctionDef, ast.ClassDef)): - if underlined or not node.name.startswith("_"): - yield PartialName( - node.name, - get_type_ast(node), - ) - elif process_imports and isinstance(node, ast.ImportFrom): - # When we process imports, we want to include names in it's own package. - if node.level == 0: - continue - if not node.module or package_name is node.module.split(".")[0]: - continue - for name in node.names: - if isinstance(name, ast.alias): - if name.asname: - real_name = name.asname - else: - real_name = name.name - else: - real_name = name - if underlined or not real_name.startswith("_"): - yield PartialName(real_name, get_type_ast(node)) - - - -class RemovePyNameVisitor(ImportInfoVisitor): - @others - -def __init__(self, project, pymodule, pyname, folder): - self.pymodule = pymodule - self.pyname = pyname - self.context = importinfo.ImportContext(project, folder) - - -def visitFromImport(self, import_stmt, import_info): - new_pairs = [] - if not import_info.is_star_import(): - for name, alias in import_info.names_and_aliases: - try: - pyname = self.pymodule[alias or name] - if occurrences.same_pyname(self.pyname, pyname): - continue - except exceptions.AttributeNotFoundError: - pass - new_pairs.append((name, alias)) - return importinfo.FromImport( - import_info.module_name, import_info.level, new_pairs - ) - - -def dispatch(self, import_): - result = ImportInfoVisitor.dispatch(self, import_) - if result is not None: - import_.import_info = result - - - -def _is_future(info): - return isinstance(info, importinfo.FromImport) and info.module_name == "__future__" - -@path C:/Repos/ekr-rope/rope/refactor/importutils/ -@others -@language python -@tabwidth -4 - -class ImportStatement: - """Represent an import in a module - - `readonly` attribute controls whether this import can be changed - by import actions or not. - - """ - - @others - -def __init__( - self, import_info, start_line, end_line, main_statement=None, blank_lines=0 -): - self.start_line = start_line - self.end_line = end_line - self.readonly = False - self.main_statement = main_statement - self._import_info = None - self.import_info = import_info - self._is_changed = False - self.new_start = None - self.blank_lines = blank_lines - - -def _get_import_info(self): - return self._import_info - - -def _set_import_info(self, new_import): - if ( - not self.readonly - and new_import is not None - and not new_import == self._import_info - ): - self._is_changed = True - self._import_info = new_import - - -@language rest -"""Rope object analysis and inference package - -Rope makes some simplifying assumptions about a python program. It -assumes that a program only performs assignments and function calls. -Tracking assignments is simple and `PyName` objects handle that. The -main problem is function calls. Rope uses these two approaches for -obtaining call information: - -* Static object analysis: `rope.base.pycore.PyCore.analyze_module()` - - It can analyze modules to obtain information about functions. This - is done by analyzing function calls in a module or scope. Currently - SOA analyzes the scopes that are changed while saving or when the - user asks to analyze a module. That is mainly because static - analysis is time-consuming. - -* Dynamic object analysis: `rope.base.pycore.PyCore.run_module()` - - When you run a module or your testsuite, when DOA is enabled, it - collects information about parameters passed to and objects returned - from functions. The main problem with this approach is that it is - quite slow; Not when looking up the information but when collecting - them. - -An instance of `rope.base.oi.objectinfo.ObjectInfoManager` can be used -for accessing these information. It saves the data in a -`rope.base.oi.objectdb.ObjectDB` internally. - -Now if our objectdb does not know anything about a function and we -need the value returned by it, static object inference, SOI, comes -into play. It analyzes function body and tries to infer the object -that is returned from it (we usually need the returned value for the -given parameter objects). - -Rope might collect and store information for other `PyName`, too. -For instance rope stores the object builtin containers hold. - -""" - - - -@language rest -@wrap - -*** git pull upstream master - -*** git diff master..ekr-walk-special-case --name-only - -*** git diff master..ekr-walk-special-case -- rope\base - -Install all required packages: (from contributing.rst) -pip install -e .[dev] - -Run all unit tests: (from contributing.rst) -pytest -v -W ignore::DeprecationWarning - -Run black: python -m black rope - -@language rest -@nosearch - -C:\Repos\rope>python310 -m pip install -e .[dev] - -C:\Repos\rope>C:\Python\Python3.10\python.exe -m pip install -e .[dev] -Obtaining file:///C:/Repos/rope - Installing build dependencies ... done - Checking if build backend supports build_editable ... done - Getting requirements to build editable ... done - Installing backend dependencies ... done - Preparing editable metadata (pyproject.toml) ... done -Collecting pytoolconfig[global]>=1.2.2 - Downloading pytoolconfig-1.2.2-py3-none-any.whl (16 kB) -Requirement already satisfied: -pytest-timeout>=2.1.0 in c:\python\python3.10\lib\site-packages (from rope==1.4.0) (2.1.0) -Requirement already satisfied: -pytest>=7.0.1 in c:\python\python3.10\lib\site-packages (from rope==1.4.0) (7.1.3) -Requirement already satisfied: -build>=0.7.0 in c:\python\python3.10\lib\site-packages (from rope==1.4.0) (0.7.0) -Requirement already satisfied: -tomli>=1.0.0 in c:\python\python3.10\lib\site-packages (from build>=0.7.0->rope==1.4.0) (2.0.1) -Requirement already satisfied: -colorama in c:\python\python3.10\lib\site-packages (from build>=0.7.0->rope==1.4.0) (0.4.5) -Requirement already satisfied: -packaging>=19.0 in c:\python\python3.10\lib\site-packages (from build>=0.7.0->rope==1.4.0) (21.3) -Requirement already satisfied: -pep517>=0.9.1 in c:\python\python3.10\lib\site-packages (from build>=0.7.0->rope==1.4.0) (0.12.0) -Requirement already satisfied: -iniconfig in c:\python\python3.10\lib\site-packages (from pytest>=7.0.1->rope==1.4.0) (1.1.1) -Requirement already satisfied: -pluggy<2.0,>=0.12 in c:\python\python3.10\lib\site-packages (from pytest>=7.0.1->rope==1.4.0) (1.0.0) -Requirement already satisfied: -py>=1.8.2 in c:\python\python3.10\lib\site-packages (from pytest>=7.0.1->rope==1.4.0) (1.11.0) -Requirement already satisfied: -attrs>=19.2.0 in c:\python\python3.10\lib\site-packages (from pytest>=7.0.1->rope==1.4.0) (22.1.0) -Collecting appdirs>=1.4.4 - Downloading appdirs-1.4.4-py2.py3-none-any.whl (9.6 kB) -Requirement already satisfied: -pyparsing!=3.0.5,>=2.0.2 in c:\python\python3.10\lib\site-packages (from packaging>=19.0->build>=0.7.0->rope==1.4.0) (3.0.8) -Building wheels for collected packages: rope - Building editable for rope (pyproject.toml) ... done - Created wheel for rope: filename=rope-1.4.0-0.editable-py3-none-any.whl size=4230 sha256=2c7cdd9e629f640d7aad483db7a304292b53f109a9edf1c74f39d556f5542584 - Stored in directory: C:\Users\Dev\AppData\Local\Temp\pip-ephem-wheel-cache-amm6vn1a\wheels\2d\c8\16\7b23335844cf0cb3ba7735e296d501c516251327f7d24e7766 - -Successfully built rope -Installing collected packages: appdirs, pytoolconfig, rope -Successfully installed appdirs-1.4.4 pytoolconfig-1.2.2 rope-1.4.0 - -**appdirs**: module for determining appropriate platform-specific dirs, e.g. a "user data dir". - -**pytoolconfig**: -- manage configuration for python tools, such as black and rope -- add support for a pyproject.toml configuration file. -c.backup_helper(sub_dir='rope') - - - - -import rope.base.builtins -import rope.base.codeanalyze -import rope.base.evaluate -import rope.base.libutils -import rope.base.oi.soi -import rope.base.pyscopes -from rope.base import ( - pynamesdef as pynames, - exceptions, - ast, - astutils, - pyobjects, - fscommands, - arguments, - utils, -) - - - -@path C:/Repos/ekr-rope/rope/base/ -from rope.base import ast - - -def get_name_levels(node): - """Return a list of ``(name, level)`` tuples for assigned names - - The `level` is `None` for simple assignments and is a list of - numbers for tuple assignments for example in:: - - a, (b, c) = x - - The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for - `c` is ``[1, 1]``. - - """ - visitor = _NodeNameCollector() - ast.walk(node, visitor) - return visitor.names - - -@others -@language python -@tabwidth -4 - - - - - - -class _NodeNameCollector: - @others - -def _Slice(self, node): - self._add_node(node) - -def __init__(self, levels=None): - self.names = [] - self.levels = levels - self.index = 0 - - -def _add_node(self, node): - new_levels = [] - if self.levels is not None: - new_levels = list(self.levels) - new_levels.append(self.index) - self.index += 1 - self._added(node, new_levels) - - -def _added(self, node, levels): - if hasattr(node, "id"): - self.names.append((node.id, levels)) - - -def _Name(self, node): - self._add_node(node) - - -def _ExceptHandler(self, node): - self.names.append((node.name, [])) - - -def _Tuple(self, node): - new_levels = [] - if self.levels is not None: - new_levels = list(self.levels) - new_levels.append(self.index) - self.index += 1 - visitor = _NodeNameCollector(new_levels) - for child in ast.get_child_nodes(node): - ast.walk(child, visitor) - self.names.extend(visitor.names) - - -def _Subscript(self, node): - self._add_node(node) - - -def _Attribute(self, node): - self._add_node(node) - - - - -When checked, the Find and Change commands ignore the case of alphabetic characters when determining matches. - - -@language rest -@wrap - -https://github.com/edreamleo/ekr-rope/pull/5 - -- Remove pylint complaint:consider using decorator instead of class method. -- Use type annotations instead of type comments. - -@language python -@nosearch - - - - - -@language rest -@wrap - -? Remove @multi ? - -@language python -@nosearch - -@nosearch -@nosearch - -# Regex, Head, Body - -# found 49 nodes - -# Fail: test_new_style_relative_imports - -@nosearch -@nosearch - -# Word, Head, Body - -# found 38 nodes - - - - - - -@nosearch - -# Word, Head, Body - -# found 7 nodes -@language rest -@wrap - -ropetest/pycoretest.py::PyCoreInProjectsTest::test_new_style_relative_imports1 - -=== Good - -test_new_style_relative_imports1 mod1 <rope.base.resources.File "pkg/mod1.py" at 0x27909c1e650> -test_new_style_relative_imports1 mod2 <rope.base.resources.File "pkg/mod2.py" at 0x27909c1e860> -test_new_style_relative_imports1 mod1_object <rope.base.pyobjectsdef.PyModule "pkg.mod1" at 0x27909ca08e0> -test_new_style_relative_imports1 mod2_object <rope.base.pyobjectsdef.PyModule "pkg.mod2" at 0x27909c1ebf0> - -*** _ImportFrom: imported_module.module_name: '' - -=== Bad - -test_new_style_relative_imports1 mod1 <rope.base.resources.File "pkg/mod1.py" at 0x20a074224d0> -test_new_style_relative_imports1 mod2 <rope.base.resources.File "pkg/mod2.py" at 0x20a074226e0> -test_new_style_relative_imports1 mod1_object <rope.base.pyobjectsdef.PyModule "pkg.mod1" at 0x20a074a8760> -test_new_style_relative_imports1 mod2_object <rope.base.pyobjectsdef.PyModule "pkg.mod2" at 0x20a07422a70> - -*** _ImportFrom: imported_module.module_name: None - -@nosearch -@nosearch - -# Word, Head, Body - -# found 4 nodes -@nosearch - -# Word, Head, Body - -# found 9 nodes -@path C:/Repos/ekr-rope/rope/base/ -@nopyflakes -import ast -from ast import * - -from rope.base import fscommands - - -@others -@language python -@tabwidth -4 - -def parse(source, filename="<string>"): - # NOTE: the raw string should be given to `compile` function - if isinstance(source, str): - source = fscommands.unicode_to_file_data(source) - if b"\r" in source: - source = source.replace(b"\r\n", b"\n").replace(b"\r", b"\n") - if not source.endswith(b"\n"): - source += b"\n" - try: - return ast.parse(source, filename="<unknown>") - except (TypeError, ValueError) as e: - error = SyntaxError() - error.lineno = 1 - error.filename = filename - error.msg = str(e) - raise error - - - -def walk(node, walker) -> None: - """Walk the syntax tree""" - method_name = "_" + node.__class__.__name__ - method = getattr(walker, method_name, None) - if method is not None: - if isinstance(node, ast.ImportFrom) and node.module is None: - # In python < 2.7 ``node.module == ''`` for relative imports - # but for python 2.7 it is None. Generalizing it to ''. - node.module = "" - method(node) - return - for child in get_child_nodes(node): - walk(child, walker) - - - -def get_child_nodes(node): - if isinstance(node, ast.Module): - return node.body - result = [] - if node._fields is not None: - for name in node._fields: - child = getattr(node, name) - if isinstance(child, list): - for entry in child: - if isinstance(entry, ast.AST): - result.append(entry) - if isinstance(child, ast.AST): - result.append(child) - return result - - - -def call_for_nodes(node, callback, recursive=False): - """If callback returns `True` the child nodes are skipped""" - result = callback(node) - if recursive and not result: - for child in get_child_nodes(node): - call_for_nodes(child, callback, recursive) - - - -def get_children(node): - result = [] - if node._fields is not None: - for name in node._fields: - if name in ["lineno", "col_offset"]: - continue - child = getattr(node, name) - result.append(child) - return result - -@nosearch - -# Word, Head, Body - -# found 8 nodes -@nosearch - -# Word, Head, Body - -# found 23 nodes -@nosearch - -# Word, Body - -# found 8 nodes -@nosearch - -# B007 Loop control variable 'i' not used within the loop body. If this is intended, start the name with an underscore. - -.\rope\base\codeanalyze.py:184:20: B007 Loop control variable 'end' not used within the loop body. - -.\rope\base\history.py:109:13: B007 Loop control variable 'i' not used within the loop body. -.\rope\base\history.py:119:13: B007 Loop control variable 'i' not used within the loop body. - -.\rope\base\project.py:159:13: B007 Loop control variable 'i' not used within the loop body. - -.\rope\base\oi\type_hinting\providers\numpydocstrings.py:22:29: B007 Loop control variable 'p_descr' not used within the loop body. - -.\rope\contrib\changestack.py:35:13: B007 Loop control variable 'i' not used within the loop body. - -.\rope\contrib\generate.py:377:23: B007 Loop control variable 'value' not used within the loop body. - -.\rope\refactor\move.py:709:13: B007 Loop control variable 'occurrence' not used within the loop body. - -.\rope\refactor\patchedast.py:192:13: B007 Loop control variable 'i' not used within the loop body. -.\rope\refactor\patchedast.py:198:13: B007 Loop control variable 'i' not used within the loop body. - -.\rope\refactor\importutils\module_imports.py:577:13: B007 Loop control variable 'index' not used within the loop body. - -# B011 Do not call assert False since python -O removes these calls. Instead callers should raise AssertionError(). -.\rope\refactor\extract.py:906:13: B011 Do not call assert False - -.\rope\refactor\patchedast.py:403:9: B011 Do not call assert False - -# E741 ambiguous variable name - -.\rope\base\pyscopes.py:331:13: E741 ambiguous variable name 'l' -.\rope\refactor\sourceutils.py:23:9: E741 ambiguous variable name 'l' -.\ropetest\builtinstest.py:360:9: E741 ambiguous variable name 'l' - -# All others - -.\rope\base\utils\pycompat.py:2:1: F401 'builtins' imported but unused - -.\rope\base\oi\soa.py:25:9: E731 do not assign a lambda expression, use a def -.\rope\base\oi\soa.py:26:9: E731 do not assign a lambda expression, use a def - -.\rope\base\pynamesdef.py:3:1: F403 'from rope.base.pynames import *' used; unable to detect undefined names -.\rope\base\pynamesdef.py:16:6: F405 'utils' may be undefined, or defined from star imports: rope.base.pynames - -# Disambiguate placeholder classes - -# PR: https://github.com/python-rope/rope/pull/539/ - - -@language rest -@wrap - -PR: https://github.com/python-rope/rope/pull/540 - -To do: create new PR that doesn't change so much. - - -# git-diff-pr won't work at present. -from leo.commands import editFileCommands as efc - -efc.GitDiffController(c).diff_two_revs( - rev1='master', # Old - # rev2='ekr-walk-special-case', # New - rev2='HEAD' -) - -g.cls() -import os -import leo.commands.editFileCommands as efc -path = g.os_path_finalize_join(g.app.loadDir, '..', '..') -print('path:', path) -os.chdir(path) - -# Any revspec is valid as an argument to the "branch1" and "branch2" args. -# See https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection - -efc.GitDiffController(c).diff_two_branches( - branch1='6.6.4', # old branch/rev - branch2='ekr-index', # new branch/rev - fn='leo/plugins/qt_text.py', # Don't use back slashes. -) - -g.cls() - -# Monkey-patched git-diff-pr command. -import leo.commands.editFileCommands as efc - -rev1 = 'master' -rev2 = 'ekr-walk-special-case' -x = efc.GitDiffController(c) - -@others - -# Monkey-patch, with x bound. -x.make_diff_outlines = make_diff_outlines_ignoring_comments -x.diff_two_revs(rev1, rev2) - -def make_diff_outlines_ignoring_comments(c1, c2, fn, rev1='', rev2=''): - """Create an outline-oriented diff from the *hidden* outlines c1 and c2.""" - self = x - added, deleted, changed = self.compute_dicts(c1, c2) - table = ( - (added, 'Added'), - (deleted, 'Deleted'), - (changed, 'Changed')) - for d, kind in table: - if kind.lower() == 'changed': - for key in d: - v1, v2 = d.get(key) - v1.b = strip_comments(v1.b) - v2.b = strip_comments(v2.b) - self.create_compare_node(c1, c2, d, kind, rev1, rev2) - -def strip_comments(aString): - """ - Strip everything that looks like a comment from aString. - It's fine, for now, to ignore strings and docstrings. - """ - result = [] - lines = g.splitLines(aString) - for s in lines: - if s.strip().startswith('#@'): - # Retain everything that looks like a sentinel. - result.append(s) - else: - # Strip the comment, ignoring the end of the line. - i = s.find('#') - if i == -1: - result.append(s) - else: - tail = s[:i] - if tail.strip(): - result.append(tail.rstrip() + '\n') - return ''.join(result) - -from leo.commands import editFileCommands as efc - -efc.GitDiffController(c).diff_two_revs( - rev1='master', # Old - rev2='HEAD' # New -) - -@ignore -@nosearch - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,14 +1,9 @@ --def walk(node, walker) -> None: -+def walk(node, walker): - """Walk the syntax tree""" - method_name = "_" + node.__class__.__name__ - method = getattr(walker, method_name, None) - if method is not None: -- if isinstance(node, ast.ImportFrom) and node.module is None: -- # In python < 2.7 ``node.module == ''`` for relative imports -- # but for python 2.7 it is None. Generalizing it to ''. -- node.module = "" -- method(node) -- return -+ return method(node) - for child in get_child_nodes(node): - walk(child, walker) - -@language python - -def walk(node, walker) -> None: - """Walk the syntax tree""" - method_name = "_" + node.__class__.__name__ - method = getattr(walker, method_name, None) - if method is not None: - if isinstance(node, ast.ImportFrom) and node.module is None: - # In python < 2.7 ``node.module == ''`` for relative imports - # but for python 2.7 it is None. Generalizing it to ''. - node.module = "" - method(node) - return - for child in get_child_nodes(node): - walk(child, walker) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -22,17 +22,12 @@ - raise error - - --def walk(node, walker) -> None: -+def walk(node, walker): - """Walk the syntax tree""" - method_name = "_" + node.__class__.__name__ - method = getattr(walker, method_name, None) - if method is not None: -- if isinstance(node, ast.ImportFrom) and node.module is None: -- # In python < 2.7 ``node.module == ''`` for relative imports -- # but for python 2.7 it is None. Generalizing it to ''. -- node.module = "" -- method(node) -- return -+ return method(node) - for child in get_child_nodes(node): - walk(child, walker) -@language python - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -537,6 +537,12 @@ - - def _ImportFrom(self, node): - level = 0 -+ # From walk -+ assert isinstance(node, ast.ImportFrom) -+ if node.module is None: -+ # In python < 2.7 ``node.module == ''`` for relative imports -+ # but for python 2.7 it is None. Generalizing it to ''. -+ node.module = "" - if node.level: - level = node.level - imported_module = pynames.ImportedModule(self.get_module(), node.module, level) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,11 @@ - def _ImportFrom(self, node): - level = 0 -+ # From walk -+ assert isinstance(node, ast.ImportFrom) -+ if node.module is None: -+ # In python < 2.7 ``node.module == ''`` for relative imports -+ # but for python 2.7 it is None. Generalizing it to ''. -+ node.module = "" - if node.level: - level = node.level - imported_module = pynames.ImportedModule(self.get_module(), node.module, level) -@language python - -def _ImportFrom(self, node): - level = 0 - if node.level: - level = node.level - imported_module = pynames.ImportedModule(self.get_module(), node.module, level) - if self._is_ignored_import(imported_module): - return - if len(node.names) == 1 and node.names[0].name == "*": - if isinstance(self.owner_object, PyModule): - self.owner_object.star_imports.append(StarImport(imported_module)) - else: - for imported_name in node.names: - imported = imported_name.name - alias = imported_name.asname - if alias is not None: - imported = alias - self.names[imported] = pynames.ImportedName( - imported_module, imported_name.name - ) - - -@ignore -@nosearch - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,20 +1,19 @@ - @path C:/Repos/ekr-rope/rope/base/ -+import ast - from operator import itemgetter - from typing import Optional, Tuple - -+import rope.base.astutils as au - import rope.base.builtins --import rope.base.pynames - import rope.base.pyobjects - from rope.base import ( -- ast, -- astutils, -+ arguments, - exceptions, -+ pynames, - pyobjects, - pyobjectsdef, -- arguments, - worder, - ) -- - - BadIdentifierError = exceptions.BadIdentifierError - -@language python - -@path C:/Repos/ekr-rope/rope/base/ -from operator import itemgetter -from typing import Optional, Tuple - -import rope.base.builtins -import rope.base.pynames -import rope.base.pyobjects -from rope.base import ( - ast, - astutils, - exceptions, - pyobjects, - pyobjectsdef, - arguments, - worder, -) - - -BadIdentifierError = exceptions.BadIdentifierError - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def eval_node2(scope, node): - evaluator = StatementEvaluator(scope) -- ast.walk(node, evaluator) -+ au.walk(node, evaluator) - return evaluator.old_result, evaluator.result - - -@language python - -def eval_node2(scope, node): - evaluator = StatementEvaluator(scope) - ast.walk(node, evaluator) - return evaluator.old_result, evaluator.result - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - def eval_str2(holding_scope, name): - try: - # parenthesizing for handling cases like 'a_var.\nattr' -- node = ast.parse("(%s)" % name) -+ node = au.parse("(%s)" % name) - except SyntaxError: - raise BadIdentifierError("Not a resolvable python identifier selected.") - return eval_node2(holding_scope, node) -@language python - -def eval_str2(holding_scope, name): - try: - # parenthesizing for handling cases like 'a_var.\nattr' - node = ast.parse("(%s)" % name) - except SyntaxError: - raise BadIdentifierError("Not a resolvable python identifier selected.") - return eval_node2(holding_scope, node) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - def get_primary_and_pyname_at( - self, - offset: int, --) -> Tuple[Optional[rope.base.pynames.PyName], Optional[rope.base.pynames.PyName]]: -+) -> Tuple[Optional[pynames.PyName], Optional[pynames.PyName]]: - lineno = self.lines.get_line_number(offset) - holding_scope = self.module_scope.get_inner_scope_for_offset(offset) - # function keyword parameter -@@ -12,7 +12,7 @@ - parameter_name = pyobject.get_parameters().get(keyword_name, None) - return (None, parameter_name) - elif isinstance(pyobject, pyobjects.AbstractFunction): -- parameter_name = rope.base.pynames.ParameterName() -+ parameter_name = pynames.ParameterName() - return (None, parameter_name) - # class body - if self._is_defined_in_class_body(holding_scope, offset, lineno): -@language python - -def get_primary_and_pyname_at( - self, - offset: int, -) -> Tuple[Optional[rope.base.pynames.PyName], Optional[rope.base.pynames.PyName]]: - lineno = self.lines.get_line_number(offset) - holding_scope = self.module_scope.get_inner_scope_for_offset(offset) - # function keyword parameter - if self.worder.is_function_keyword_parameter(offset): - keyword_name = self.worder.get_word_at(offset) - pyobject = self.get_enclosing_function(offset) - if isinstance(pyobject, pyobjectsdef.PyFunction): - parameter_name = pyobject.get_parameters().get(keyword_name, None) - return (None, parameter_name) - elif isinstance(pyobject, pyobjects.AbstractFunction): - parameter_name = rope.base.pynames.ParameterName() - return (None, parameter_name) - # class body - if self._is_defined_in_class_body(holding_scope, offset, lineno): - class_scope = holding_scope - if lineno == holding_scope.get_start(): - class_scope = holding_scope.parent - name = self.worder.get_primary_at(offset).strip() - try: - return (None, class_scope.pyobject[name]) - except rope.base.exceptions.AttributeNotFoundError: - return (None, None) - # function header - if self._is_function_name_in_function_header(holding_scope, offset, lineno): - name = self.worder.get_primary_at(offset).strip() - return (None, holding_scope.parent[name]) - # module in a from statement or an imported name that is aliased - if self.worder.is_from_statement_module( - offset - ) or self.worder.is_import_statement_aliased_module(offset): - module = self.worder.get_primary_at(offset) - module_pyname = self._find_module(module) - return (None, module_pyname) - if self.worder.is_from_aliased(offset): - name = self.worder.get_from_aliased(offset) - else: - name = self.worder.get_primary_at(offset) - return eval_str2(holding_scope, name) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,7 @@ - dots = 0 - while module_name[dots] == ".": - dots += 1 -- return rope.base.pynames.ImportedModule( -+ return pynames.ImportedModule( - self.module_scope.pyobject, module_name[dots:], dots - ) - -@language python - -def _find_module(self, module_name): - dots = 0 - while module_name[dots] == ".": - dots += 1 - return rope.base.pynames.ImportedModule( - self.module_scope.pyobject, module_name[dots:], dots - ) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - def _Attribute(self, node): - pyname = eval_node(self.scope, node.value) - if pyname is None: -- pyname = rope.base.pynames.UnboundName() -+ pyname = pynames.UnboundName() - self.old_result = pyname - if pyname.get_object() != rope.base.pyobjects.get_unknown(): - try: -@language python - -def _Attribute(self, node): - pyname = eval_node(self.scope, node.value) - if pyname is None: - pyname = rope.base.pynames.UnboundName() - self.old_result = pyname - if pyname.get_object() != rope.base.pyobjects.get_unknown(): - try: - self.result = pyname.get_object()[node.attr] - except exceptions.AttributeNotFoundError: - self.result = None - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -14,7 +14,7 @@ - result = _get_returned(new_function) - if result is None or result == rope.base.pyobjects.get_unknown(): - result = rope.base.pyobjects.PyObject(pyobject) -- self.result = rope.base.pynames.UnboundName(pyobject=result) -+ self.result = pynames.UnboundName(pyobject=result) - return - - pyfunction = None -@@ -23,7 +23,7 @@ - elif "__call__" in pyobject: - pyfunction = pyobject["__call__"].get_object() - if pyfunction is not None: -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=_get_returned(pyfunction) - ) - -@language python - -def _Call(self, node): - primary, pyobject = self._get_primary_and_object_for_node(node.func) - if pyobject is None: - return - - def _get_returned(pyobject): - args = arguments.create_arguments(primary, pyobject, node, self.scope) - return pyobject.get_returned_object(args) - - if isinstance(pyobject, rope.base.pyobjects.AbstractClass): - result = None - if "__new__" in pyobject: - new_function = pyobject["__new__"].get_object() - result = _get_returned(new_function) - if result is None or result == rope.base.pyobjects.get_unknown(): - result = rope.base.pyobjects.PyObject(pyobject) - self.result = rope.base.pynames.UnboundName(pyobject=result) - return - - pyfunction = None - if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): - pyfunction = pyobject - elif "__call__" in pyobject: - pyfunction = pyobject["__call__"].get_object() - if pyfunction is not None: - self.result = rope.base.pynames.UnboundName( - pyobject=_get_returned(pyfunction) - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _Str(self, node): -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_str() - ) - -@language python - -def _Str(self, node): - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_str() - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,4 @@ - def _get_builtin_name(self, type_name): - pytype = rope.base.builtins.builtins[type_name].get_object() -- return rope.base.pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) -+ return pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) - -@language python - -def _get_builtin_name(self, type_name): - pytype = rope.base.builtins.builtins[type_name].get_object() - return rope.base.pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _BinOp(self, node): -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - self._get_object_for_node(node.left) - ) - -@language python - -def _BinOp(self, node): - self.result = rope.base.pynames.UnboundName( - self._get_object_for_node(node.left) - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,5 +2,5 @@ - pyobject = self._get_object_for_node(node.values[0]) - if pyobject is None: - pyobject = self._get_object_for_node(node.values[1]) -- self.result = rope.base.pynames.UnboundName(pyobject) -+ self.result = pynames.UnboundName(pyobject) - -@language python - -def _BoolOp(self, node): - pyobject = self._get_object_for_node(node.values[0]) - if pyobject is None: - pyobject = self._get_object_for_node(node.values[1]) - self.result = rope.base.pynames.UnboundName(pyobject) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _UnaryOp(self, node): -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - self._get_object_for_node(node.operand) - ) - -@language python - -def _UnaryOp(self, node): - self.result = rope.base.pynames.UnboundName( - self._get_object_for_node(node.operand) - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -9,7 +9,7 @@ - keys = self._get_object_for_node(keys) - if values: - values = self._get_object_for_node(values) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_dict(keys, values) - ) - -@language python - -def _Dict(self, node): - keys = None - values = None - if node.keys and node.keys[0]: - keys, values = next( - iter(filter(itemgetter(0), zip(node.keys, node.values))), (None, None) - ) - if keys: - keys = self._get_object_for_node(keys) - if values: - values = self._get_object_for_node(values) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_dict(keys, values) - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,7 @@ - holding = None - if node.elts: - holding = self._get_object_for_node(node.elts[0]) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_list(holding) - ) - -@language python - -def _List(self, node): - holding = None - if node.elts: - holding = self._get_object_for_node(node.elts[0]) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_list(holding) - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def _ListComp(self, node): - pyobject = self._what_does_comprehension_hold(node) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_list(pyobject) - ) - -@language python - -def _ListComp(self, node): - pyobject = self._what_does_comprehension_hold(node) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_list(pyobject) - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def _GeneratorExp(self, node): - pyobject = self._what_does_comprehension_hold(node) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_iterator(pyobject) - ) - -@language python - -def _GeneratorExp(self, node): - pyobject = self._what_does_comprehension_hold(node) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_iterator(pyobject) - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,7 +6,7 @@ - objects.append(pyobject) - else: - objects.append(self._get_object_for_node(node.elts[0])) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_tuple(*objects) - ) - -@language python - -def _Tuple(self, node): - objects = [] - if len(node.elts) < 4: - for stmt in node.elts: - pyobject = self._get_object_for_node(stmt) - objects.append(pyobject) - else: - objects.append(self._get_object_for_node(node.elts[0])) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_tuple(*objects) - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -12,7 +12,7 @@ - if other_args: - args += other_args - arguments_ = arguments.Arguments(args, self.scope) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=called.get_returned_object(arguments_) - ) - -@language python - -def _call_function(self, node, function_name, other_args=None): - pyname = eval_node(self.scope, node) - if pyname is not None: - pyobject = pyname.get_object() - else: - return - if function_name in pyobject: - called = pyobject[function_name].get_object() - if not called or not isinstance(called, pyobjects.AbstractFunction): - return - args = [node] - if other_args: - args += other_args - arguments_ = arguments.Arguments(args, self.scope) - self.result = rope.base.pynames.UnboundName( - pyobject=called.get_returned_object(arguments_) - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _Lambda(self, node): -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.Lambda(node, self.scope) - ) - -@language python - -def _Lambda(self, node): - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.Lambda(node, self.scope) - ) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,8 @@ - def _get_evaluated_names(targets, assigned, module, evaluation, lineno): - result = {} -- for name, levels in astutils.get_name_levels(targets): -- assignment = rope.base.pynames.AssignmentValue(assigned, levels, evaluation) -- # XXX: this module should not access `rope.base.pynamesdef`! -- pyname = rope.base.pynamesdef.AssignedName(lineno, module) -+ for name, levels in au.get_name_levels(targets): -+ assignment = pynames.AssignmentValue(assigned, levels, evaluation) -+ pyname = rope.base.pynames.AssignedName(lineno, module) - pyname.assignments.append(assignment) - result[name] = pyname - return result -@language python - -def _get_evaluated_names(targets, assigned, module, evaluation, lineno): - result = {} - for name, levels in astutils.get_name_levels(targets): - assignment = rope.base.pynames.AssignmentValue(assigned, levels, evaluation) - # XXX: this module should not access `rope.base.pynamesdef`! - pyname = rope.base.pynamesdef.AssignedName(lineno, module) - pyname.assignments.append(assignment) - result[name] = pyname - return result - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,8 @@ --import rope.base.ast -+import ast -+ -+import rope.base.astutils as au - import rope.base.oi.soi --import rope.base.pynames --from rope.base import pyobjects, evaluate, astutils, arguments -- -+from rope.base import arguments, evaluate, pyobjects, pynames - - def analyze_module(pycore, pymodule, should_analyze, search_subscopes, followed_calls): - """Analyze `pymodule` for static object inference -@@ -33,8 +33,8 @@ - if not followed_calls: - _follow = None - visitor = SOAVisitor(pycore, pydefined, _follow) -- for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): -- rope.base.ast.walk(child, visitor) -+ for child in au.get_child_nodes(pydefined.get_ast()): -+ au.walk(child, visitor) - - - class SOAVisitor: -@@ -51,8 +51,8 @@ - pass - - def _Call(self, node): -- for child in rope.base.ast.get_child_nodes(node): -- rope.base.ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - primary, pyname = evaluate.eval_node2(self.scope, node.func) - if pyname is None: - return -@@ -63,7 +63,7 @@ - pyclass = pyfunction - if "__init__" in pyfunction: - pyfunction = pyfunction["__init__"].get_object() -- pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass)) -+ pyname = pynames.UnboundName(pyobjects.PyObject(pyclass)) - args = self._args_with_self(primary, pyname, pyfunction, node) - elif "__call__" in pyfunction: - pyfunction = pyfunction["__call__"].get_object() -@@ -99,23 +99,23 @@ - ] - - def _AnnAssign(self, node): -- for child in rope.base.ast.get_child_nodes(node): -- rope.base.ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - visitor = _SOAAssignVisitor() - nodes = [] - -- rope.base.ast.walk(node.target, visitor) -+ au.walk(node.target, visitor) - nodes.extend(visitor.nodes) - - self._evaluate_assign_value(node, nodes, type_hint=node.annotation) - - def _Assign(self, node): -- for child in rope.base.ast.get_child_nodes(node): -- rope.base.ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - visitor = _SOAAssignVisitor() - nodes = [] - for child in node.targets: -- rope.base.ast.walk(child, visitor) -+ au.walk(child, visitor) - nodes.extend(visitor.nodes) - self._evaluate_assign_value(node, nodes) - -@@ -124,12 +124,12 @@ - instance = evaluate.eval_node(self.scope, subscript.value) - args_pynames = [evaluate.eval_node(self.scope, subscript.slice)] - value = rope.base.oi.soi._infer_assignment( -- rope.base.pynames.AssignmentValue( -+ pynames.AssignmentValue( - node.value, levels, type_hint=type_hint - ), - self.pymodule, - ) -- args_pynames.append(rope.base.pynames.UnboundName(value)) -+ args_pynames.append(pynames.UnboundName(value)) - if instance is not None and value is not None: - pyobject = instance.get_object() - if "__setitem__" in pyobject: -@@ -139,13 +139,13 @@ - # IDEA: handle `__setslice__`, too - - --class _SOAAssignVisitor(astutils._NodeNameCollector): -+class _SOAAssignVisitor(au._NodeNameCollector): - def __init__(self): - super().__init__() - self.nodes = [] - - def _added(self, node, levels): -- if isinstance(node, rope.base.ast.Subscript) and isinstance( -- node.slice, (rope.base.ast.Index, rope.base.ast.expr) -+ if isinstance(node, ast.Subscript) and isinstance( -+ node.slice, (ast.Index, ast.expr) - ): - self.nodes.append((node, levels)) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,9 @@ - @path C:/Repos/ekr-rope/rope/base/oi/ --import rope.base.ast -+import ast -+ -+import rope.base.astutils as au - import rope.base.oi.soi --import rope.base.pynames --from rope.base import pyobjects, evaluate, astutils, arguments -- -+from rope.base import arguments, evaluate, pyobjects, pynames - - @others - @language python -@language python - -@path C:/Repos/ekr-rope/rope/base/oi/ -import rope.base.ast -import rope.base.oi.soi -import rope.base.pynames -from rope.base import pyobjects, evaluate, astutils, arguments - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -17,7 +17,7 @@ - if not followed_calls: - _follow = None - visitor = SOAVisitor(pycore, pydefined, _follow) -- for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): -- rope.base.ast.walk(child, visitor) -+ for child in au.get_child_nodes(pydefined.get_ast()): -+ au.walk(child, visitor) - - -@language python - -def _analyze_node(pycore, pydefined, should_analyze, search_subscopes, followed_calls): - if search_subscopes(pydefined): - for scope in pydefined.get_scope().get_scopes(): - _analyze_node( - pycore, scope.pyobject, should_analyze, search_subscopes, followed_calls - ) - if should_analyze(pydefined): - new_followed_calls = max(0, followed_calls - 1) - return_true = lambda pydefined: True - return_false = lambda pydefined: False - - def _follow(pyfunction): - _analyze_node( - pycore, pyfunction, return_true, return_false, new_followed_calls - ) - - if not followed_calls: - _follow = None - visitor = SOAVisitor(pycore, pydefined, _follow) - for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): - rope.base.ast.walk(child, visitor) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def _Call(self, node): -- for child in rope.base.ast.get_child_nodes(node): -- rope.base.ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - primary, pyname = evaluate.eval_node2(self.scope, node.func) - if pyname is None: - return -@@ -11,7 +11,7 @@ - pyclass = pyfunction - if "__init__" in pyfunction: - pyfunction = pyfunction["__init__"].get_object() -- pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass)) -+ pyname = pynames.UnboundName(pyobjects.PyObject(pyclass)) - args = self._args_with_self(primary, pyname, pyfunction, node) - elif "__call__" in pyfunction: - pyfunction = pyfunction["__call__"].get_object() -@language python - -def _Call(self, node): - for child in rope.base.ast.get_child_nodes(node): - rope.base.ast.walk(child, self) - primary, pyname = evaluate.eval_node2(self.scope, node.func) - if pyname is None: - return - pyfunction = pyname.get_object() - if isinstance(pyfunction, pyobjects.AbstractFunction): - args = arguments.create_arguments(primary, pyfunction, node, self.scope) - elif isinstance(pyfunction, pyobjects.PyClass): - pyclass = pyfunction - if "__init__" in pyfunction: - pyfunction = pyfunction["__init__"].get_object() - pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass)) - args = self._args_with_self(primary, pyname, pyfunction, node) - elif "__call__" in pyfunction: - pyfunction = pyfunction["__call__"].get_object() - args = self._args_with_self(primary, pyname, pyfunction, node) - else: - return - self._call(pyfunction, args) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,10 +1,10 @@ - def _AnnAssign(self, node): -- for child in rope.base.ast.get_child_nodes(node): -- rope.base.ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - visitor = _SOAAssignVisitor() - nodes = [] - -- rope.base.ast.walk(node.target, visitor) -+ au.walk(node.target, visitor) - nodes.extend(visitor.nodes) - - self._evaluate_assign_value(node, nodes, type_hint=node.annotation) -@language python - -def _AnnAssign(self, node): - for child in rope.base.ast.get_child_nodes(node): - rope.base.ast.walk(child, self) - visitor = _SOAAssignVisitor() - nodes = [] - - rope.base.ast.walk(node.target, visitor) - nodes.extend(visitor.nodes) - - self._evaluate_assign_value(node, nodes, type_hint=node.annotation) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,10 +1,10 @@ - def _Assign(self, node): -- for child in rope.base.ast.get_child_nodes(node): -- rope.base.ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - visitor = _SOAAssignVisitor() - nodes = [] - for child in node.targets: -- rope.base.ast.walk(child, visitor) -+ au.walk(child, visitor) - nodes.extend(visitor.nodes) - self._evaluate_assign_value(node, nodes) - -@language python - -def _Assign(self, node): - for child in rope.base.ast.get_child_nodes(node): - rope.base.ast.walk(child, self) - visitor = _SOAAssignVisitor() - nodes = [] - for child in node.targets: - rope.base.ast.walk(child, visitor) - nodes.extend(visitor.nodes) - self._evaluate_assign_value(node, nodes) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -3,12 +3,12 @@ - instance = evaluate.eval_node(self.scope, subscript.value) - args_pynames = [evaluate.eval_node(self.scope, subscript.slice)] - value = rope.base.oi.soi._infer_assignment( -- rope.base.pynames.AssignmentValue( -+ pynames.AssignmentValue( - node.value, levels, type_hint=type_hint - ), - self.pymodule, - ) -- args_pynames.append(rope.base.pynames.UnboundName(value)) -+ args_pynames.append(pynames.UnboundName(value)) - if instance is not None and value is not None: - pyobject = instance.get_object() - if "__setitem__" in pyobject: -@language python - -def _evaluate_assign_value(self, node, nodes, type_hint=False): - for subscript, levels in nodes: - instance = evaluate.eval_node(self.scope, subscript.value) - args_pynames = [evaluate.eval_node(self.scope, subscript.slice)] - value = rope.base.oi.soi._infer_assignment( - rope.base.pynames.AssignmentValue( - node.value, levels, type_hint=type_hint - ), - self.pymodule, - ) - args_pynames.append(rope.base.pynames.UnboundName(value)) - if instance is not None and value is not None: - pyobject = instance.get_object() - if "__setitem__" in pyobject: - pyfunction = pyobject["__setitem__"].get_object() - args = arguments.ObjectArguments([instance] + args_pynames) - self._call(pyfunction, args) - # IDEA: handle `__setslice__`, too - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,2 +1,2 @@ --class _SOAAssignVisitor(astutils._NodeNameCollector): -+class _SOAAssignVisitor(au._NodeNameCollector): - @others -@language python - -class _SOAAssignVisitor(astutils._NodeNameCollector): - @others - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _added(self, node, levels): -- if isinstance(node, rope.base.ast.Subscript) and isinstance( -- node.slice, (rope.base.ast.Index, rope.base.ast.expr) -+ if isinstance(node, ast.Subscript) and isinstance( -+ node.slice, (ast.Index, ast.expr) - ): - self.nodes.append((node, levels)) -@language python - -def _added(self, node, levels): - if isinstance(node, rope.base.ast.Subscript) and isinstance( - node.slice, (rope.base.ast.Index, rope.base.ast.expr) - ): - self.nodes.append((node, levels)) - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,11 +5,9 @@ - - """ - import rope.base.builtins --import rope.base.pynames - import rope.base.pyobjects --from rope.base import evaluate, utils, arguments -+from rope.base import arguments, evaluate, pynames, utils - from rope.base.oi.type_hinting.factory import get_type_hinting_factory -- - - _ignore_inferred = utils.ignore_exception(rope.base.pyobjects.IsBeingInferredError) - -@@ -142,7 +140,6 @@ - - # handling `rope.base.pynames.AssignmentValue` - -- - @_ignore_inferred - def _infer_assignment(assignment, pymodule): - result = _follow_pyname(assignment, pymodule) -@@ -185,7 +182,7 @@ - isinstance(result.get_type(), rope.base.builtins.Property) - and holding_scope.get_kind() == "Class" - ): -- arg = rope.base.pynames.UnboundName( -+ arg = pynames.UnboundName( - rope.base.pyobjects.PyObject(holding_scope.pyobject) - ) - return pyname, result.get_type().get_property_object( -@language python - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ -+ -+import ast - import rope.base.evaluate --from rope.base import ast -- - - class Arguments: - """A class for evaluating parameters passed to a function -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,11 +6,9 @@ - - """ - import rope.base.builtins --import rope.base.pynames - import rope.base.pyobjects --from rope.base import evaluate, utils, arguments -+from rope.base import arguments, evaluate, pynames, utils - from rope.base.oi.type_hinting.factory import get_type_hinting_factory -- - - _ignore_inferred = utils.ignore_exception(rope.base.pyobjects.IsBeingInferredError) - -@language python - -@path C:/Repos/ekr-rope/rope/base/oi/ -"""A module for inferring objects - -For more information see the documentation in `rope.base.oi` -package. - -""" -import rope.base.builtins -import rope.base.pynames -import rope.base.pyobjects -from rope.base import evaluate, utils, arguments -from rope.base.oi.type_hinting.factory import get_type_hinting_factory - - -_ignore_inferred = utils.ignore_exception(rope.base.pyobjects.IsBeingInferredError) - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,4 @@ - # handling `rope.base.pynames.AssignmentValue` -- - - @_ignore_inferred - def _infer_assignment(assignment, pymodule): -@language python - -# handling `rope.base.pynames.AssignmentValue` - - -@_ignore_inferred -def _infer_assignment(assignment, pymodule): - result = _follow_pyname(assignment, pymodule) - if result is None: - return None - pyname, pyobject = result - pyobject = _follow_evaluations(assignment, pyname, pyobject) - if pyobject is None: - return None - return _follow_levels(assignment, pyobject) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -11,7 +11,7 @@ - isinstance(result.get_type(), rope.base.builtins.Property) - and holding_scope.get_kind() == "Class" - ): -- arg = rope.base.pynames.UnboundName( -+ arg = pynames.UnboundName( - rope.base.pyobjects.PyObject(holding_scope.pyobject) - ) - return pyname, result.get_type().get_property_object( -@language python - -@_ignore_inferred -def _follow_pyname(assignment, pymodule, lineno=None): - assign_node = assignment.type_hint or assignment.ast_node - if lineno is None: - lineno = _get_lineno_for_node(assign_node) - holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) - pyname = evaluate.eval_node(holding_scope, assign_node) - if pyname is not None: - result = pyname.get_object() - if ( - isinstance(result.get_type(), rope.base.builtins.Property) - and holding_scope.get_kind() == "Class" - ): - arg = rope.base.pynames.UnboundName( - rope.base.pyobjects.PyObject(holding_scope.pyobject) - ) - return pyname, result.get_type().get_property_object( - arguments.ObjectArguments([arg]) - ) - return pyname, result - - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - @path C:/Repos/ekr-rope/rope/base/ -+ -+import ast - import rope.base.evaluate --from rope.base import ast -- - - @others - @language python -@language python - -@path C:/Repos/ekr-rope/rope/base/ -import rope.base.evaluate -from rope.base import ast - - -@others -@language python -@tabwidth -4 - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,22 +1,8 @@ --from rope.base import ast -- -- --def get_name_levels(node): -- """Return a list of ``(name, level)`` tuples for assigned names -- -- The `level` is `None` for simple assignments and is a list of -- numbers for tuple assignments for example in:: -- -- a, (b, c) = x -- -- The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for -- `c` is ``[1, 1]``. -- -- """ -- visitor = _NodeNameCollector() -- ast.walk(node, visitor) -- return visitor.names -- -+""" -+ast utilities, renamed from base.ast.py. -+""" -+import ast -+from rope.base.fscommands import unicode_to_file_data - - class _NodeNameCollector: - def __init__(self, levels=None): -@@ -49,8 +35,8 @@ - new_levels.append(self.index) - self.index += 1 - visitor = _NodeNameCollector(new_levels) -- for child in ast.get_child_nodes(node): -- ast.walk(child, visitor) -+ for child in get_child_nodes(node): -+ walk(child, visitor) - self.names.extend(visitor.names) - - def _Subscript(self, node): -@@ -61,3 +47,78 @@ - - def _Slice(self, node): - self._add_node(node) -+ -+ -+def call_for_nodes(node, callback, recursive=False): -+ """If callback returns `True` the child nodes are skipped""" -+ result = callback(node) -+ if recursive and not result: -+ for child in get_child_nodes(node): -+ call_for_nodes(child, callback, recursive) -+def get_child_nodes(node): -+ if isinstance(node, ast.Module): -+ return node.body -+ result = [] -+ if node._fields is not None: -+ for name in node._fields: -+ child = getattr(node, name) -+ if isinstance(child, list): -+ for entry in child: -+ if isinstance(entry, ast.AST): -+ result.append(entry) -+ if isinstance(child, ast.AST): -+ result.append(child) -+ return result -+def get_children(node): -+ result = [] -+ if node._fields is not None: -+ for name in node._fields: -+ if name in ["lineno", "col_offset"]: -+ continue -+ child = getattr(node, name) -+ result.append(child) -+ return result -+def get_name_levels(node): -+ """Return a list of ``(name, level)`` tuples for assigned names -+ -+ The `level` is `None` for simple assignments and is a list of -+ numbers for tuple assignments for example in:: -+ -+ a, (b, c) = x -+ -+ The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for -+ `c` is ``[1, 1]``. -+ -+ """ -+ visitor = _NodeNameCollector() -+ walk(node, visitor) -+ return visitor.names -+def parse(source, filename="<string>"): -+ # NOTE: the raw string should be given to `compile` function -+ if isinstance(source, str): -+ source = unicode_to_file_data(source) -+ if b"\r" in source: -+ source = source.replace(b"\r\n", b"\n").replace(b"\r", b"\n") -+ if not source.endswith(b"\n"): -+ source += b"\n" -+ try: -+ return ast.parse(source, filename="<unknown>") -+ except (TypeError, ValueError) as e: -+ error = SyntaxError() -+ error.lineno = 1 -+ error.filename = filename -+ error.msg = str(e) -+ raise error # pylint: disable=raise-missing-from -+ -+def walk(node, walker): # pylint: disable=inconsistent-return-statements -+ """Walk the syntax tree""" -+ method_name = "_" + node.__class__.__name__ -+ method = getattr(walker, method_name, None) -+ if method is not None: -+ if isinstance(node, ast.ImportFrom) and node.module is None: -+ # In python < 2.7 ``node.module == ''`` for relative imports -+ # but for python 2.7 it is None. Generalizing it to ''. -+ node.module = "" -+ return method(node) -+ for child in get_child_nodes(node): -+ walk(child, walker) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,23 +1,9 @@ - @path C:/Repos/ekr-rope/rope/base/ --from rope.base import ast -- -- --def get_name_levels(node): -- """Return a list of ``(name, level)`` tuples for assigned names -- -- The `level` is `None` for simple assignments and is a list of -- numbers for tuple assignments for example in:: -- -- a, (b, c) = x -- -- The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for -- `c` is ``[1, 1]``. -- -- """ -- visitor = _NodeNameCollector() -- ast.walk(node, visitor) -- return visitor.names -- -+""" -+ast utilities, renamed from base.ast.py. -+""" -+import ast -+from rope.base.fscommands import unicode_to_file_data - - @others - @language python -@language python - -@path C:/Repos/ekr-rope/rope/base/ -from rope.base import ast - - -def get_name_levels(node): - """Return a list of ``(name, level)`` tuples for assigned names - - The `level` is `None` for simple assignments and is a list of - numbers for tuple assignments for example in:: - - a, (b, c) = x - - The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for - `c` is ``[1, 1]``. - - """ - visitor = _NodeNameCollector() - ast.walk(node, visitor) - return visitor.names - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,7 +5,7 @@ - new_levels.append(self.index) - self.index += 1 - visitor = _NodeNameCollector(new_levels) -- for child in ast.get_child_nodes(node): -- ast.walk(child, visitor) -+ for child in get_child_nodes(node): -+ walk(child, visitor) - self.names.extend(visitor.names) - -@language python - -def _Tuple(self, node): - new_levels = [] - if self.levels is not None: - new_levels = list(self.levels) - new_levels.append(self.index) - self.index += 1 - visitor = _NodeNameCollector(new_levels) - for child in ast.get_child_nodes(node): - ast.walk(child, visitor) - self.names.extend(visitor.names) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,2 +1,77 @@ - def _Slice(self, node): - self._add_node(node) -+ -+ -+def call_for_nodes(node, callback, recursive=False): -+"""If callback returns `True` the child nodes are skipped""" -+result = callback(node) -+if recursive and not result: -+ for child in get_child_nodes(node): -+ call_for_nodes(child, callback, recursive) -+def get_child_nodes(node): -+if isinstance(node, ast.Module): -+ return node.body -+result = [] -+if node._fields is not None: -+ for name in node._fields: -+ child = getattr(node, name) -+ if isinstance(child, list): -+ for entry in child: -+ if isinstance(entry, ast.AST): -+ result.append(entry) -+ if isinstance(child, ast.AST): -+ result.append(child) -+return result -+def get_children(node): -+result = [] -+if node._fields is not None: -+ for name in node._fields: -+ if name in ["lineno", "col_offset"]: -+ continue -+ child = getattr(node, name) -+ result.append(child) -+return result -+def get_name_levels(node): -+"""Return a list of ``(name, level)`` tuples for assigned names -+ -+The `level` is `None` for simple assignments and is a list of -+numbers for tuple assignments for example in:: -+ -+ a, (b, c) = x -+ -+The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for -+`c` is ``[1, 1]``. -+ -+""" -+visitor = _NodeNameCollector() -+walk(node, visitor) -+return visitor.names -+def parse(source, filename="<string>"): -+# NOTE: the raw string should be given to `compile` function -+if isinstance(source, str): -+ source = unicode_to_file_data(source) -+if b"\r" in source: -+ source = source.replace(b"\r\n", b"\n").replace(b"\r", b"\n") -+if not source.endswith(b"\n"): -+ source += b"\n" -+try: -+ return ast.parse(source, filename="<unknown>") -+except (TypeError, ValueError) as e: -+ error = SyntaxError() -+ error.lineno = 1 -+ error.filename = filename -+ error.msg = str(e) -+ raise error # pylint: disable=raise-missing-from -+ -+def walk(node, walker): # pylint: disable=inconsistent-return-statements -+"""Walk the syntax tree""" -+method_name = "_" + node.__class__.__name__ -+method = getattr(walker, method_name, None) -+if method is not None: -+ if isinstance(node, ast.ImportFrom) and node.module is None: -+ # In python < 2.7 ``node.module == ''`` for relative imports -+ # but for python 2.7 it is None. Generalizing it to ''. -+ node.module = "" -+ return method(node) -+for child in get_child_nodes(node): -+ walk(child, walker) -@language python - -def _Slice(self, node): - self._add_node(node) - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,19 +1,18 @@ -+import ast - from operator import itemgetter - from typing import Optional, Tuple - -+import rope.base.astutils as au - import rope.base.builtins --import rope.base.pynames - import rope.base.pyobjects - from rope.base import ( -- ast, -- astutils, -+ arguments, - exceptions, -+ pynames, - pyobjects, - pyobjectsdef, -- arguments, - worder, - ) -- - - BadIdentifierError = exceptions.BadIdentifierError - -@@ -39,7 +38,7 @@ - - def eval_node2(scope, node): - evaluator = StatementEvaluator(scope) -- ast.walk(node, evaluator) -+ au.walk(node, evaluator) - return evaluator.old_result, evaluator.result - - -@@ -50,7 +49,7 @@ - def eval_str2(holding_scope, name): - try: - # parenthesizing for handling cases like 'a_var.\nattr' -- node = ast.parse("(%s)" % name) -+ node = au.parse("(%s)" % name) - except SyntaxError: - raise BadIdentifierError("Not a resolvable python identifier selected.") - return eval_node2(holding_scope, node) -@@ -91,7 +90,7 @@ - def get_primary_and_pyname_at( - self, - offset: int, -- ) -> Tuple[Optional[rope.base.pynames.PyName], Optional[rope.base.pynames.PyName]]: -+ ) -> Tuple[Optional[pynames.PyName], Optional[pynames.PyName]]: - lineno = self.lines.get_line_number(offset) - holding_scope = self.module_scope.get_inner_scope_for_offset(offset) - # function keyword parameter -@@ -102,7 +101,7 @@ - parameter_name = pyobject.get_parameters().get(keyword_name, None) - return (None, parameter_name) - elif isinstance(pyobject, pyobjects.AbstractFunction): -- parameter_name = rope.base.pynames.ParameterName() -+ parameter_name = pynames.ParameterName() - return (None, parameter_name) - # class body - if self._is_defined_in_class_body(holding_scope, offset, lineno): -@@ -153,7 +152,7 @@ - dots = 0 - while module_name[dots] == ".": - dots += 1 -- return rope.base.pynames.ImportedModule( -+ return pynames.ImportedModule( - self.module_scope.pyobject, module_name[dots:], dots - ) - -@@ -170,7 +169,7 @@ - def _Attribute(self, node): - pyname = eval_node(self.scope, node.value) - if pyname is None: -- pyname = rope.base.pynames.UnboundName() -+ pyname = pynames.UnboundName() - self.old_result = pyname - if pyname.get_object() != rope.base.pyobjects.get_unknown(): - try: -@@ -194,7 +193,7 @@ - result = _get_returned(new_function) - if result is None or result == rope.base.pyobjects.get_unknown(): - result = rope.base.pyobjects.PyObject(pyobject) -- self.result = rope.base.pynames.UnboundName(pyobject=result) -+ self.result = pynames.UnboundName(pyobject=result) - return - - pyfunction = None -@@ -203,12 +202,12 @@ - elif "__call__" in pyobject: - pyfunction = pyobject["__call__"].get_object() - if pyfunction is not None: -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=_get_returned(pyfunction) - ) - - def _Str(self, node): -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_str() - ) - -@@ -226,10 +225,10 @@ - - def _get_builtin_name(self, type_name): - pytype = rope.base.builtins.builtins[type_name].get_object() -- return rope.base.pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) -+ return pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) - - def _BinOp(self, node): -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - self._get_object_for_node(node.left) - ) - -@@ -237,13 +236,13 @@ - pyobject = self._get_object_for_node(node.values[0]) - if pyobject is None: - pyobject = self._get_object_for_node(node.values[1]) -- self.result = rope.base.pynames.UnboundName(pyobject) -+ self.result = pynames.UnboundName(pyobject) - - def _Repr(self, node): - self.result = self._get_builtin_name("str") - - def _UnaryOp(self, node): -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - self._get_object_for_node(node.operand) - ) - -@@ -261,7 +260,7 @@ - keys = self._get_object_for_node(keys) - if values: - values = self._get_object_for_node(values) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_dict(keys, values) - ) - -@@ -269,19 +268,19 @@ - holding = None - if node.elts: - holding = self._get_object_for_node(node.elts[0]) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_list(holding) - ) - - def _ListComp(self, node): - pyobject = self._what_does_comprehension_hold(node) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_list(pyobject) - ) - - def _GeneratorExp(self, node): - pyobject = self._what_does_comprehension_hold(node) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_iterator(pyobject) - ) - -@@ -309,7 +308,7 @@ - objects.append(pyobject) - else: - objects.append(self._get_object_for_node(node.elts[0])) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.get_tuple(*objects) - ) - -@@ -352,22 +351,21 @@ - if other_args: - args += other_args - arguments_ = arguments.Arguments(args, self.scope) -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=called.get_returned_object(arguments_) - ) - - def _Lambda(self, node): -- self.result = rope.base.pynames.UnboundName( -+ self.result = pynames.UnboundName( - pyobject=rope.base.builtins.Lambda(node, self.scope) - ) - - - def _get_evaluated_names(targets, assigned, module, evaluation, lineno): - result = {} -- for name, levels in astutils.get_name_levels(targets): -- assignment = rope.base.pynames.AssignmentValue(assigned, levels, evaluation) -- # XXX: this module should not access `rope.base.pynamesdef`! -- pyname = rope.base.pynamesdef.AssignedName(lineno, module) -+ for name, levels in au.get_name_levels(targets): -+ assignment = pynames.AssignmentValue(assigned, levels, evaluation) -+ pyname = rope.base.pynames.AssignedName(lineno, module) - pyname.assignments.append(assignment) - result[name] = pyname - return result -@language python - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -47,7 +47,7 @@ - - def __call__(self, pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - for delegate in self._delegates: -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -8,7 +8,7 @@ - - def __call__(self, pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - raise NotImplementedError -@language python - - -class IAssignmentProvider: -""" -:type resolve: rope.base.oi.type_hinting.resolvers.interfaces.IResolver -""" - -resolve = None - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - raise NotImplementedError - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -14,7 +14,7 @@ - - def __call__(self, pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - from rope.base.oi.soi import _get_lineno_for_node -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def __call__(self, pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - from rope.base.oi.soi import _get_lineno_for_node -@language python - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - from rope.base.oi.soi import _get_lineno_for_node - - lineno = _get_lineno_for_node(pyname.assignments[0].ast_node) - holding_scope = pyname.module.get_scope().get_inner_scope_for_line(lineno) - line = holding_scope._get_global_scope()._scope_finder.lines.get_line(lineno) - if "#" in line: - type_strs = self._search_type_in_type_comment(line.split("#", 1)[1]) - if type_strs: - return self._resolve(type_strs[0], holding_scope.pyobject) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -28,8 +28,8 @@ - - def get_super_assignment(pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -- :type: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName -+ :type: rope.base.pynames.AssignedName - """ - try: - pyclass, attr_name = get_class_with_attr_name(pyname) -@@ -43,7 +43,7 @@ - - def get_class_with_attr_name(pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :return: rope.base.pyobjectsdef.PyClass, str - :rtype: tuple - """ -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - def get_super_assignment(pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -- :type: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName -+ :type: rope.base.pynames.AssignedName - """ - try: - pyclass, attr_name = get_class_with_attr_name(pyname) -@language python - -def get_super_assignment(pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :type: rope.base.pynamesdef.AssignedName - """ - try: - pyclass, attr_name = get_class_with_attr_name(pyname) - except TypeError: - return - else: - for super_pyclass in get_mro(pyclass)[1:]: - if attr_name in super_pyclass: - return super_pyclass[attr_name] - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def get_class_with_attr_name(pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :return: rope.base.pyobjectsdef.PyClass, str - :rtype: tuple - """ -@language python - -def get_class_with_attr_name(pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :return: rope.base.pyobjectsdef.PyClass, str - :rtype: tuple - """ - lineno = get_lineno_for_node(pyname.assignments[0].ast_node) - holding_scope = pyname.module.get_scope().get_inner_scope_for_line(lineno) - pyobject = holding_scope.pyobject - if isinstance(pyobject, PyClass): - pyclass = pyobject - elif isinstance(pyobject, PyFunction) and isinstance(pyobject.parent, PyClass): - pyclass = pyobject.parent - else: - return - for name, attr in pyclass.get_attributes().items(): - if attr is pyname: - return (pyclass, name) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,5 @@ - import bisect - import difflib --import sys - import warnings - - import rope.base.libutils -@@ -15,7 +14,6 @@ - from rope.base import stdmods - from rope.base import taskhandle - from rope.base import utils --from rope.base.exceptions import ModuleNotFoundError - - - class PyCore: -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def __call__(self, pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - for delegate in self._delegates: -@language python - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - for delegate in self._delegates: - result = delegate(pyname) - if result: - return result - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,6 @@ - @path C:/Repos/ekr-rope/rope/base/ - import bisect - import difflib --import sys - import warnings - - import rope.base.libutils -@@ -16,7 +15,6 @@ - from rope.base import stdmods - from rope.base import taskhandle - from rope.base import utils --from rope.base.exceptions import ModuleNotFoundError - - - @others -@language python - -@path C:/Repos/ekr-rope/rope/base/ -import bisect -import difflib -import sys -import warnings - -import rope.base.libutils -import rope.base.resourceobserver -import rope.base.resources -import rope.base.oi.doa -import rope.base.oi.objectinfo -import rope.base.oi.soa -from rope.base import builtins -from rope.base import exceptions -from rope.base import pyobjectsdef -from rope.base import stdmods -from rope.base import taskhandle -from rope.base import utils -from rope.base.exceptions import ModuleNotFoundError - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,5 @@ - import rope.base.pyobjects - from rope.base import exceptions, utils -- - - class PyName: - """References to `PyObject` inside python programs""" -@@ -27,7 +26,36 @@ - - - class AssignedName(PyName): -- """Only a placeholder""" -+ def __init__(self, lineno=None, module=None, pyobject=None): -+ self.lineno = lineno -+ self.module = module -+ self.assignments = [] -+ self.pyobject = _Inferred( -+ self._get_inferred, _get_concluded_data(module) -+ ) -+ self.pyobject.set(pyobject) -+ -+ @utils.prevent_recursion(lambda: None) -+ def _get_inferred(self): -+ if self.module is not None: -+ return rope.base.oi.soi.infer_assigned_object(self) -+ return None -+ -+ def get_object(self): -+ return self.pyobject.get() -+ -+ def get_definition_location(self): -+ """Returns a (module, lineno) tuple""" -+ if self.lineno is None and self.assignments: -+ try: -+ self.lineno = self.assignments[0].get_lineno() -+ except AttributeError: -+ pass -+ return (self.module, self.lineno) -+ -+ def invalidate(self): -+ """Forget the `PyObject` this `PyName` holds""" -+ self.pyobject.set(None) - - - class UnboundName(PyName): -@@ -92,7 +120,22 @@ - - - class ParameterName(PyName): -- """Only a placeholder""" -+ def __init__(self, pyfunction=None, index=0): -+ self.pyfunction = pyfunction -+ self.index = index -+ -+ def get_object(self): -+ result = self.pyfunction.get_parameter(self.index) -+ if result is None: -+ result = rope.base.pyobjects.get_unknown() -+ return result -+ -+ def get_objects(self): -+ """Returns the list of objects passed as this parameter""" -+ return rope.base.oi.soi.get_passed_objects(self.pyfunction, self.index) -+ -+ def get_definition_location(self): -+ return (self.pyfunction.get_module(), self.pyfunction.get_ast().lineno) - - - class ImportedModule(PyName): -@language python - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -77,7 +77,7 @@ - - def __call__(self, pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - try: -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,6 @@ - import rope.base.pyobjects - from rope.base import exceptions, utils - -- - @others - @language python - @tabwidth -4 -@language python - -@path C:/Repos/ekr-rope/rope/base/ -import rope.base.pyobjects -from rope.base import exceptions, utils - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1 +1,30 @@ --"""Only a placeholder""" -+def __init__(self, lineno=None, module=None, pyobject=None): -+ self.lineno = lineno -+ self.module = module -+ self.assignments = [] -+ self.pyobject = _Inferred( -+ self._get_inferred, _get_concluded_data(module) -+ ) -+ self.pyobject.set(pyobject) -+ -+@utils.prevent_recursion(lambda: None) -+def _get_inferred(self): -+ if self.module is not None: -+ return rope.base.oi.soi.infer_assigned_object(self) -+ return None -+ -+def get_object(self): -+ return self.pyobject.get() -+ -+def get_definition_location(self): -+ """Returns a (module, lineno) tuple""" -+ if self.lineno is None and self.assignments: -+ try: -+ self.lineno = self.assignments[0].get_lineno() -+ except AttributeError: -+ pass -+ return (self.module, self.lineno) -+ -+def invalidate(self): -+ """Forget the `PyObject` this `PyName` holds""" -+ self.pyobject.set(None) -@language python - -"""Only a placeholder""" - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1 +1,16 @@ --"""Only a placeholder""" -+def __init__(self, pyfunction=None, index=0): -+ self.pyfunction = pyfunction -+ self.index = index -+ -+def get_object(self): -+ result = self.pyfunction.get_parameter(self.index) -+ if result is None: -+ result = rope.base.pyobjects.get_unknown() -+ return result -+ -+def get_objects(self): -+ """Returns the list of objects passed as this parameter""" -+ return rope.base.oi.soi.get_passed_objects(self.pyfunction, self.index) -+ -+def get_definition_location(self): -+ return (self.pyfunction.get_module(), self.pyfunction.get_ast().lineno) -@language python - -"""Only a placeholder""" - -@ignore -@nosearch -@language patch - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,7 @@ --from typing import Optional -- --from rope.base import ast, exceptions, utils -+import ast -+from rope.base import exceptions, utils -+import rope.base.astutils as au -+from rope.base.fscommands import _decode_data - - - class PyObject: -@@ -225,14 +226,13 @@ - current_object = current_object.parent - return current_object - -- def get_doc(self) -> Optional[str]: -+ def get_doc(self): - if len(self.get_ast().body) > 0: - expr = self.get_ast().body[0] - if isinstance(expr, ast.Expr) and isinstance(expr.value, ast.Str): - docstring = expr.value.s -- assert isinstance(docstring, str) -- return docstring -- return None -+ coding = self.get_module().coding -+ return _decode_data(docstring, coding) - - def _get_defined_objects(self): - if self.defineds is None: -@@ -243,8 +243,8 @@ - if self.visitor_class is None: - return {} - new_visitor = self.visitor_class(self.pycore, self) -- for child in ast.get_child_nodes(self.ast_node): -- ast.walk(child, new_visitor) -+ for child in au.get_child_nodes(self.ast_node): -+ au.walk(child, new_visitor) - self.defineds = new_visitor.defineds - return new_visitor.names -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,8 @@ - @path C:/Repos/ekr-rope/rope/base/ --from typing import Optional -- --from rope.base import ast, exceptions, utils -+import ast -+from rope.base import exceptions, utils -+import rope.base.astutils as au -+from rope.base.fscommands import _decode_data - - - @others -@language python - -@path C:/Repos/ekr-rope/rope/base/ -from typing import Optional - -from rope.base import ast, exceptions, utils - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,8 @@ --def get_doc(self) -> Optional[str]: -+def get_doc(self): - if len(self.get_ast().body) > 0: - expr = self.get_ast().body[0] - if isinstance(expr, ast.Expr) and isinstance(expr.value, ast.Str): - docstring = expr.value.s -- assert isinstance(docstring, str) -- return docstring -- return None -+ coding = self.get_module().coding -+ return _decode_data(docstring, coding) - -@language python - -def get_doc(self) -> Optional[str]: - if len(self.get_ast().body) > 0: - expr = self.get_ast().body[0] - if isinstance(expr, ast.Expr) and isinstance(expr.value, ast.Str): - docstring = expr.value.s - assert isinstance(docstring, str) - return docstring - return None - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,8 +2,8 @@ - if self.visitor_class is None: - return {} - new_visitor = self.visitor_class(self.pycore, self) -- for child in ast.get_child_nodes(self.ast_node): -- ast.walk(child, new_visitor) -+ for child in au.get_child_nodes(self.ast_node): -+ au.walk(child, new_visitor) - self.defineds = new_visitor.defineds - return new_visitor.names - -@language python - -def _create_structural_attributes(self): - if self.visitor_class is None: - return {} - new_visitor = self.visitor_class(self.pycore, self) - for child in ast.get_child_nodes(self.ast_node): - ast.walk(child, new_visitor) - self.defineds = new_visitor.defineds - return new_visitor.names - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def __call__(self, pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - try: -@language python - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - try: - pyclass, attr_name = utils.get_class_with_attr_name(pyname) - except TypeError: - return - else: - type_strs = self._parse_docstring(pyclass.get_doc(), attr_name) - if type_strs: - return self._resolve(type_strs[0], pyclass) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -52,7 +52,7 @@ - - def __call__(self, pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - super_pyname = pyname -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def __call__(self, pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - super_pyname = pyname -@language python - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - super_pyname = pyname - while super_pyname: - result = self._delegate(super_pyname) - if result: - return result - super_pyname = utils.get_super_assignment(super_pyname) - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -32,7 +32,7 @@ - - def __call__(self, pyname): - """ -- :type pyname: rope.base.pynamesdef.AssignedName -+ :type pyname: rope.base.pynames.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - raise NotImplementedError -@language python - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,6 @@ --from rope.base.pynames import DefinedName -+import ast -+ -+import rope.base.astutils as au - import rope.base.builtins - import rope.base.codeanalyze - import rope.base.evaluate -@@ -6,18 +8,14 @@ - import rope.base.oi.soi - import rope.base.pyscopes - from rope.base import ( -- pynamesdef as pynames, -+ arguments, - exceptions, -- ast, -- astutils, -+ fscommands, -+ pynames, - pyobjects, -- fscommands, -- arguments, - utils, - ) - from rope.base.utils import pycompat -- -- - class PyFunction(pyobjects.PyFunction): - def __init__(self, pycore, ast_node, parent): - rope.base.pyobjects.AbstractFunction.__init__(self) -@@ -183,7 +181,7 @@ - raise - else: - source = "\n" -- node = ast.parse("\n") -+ node = au.parse("\n") - self.source_code = source - self.star_imports = [] - self.visitor_class = _GlobalVisitor -@@ -203,7 +201,7 @@ - source_bytes = fscommands.unicode_to_file_data(source_code) - else: - source_bytes = source_code -- ast_node = ast.parse(source_bytes, filename=filename) -+ ast_node = au.parse(source_bytes, filename=filename) - except SyntaxError as e: - raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg) - except UnicodeDecodeError as e: -@@ -245,7 +243,7 @@ - init_dot_py, force_errors=force_errors - ).get_ast() - else: -- ast_node = ast.parse("\n") -+ ast_node = au.parse("\n") - super().__init__(pycore, ast_node, resource) - - def _create_structural_attributes(self): -@@ -307,7 +305,7 @@ - self.assigned_ast = node.value - self.type_hint = node.annotation - -- ast.walk(node.target, self) -+ au.walk(node.target, self) - - def _assigned(self, name, assignment=None): - self.scope_visitor._assigned(name, assignment) -@@ -319,7 +317,7 @@ - self._assigned(node.id, assignment) - - def _Tuple(self, node): -- names = astutils.get_name_levels(node) -+ names = au.get_name_levels(node) - for name, levels in names: - assignment = None - if self.assigned_ast is not None: -@@ -362,8 +360,8 @@ - self._GeneratorExp(node) - - def _NamedExpr(self, node): -- ast.walk(node.target, _AssignVisitor(self)) -- ast.walk(node.value, self) -+ au.walk(node.target, _AssignVisitor(self)) -+ au.walk(node.value, self) - - - class _AssignVisitor: -@@ -374,8 +372,8 @@ - def _Assign(self, node): - self.assigned_ast = node.value - for child_node in node.targets: -- ast.walk(child_node, self) -- ast.walk(node.value, _ExpressionVisitor(self.scope_visitor)) -+ au.walk(child_node, self) -+ au.walk(node.value, _ExpressionVisitor(self.scope_visitor)) - - def _assigned(self, name, assignment=None): - self.scope_visitor._assigned(name, assignment) -@@ -387,7 +385,7 @@ - self._assigned(node.id, assignment) - - def _Tuple(self, node): -- names = astutils.get_name_levels(node) -+ names = au.get_name_levels(node) - for name, levels in names: - assignment = None - if self.assigned_ast is not None: -@@ -452,20 +450,18 @@ - return self._FunctionDef(node) - - def _Assign(self, node): -- ast.walk(node, _AssignVisitor(self)) -+ au.walk(node, _AssignVisitor(self)) - - def _AnnAssign(self, node): -- ast.walk(node, _AnnAssignVisitor(self)) -+ au.walk(node, _AnnAssignVisitor(self)) - - def _AugAssign(self, node): - pass - - def _For(self, node): -- names = self._update_evaluated( -- node.target, node.iter, ".__iter__().next()" # noqa -- ) -+ self._update_evaluated(node.target, node.iter, ".__iter__().next()") # noqa - for child in node.body + node.orelse: -- ast.walk(child, self) -+ au.walk(child, self) - - def _AsyncFor(self, node): - return self._For(node) -@@ -487,7 +483,7 @@ - assignment = pynames.AssignmentValue(assigned, [], evaluation, eval_type) - self._assigned(targets, assignment) - else: -- names = astutils.get_name_levels(targets) -+ names = au.get_name_levels(targets) - for name, levels in names: - assignment = pynames.AssignmentValue( - assigned, levels, evaluation, eval_type -@@ -502,7 +498,7 @@ - item.optional_vars, item.context_expr, ".__enter__()" - ) - for child in node.body: -- ast.walk(child, self) -+ au.walk(child, self) - - def _AsyncWith(self, node): - return self._With(node) -@@ -516,7 +512,7 @@ - self._update_evaluated(node.name, type_node, eval_type=True) - - for child in node.body: -- ast.walk(child, self) -+ au.walk(child, self) - - def _ExceptHandler(self, node): - self._excepthandler(node) -@@ -575,8 +571,8 @@ - - class _ComprehensionVisitor(_ScopeVisitor): - def _comprehension(self, node): -- ast.walk(node.target, self) -- ast.walk(node.iter, self) -+ au.walk(node.target, self) -+ au.walk(node.iter, self) - - def _Name(self, node): - if isinstance(node.ctx, ast.Store): -@@ -603,8 +599,8 @@ - if isinstance(first, pycompat.ast_arg_type): - new_visitor = _ClassInitVisitor(self, pycompat.get_ast_arg_arg(first)) - if new_visitor is not None: -- for child in ast.get_child_nodes(node): -- ast.walk(child, new_visitor) -+ for child in au.get_child_nodes(node): -+ au.walk(child, new_visitor) - - - class _FunctionVisitor(_ScopeVisitor): -@@ -646,8 +642,8 @@ - def _Tuple(self, node): - if not isinstance(node.ctx, ast.Store): - return -- for child in ast.get_child_nodes(node): -- ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - - def _Name(self, node): - pass -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,16 +1,18 @@ - @path C:/Repos/ekr-rope/rope/refactor/ -+ -+import ast - import re - from contextlib import contextmanager - from itertools import chain - --from rope.base import ast, codeanalyze -+from rope.base import codeanalyze -+import rope.base.astutils as au - from rope.base.change import ChangeSet, ChangeContents - from rope.base.exceptions import RefactoringError - from rope.base.utils import pycompat - from rope.base.utils.datastructures import OrderedSet - from rope.refactor import sourceutils, similarfinder, patchedast, suites, usefunction - -- - @others - @language python - @tabwidth -4 -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -import re -from contextlib import contextmanager -from itertools import chain - -from rope.base import ast, codeanalyze -from rope.base.change import ChangeSet, ChangeContents -from rope.base.exceptions import RefactoringError -from rope.base.utils import pycompat -from rope.base.utils.datastructures import OrderedSet -from rope.refactor import sourceutils, similarfinder, patchedast, suites, usefunction - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -7,6 +7,6 @@ - ) - body = self.info.source[self.info.scope_region[0] : self.info.scope_region[1]] - node = _parse_text(body) -- ast.walk(node, info_collector) -+ au.walk(node, info_collector) - return info_collector - -@language python - -def _create_info_collector(self): - zero = self.info.scope.get_start() - 1 - start_line = self.info.region_lines[0] - zero - end_line = self.info.region_lines[1] - zero - info_collector = _FunctionInformationCollector( - start_line, end_line, self.info.global_ - ) - body = self.info.source[self.info.scope_region[0] : self.info.scope_region[1]] - node = _parse_text(body) - ast.walk(node, info_collector) - return info_collector - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,7 @@ - def _get_globals_in_body(unindented_body): - node = _parse_text(unindented_body) - visitor = _GlobalFinder() -- ast.walk(node, visitor) -+ au.walk(node, visitor) - return visitor.globals_ - - -@language python - -@staticmethod -def _get_globals_in_body(unindented_body): - node = _parse_text(unindented_body) - visitor = _GlobalFinder() - ast.walk(node, visitor) - return visitor.globals_ - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,12 +4,12 @@ - for name in _get_argnames(node.args): - self._written_variable(name, node.lineno) - for child in node.body: -- ast.walk(child, self) -+ au.walk(child, self) - else: - self._written_variable(node.name, node.lineno) - visitor = _VariableReadsAndWritesFinder() - for child in node.body: -- ast.walk(child, visitor) -+ au.walk(child, visitor) - for name in visitor.read - visitor.written: - self._read_variable(name, node.lineno) - -@language python - -def _FunctionDef(self, node): - if not self.is_global and self.host_function: - self.host_function = False - for name in _get_argnames(node.args): - self._written_variable(name, node.lineno) - for child in node.body: - ast.walk(child, self) - else: - self._written_variable(node.name, node.lineno) - visitor = _VariableReadsAndWritesFinder() - for child in node.body: - ast.walk(child, visitor) - for name in visitor.read - visitor.written: - self._read_variable(name, node.lineno) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _MatchAs(self, node): - self._written_variable(node.name, node.lineno) - if node.pattern: -- ast.walk(node.pattern, self) -+ au.walk(node.pattern, self) - -@language python - -def _MatchAs(self, node): - self._written_variable(node.name, node.lineno) - if node.pattern: - ast.walk(node.pattern, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _Assign(self, node): -- ast.walk(node.value, self) -+ au.walk(node.value, self) - for child in node.targets: -- ast.walk(child, self) -+ au.walk(child, self) - -@language python - -def _Assign(self, node): - ast.walk(node.value, self) - for child in node.targets: - ast.walk(child, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,9 @@ - def _AugAssign(self, node): -- ast.walk(node.value, self) -+ au.walk(node.value, self) - if isinstance(node.target, ast.Name): - target_id = node.target.id - self._read_variable(target_id, node.target.lineno) - self._written_variable(target_id, node.target.lineno) - else: -- ast.walk(node.target, self) -+ au.walk(node.target, self) - -@language python - -def _AugAssign(self, node): - ast.walk(node.value, self) - if isinstance(node.target, ast.Name): - target_id = node.target.id - self._read_variable(target_id, node.target.lineno) - self._written_variable(target_id, node.target.lineno) - else: - ast.walk(node.target, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -3,8 +3,8 @@ - written = OrderedSet(self.written) - maybe_written = OrderedSet(self.maybe_written) - -- for child in ast.get_child_nodes(node): -- ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - - comp_names = list( - chain.from_iterable( -@language python - -def _comp_exp(self, node): - read = OrderedSet(self.read) - written = OrderedSet(self.written) - maybe_written = OrderedSet(self.maybe_written) - - for child in ast.get_child_nodes(node): - ast.walk(child, self) - - comp_names = list( - chain.from_iterable( - self._flatten_nested_tuple_of_names(generator.target) - for generator in node.generators - ) - ) - self.read = self.read - comp_names | read - self.written = self.written - comp_names | written - self.maybe_written = self.maybe_written - comp_names | maybe_written - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,11 +1,11 @@ - def _For(self, node): - with self._handle_loop_context(node), self._handle_conditional_context(node): - # iter has to be checked before the target variables -- ast.walk(node.iter, self) -- ast.walk(node.target, self) -+ au.walk(node.iter, self) -+ au.walk(node.target, self) - - for child in node.body: -- ast.walk(child, self) -+ au.walk(child, self) - for child in node.orelse: -- ast.walk(child, self) -+ au.walk(child, self) - -@language python - -def _For(self, node): - with self._handle_loop_context(node), self._handle_conditional_context(node): - # iter has to be checked before the target variables - ast.walk(node.iter, self) - ast.walk(node.target, self) - - for child in node.body: - ast.walk(child, self) - for child in node.orelse: - ast.walk(child, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _handle_conditional_node(self, node): - with self._handle_conditional_context(node): -- for child in ast.get_child_nodes(node): -- ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - -@language python - -def _handle_conditional_node(self, node): - with self._handle_conditional_context(node): - for child in ast.get_child_nodes(node): - ast.walk(child, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - def _FunctionDef(self, node): - self.written.add(node.name) - visitor = _VariableReadsAndWritesFinder() -- for child in ast.get_child_nodes(node): -- ast.walk(child, visitor) -+ for child in au.get_child_nodes(node): -+ au.walk(child, visitor) - self.read.update(visitor.read - visitor.written) - -@language python - -def _FunctionDef(self, node): - self.written.add(node.name) - visitor = _VariableReadsAndWritesFinder() - for child in ast.get_child_nodes(node): - ast.walk(child, visitor) - self.read.update(visitor.read - visitor.written) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,6 +4,6 @@ - return set(), set() - node = _parse_text(code) - visitor = _VariableReadsAndWritesFinder() -- ast.walk(node, visitor) -+ au.walk(node, visitor) - return visitor.read, visitor.written - -@language python - -@staticmethod -def find_reads_and_writes(code): - if code.strip() == "": - return set(), set() - node = _parse_text(code) - visitor = _VariableReadsAndWritesFinder() - ast.walk(node, visitor) - return visitor.read, visitor.written - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,7 +4,7 @@ - return set(), set() - node = _parse_text(code) - visitor = _VariableReadsAndWritesFinder() -- ast.walk(node, visitor) -+ au.walk(node, visitor) - return visitor.read - - -@language python - -@staticmethod -def find_reads_for_one_liners(code): - if code.strip() == "": - return set(), set() - node = _parse_text(code) - visitor = _VariableReadsAndWritesFinder() - ast.walk(node, visitor) - return visitor.read - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,7 +4,7 @@ - return False - node = _parse_text(code) - visitor = cls() -- ast.walk(node, visitor) -+ au.walk(node, visitor) - return visitor.error - - -@language python - -@classmethod -def has_errors(cls, code): - if code.strip() == "": - return False - node = _parse_text(code) - visitor = cls() - ast.walk(node, visitor) - return visitor.error - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,12 +1,12 @@ - def loop_encountered(self, node): - self.loop_count += 1 - for child in node.body: -- ast.walk(child, self) -+ au.walk(child, self) - self.loop_count -= 1 - if node.orelse: - if isinstance(node.orelse, (list, tuple)): - for node_ in node.orelse: -- ast.walk(node_, self) -+ au.walk(node_, self) - else: -- ast.walk(node.orelse, self) -+ au.walk(node.orelse, self) - -@language python - -def loop_encountered(self, node): - self.loop_count += 1 - for child in node.body: - ast.walk(child, self) - self.loop_count -= 1 - if node.orelse: - if isinstance(node.orelse, (list, tuple)): - for node_ in node.orelse: - ast.walk(node_, self) - else: - ast.walk(node.orelse, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,9 @@ -+import ast - from typing import Union, List - --from rope.base import ast, exceptions, pynames, pynamesdef, utils -+from rope.base import exceptions, pynames, utils -+import rope.base.astutils as au - from rope.refactor.importutils import actions, importinfo -- - - class ModuleImports: - def __init__(self, project, pymodule, import_filter=None): -@@ -26,12 +27,12 @@ - - def _get_unbound_names(self, defined_pyobject): - visitor = _GlobalUnboundNameFinder(self.pymodule, defined_pyobject) -- ast.walk(self.pymodule.get_ast(), visitor) -+ au.walk(self.pymodule.get_ast(), visitor) - return visitor.unbound - - def _get_all_star_list(self, pymodule): - def _resolve_name( -- name: Union[pynamesdef.AssignedName, pynames.ImportedName] -+ name: Union[pynames.AssignedName, pynames.ImportedName] - ) -> List: - while isinstance(name, pynames.ImportedName): - try: -@@ -40,7 +41,7 @@ - ) - except exceptions.AttributeNotFoundError: - return [] -- assert isinstance(name, pynamesdef.AssignedName) -+ assert isinstance(name, pynames.AssignedName) - return name.assignments - - result = set() -@@ -427,8 +428,8 @@ - .pyobject - ) - visitor = _LocalUnboundNameFinder(pyobject, self) -- for child in ast.get_child_nodes(node): -- ast.walk(child, visitor) -+ for child in au.get_child_nodes(node): -+ au.walk(child, visitor) - - def _FunctionDef(self, node): - self._visit_child_scope(node) -@@ -453,7 +454,7 @@ - ): - self.add_unbound(primary) - else: -- ast.walk(node, self) -+ au.walk(node, self) - - def _get_root(self): - pass -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,6 @@ --from rope.base.pynames import DefinedName -+import ast -+ -+import rope.base.astutils as au - import rope.base.builtins - import rope.base.codeanalyze - import rope.base.evaluate -@@ -6,15 +8,11 @@ - import rope.base.oi.soi - import rope.base.pyscopes - from rope.base import ( -- pynamesdef as pynames, -+ arguments, - exceptions, -- ast, -- astutils, -+ fscommands, -+ pynames, - pyobjects, -- fscommands, -- arguments, - utils, - ) - from rope.base.utils import pycompat -- -- -@language python - -from rope.base.pynames import DefinedName -import rope.base.builtins -import rope.base.codeanalyze -import rope.base.evaluate -import rope.base.libutils -import rope.base.oi.soi -import rope.base.pyscopes -from rope.base import ( - pynamesdef as pynames, - exceptions, - ast, - astutils, - pyobjects, - fscommands, - arguments, - utils, -) -from rope.base.utils import pycompat - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -10,7 +10,7 @@ - raise - else: - source = "\n" -- node = ast.parse("\n") -+ node = au.parse("\n") - self.source_code = source - self.star_imports = [] - self.visitor_class = _GlobalVisitor -@language python - -def __init__(self, pycore, source=None, resource=None, force_errors=False): - ignore = pycore.project.prefs.get("ignore_syntax_errors", False) - syntax_errors = force_errors or not ignore - self.has_errors = False - try: - source, node = self._init_source(pycore, source, resource) - except exceptions.ModuleSyntaxError: - self.has_errors = True - if syntax_errors: - raise - else: - source = "\n" - node = ast.parse("\n") - self.source_code = source - self.star_imports = [] - self.visitor_class = _GlobalVisitor - self.coding = fscommands.read_str_coding(self.source_code) - super().__init__(pycore, node, resource) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -11,7 +11,7 @@ - source_bytes = fscommands.unicode_to_file_data(source_code) - else: - source_bytes = source_code -- ast_node = ast.parse(source_bytes, filename=filename) -+ ast_node = au.parse(source_bytes, filename=filename) - except SyntaxError as e: - raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg) - except UnicodeDecodeError as e: -@language python - -def _init_source(self, pycore, source_code, resource): - filename = "string" - if resource: - filename = resource.path - try: - if source_code is None: - source_bytes = resource.read_bytes() - source_code, _ = fscommands.file_data_to_unicode(source_bytes) - else: - if isinstance(source_code, str): - source_bytes = fscommands.unicode_to_file_data(source_code) - else: - source_bytes = source_code - ast_node = ast.parse(source_bytes, filename=filename) - except SyntaxError as e: - raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg) - except UnicodeDecodeError as e: - raise exceptions.ModuleSyntaxError(filename, 1, "%s" % (e.reason)) - return source_code, ast_node - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,6 +6,6 @@ - init_dot_py, force_errors=force_errors - ).get_ast() - else: -- ast_node = ast.parse("\n") -+ ast_node = au.parse("\n") - super().__init__(pycore, ast_node, resource) - -@language python - -def __init__(self, pycore, resource=None, force_errors=False): - self.resource = resource - init_dot_py = self._get_init_dot_py() - if init_dot_py is not None: - ast_node = pycore.project.get_pymodule( - init_dot_py, force_errors=force_errors - ).get_ast() - else: - ast_node = ast.parse("\n") - super().__init__(pycore, ast_node, resource) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,5 +2,5 @@ - self.assigned_ast = node.value - self.type_hint = node.annotation - -- ast.walk(node.target, self) -+ au.walk(node.target, self) - -@language python - -def _AnnAssign(self, node): - self.assigned_ast = node.value - self.type_hint = node.annotation - - ast.walk(node.target, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _Tuple(self, node): -- names = astutils.get_name_levels(node) -+ names = au.get_name_levels(node) - for name, levels in names: - assignment = None - if self.assigned_ast is not None: -@language python - -def _Tuple(self, node): - names = astutils.get_name_levels(node) - for name, levels in names: - assignment = None - if self.assigned_ast is not None: - assignment = pynames.AssignmentValue(self.assigned_ast, levels) - self._assigned(name, assignment) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _NamedExpr(self, node): -- ast.walk(node.target, _AssignVisitor(self)) -- ast.walk(node.value, self) -+ au.walk(node.target, _AssignVisitor(self)) -+ au.walk(node.value, self) - - -@language python - -def _NamedExpr(self, node): - ast.walk(node.target, _AssignVisitor(self)) - ast.walk(node.value, self) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def _Assign(self, node): - self.assigned_ast = node.value - for child_node in node.targets: -- ast.walk(child_node, self) -- ast.walk(node.value, _ExpressionVisitor(self.scope_visitor)) -+ au.walk(child_node, self) -+ au.walk(node.value, _ExpressionVisitor(self.scope_visitor)) - -@language python - -def _Assign(self, node): - self.assigned_ast = node.value - for child_node in node.targets: - ast.walk(child_node, self) - ast.walk(node.value, _ExpressionVisitor(self.scope_visitor)) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _Tuple(self, node): -- names = astutils.get_name_levels(node) -+ names = au.get_name_levels(node) - for name, levels in names: - assignment = None - if self.assigned_ast is not None: -@language python - -def _Tuple(self, node): - names = astutils.get_name_levels(node) - for name, levels in names: - assignment = None - if self.assigned_ast is not None: - assignment = pynames.AssignmentValue(self.assigned_ast, levels) - self._assigned(name, assignment) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,3 +1,3 @@ - def _Assign(self, node): -- ast.walk(node, _AssignVisitor(self)) -+ au.walk(node, _AssignVisitor(self)) - -@language python - -def _Assign(self, node): - ast.walk(node, _AssignVisitor(self)) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,3 +1,3 @@ - def _AnnAssign(self, node): -- ast.walk(node, _AnnAssignVisitor(self)) -+ au.walk(node, _AnnAssignVisitor(self)) - -@language python - -def _AnnAssign(self, node): - ast.walk(node, _AnnAssignVisitor(self)) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,5 @@ - def _For(self, node): -- names = self._update_evaluated( -- node.target, node.iter, ".__iter__().next()" # noqa -- ) -+ self._update_evaluated(node.target, node.iter, ".__iter__().next()") # noqa - for child in node.body + node.orelse: -- ast.walk(child, self) -+ au.walk(child, self) - -@language python - -def _For(self, node): - names = self._update_evaluated( - node.target, node.iter, ".__iter__().next()" # noqa - ) - for child in node.body + node.orelse: - ast.walk(child, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,7 +6,7 @@ - assignment = pynames.AssignmentValue(assigned, [], evaluation, eval_type) - self._assigned(targets, assignment) - else: -- names = astutils.get_name_levels(targets) -+ names = au.get_name_levels(targets) - for name, levels in names: - assignment = pynames.AssignmentValue( - assigned, levels, evaluation, eval_type -@language python - -def _update_evaluated( - self, targets, assigned, evaluation="", eval_type=False, type_hint=None -): - result = {} - if isinstance(targets, str): - assignment = pynames.AssignmentValue(assigned, [], evaluation, eval_type) - self._assigned(targets, assignment) - else: - names = astutils.get_name_levels(targets) - for name, levels in names: - assignment = pynames.AssignmentValue( - assigned, levels, evaluation, eval_type - ) - self._assigned(name, assignment) - return result - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,5 +5,5 @@ - item.optional_vars, item.context_expr, ".__enter__()" - ) - for child in node.body: -- ast.walk(child, self) -+ au.walk(child, self) - -@language python - -def _With(self, node): - for item in pycompat.get_ast_with_items(node): - if item.optional_vars: - self._update_evaluated( - item.optional_vars, item.context_expr, ".__enter__()" - ) - for child in node.body: - ast.walk(child, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -7,5 +7,5 @@ - self._update_evaluated(node.name, type_node, eval_type=True) - - for child in node.body: -- ast.walk(child, self) -+ au.walk(child, self) - -@language python - -def _excepthandler(self, node): - node_name_type = str - if node.name is not None and isinstance(node.name, node_name_type): - type_node = node.type - if isinstance(node.type, ast.Tuple) and type_node.elts: - type_node = type_node.elts[0] - self._update_evaluated(node.name, type_node, eval_type=True) - - for child in node.body: - ast.walk(child, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,4 @@ - def _comprehension(self, node): -- ast.walk(node.target, self) -- ast.walk(node.iter, self) -+ au.walk(node.target, self) -+ au.walk(node.iter, self) - -@language python - -def _comprehension(self, node): - ast.walk(node.target, self) - ast.walk(node.iter, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,7 +6,7 @@ - if isinstance(first, pycompat.ast_arg_type): - new_visitor = _ClassInitVisitor(self, pycompat.get_ast_arg_arg(first)) - if new_visitor is not None: -- for child in ast.get_child_nodes(node): -- ast.walk(child, new_visitor) -+ for child in au.get_child_nodes(node): -+ au.walk(child, new_visitor) - - -@language python - -def _FunctionDef(self, node): - _ScopeVisitor._FunctionDef(self, node) - if len(node.args.args) > 0: - first = node.args.args[0] - new_visitor = None - if isinstance(first, pycompat.ast_arg_type): - new_visitor = _ClassInitVisitor(self, pycompat.get_ast_arg_arg(first)) - if new_visitor is not None: - for child in ast.get_child_nodes(node): - ast.walk(child, new_visitor) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def _Tuple(self, node): - if not isinstance(node.ctx, ast.Store): - return -- for child in ast.get_child_nodes(node): -- ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - -@language python - -def _Tuple(self, node): - if not isinstance(node.ctx, ast.Store): - return - for child in ast.get_child_nodes(node): - ast.walk(child, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,8 @@ -+import rope.base.astutils as au - import rope.base.builtins - import rope.base.codeanalyze - import rope.base.pynames --from rope.base import ast, exceptions, utils -+from rope.base import exceptions, utils - from rope.refactor import patchedast - - -@@ -186,8 +187,8 @@ - def _visit_comprehension(self): - if self.names is None: - new_visitor = self.visitor(self.pycore, self.pyobject) -- for node in ast.get_child_nodes(self.pyobject.get_ast()): -- ast.walk(node, new_visitor) -+ for node in au.get_child_nodes(self.pyobject.get_ast()): -+ au.walk(node, new_visitor) - self.names = dict(self.parent.get_names()) - self.names.update(new_visitor.names) - self.defineds = new_visitor.defineds -@@ -218,8 +219,8 @@ - def _visit_function(self): - if self.names is None: - new_visitor = self.visitor(self.pycore, self.pyobject) -- for n in ast.get_child_nodes(self.pyobject.get_ast()): -- ast.walk(n, new_visitor) -+ for n in au.get_child_nodes(self.pyobject.get_ast()): -+ au.walk(n, new_visitor) - self.names = new_visitor.names - self.names.update(self.pyobject.get_parameters()) - self.returned_asts = new_visitor.returned_asts -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,9 @@ - @path C:/Repos/ekr-rope/rope/base/ -+import rope.base.astutils as au - import rope.base.builtins - import rope.base.codeanalyze - import rope.base.pynames --from rope.base import ast, exceptions, utils -+from rope.base import exceptions, utils - from rope.refactor import patchedast - - -@language python - -@path C:/Repos/ekr-rope/rope/base/ -import rope.base.builtins -import rope.base.codeanalyze -import rope.base.pynames -from rope.base import ast, exceptions, utils -from rope.refactor import patchedast - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,8 @@ - def _visit_comprehension(self): - if self.names is None: - new_visitor = self.visitor(self.pycore, self.pyobject) -- for node in ast.get_child_nodes(self.pyobject.get_ast()): -- ast.walk(node, new_visitor) -+ for node in au.get_child_nodes(self.pyobject.get_ast()): -+ au.walk(node, new_visitor) - self.names = dict(self.parent.get_names()) - self.names.update(new_visitor.names) - self.defineds = new_visitor.defineds -@language python - -def _visit_comprehension(self): - if self.names is None: - new_visitor = self.visitor(self.pycore, self.pyobject) - for node in ast.get_child_nodes(self.pyobject.get_ast()): - ast.walk(node, new_visitor) - self.names = dict(self.parent.get_names()) - self.names.update(new_visitor.names) - self.defineds = new_visitor.defineds - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,8 @@ - def _visit_function(self): - if self.names is None: - new_visitor = self.visitor(self.pycore, self.pyobject) -- for n in ast.get_child_nodes(self.pyobject.get_ast()): -- ast.walk(n, new_visitor) -+ for n in au.get_child_nodes(self.pyobject.get_ast()): -+ au.walk(n, new_visitor) - self.names = new_visitor.names - self.names.update(self.pyobject.get_parameters()) - self.returned_asts = new_visitor.returned_asts -@language python - -def _visit_function(self): - if self.names is None: - new_visitor = self.visitor(self.pycore, self.pyobject) - for n in ast.get_child_nodes(self.pyobject.get_ast()): - ast.walk(n, new_visitor) - self.names = new_visitor.names - self.names.update(self.pyobject.get_parameters()) - self.returned_asts = new_visitor.returned_asts - self.is_generator = new_visitor.generator - self.defineds = new_visitor.defineds - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -8,7 +8,6 @@ - from rope.base import exceptions - from rope.base import libutils - from rope.base import pynames --from rope.base import pynamesdef - from rope.base import pyobjects - from rope.base import pyobjectsdef - from rope.base import pyscopes -@@ -186,9 +185,9 @@ - - # Start with the name of the object we're interested in. - names = [] -- if isinstance(pyname, pynamesdef.ParameterName): -+ if isinstance(pyname, pynames.ParameterName): - names = [(worder.get_name_at(pymod.get_resource(), offset), "PARAMETER")] -- elif isinstance(pyname, pynamesdef.AssignedName): -+ elif isinstance(pyname, pynames.AssignedName): - names = [(worder.get_name_at(pymod.get_resource(), offset), "VARIABLE")] - - # Collect scope names. -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -9,7 +9,6 @@ - from rope.base import exceptions - from rope.base import libutils - from rope.base import pynames --from rope.base import pynamesdef - from rope.base import pyobjects - from rope.base import pyobjectsdef - from rope.base import pyscopes -@language python - -@path C:/Repos/ekr-rope/rope/contrib/ -import keyword -import sys -import warnings - -import rope.base.codeanalyze -import rope.base.evaluate -from rope.base import builtins -from rope.base import exceptions -from rope.base import libutils -from rope.base import pynames -from rope.base import pynamesdef -from rope.base import pyobjects -from rope.base import pyobjectsdef -from rope.base import pyscopes -from rope.base import worder -from rope.contrib import fixsyntax -from rope.refactor import functionutils - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -33,9 +33,9 @@ - - # Start with the name of the object we're interested in. - names = [] -- if isinstance(pyname, pynamesdef.ParameterName): -+ if isinstance(pyname, pynames.ParameterName): - names = [(worder.get_name_at(pymod.get_resource(), offset), "PARAMETER")] -- elif isinstance(pyname, pynamesdef.AssignedName): -+ elif isinstance(pyname, pynames.AssignedName): - names = [(worder.get_name_at(pymod.get_resource(), offset), "VARIABLE")] - - # Collect scope names. -@language python - -def get_canonical_path(project, resource, offset): - """Get the canonical path to an object. - - Given the offset of the object, this returns a list of - (name, name_type) tuples representing the canonical path to the - object. For example, the 'x' in the following code: - - class Foo(object): - def bar(self): - class Qux(object): - def mux(self, x): - pass - - we will return: - - [('Foo', 'CLASS'), ('bar', 'FUNCTION'), ('Qux', 'CLASS'), - ('mux', 'FUNCTION'), ('x', 'PARAMETER')] - - `resource` is a `rope.base.resources.Resource` object. - - `offset` is the offset of the pyname you want the path to. - - """ - # Retrieve the PyName. - pymod = project.get_pymodule(resource) - pyname = rope.base.evaluate.eval_location(pymod, offset) - - # Now get the location of the definition and its containing scope. - defmod, lineno = pyname.get_definition_location() - if not defmod: - return None - scope = defmod.get_scope().get_inner_scope_for_line(lineno) - - # Start with the name of the object we're interested in. - names = [] - if isinstance(pyname, pynamesdef.ParameterName): - names = [(worder.get_name_at(pymod.get_resource(), offset), "PARAMETER")] - elif isinstance(pyname, pynamesdef.AssignedName): - names = [(worder.get_name_at(pymod.get_resource(), offset), "VARIABLE")] - - # Collect scope names. - while scope.parent: - if isinstance(scope, pyscopes.FunctionScope): - scope_type = "FUNCTION" - elif isinstance(scope, pyscopes.ClassScope): - scope_type = "CLASS" - else: - scope_type = None - names.append((scope.pyobject.get_name(), scope_type)) - scope = scope.parent - - names.append((defmod.get_resource().real_path, "MODULE")) - names.reverse() - return names - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -23,8 +23,9 @@ - * ... ;-) - - """ --from rope.base import ast, evaluate, pyobjects -- -+import ast -+from rope.base import evaluate, pyobjects -+import rope.base.astutils as au - - def find_errors(project, resource): - """Find possible bad name and attribute accesses -@@ -33,7 +34,7 @@ - """ - pymodule = project.get_pymodule(resource) - finder = _BadAccessFinder(pymodule) -- ast.walk(pymodule.get_ast(), finder) -+ au.walk(pymodule.get_ast(), finder) - return finder.errors - - -@@ -60,7 +61,7 @@ - if pyname is not None and pyname.get_object() != pyobjects.get_unknown(): - if node.attr not in pyname.get_object(): - self._add_error(node, "Unresolved attribute") -- ast.walk(node.value, self) -+ au.walk(node.value, self) - - def _add_error(self, node, msg): - if isinstance(node, ast.Attribute): -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -24,8 +24,9 @@ - * ... ;-) - - """ --from rope.base import ast, evaluate, pyobjects -- -+import ast -+from rope.base import evaluate, pyobjects -+import rope.base.astutils as au - - @others - @language python -@language python - -@path C:/Repos/ekr-rope/rope/contrib/ -"""Finding bad name and attribute accesses - -`find_errors` function can be used to find possible bad name and -attribute accesses. As an example:: - - errors = find_errors(project, project.get_resource('mod.py')) - for error in errors: - print('%s: %s' % (error.lineno, error.error)) - -prints possible errors for ``mod.py`` file. - -TODO: - -* use task handles -* reporting names at most once -* attributes of extension modules that don't appear in - extension_modules project config can be ignored -* not calling `PyScope.get_inner_scope_for_line()` if it is a - bottleneck; needs profiling -* not reporting occurrences where rope cannot infer the object -* rope saves multiple objects for some of the names in its objectdb - use all of them not to give false positives -* ... ;-) - -""" -from rope.base import ast, evaluate, pyobjects - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,7 +5,7 @@ - """ - pymodule = project.get_pymodule(resource) - finder = _BadAccessFinder(pymodule) -- ast.walk(pymodule.get_ast(), finder) -+ au.walk(pymodule.get_ast(), finder) - return finder.errors - - -@language python - -def find_errors(project, resource): - """Find possible bad name and attribute accesses - - It returns a list of `Error`. - """ - pymodule = project.get_pymodule(resource) - finder = _BadAccessFinder(pymodule) - ast.walk(pymodule.get_ast(), finder) - return finder.errors - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,5 +5,5 @@ - if pyname is not None and pyname.get_object() != pyobjects.get_unknown(): - if node.attr not in pyname.get_object(): - self._add_error(node, "Unresolved attribute") -- ast.walk(node.value, self) -+ au.walk(node.value, self) - -@language python - -def _Attribute(self, node): - if not isinstance(node.ctx, ast.Store): - scope = self.scope.get_inner_scope_for_line(node.lineno) - pyname = evaluate.eval_node(scope, node.value) - if pyname is not None and pyname.get_object() != pyobjects.get_unknown(): - if node.attr not in pyname.get_object(): - self._add_error(node, "Unresolved attribute") - ast.walk(node.value, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,6 @@ - import rope.base.evaluate --from rope.base import libutils --from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze --from rope.refactor import sourceutils, importutils, functionutils, suites -- -+from rope.base import change, codeanalyze, exceptions, libutils, pyobjects, pynames, worder -+from rope.refactor import functionutils, importutils, sourceutils, suites - - def create_generate(kind, project, resource, offset, goal_resource=None): - """A factory for creating `Generate` objects -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,7 @@ - @path C:/Repos/ekr-rope/rope/contrib/ - import rope.base.evaluate --from rope.base import libutils --from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze --from rope.refactor import sourceutils, importutils, functionutils, suites -- -+from rope.base import change, codeanalyze, exceptions, libutils, pyobjects, pynames, worder -+from rope.refactor import functionutils, importutils, sourceutils, suites - - @others - @language python -@language python - -@path C:/Repos/ekr-rope/rope/contrib/ -import rope.base.evaluate -from rope.base import libutils -from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze -from rope.refactor import sourceutils, importutils, functionutils, suites - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,14 +1,16 @@ -+ -+import ast - import re - from contextlib import contextmanager - from itertools import chain - --from rope.base import ast, codeanalyze -+from rope.base import codeanalyze -+import rope.base.astutils as au - from rope.base.change import ChangeSet, ChangeContents - from rope.base.exceptions import RefactoringError - from rope.base.utils import pycompat - from rope.base.utils.datastructures import OrderedSet - from rope.refactor import sourceutils, similarfinder, patchedast, suites, usefunction -- - - # Extract refactoring has lots of special cases. I tried to split it - # to smaller parts to make it more manageable: -@@ -590,7 +592,7 @@ - ) - body = self.info.source[self.info.scope_region[0] : self.info.scope_region[1]] - node = _parse_text(body) -- ast.walk(node, info_collector) -+ au.walk(node, info_collector) - return info_collector - - def _get_function_definition(self): -@@ -756,7 +758,7 @@ - def _get_globals_in_body(unindented_body): - node = _parse_text(unindented_body) - visitor = _GlobalFinder() -- ast.walk(node, visitor) -+ au.walk(node, visitor) - return visitor.globals_ - - -@@ -823,12 +825,12 @@ - for name in _get_argnames(node.args): - self._written_variable(name, node.lineno) - for child in node.body: -- ast.walk(child, self) -+ au.walk(child, self) - else: - self._written_variable(node.name, node.lineno) - visitor = _VariableReadsAndWritesFinder() - for child in node.body: -- ast.walk(child, visitor) -+ au.walk(child, visitor) - for name in visitor.read - visitor.written: - self._read_variable(name, node.lineno) - -@@ -847,21 +849,21 @@ - def _MatchAs(self, node): - self._written_variable(node.name, node.lineno) - if node.pattern: -- ast.walk(node.pattern, self) -+ au.walk(node.pattern, self) - - def _Assign(self, node): -- ast.walk(node.value, self) -+ au.walk(node.value, self) - for child in node.targets: -- ast.walk(child, self) -+ au.walk(child, self) - - def _AugAssign(self, node): -- ast.walk(node.value, self) -+ au.walk(node.value, self) - if isinstance(node.target, ast.Name): - target_id = node.target.id - self._read_variable(target_id, node.target.lineno) - self._written_variable(target_id, node.target.lineno) - else: -- ast.walk(node.target, self) -+ au.walk(node.target, self) - - def _ClassDef(self, node): - self._written_variable(node.name, node.lineno) -@@ -883,8 +885,8 @@ - written = OrderedSet(self.written) - maybe_written = OrderedSet(self.maybe_written) - -- for child in ast.get_child_nodes(node): -- ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - - comp_names = list( - chain.from_iterable( -@@ -915,18 +917,18 @@ - def _For(self, node): - with self._handle_loop_context(node), self._handle_conditional_context(node): - # iter has to be checked before the target variables -- ast.walk(node.iter, self) -- ast.walk(node.target, self) -+ au.walk(node.iter, self) -+ au.walk(node.target, self) - - for child in node.body: -- ast.walk(child, self) -+ au.walk(child, self) - for child in node.orelse: -- ast.walk(child, self) -+ au.walk(child, self) - - def _handle_conditional_node(self, node): - with self._handle_conditional_context(node): -- for child in ast.get_child_nodes(node): -- ast.walk(child, self) -+ for child in au.get_child_nodes(node): -+ au.walk(child, self) - - @contextmanager - def _handle_conditional_context(self, node): -@@ -974,8 +976,8 @@ - def _FunctionDef(self, node): - self.written.add(node.name) - visitor = _VariableReadsAndWritesFinder() -- for child in ast.get_child_nodes(node): -- ast.walk(child, visitor) -+ for child in au.get_child_nodes(node): -+ au.walk(child, visitor) - self.read.update(visitor.read - visitor.written) - - def _Class(self, node): -@@ -987,7 +989,7 @@ - return set(), set() - node = _parse_text(code) - visitor = _VariableReadsAndWritesFinder() -- ast.walk(node, visitor) -+ au.walk(node, visitor) - return visitor.read, visitor.written - - @staticmethod -@@ -996,7 +998,7 @@ - return set(), set() - node = _parse_text(code) - visitor = _VariableReadsAndWritesFinder() -- ast.walk(node, visitor) -+ au.walk(node, visitor) - return visitor.read - - -@@ -1007,7 +1009,7 @@ - return False - node = _parse_text(code) - visitor = cls() -- ast.walk(node, visitor) -+ au.walk(node, visitor) - return visitor.error - - -@@ -1025,14 +1027,14 @@ - def loop_encountered(self, node): - self.loop_count += 1 - for child in node.body: -- ast.walk(child, self) -+ au.walk(child, self) - self.loop_count -= 1 - if node.orelse: - if isinstance(node.orelse, (list, tuple)): - for node_ in node.orelse: -- ast.walk(node_, self) -+ au.walk(node_, self) - else: -- ast.walk(node.orelse, self) -+ au.walk(node.orelse, self) - - def _Break(self, node): - self.check_loop() -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,11 +1,13 @@ - @path C:/Repos/ekr-rope/rope/refactor/ -+import ast - import collections - import numbers - import re - import warnings - from itertools import chain - --from rope.base import ast, codeanalyze, exceptions -+import rope.base.astutils as au -+from rope.base import codeanalyze, exceptions - from rope.base.utils import pycompat - - -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -import collections -import numbers -import re -import warnings -from itertools import chain - -from rope.base import ast, codeanalyze, exceptions -from rope.base.utils import pycompat - - -try: - basestring -except NameError: - basestring = (str, bytes) - -COMMA_IN_WITH_PATTERN = re.compile(r"\(.*?\)|(,)") - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,6 +4,6 @@ - Adds ``sorted_children`` field only if `sorted_children` is True. - - """ -- return patch_ast(ast.parse(source), source, sorted_children) -+ return patch_ast(au.parse(source), source, sorted_children) - - -@language python - -def get_patched_ast(source, sorted_children=False): - """Adds ``region`` and ``sorted_children`` fields to nodes - - Adds ``sorted_children`` field only if `sorted_children` is True. - - """ - return patch_ast(ast.parse(source), source, sorted_children) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -14,7 +14,7 @@ - if hasattr(node, "region"): - return node - walker = _PatchingASTWalker(source, children=sorted_children) -- ast.call_for_nodes(node, walker) -+ au.call_for_nodes(node, walker) - return node - - -@language python - -def patch_ast(node, source, sorted_children=False): - """Patches the given node - - After calling, each node in `node` will have a new field named - `region` that is a tuple containing the start and end offsets - of the code that generated it. - - If `sorted_children` is true, a `sorted_children` field will - be created for each node, too. It is a list containing child - nodes as well as whitespaces and comments that occur between - them. - - """ - if hasattr(node, "region"): - return node - walker = _PatchingASTWalker(source, children=sorted_children) - ast.call_for_nodes(node, walker) - return node - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -9,5 +9,5 @@ - ) - node.region = (self.source.offset, self.source.offset) - if self.children: -- node.sorted_children = ast.get_children(node) -+ node.sorted_children = au.get_children(node) - -@language python - -def __call__(self, node): - method = getattr(self, "_" + node.__class__.__name__, None) - if method is not None: - return method(node) - # ???: Unknown node; what should we do here? - warnings.warn( - "Unknown node type <%s>; please report!" % node.__class__.__name__, - RuntimeWarning, - ) - node.region = (self.source.offset, self.source.offset) - if self.children: - node.sorted_children = ast.get_children(node) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -21,7 +21,7 @@ - continue - offset = self.source.offset - if isinstance(child, ast.AST): -- ast.call_for_nodes(child, self) -+ au.call_for_nodes(child, self) - token_start = child.region[0] - else: - if child is self.String: -@language python - -def _handle(self, node, base_children, eat_parens=False, eat_spaces=False): - if hasattr(node, "region"): - # ???: The same node was seen twice; what should we do? - warnings.warn( - "Node <%s> has been already patched; please report!" - % node.__class__.__name__, - RuntimeWarning, - ) - return - - base_children = collections.deque(base_children) - self.children_stack.append(base_children) - children = collections.deque() - formats = [] - suspected_start = self.source.offset - start = suspected_start - first_token = True - while base_children: - child = base_children.popleft() - if child is None: - continue - offset = self.source.offset - if isinstance(child, ast.AST): - ast.call_for_nodes(child, self) - token_start = child.region[0] - else: - if child is self.String: - region = self.source.consume_string( - end=self._find_next_statement_start() - ) - elif child is self.Number: - region = self.source.consume_number() - elif child == self.empty_tuple: - region = self.source.consume_empty_tuple() - elif child == "!=": - # INFO: This has been added to handle deprecated ``<>`` - region = self.source.consume_not_equal() - elif child == self.semicolon_or_as_in_except: - # INFO: This has been added to handle deprecated - # semicolon in except - region = self.source.consume_except_as_or_semicolon() - elif child == self.exec_open_paren_or_space: - # These three cases handle the differences between - # the deprecated exec statement and the exec - # function. - region = self.source.consume_exec_open_paren_or_space() - elif child == self.exec_in_or_comma: - region = self.source.consume_exec_in_or_comma() - elif child == self.exec_close_paren_or_space: - region = self.source.consume_exec_close_paren_or_space() - elif child == self.with_or_comma_context_manager: - region = self.source.consume_with_or_comma_context_manager() - else: - if hasattr(ast, "JoinedStr") and isinstance( - node, (ast.JoinedStr, ast.FormattedValue) - ): - region = self.source.consume_joined_string(child) - else: - region = self.source.consume(child) - child = self.source[region[0] : region[1]] - token_start = region[0] - if not first_token: - formats.append(self.source[offset:token_start]) - if self.children: - children.append(self.source[offset:token_start]) - else: - first_token = False - start = token_start - if self.children: - children.append(child) - start = self._handle_parens(children, start, formats) - if eat_parens: - start = self._eat_surrounding_parens(children, suspected_start, start) - if eat_spaces: - if self.children: - children.appendleft(self.source[0:start]) - end_spaces = self.source[self.source.offset :] - self.source.consume(end_spaces) - if self.children: - children.append(end_spaces) - start = 0 - if self.children: - node.sorted_children = children - node.region = (start, self.source.offset) - self.children_stack.pop() - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,7 +6,7 @@ - break - else: - self._skip_comment() -- except (ValueError, TypeError) as e: -+ except (ValueError, TypeError): - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) -@language python - -def consume(self, token, skip_comment=True): - try: - while True: - new_offset = self.source.index(token, self.offset) - if self._good_token(token, new_offset) or not skip_comment: - break - else: - self._skip_comment() - except (ValueError, TypeError) as e: - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) - self.offset = new_offset + len(token) - return (new_offset, self.offset) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,7 @@ - import warnings - --from rope.base import change, taskhandle, builtins, ast, codeanalyze -+import rope.base.astutils as au -+from rope.base import change, taskhandle, builtins, codeanalyze - from rope.base import libutils - from rope.refactor import patchedast, similarfinder, sourceutils - from rope.refactor.importutils import module_imports -@@ -312,7 +313,7 @@ - def _get_nearest_roots(self, node): - if node not in self._nearest_roots: - result = [] -- for child in ast.get_child_nodes(node): -+ for child in au.get_child_nodes(node): - if child in self.matched_asts: - result.append(child) - else: -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,8 @@ - @path C:/Repos/ekr-rope/rope/refactor/ - import warnings - --from rope.base import change, taskhandle, builtins, ast, codeanalyze -+import rope.base.astutils as au -+from rope.base import change, taskhandle, builtins, codeanalyze - from rope.base import libutils - from rope.refactor import patchedast, similarfinder, sourceutils - from rope.refactor.importutils import module_imports -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -import warnings - -from rope.base import change, taskhandle, builtins, ast, codeanalyze -from rope.base import libutils -from rope.refactor import patchedast, similarfinder, sourceutils -from rope.refactor.importutils import module_imports - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - def _get_nearest_roots(self, node): - if node not in self._nearest_roots: - result = [] -- for child in ast.get_child_nodes(node): -+ for child in au.get_child_nodes(node): - if child in self.matched_asts: - result.append(child) - else: -@language python - -def _get_nearest_roots(self, node): - if node not in self._nearest_roots: - result = [] - for child in ast.get_child_nodes(node): - if child in self.matched_asts: - result.append(child) - else: - result.extend(self._get_nearest_roots(child)) - self._nearest_roots[node] = result - return self._nearest_roots[node] - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,11 +1,11 @@ - """This module can be used for finding similar code""" -+import ast - import re - -+import rope.base.astutils as au - import rope.refactor.wildcards --from rope.base import libutils --from rope.base import codeanalyze, exceptions, ast, builtins -+from rope.base import builtins, codeanalyze, exceptions, libutils - from rope.refactor import patchedast, wildcards -- - from rope.refactor.patchedast import MismatchedTokenError - - -@@ -72,10 +72,10 @@ - def __init__(self, source, node=None, does_match=None): - if node is None: - try: -- node = ast.parse(source) -+ node = au.parse(source) - except SyntaxError: - # needed to parse expression containing := operator -- node = ast.parse("(" + source + ")") -+ node = au.parse("(" + source + ")") - if does_match is None: - self.does_match = self._simple_does_match - else: -@@ -119,7 +119,7 @@ - - def _create_pattern(self, expression): - expression = self._replace_wildcards(expression) -- node = ast.parse(expression) -+ node = au.parse(expression) - # Getting Module.Stmt.nodes - nodes = node.body - if len(nodes) == 1 and isinstance(nodes[0], ast.Expr): -@@ -154,7 +154,7 @@ - def find_matches(self): - if self.matches is None: - self.matches = [] -- ast.call_for_nodes(self.body, self._check_node, recursive=True) -+ au.call_for_nodes(self.body, self._check_node, recursive=True) - return self.matches - - def _check_node(self, node): -@@ -169,7 +169,7 @@ - self.matches.append(ExpressionMatch(node, mapping)) - - def _check_statements(self, node): -- for child in ast.get_children(node): -+ for child in au.get_children(node): - if isinstance(child, (list, tuple)): - self.__check_stmt_list(child) - -@@ -211,7 +211,7 @@ - - def _get_children(self, node): - """Return not `ast.expr_context` children of `node`""" -- children = ast.get_children(node) -+ children = au.get_children(node) - return [child for child in children if not isinstance(child, ast.expr_context)] - - def _match_stmts(self, current_stmts, mapping): -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,12 +1,12 @@ - @path C:/Repos/ekr-rope/rope/refactor/ - """This module can be used for finding similar code""" -+import ast - import re - -+import rope.base.astutils as au - import rope.refactor.wildcards --from rope.base import libutils --from rope.base import codeanalyze, exceptions, ast, builtins -+from rope.base import builtins, codeanalyze, exceptions, libutils - from rope.refactor import patchedast, wildcards -- - from rope.refactor.patchedast import MismatchedTokenError - - -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -"""This module can be used for finding similar code""" -import re - -import rope.refactor.wildcards -from rope.base import libutils -from rope.base import codeanalyze, exceptions, ast, builtins -from rope.refactor import patchedast, wildcards - -from rope.refactor.patchedast import MismatchedTokenError - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,10 +1,10 @@ - def __init__(self, source, node=None, does_match=None): - if node is None: - try: -- node = ast.parse(source) -+ node = au.parse(source) - except SyntaxError: - # needed to parse expression containing := operator -- node = ast.parse("(" + source + ")") -+ node = au.parse("(" + source + ")") - if does_match is None: - self.does_match = self._simple_does_match - else: -@language python - -def __init__(self, source, node=None, does_match=None): - if node is None: - try: - node = ast.parse(source) - except SyntaxError: - # needed to parse expression containing := operator - node = ast.parse("(" + source + ")") - if does_match is None: - self.does_match = self._simple_does_match - else: - self.does_match = does_match - self._init_using_ast(node, source) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def _create_pattern(self, expression): - expression = self._replace_wildcards(expression) -- node = ast.parse(expression) -+ node = au.parse(expression) - # Getting Module.Stmt.nodes - nodes = node.body - if len(nodes) == 1 and isinstance(nodes[0], ast.Expr): -@language python - -def _create_pattern(self, expression): - expression = self._replace_wildcards(expression) - node = ast.parse(expression) - # Getting Module.Stmt.nodes - nodes = node.body - if len(nodes) == 1 and isinstance(nodes[0], ast.Expr): - # Getting Discard.expr - wanted = nodes[0].value - else: - wanted = nodes - return wanted - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def find_matches(self): - if self.matches is None: - self.matches = [] -- ast.call_for_nodes(self.body, self._check_node, recursive=True) -+ au.call_for_nodes(self.body, self._check_node, recursive=True) - return self.matches - -@language python - -def find_matches(self): - if self.matches is None: - self.matches = [] - ast.call_for_nodes(self.body, self._check_node, recursive=True) - return self.matches - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _check_statements(self, node): -- for child in ast.get_children(node): -+ for child in au.get_children(node): - if isinstance(child, (list, tuple)): - self.__check_stmt_list(child) - -@language python - -def _check_statements(self, node): - for child in ast.get_children(node): - if isinstance(child, (list, tuple)): - self.__check_stmt_list(child) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _get_children(self, node): - """Return not `ast.expr_context` children of `node`""" -- children = ast.get_children(node) -+ children = au.get_children(node) - return [child for child in children if not isinstance(child, ast.expr_context)] - -@language python - -def _get_children(self, node): - """Return not `ast.expr_context` children of `node`""" - children = ast.get_children(node) - return [child for child in children if not isinstance(child, ast.expr_context)] - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ -+import ast - from itertools import chain - --from rope.base import ast --from rope.base.utils import pycompat -+import rope.base.astutils as au - - - def find_visible(node, lines): -@@ -72,7 +72,7 @@ - if self._children is None: - walker = _SuiteWalker(self) - for child in self.child_nodes: -- ast.walk(child, walker) -+ au.walk(child, walker) - self._children = walker.suites - return self._children -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,8 @@ - @path C:/Repos/ekr-rope/rope/refactor/ -+import ast - from itertools import chain - --from rope.base import ast --from rope.base.utils import pycompat -+import rope.base.astutils as au - - - @others -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -from itertools import chain - -from rope.base import ast -from rope.base.utils import pycompat - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,7 @@ - if self._children is None: - walker = _SuiteWalker(self) - for child in self.child_nodes: -- ast.walk(child, walker) -+ au.walk(child, walker) - self._children = walker.suites - return self._children - -@language python - -def get_children(self): - if self._children is None: - walker = _SuiteWalker(self) - for child in self.child_nodes: - ast.walk(child, walker) - self._children = walker.suites - return self._children - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,8 @@ --from rope.base import change, taskhandle, evaluate, exceptions, pyobjects, pynames, ast --from rope.base import libutils -+ -+import ast -+ -+import rope.base.astutils as au -+from rope.base import change, taskhandle, evaluate, exceptions, libutils, pyobjects, pynames - from rope.refactor import restructure, sourceutils, similarfinder - - -@@ -191,6 +194,6 @@ - def start_walking(self, node): - nodes = [node] - if isinstance(node, ast.FunctionDef): -- nodes = ast.get_child_nodes(node) -+ nodes = au.get_child_nodes(node) - for child in nodes: -- ast.walk(child, self) -+ au.walk(child, self) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,9 @@ - @path C:/Repos/ekr-rope/rope/refactor/ --from rope.base import change, taskhandle, evaluate, exceptions, pyobjects, pynames, ast --from rope.base import libutils -+ -+import ast -+ -+import rope.base.astutils as au -+from rope.base import change, taskhandle, evaluate, exceptions, libutils, pyobjects, pynames - from rope.refactor import restructure, sourceutils, similarfinder - - -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -from rope.base import change, taskhandle, evaluate, exceptions, pyobjects, pynames, ast -from rope.base import libutils -from rope.refactor import restructure, sourceutils, similarfinder - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def start_walking(self, node): - nodes = [node] - if isinstance(node, ast.FunctionDef): -- nodes = ast.get_child_nodes(node) -+ nodes = au.get_child_nodes(node) - for child in nodes: -- ast.walk(child, self) -+ au.walk(child, self) -@language python - -def start_walking(self, node): - nodes = [node] - if isinstance(node, ast.FunctionDef): - nodes = ast.get_child_nodes(node) - for child in nodes: - ast.walk(child, self) - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,5 @@ --from rope.base import ast, evaluate, builtins, pyobjects -+import ast -+from rope.base import evaluate, builtins, pyobjects - from rope.refactor import patchedast, occurrences -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,6 @@ - @path C:/Repos/ekr-rope/rope/refactor/ --from rope.base import ast, evaluate, builtins, pyobjects -+import ast -+from rope.base import evaluate, builtins, pyobjects - from rope.refactor import patchedast, occurrences - - -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -from rope.base import ast, evaluate, builtins, pyobjects -from rope.refactor import patchedast, occurrences - - -@others -@language python -@tabwidth -4 - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,10 @@ - @path C:/Repos/ekr-rope/rope/refactor/importutils/ -+import ast - from typing import Union, List - --from rope.base import ast, exceptions, pynames, pynamesdef, utils -+from rope.base import exceptions, pynames, utils -+import rope.base.astutils as au - from rope.refactor.importutils import actions, importinfo -- - - @others - @language python -@language python - -@path C:/Repos/ekr-rope/rope/refactor/importutils/ -from typing import Union, List - -from rope.base import ast, exceptions, pynames, pynamesdef, utils -from rope.refactor.importutils import actions, importinfo - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def _get_unbound_names(self, defined_pyobject): - visitor = _GlobalUnboundNameFinder(self.pymodule, defined_pyobject) -- ast.walk(self.pymodule.get_ast(), visitor) -+ au.walk(self.pymodule.get_ast(), visitor) - return visitor.unbound - -@language python - -def _get_unbound_names(self, defined_pyobject): - visitor = _GlobalUnboundNameFinder(self.pymodule, defined_pyobject) - ast.walk(self.pymodule.get_ast(), visitor) - return visitor.unbound - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - def _get_all_star_list(self, pymodule): - def _resolve_name( -- name: Union[pynamesdef.AssignedName, pynames.ImportedName] -+ name: Union[pynames.AssignedName, pynames.ImportedName] - ) -> List: - while isinstance(name, pynames.ImportedName): - try: -@@ -9,7 +9,7 @@ - ) - except exceptions.AttributeNotFoundError: - return [] -- assert isinstance(name, pynamesdef.AssignedName) -+ assert isinstance(name, pynames.AssignedName) - return name.assignments - - result = set() -@language python - -def _get_all_star_list(self, pymodule): - def _resolve_name( - name: Union[pynamesdef.AssignedName, pynames.ImportedName] - ) -> List: - while isinstance(name, pynames.ImportedName): - try: - name = name.imported_module.get_object().get_attribute( - name.imported_name, - ) - except exceptions.AttributeNotFoundError: - return [] - assert isinstance(name, pynamesdef.AssignedName) - return name.assignments - - result = set() - try: - all_star_list = pymodule.get_attribute("__all__") - except exceptions.AttributeNotFoundError: - return result - - assignments = [ - assignment.ast_node for assignment in _resolve_name(all_star_list) - ] - - # FIXME: Need a better way to recursively infer possible values. - # Currently pyobjects can recursively infer type, but not values. - # Do a very basic 1-level value inference - - while assignments: - assignment = assignments.pop() - if isinstance(assignment, ast.List): - stack = list(assignment.elts) - while stack: - el = stack.pop() - if isinstance(el, ast.IfExp): - stack.append(el.body) - stack.append(el.orelse) - elif isinstance(el, ast.Starred): - assignments.append(el.value) - else: - if isinstance(el, ast.Str): - result.add(el.s) - elif isinstance(el, ast.Name): - try: - name = pymodule.get_attribute(el.id) - except exceptions.AttributeNotFoundError: - continue - else: - for av in _resolve_name(name): - if isinstance(av.ast_node, ast.Str): - result.add(av.ast_node.s) - elif isinstance(assignment, ast.Name): - try: - name = pymodule.get_attribute(assignment.id) - except exceptions.AttributeNotFoundError: - continue - else: - assignments.extend( - assignment.ast_node for assignment in _resolve_name(name) - ) - elif isinstance(assignment, ast.BinOp): - assignments.append(assignment.left) - assignments.append(assignment.right) - return result - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,6 +6,6 @@ - .pyobject - ) - visitor = _LocalUnboundNameFinder(pyobject, self) -- for child in ast.get_child_nodes(node): -- ast.walk(child, visitor) -+ for child in au.get_child_nodes(node): -+ au.walk(child, visitor) - -@language python - -def _visit_child_scope(self, node): - pyobject = ( - self.pyobject.get_module() - .get_scope() - .get_inner_scope_for_line(node.lineno) - .pyobject - ) - visitor = _LocalUnboundNameFinder(pyobject, self) - for child in ast.get_child_nodes(node): - ast.walk(child, visitor) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -11,5 +11,5 @@ - ): - self.add_unbound(primary) - else: -- ast.walk(node, self) -+ au.walk(node, self) - -@language python - -def _Attribute(self, node): - result = [] - while isinstance(node, ast.Attribute): - result.append(node.attr) - node = node.value - if isinstance(node, ast.Name): - result.append(node.id) - primary = ".".join(reversed(result)) - if self._get_root()._is_node_interesting(node) and not self.is_bound( - primary - ): - self.add_unbound(primary) - else: - ast.walk(node, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,10 +1,12 @@ -+import ast - import collections - import numbers - import re - import warnings - from itertools import chain - --from rope.base import ast, codeanalyze, exceptions -+import rope.base.astutils as au -+from rope.base import codeanalyze, exceptions - from rope.base.utils import pycompat - - -@@ -22,7 +24,7 @@ - Adds ``sorted_children`` field only if `sorted_children` is True. - - """ -- return patch_ast(ast.parse(source), source, sorted_children) -+ return patch_ast(au.parse(source), source, sorted_children) - - - def patch_ast(node, source, sorted_children=False): -@@ -41,7 +43,7 @@ - if hasattr(node, "region"): - return node - walker = _PatchingASTWalker(source, children=sorted_children) -- ast.call_for_nodes(node, walker) -+ au.call_for_nodes(node, walker) - return node - - -@@ -96,7 +98,7 @@ - ) - node.region = (self.source.offset, self.source.offset) - if self.children: -- node.sorted_children = ast.get_children(node) -+ node.sorted_children = au.get_children(node) - - def _handle(self, node, base_children, eat_parens=False, eat_spaces=False): - if hasattr(node, "region"): -@@ -121,7 +123,7 @@ - continue - offset = self.source.offset - if isinstance(child, ast.AST): -- ast.call_for_nodes(child, self) -+ au.call_for_nodes(child, self) - token_start = child.region[0] - else: - if child is self.String: -@@ -927,7 +929,7 @@ - break - else: - self._skip_comment() -- except (ValueError, TypeError) as e: -+ except (ValueError, TypeError): - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) -@language python - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,4 @@ - """Tests for autoimport utility functions, written in pytest""" -- --from sys import platform -- --import pytest - - from rope.contrib.autoimport import utils - from rope.contrib.autoimport.defs import Package, PackageType, Source -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,5 @@ - @path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ - """Tests for autoimport utility functions, written in pytest""" -- --from sys import platform -- --import pytest - - from rope.contrib.autoimport import utils - from rope.contrib.autoimport.defs import Package, PackageType, Source -@language python - -@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ -"""Tests for autoimport utility functions, written in pytest""" - -from sys import platform - -import pytest - -from rope.contrib.autoimport import utils -from rope.contrib.autoimport.defs import Package, PackageType, Source - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -9,7 +9,7 @@ - from rope.base import libutils - from rope.base.pycore import _TextChangeDetector - from rope.base.pyobjects import get_base_type, AbstractFunction --from rope.base.pynamesdef import AssignedName -+from rope.base.pynames import AssignedName - from ropetest import testutils -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -10,7 +10,7 @@ - from rope.base import libutils - from rope.base.pycore import _TextChangeDetector - from rope.base.pyobjects import get_base_type, AbstractFunction --from rope.base.pynamesdef import AssignedName -+from rope.base.pynames import AssignedName - from ropetest import testutils - - -@language python - -@path C:/Repos/ekr-rope/ropetest/ -import sys -from textwrap import dedent - -from rope.base.builtins import File, BuiltinClass - -import unittest - -from rope.base import exceptions -from rope.base import libutils -from rope.base.pycore import _TextChangeDetector -from rope.base.pyobjects import get_base_type, AbstractFunction -from rope.base.pynamesdef import AssignedName -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - - - - - - - - -@language rest -@wrap - -PR: move special case from walk to _ScopeVisitor._ImportFrom -https://github.com/python-rope/rope/pull/538 - -To do: -- comment out parts of unit test to increase focus. - -@language python - - -@language rest -@wrap - -- Add # pragma: no cover - -@language python - - -@ignore -@nosearch - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -11,8 +11,6 @@ - import os - import shutil - import subprocess -- --import rope.base.utils.pycompat as pycompat - import typing - - -@language python - -@path C:/Repos/ekr-rope/rope/base/ -"""Project file system commands. - -This modules implements file system operations used by rope. Different -version control systems can be supported by implementing the interface -provided by `FileSystemCommands` class. See `SubversionCommands` and -`MercurialCommands` for example. - -""" -import re -import os -import shutil -import subprocess - -import rope.base.utils.pycompat as pycompat -import typing - - -FileContent = typing.NewType("FileContent", bytes) - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -30,9 +30,7 @@ - pycore, pyfunction, return_true, return_false, new_followed_calls - ) - -- if not followed_calls: -- _follow = None -- visitor = SOAVisitor(pycore, pydefined, _follow) -+ visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None) - for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): - rope.base.ast.walk(child, visitor) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -14,9 +14,7 @@ - pycore, pyfunction, return_true, return_false, new_followed_calls - ) - -- if not followed_calls: -- _follow = None -- visitor = SOAVisitor(pycore, pydefined, _follow) -+ visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None) - for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): - rope.base.ast.walk(child, visitor) - -@language python - -def _analyze_node(pycore, pydefined, should_analyze, search_subscopes, followed_calls): - if search_subscopes(pydefined): - for scope in pydefined.get_scope().get_scopes(): - _analyze_node( - pycore, scope.pyobject, should_analyze, search_subscopes, followed_calls - ) - if should_analyze(pydefined): - new_followed_calls = max(0, followed_calls - 1) - return_true = lambda pydefined: True - return_false = lambda pydefined: False - - def _follow(pyfunction): - _analyze_node( - pycore, pyfunction, return_true, return_false, new_followed_calls - ) - - if not followed_calls: - _follow = None - visitor = SOAVisitor(pycore, pydefined, _follow) - for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): - rope.base.ast.walk(child, visitor) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,6 @@ - # Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm - # and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py - import re --from rope.base.utils import pycompat - from rope.base.oi.type_hinting import utils - from rope.base import utils as base_utils - -@@ -268,7 +267,7 @@ - - - @method(symbol("[")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa - return utils.parametrize_type( - self.first.evaluate(pyobject), *[i.evaluate(pyobject) for i in self.second] - ) -@@ -276,7 +275,7 @@ - - # Anonymous Function Calls - @method(symbol("(")) --def nud(self, parser): -+def nud(self, parser): # noqa - self.second = [] - if parser.token.name != ")": - while 1: -@@ -292,7 +291,7 @@ - - # Function Calls - @method(symbol("(")) --def led(self, left, parser): -+def led(self, left, parser): # noqa - self.first = left - self.second = [] - if parser.token.name != ")": -@@ -308,14 +307,14 @@ - - - @method(symbol("(")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa - # TODO: Implement me - raise NotImplementedError - - - @method(symbol("or")) - @method(symbol("|")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa - # TODO: Implement me - raise NotImplementedError - -@@ -355,4 +354,4 @@ - return ast.evaluate(pyobject) - - --evaluate = Evaluator() -+evaluate = Evaluator() # noqa -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - @path C:/Repos/ekr-rope/rope/base/ - @nopyflakes --import ast --from ast import * -+import ast # noqu -+from ast import * # noqa - - from rope.base import fscommands - -@language python - -@path C:/Repos/ekr-rope/rope/base/ -@nopyflakes -import ast -from ast import * - -from rope.base import fscommands - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ --import ast --from ast import * -+import ast # noqu -+from ast import * # noqa - - from rope.base import fscommands -@language python - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -10,8 +10,6 @@ - import os - import shutil - import subprocess -- --import rope.base.utils.pycompat as pycompat - import typing -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,6 @@ - # Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm - # and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py - import re --from rope.base.utils import pycompat - from rope.base.oi.type_hinting import utils - from rope.base import utils as base_utils - -@language python - -@path C:/Repos/ekr-rope/rope/base/ -# Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm -# and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py -import re -from rope.base.utils import pycompat -from rope.base.oi.type_hinting import utils -from rope.base import utils as base_utils - - -class SymbolBase: - - name = None # node/token type name - - def __init__(self): - self.value = None # used by name and literals - self.first = None - self.second = None - self.third = None # used by tree nodes - - def nud(self, parser): - raise SyntaxError("Syntax error (%r)." % self.name) - - def led(self, left, parser): - raise SyntaxError("Unknown operator (%r)." % self.name) - - def evaluate(self, pyobject): - raise NotImplementedError(self.name, self) - - def __repr__(self): - if self.name == "(name)": - return "({} {})".format(self.name[1:-1], self.value) - out = [repr(self.name), self.first, self.second, self.third] - out = [str(i) for i in out if i] - return "(" + " ".join(out) + ")" - - -class SymbolTable: - def multi(func): - def _inner(self, names, *a, **kw): - for name in names.split(): - func(self, name, *a, **kw) - - return _inner - - def __init__(self): - self.symbol_table = {} - - def get(self, name, default=None): - return self.symbol_table.get(name, default) - - def __getitem__(self, name): - return self.symbol_table[name] - - def __iter__(self): - return iter(self.symbol_table) - - def symbol(self, name, bp=0): - try: - s = self.symbol_table[name] - except KeyError: - - class S(SymbolBase): - pass - - s = S - s.__name__ = "symbol-" + name # for debugging - s.name = name - s.lbp = bp - self.symbol_table[name] = s - else: - s.lbp = max(bp, s.lbp) - return s - - @multi - def infix(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def led(self, left, parser): - self.first = left - self.second = parser.expression(bp) - return self - - @multi - def infix_r(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def led(self, left, parser): - self.first = left - self.second = parser.expression(bp - 0.1) - return self - - def ternary(self, name, name2, bp): - symbol = self.symbol(name, bp) - symbol2 = self.symbol(name2) - - @method(symbol) - def led(self, left, parser): - self.first = left - self.second = parser.expression(symbol2.lbp) - parser.advance(symbol2.name) - self.third = parser.expression(symbol2.lbp + 0.1) - return self - - @multi - def prefix(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def nud(self, parser): - self.first = parser.expression(bp) - return self - - @multi - def postfix(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def led(self, left, parser): - self.first = left - return self - - multi = staticmethod(multi) # Just for code checker - - -symbol_table = SymbolTable() - - -class Lexer: - - _token_pattern = re.compile( - r""" - \s* - (?: - ( - [,()\[\]|] - | -> - | (?<=\s)(?:or)\b - ) # operator - | ([a-zA-Z](?:\w|\.)*) # name - ) - """, - re.U | re.S | re.X, - ) - - def __init__(self, symbol_table): - self.symbol_table = symbol_table - - def tokenize(self, program): - for name, value in self._tokenize_expr(program): - symbol = symbol_table.get(value) - if symbol: - s = symbol() - elif name == "(name)": - symbol = symbol_table[name] - s = symbol() - s.value = value - else: - raise SyntaxError( - "Unknown operator ({}). Possible operators are {!r}".format( - value, list(self.symbol_table) - ) - ) - - yield s - - def _tokenize_expr(self, program): - if isinstance(program, bytes): - program = program.decode("utf-8") - # import pprint; pprint.pprint(self._token_pattern.findall(program)) - for operator, name in self._token_pattern.findall(program): - if operator: - yield "(operator)", operator - elif name: - yield "(name)", name - else: - raise SyntaxError - yield "(end)", "(end)" - - -class Parser: - - token = None - next = None - - def __init__(self, lexer): - self.lexer = lexer - - def parse(self, program): - generator = self.lexer.tokenize(program) - self.next = generator.__next__ - self.token = self.next() - return self.expression() - - def expression(self, rbp=0): - t = self.token - self.token = self.next() - left = t.nud(self) - while rbp < self.token.lbp: - t = self.token - self.token = self.next() - left = t.led(left, self) - return left - - def advance(self, name=None): - if name and self.token.name != name: - raise SyntaxError(f"Expected {name!r} but found {self.token.name!r}") - self.token = self.next() - - -def method(s): - assert issubclass(s, SymbolBase) - - def bind(fn): - setattr(s, fn.__name__, fn) - return fn - - return bind - - -symbol, infix, infix_r, prefix, postfix, ternary = ( - symbol_table.symbol, - symbol_table.infix, - symbol_table.infix_r, - symbol_table.prefix, - symbol_table.postfix, - symbol_table.ternary, -) - -symbol("(", 270) -symbol(")") -symbol("[", 250) # Parameters -symbol("]") -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,4 +6,4 @@ - - - @method(symbol("[")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa -@language python - - if parser.token.name != ",": - break - parser.advance(",") - parser.advance("]") - return self - - -@method(symbol("[")) -def evaluate(self, pyobject): - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - @method(symbol("(")) --def nud(self, parser): -+def nud(self, parser): # noqa - self.second = [] - if parser.token.name != ")": - while 1: -@language python - -@method(symbol("(")) -def nud(self, parser): -self.second = [] -if parser.token.name != ")": - while 1: - self.second.append(parser.expression()) - if parser.token.name != ",": - break - parser.advance(",") -parser.advance(")") -parser.advance("->") -self.third = parser.expression(symbol("->").lbp + 0.1) -return self - - -# Function Calls - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - @method(symbol("(")) --def led(self, left, parser): -+def led(self, left, parser): # noqa - self.first = left - self.second = [] - if parser.token.name != ")": -@language python - -@method(symbol("(")) -def led(self, left, parser): -self.first = left -self.second = [] -if parser.token.name != ")": - while 1: - self.second.append(parser.expression()) - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,14 +5,14 @@ - - - @method(symbol("(")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa - # TODO: Implement me - raise NotImplementedError - - - @method(symbol("or")) - @method(symbol("|")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa - # TODO: Implement me - raise NotImplementedError - -@language python - -parser.advance(")") -parser.advance("->") -self.third = parser.expression(symbol("->").lbp + 0.1) -return self - - -@method(symbol("(")) -def evaluate(self, pyobject): -# TODO: Implement me -raise NotImplementedError - - -@method(symbol("or")) -@method(symbol("|")) -def evaluate(self, pyobject): -# TODO: Implement me -raise NotImplementedError - - -class Compiler: - -parser_factory = Parser -lexer_factory = Lexer -symbol_table = symbol_table - -def _make_parser(self): - return self.parser_factory(self.lexer_factory(self.symbol_table)) - -@base_utils.cached(500) -def __call__(self, program): - """ - :type program: str - :rtype: rope.base.oi.type_hinting.evaluate.SymbolBase - """ - return self._make_parser().parse(program) - - -compile = Compiler() - - -class Evaluator: - -compile = compile - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -9,4 +9,4 @@ - return ast.evaluate(pyobject) - - --evaluate = Evaluator() -+evaluate = Evaluator() # noqa -@language python - - -def __call__(self, program, pyobject): - """Evaluates the program string or AST - - :type program: str or rope.base.oi.type_hinting.evaluate.SymbolBase - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - ast = self.compile(program) if isinstance(program, str) else program - return ast.evaluate(pyobject) - - -evaluate = Evaluator() - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - import re --from rope.base.oi.type_hinting import utils -+ - from rope.base.oi.type_hinting.providers import interfaces -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - @path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ - import re --from rope.base.oi.type_hinting import utils -+ - from rope.base.oi.type_hinting.providers import interfaces - - -@language python - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ -import re -from rope.base.oi.type_hinting import utils -from rope.base.oi.type_hinting.providers import interfaces - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,14 +1,10 @@ - import logging -+from typing import Optional, Union - --try: -- from typing import Union, Optional --except ImportError: -- pass - import rope.base.utils as base_utils - from rope.base import evaluate - from rope.base.exceptions import AttributeNotFoundError - from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject --from rope.base.utils import pycompat - - - def get_super_func(pyfunc): -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,15 +1,11 @@ - @path C:/Repos/ekr-rope/rope/base/ - import logging -+from typing import Optional, Union - --try: -- from typing import Union, Optional --except ImportError: -- pass - import rope.base.utils as base_utils - from rope.base import evaluate - from rope.base.exceptions import AttributeNotFoundError - from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject --from rope.base.utils import pycompat - - - @others -@language python - -@path C:/Repos/ekr-rope/rope/base/ -import logging - -try: - from typing import Union, Optional -except ImportError: - pass -import rope.base.utils as base_utils -from rope.base import evaluate -from rope.base.exceptions import AttributeNotFoundError -from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject -from rope.base.utils import pycompat - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,5 @@ - import bisect - import difflib --import sys - import warnings - - import rope.base.libutils -@@ -15,7 +14,6 @@ - from rope.base import stdmods - from rope.base import taskhandle - from rope.base import utils --from rope.base.exceptions import ModuleNotFoundError - - - class PyCore: -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,3 @@ --from rope.base.pynames import DefinedName - import rope.base.builtins - import rope.base.codeanalyze - import rope.base.evaluate -@language python - -from rope.base.pynames import DefinedName -import rope.base.builtins -import rope.base.codeanalyze -import rope.base.evaluate -import rope.base.libutils -import rope.base.oi.soi -import rope.base.pyscopes -from rope.base import ( - pynamesdef as pynames, - exceptions, - ast, - astutils, - pyobjects, - fscommands, - arguments, - utils, -) -from rope.base.utils import pycompat - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,5 @@ - def _For(self, node): -- names = self._update_evaluated( -- node.target, node.iter, ".__iter__().next()" # noqa -- ) -+ self._update_evaluated(node.target, node.iter, ".__iter__().next()") - for child in node.body + node.orelse: - ast.walk(child, self) - -@language python - -def _For(self, node): - names = self._update_evaluated( - node.target, node.iter, ".__iter__().next()" # noqa - ) - for child in node.body + node.orelse: - ast.walk(child, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,6 +2,7 @@ - from .pickle import AutoImport as _PickleAutoImport - from .sqlite import AutoImport as _SqliteAutoImport - -+assert _SqliteAutoImport # Workaround for an apparent pyflakes bug. - - AutoImport = _PickleAutoImport -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -3,6 +3,7 @@ - from .pickle import AutoImport as _PickleAutoImport - from .sqlite import AutoImport as _SqliteAutoImport - -+assert _SqliteAutoImport # Workaround for an apparent pyflakes bug. - - AutoImport = _PickleAutoImport - -@language python - -@path C:/Repos/ekr-rope/rope/ -"""AutoImport module for rope.""" -from .pickle import AutoImport as _PickleAutoImport -from .sqlite import AutoImport as _SqliteAutoImport - - -AutoImport = _PickleAutoImport - -__all__ = ["AutoImport"] -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -45,8 +45,11 @@ - monitoring the progress of refactorings. - - """ --from rope.refactor.importutils import ImportOrganizer # noqa --from rope.refactor.topackage import ModuleToPackage # noqa -+from rope.refactor.importutils import ImportOrganizer # essential. -+from rope.refactor.topackage import ModuleToPackage # essential. -+ -+assert ImportOrganizer -+assert ModuleToPackage - - - __all__ = [ -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -46,8 +46,11 @@ - monitoring the progress of refactorings. - - """ --from rope.refactor.importutils import ImportOrganizer # noqa --from rope.refactor.topackage import ModuleToPackage # noqa -+from rope.refactor.importutils import ImportOrganizer # essential. -+from rope.refactor.topackage import ModuleToPackage # essential. -+ -+assert ImportOrganizer -+assert ModuleToPackage - - - __all__ = [ -@language python - -@path C:/Repos/ekr-rope/rope/ -"""rope refactor package - -This package contains modules that perform python refactorings. -Refactoring classes perform refactorings in 4 steps: - -1. Collect some data for performing the refactoring and use them - to construct a refactoring class. Like:: - - renamer = Rename(project, resource, offset) - -2. Some refactorings give you useful information about the - refactoring after their construction. Like:: - - print(renamer.get_old_name()) - -3. Give the refactoring class more information about how to - perform the refactoring and get the changes this refactoring is - going to make. This is done by calling `get_changes` method of the - refactoring class. Like:: - - changes = renamer.get_changes(new_name) - -4. You can commit the changes. Like:: - - project.do(changes) - -These steps are like the steps IDEs usually do for performing a -refactoring. These are the things an IDE does in each step: - -1. Construct a refactoring object by giving it information like - resource, offset and ... . Some of the refactoring problems (like - performing rename refactoring on language keywords) can be reported - here. -2. Print some information about the refactoring and ask the user - about the information that are necessary for completing the - refactoring (like new name). -3. Call the `get_changes` by passing it information asked from - the user (if necessary) and get and preview the changes returned by - it. -4. perform the refactoring. - -From ``0.5m5`` release the `get_changes()` method of some time- -consuming refactorings take an optional `rope.base.taskhandle. -TaskHandle` parameter. You can use this object for stopping or -monitoring the progress of refactorings. - -""" -from rope.refactor.importutils import ImportOrganizer # noqa -from rope.refactor.topackage import ModuleToPackage # noqa - - -__all__ = [ - "rename", - "move", - "inline", - "extract", - "restructure", - "topackage", - "importutils", - "usefunction", - "change_signature", - "encapsulate_field", - "introduce_factory", - "introduce_parameter", - "localtofield", - "method_object", - "multiproject", -] -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -22,7 +22,6 @@ - import rope.base.exceptions - import rope.refactor.functionutils - from rope.base import ( -- ast, - pynames, - pyobjects, - codeanalyze, -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -23,7 +23,6 @@ - import rope.base.exceptions - import rope.refactor.functionutils - from rope.base import ( -- ast, - pynames, - pyobjects, - codeanalyze, -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -# Known Bugs when inlining a function/method -# The values passed to function are inlined using _inlined_variable. -# This may cause two problems, illustrated in the examples below -# -# def foo(var1): -# var1 = var1*10 -# return var1 -# -# If a call to foo(20) is inlined, the result of inlined function is 20, -# but it should be 200. -# -# def foo(var1): -# var2 = var1*10 -# return var2 -# -# 2- If a call to foo(10+10) is inlined the result of inlined function is 110 -# but it should be 200. - -import re -from typing import List - -import rope.base.exceptions -import rope.refactor.functionutils -from rope.base import ( - ast, - pynames, - pyobjects, - codeanalyze, - taskhandle, - evaluate, - worder, - utils, - libutils, -) -from rope.base.change import ChangeSet, ChangeContents -from rope.refactor import ( - occurrences, - rename, - sourceutils, - importutils, - move, - change_signature, -) - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -927,7 +927,7 @@ - break - else: - self._skip_comment() -- except (ValueError, TypeError) as e: -+ except (ValueError, TypeError): - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,7 +6,7 @@ - break - else: - self._skip_comment() -- except (ValueError, TypeError) as e: -+ except (ValueError, TypeError): - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) -@language python - -def consume(self, token, skip_comment=True): - try: - while True: - new_offset = self.source.index(token, self.offset) - if self._good_token(token, new_offset) or not skip_comment: - break - else: - self._skip_comment() - except (ValueError, TypeError) as e: - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) - self.offset = new_offset + len(token) - return (new_offset, self.offset) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,6 @@ - from itertools import chain - - from rope.base import ast --from rope.base.utils import pycompat - - - def find_visible(node, lines): -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,6 @@ - from itertools import chain - - from rope.base import ast --from rope.base.utils import pycompat - - - @others -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -from itertools import chain - -from rope.base import ast -from rope.base.utils import pycompat - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,12 +1,9 @@ - from textwrap import dedent -+import unittest - - from rope.base.builtins import Str -- --import unittest -- - import rope.base.libutils - import rope.base.oi --from rope.base.utils import pycompat - from ropetest import testutils - - -@@ -1052,9 +1049,10 @@ - l = {} - v = l["key"] - """)) -- pymod1 = self.project.get_pymodule(mod1) # noqa -- var = pymod1["v"].get_object() # noqa -- -+ pymod1 = self.project.get_pymodule(mod1) -+ var = pymod1["v"].get_object() -+ self.assertTrue(pymod1 is not None) -+ self.assertTrue(var is not None) - def test_always_returning_containing_class_for_selfs(self): - code = dedent("""\ - class A(object): -@@ -1100,3 +1098,4 @@ - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - x_var = pymod["x"].pyobject.get() -+ self.assertTrue(x_var is not None) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,13 +1,10 @@ - @path C:/Repos/ekr-rope/ropetest/ - from textwrap import dedent -+import unittest - - from rope.base.builtins import Str -- --import unittest -- - import rope.base.libutils - import rope.base.oi --from rope.base.utils import pycompat - from ropetest import testutils - - -@language python - -@path C:/Repos/ekr-rope/ropetest/ -from textwrap import dedent - -from rope.base.builtins import Str - -import unittest - -import rope.base.libutils -import rope.base.oi -from rope.base.utils import pycompat -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -10,6 +10,7 @@ - l = {} - v = l["key"] - """)) -- pymod1 = self.project.get_pymodule(mod1) # noqa -- var = pymod1["v"].get_object() # noqa -- -+ pymod1 = self.project.get_pymodule(mod1) -+ var = pymod1["v"].get_object() -+ self.assertTrue(pymod1 is not None) -+ self.assertTrue(var is not None) -@language python - -def test_validation_problems_for_changing_builtin_types(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - l = [] - l.append("") - """)) - self.pycore.analyze_module(mod1) - - mod1.write(dedent("""\ - l = {} - v = l["key"] - """)) - pymod1 = self.project.get_pymodule(mod1) # noqa - var = pymod1["v"].get_object() # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,3 +6,4 @@ - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - x_var = pymod["x"].pyobject.get() -+ self.assertTrue(x_var is not None) -@language python - -def test_set_comprehension(self): - code = dedent("""\ - x = {s.strip() for s in X()} - x.add('x') - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - x_var = pymod["x"].pyobject.get() - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -485,8 +485,9 @@ - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a"].get_object() -- b_var = pymod["b"].get_object() # noqa -+ b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) -+ self.assertTrue(b_var is not None) - - def test_enumerate_builtin_function(self): - self.mod.write(dedent("""\ -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,6 @@ - @path C:/Repos/ekr-rope/rope/base/ - import bisect - import difflib --import sys - import warnings - - import rope.base.libutils -@@ -16,7 +15,6 @@ - from rope.base import stdmods - from rope.base import taskhandle - from rope.base import utils --from rope.base.exceptions import ModuleNotFoundError - - - @others -@language python - -@path C:/Repos/ekr-rope/rope/base/ -import bisect -import difflib -import sys -import warnings - -import rope.base.libutils -import rope.base.resourceobserver -import rope.base.resources -import rope.base.oi.doa -import rope.base.oi.objectinfo -import rope.base.oi.soa -from rope.base import builtins -from rope.base import exceptions -from rope.base import pyobjectsdef -from rope.base import stdmods -from rope.base import taskhandle -from rope.base import utils -from rope.base.exceptions import ModuleNotFoundError - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,3 @@ --from rope.base.pynames import DefinedName - import rope.base.builtins - import rope.base.codeanalyze - import rope.base.evaluate -@@ -461,9 +460,7 @@ - pass - - def _For(self, node): -- names = self._update_evaluated( -- node.target, node.iter, ".__iter__().next()" # noqa -- ) -+ self._update_evaluated(node.target, node.iter, ".__iter__().next()") - for child in node.body + node.orelse: - ast.walk(child, self) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,5 +5,6 @@ - """) - mod = libutils.get_string_module(self.project, code) - -- a = mod["a"].get_object() # noqa -+ a = mod["a"].get_object() -+ self.assertTrue(a is not None) - -@language python - -def test_empty_tuples(self): - code = dedent("""\ - t = () - a, b = t - """) - mod = libutils.get_string_module(self.project, code) - - a = mod["a"].get_object() # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,7 @@ - import os.path - import shutil - from textwrap import dedent -- --import pytest -+import unittest - - from rope.base.exceptions import RopeError, ResourceNotFoundError - from rope.base.fscommands import FileSystemCommands -@@ -10,9 +9,6 @@ - from rope.base.project import Project, NoProject, _realpath - from rope.base.resourceobserver import FilteredResourceObserver - from ropetest import testutils -- -- --import unittest - - - class ProjectTest(unittest.TestCase): -@@ -705,7 +701,7 @@ - def test_revalidating_folders(self): - root = self.project.root - my_folder = root.create_folder("myfolder") -- my_file = my_folder.create_file("myfile.txt") # noqa -+ my_file = my_folder.create_file("myfile.txt") - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [my_folder]) -@@ -714,6 +710,7 @@ - self.project.validate(root) - self.assertEqual(my_folder, sample_observer.last_removed) - self.assertEqual(1, sample_observer.change_count) -+ self.assertTrue(my_file is not None) - - def test_removing_and_adding_resources_to_filtered_observer(self): - my_file = self.project.root.create_file("my_file.txt") -@@ -812,7 +809,7 @@ - self.assertEqual(1, sample_observer.change_count) - - def test_changes_and_adding_resources(self): -- root = self.project.root # noqa -+ # root = self.project.root - file1 = self.project.get_file("file1.txt") - file2 = self.project.get_file("file2.txt") - file1.create() -@@ -826,7 +823,7 @@ - self.assertEqual((file1, file2), sample_observer.last_moved) - - def test_validating_get_files_list(self): -- root = self.project.root # noqa -+ # root = self.project.root - self.assertEqual(0, len(self.project.get_files())) - file = open(os.path.join(self.project.address, "myfile.txt"), "w") - file.close() -@@ -1040,8 +1037,9 @@ - self.project = testutils.sample_project( - ignored_resources=["myfile.txt"], ropefolder=None - ) -- myfile = self.project.root.create_file("myfile.txt") # noqa -+ myfile = self.project.root.create_file("myfile.txt") - self.assertEqual(0, len(self.project.get_files())) -+ self.assertTrue(myfile is not None) - - def test_setting_ignored_resources_patterns(self): - self.project = testutils.sample_project(ignored_resources=["m?file.*"]) -@@ -1162,7 +1160,8 @@ - ) - mod = testutils.create_module(self.project, "mod") - mod.write("xyz print") -- pymod = self.project.get_pymodule(mod) # noqa -+ pymod = self.project.get_pymodule(mod) -+ self.assertTrue(pymod is not None) - - def test_compressed_history(self): - self.project = testutils.sample_project(compress_history=True) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -8,6 +8,7 @@ - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a"].get_object() -- b_var = pymod["b"].get_object() # noqa -+ b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) -+ self.assertTrue(b_var is not None) - -@language python - -def test_wrong_arguments_to_zip_function(self): - self.mod.write(dedent("""\ - class C1(object): - pass - c1_list = [C1()] - a, b = zip(c1_list, 1)[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() # noqa - self.assertEqual(c1_class, a_var.get_type()) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -335,7 +335,8 @@ - - def test_getting_primary_and_strings_at_the_end_of_line(self): - code = "f('\\'')\n" -- result = self._find_primary(code, len(code) - 1) # noqa -+ result = self._find_primary(code, len(code) - 1) -+ self.assertTrue(result is not None) - - def test_getting_primary_and_not_crossing_newlines(self): - code = "\na = (b + c)\n(4 + 1).x\n" -@@ -753,7 +754,7 @@ - mod1 = testutils.create_module(self.project, "mod1") - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) -- mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa -+ mod2 = testutils.create_module(self.project, "mod2", pkg2) - mod1.write("import pkg1.pkg2.mod2") - - mod1_scope = self.project.get_pymodule(mod1).get_scope() -@@ -761,6 +762,7 @@ - pkg2_pyobject = self.project.get_pymodule(pkg2) - found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) - self.assertEqual(pkg2_pyobject, found_pyname.get_object()) -+ self.assertTrue(mod2 is not None) - - def test_get_pyname_at_on_language_keywords(self): - code = dedent("""\ -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,5 @@ - def test_getting_primary_and_strings_at_the_end_of_line(self): - code = "f('\\'')\n" -- result = self._find_primary(code, len(code) - 1) # noqa -+ result = self._find_primary(code, len(code) - 1) -+ self.assertTrue(result is not None) - -@language python - -def test_getting_primary_and_strings_at_the_end_of_line(self): - code = "f('\\'')\n" - result = self._find_primary(code, len(code) - 1) # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,7 @@ - mod1 = testutils.create_module(self.project, "mod1") - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) -- mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa -+ mod2 = testutils.create_module(self.project, "mod2", pkg2) - mod1.write("import pkg1.pkg2.mod2") - - mod1_scope = self.project.get_pymodule(mod1).get_scope() -@@ -10,4 +10,5 @@ - pkg2_pyobject = self.project.get_pymodule(pkg2) - found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) - self.assertEqual(pkg2_pyobject, found_pyname.get_object()) -+ self.assertTrue(mod2 is not None) - -@language python - -def test_relative_modules_after_from_statements2(self): - mod1 = testutils.create_module(self.project, "mod1") - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) - mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa - mod1.write("import pkg1.pkg2.mod2") - - mod1_scope = self.project.get_pymodule(mod1).get_scope() - name_finder = rope.base.evaluate.ScopeNameFinder(mod1_scope.pyobject) - pkg2_pyobject = self.project.get_pymodule(pkg2) - found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) - self.assertEqual(pkg2_pyobject, found_pyname.get_object()) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,4 @@ - """Tests for autoimport utility functions, written in pytest""" -- --from sys import platform -- --import pytest - - from rope.contrib.autoimport import utils - from rope.contrib.autoimport.defs import Package, PackageType, Source -@@ -59,5 +55,5 @@ - def test_get_package_tuple_compiled(compiled_lib): - lib_name, lib_path = compiled_lib - assert Package( -- lib_name, Source.STANDARD, lib_path, PackageType.COMPILED -+ lib_name, Source.STANDARD, lib_path, PackageType.COMPILED - ) == utils.get_package_tuple(lib_path) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,5 @@ - @path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ - """Tests for autoimport utility functions, written in pytest""" -- --from sys import platform -- --import pytest - - from rope.contrib.autoimport import utils - from rope.contrib.autoimport.defs import Package, PackageType, Source -@language python - -@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ -"""Tests for autoimport utility functions, written in pytest""" - -from sys import platform - -import pytest - -from rope.contrib.autoimport import utils -from rope.contrib.autoimport.defs import Package, PackageType, Source - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def test_get_package_tuple_compiled(compiled_lib): - lib_name, lib_path = compiled_lib - assert Package( -- lib_name, Source.STANDARD, lib_path, PackageType.COMPILED -+ lib_name, Source.STANDARD, lib_path, PackageType.COMPILED - ) == utils.get_package_tuple(lib_path) -@language python - -def test_get_package_tuple_compiled(compiled_lib): - lib_name, lib_path = compiled_lib - assert Package( - lib_name, Source.STANDARD, lib_path, PackageType.COMPILED - ) == utils.get_package_tuple(lib_path) - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -718,7 +718,8 @@ - pass - my_""") - result = self._assist(code) -- proposals = sorted_proposals(result, typepref=["function"]) # noqa -+ proposals = sorted_proposals(result, typepref=["function"]) -+ self.assertTrue(proposals is not None) - - def test_get_pydoc_unicode(self): - src = dedent('''\ -@@ -824,7 +825,8 @@ - s = "hey" - s.replace() - """) -- doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa -+ doc = get_doc(self.project, src, src.rindex("replace") + 1) -+ self.assertTrue(doc is not None) - - def test_proposing_variables_defined_till_the_end_of_scope(self): - code = dedent("""\ -@@ -928,7 +930,8 @@ - except: - pass - """) -- result = self._assist(code, code.index("."), maxfixes=1) # noqa -+ result = self._assist(code, code.index("."), maxfixes=1) -+ self.assertTrue(result is not None) - - def test_nested_blocks(self): - code = dedent("""\ -@@ -951,7 +954,8 @@ - code = dedent("""\ - f = 1 - f(p""") -- result = self._assist(code) # noqa -+ result = self._assist(code) -+ self.assertTrue(result is not None) - - def test_proposing_function_keywords_when_calling_extra_spaces(self): - code = dedent("""\ -@@ -1337,7 +1341,8 @@ - """) - samplemod.write(code) - package = testutils.create_package(self.project, "package") -- nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa -+ nestedmod = testutils.create_module(self.project, "nestedmod", package) -+ self.assertTrue(nestedmod is not None) - - def tearDown(self): - testutils.remove_project(self.project) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,5 +5,6 @@ - pass - my_""") - result = self._assist(code) -- proposals = sorted_proposals(result, typepref=["function"]) # noqa -+ proposals = sorted_proposals(result, typepref=["function"]) -+ self.assertTrue(proposals is not None) - -@language python - -def test_proposals_sorter_and_missing_type_in_typepref(self): - code = dedent("""\ - my_global_var = 1 - def my_global_func(): - pass - my_""") - result = self._assist(code) - proposals = sorted_proposals(result, typepref=["function"]) # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,5 +4,6 @@ - s = "hey" - s.replace() - """) -- doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa -+ doc = get_doc(self.project, src, src.rindex("replace") + 1) -+ self.assertTrue(doc is not None) - -@language python - -def test_commenting_errors_before_offset(self): - src = dedent("""\ - lsjd lsjdf - s = "hey" - s.replace() - """) - doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,5 +5,6 @@ - except: - pass - """) -- result = self._assist(code, code.index("."), maxfixes=1) # noqa -+ result = self._assist(code, code.index("."), maxfixes=1) -+ self.assertTrue(result is not None) - -@language python - -def test_and_normal_complete_blocks_and_single_fixing(self): - code = dedent("""\ - try: - range. - except: - pass - """) - result = self._assist(code, code.index("."), maxfixes=1) # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,5 +2,6 @@ - code = dedent("""\ - f = 1 - f(p""") -- result = self._assist(code) # noqa -+ result = self._assist(code) -+ self.assertTrue(result is not None) - -@language python - -def test_proposing_function_keywords_when_calling_for_non_functions(self): - code = dedent("""\ - f = 1 - f(p""") - result = self._assist(code) # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -18,5 +18,6 @@ - """) - samplemod.write(code) - package = testutils.create_package(self.project, "package") -- nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa -+ nestedmod = testutils.create_module(self.project, "nestedmod", package) -+ self.assertTrue(nestedmod is not None) - -@language python - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - samplemod = testutils.create_module(self.project, "samplemod") - code = dedent("""\ - class SampleClass(object): - def sample_method(): - pass - - def sample_func(): - pass - sample_var = 10 - - def _underlined_func(): - pass - - """) - samplemod.write(code) - package = testutils.create_package(self.project, "package") - nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -42,11 +42,12 @@ - - def test_handling_nested_modules(self): - pkg = create_package(self.project, "xkg") -- mod = create_module(self.project, "xkg.xod") # noqa -+ mod = create_module(self.project, "xkg.xod") - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - self.assertFalse(pkg.exists()) - self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) - self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) -+ self.assertTrue(mod is not None) - - - def _fixer(name): -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,10 @@ - def test_handling_nested_modules(self): - pkg = create_package(self.project, "xkg") -- mod = create_module(self.project, "xkg.xod") # noqa -+ mod = create_module(self.project, "xkg.xod") - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - self.assertFalse(pkg.exists()) - self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) - self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) -+ self.assertTrue(mod is not None) - - -@language python - -def test_handling_nested_modules(self): - pkg = create_package(self.project, "xkg") - mod = create_module(self.project, "xkg.xod") # noqa - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - self.assertFalse(pkg.exists()) - self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) - self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -373,7 +373,7 @@ - self.assertFalse(myfile.exists()) - - def test_writing_and_reading_history(self): -- history_file = self.project.get_file("history.pickle") # noqa -+ history_file = self.project.get_file("history.pickle") - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") -@@ -383,9 +383,10 @@ - history = rope.base.history.History(self.project) - history.undo() - self.assertFalse(myfile.exists()) -+ self.assertTrue(history_file is not None) - - def test_writing_and_reading_history2(self): -- history_file = self.project.get_file("history.pickle") # noqa -+ history_file = self.project.get_file("history.pickle") - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") -@@ -396,3 +397,4 @@ - history = rope.base.history.History(self.project) - history.redo() - self.assertTrue(myfile.exists()) -+ self.assertTrue(history_file is not None) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def test_writing_and_reading_history(self): -- history_file = self.project.get_file("history.pickle") # noqa -+ history_file = self.project.get_file("history.pickle") - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") -@@ -9,4 +9,5 @@ - history = rope.base.history.History(self.project) - history.undo() - self.assertFalse(myfile.exists()) -+ self.assertTrue(history_file is not None) - -@language python - -def test_writing_and_reading_history(self): - history_file = self.project.get_file("history.pickle") # noqa - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") - history.do(rope.base.change.CreateResource(myfile)) - history.write() - - history = rope.base.history.History(self.project) - history.undo() - self.assertFalse(myfile.exists()) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def test_writing_and_reading_history2(self): -- history_file = self.project.get_file("history.pickle") # noqa -+ history_file = self.project.get_file("history.pickle") - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") -@@ -10,3 +10,4 @@ - history = rope.base.history.History(self.project) - history.redo() - self.assertTrue(myfile.exists()) -+ self.assertTrue(history_file is not None) -@language python - -def test_writing_and_reading_history2(self): - history_file = self.project.get_file("history.pickle") # noqa - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") - history.do(rope.base.change.CreateResource(myfile)) - history.undo() - history.write() - - history = rope.base.history.History(self.project) - history.redo() - self.assertTrue(myfile.exists()) - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -285,7 +285,8 @@ - """) - mod = libutils.get_string_module(self.project, code) - -- a = mod["a"].get_object() # noqa -+ a = mod["a"].get_object() -+ self.assertTrue(a is not None) - - def test_handling_generator_functions(self): - code = dedent("""\ -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -12,6 +12,8 @@ - p1 = testutils.create_package(self.project, "p1") - p2 = testutils.create_package(self.project, "p2", p1) - p3 = testutils.create_package(self.project, "p3", p2) -- m1 = testutils.create_module(self.project, "m1", p3) # noqa -- l = testutils.create_module(self.project, "l", p3) # noqa -+ m1 = testutils.create_module(self.project, "m1", p3) -+ mod_l = testutils.create_module(self.project, "l", p3) -+ self.assertTrue(m1 is not None) -+ self.assertTrue(mod_l is not None) - -@language python - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.import_tools = ImportTools(self.project) - - self.mod = testutils.create_module(self.project, "mod") - self.pkg1 = testutils.create_package(self.project, "pkg1") - self.mod1 = testutils.create_module(self.project, "mod1", self.pkg1) - self.pkg2 = testutils.create_package(self.project, "pkg2") - self.mod2 = testutils.create_module(self.project, "mod2", self.pkg2) - self.mod3 = testutils.create_module(self.project, "mod3", self.pkg2) - p1 = testutils.create_package(self.project, "p1") - p2 = testutils.create_package(self.project, "p2", p1) - p3 = testutils.create_package(self.project, "p3", p2) - m1 = testutils.create_module(self.project, "m1", p3) # noqa - l = testutils.create_module(self.project, "l", p3) # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -314,6 +314,7 @@ - mover = move.create_move( - self.project, self.mod1, code.index("CONSTANT") + 1 - ) -+ self.assertTrue(mover is not None) - - def test_raising_exception_for_mov_glob_elemnts_to_the_same_module(self): - self.mod1.write("def a_func():\n pass\n") -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -8,4 +8,5 @@ - mover = move.create_move( - self.project, self.mod1, code.index("CONSTANT") + 1 - ) -+ self.assertTrue(mover is not None) - -@language python - -def test_raising_an_exception_for_moving_non_global_variable(self): - code = dedent("""\ - class TestClass: - CONSTANT = 5 - """) - self.mod1.write(code) - with self.assertRaises(exceptions.RefactoringError): - mover = move.create_move( - self.project, self.mod1, code.index("CONSTANT") + 1 - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1558,7 +1558,6 @@ - ")", - ]) - -- - @testutils.only_for_versions_higher("3.10") - def test_match_node_with_match_mapping_match_as(self): - source = dedent("""\ -@@ -1587,8 +1586,6 @@ - "", - "}", - ]) -- -- - class _ResultChecker: - def __init__(self, test_case, ast): - self.test_case = test_case -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,8 +2,7 @@ - import os.path - import shutil - from textwrap import dedent -- --import pytest -+import unittest - - from rope.base.exceptions import RopeError, ResourceNotFoundError - from rope.base.fscommands import FileSystemCommands -@@ -13,9 +12,6 @@ - from ropetest import testutils - - --import unittest -- -- - @others - @language python - @tabwidth -4 -@language python - -@path C:/Repos/ekr-rope/ropetest/ -import os.path -import shutil -from textwrap import dedent - -import pytest - -from rope.base.exceptions import RopeError, ResourceNotFoundError -from rope.base.fscommands import FileSystemCommands -from rope.base.libutils import path_to_resource -from rope.base.project import Project, NoProject, _realpath -from rope.base.resourceobserver import FilteredResourceObserver -from ropetest import testutils - - -import unittest - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - def test_revalidating_folders(self): - root = self.project.root - my_folder = root.create_folder("myfolder") -- my_file = my_folder.create_file("myfile.txt") # noqa -+ my_file = my_folder.create_file("myfile.txt") - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [my_folder]) -@@ -10,4 +10,5 @@ - self.project.validate(root) - self.assertEqual(my_folder, sample_observer.last_removed) - self.assertEqual(1, sample_observer.change_count) -+ self.assertTrue(my_file is not None) - -@language python - -def test_revalidating_folders(self): - root = self.project.root - my_folder = root.create_folder("myfolder") - my_file = my_folder.create_file("myfile.txt") # noqa - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [my_folder]) - ) - testutils.remove_recursively(my_folder.real_path) - self.project.validate(root) - self.assertEqual(my_folder, sample_observer.last_removed) - self.assertEqual(1, sample_observer.change_count) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def test_changes_and_adding_resources(self): -- root = self.project.root # noqa -+ # root = self.project.root - file1 = self.project.get_file("file1.txt") - file2 = self.project.get_file("file2.txt") - file1.create() -@language python - -def test_changes_and_adding_resources(self): - root = self.project.root # noqa - file1 = self.project.get_file("file1.txt") - file2 = self.project.get_file("file2.txt") - file1.create() - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [file1, file2]) - ) - file1.move(file2.path) - self.assertEqual(2, sample_observer.change_count) - self.assertEqual(file2, sample_observer.last_created) - self.assertEqual((file1, file2), sample_observer.last_moved) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def test_validating_get_files_list(self): -- root = self.project.root # noqa -+ # root = self.project.root - self.assertEqual(0, len(self.project.get_files())) - file = open(os.path.join(self.project.address, "myfile.txt"), "w") - file.close() -@language python - -def test_validating_get_files_list(self): - root = self.project.root # noqa - self.assertEqual(0, len(self.project.get_files())) - file = open(os.path.join(self.project.address, "myfile.txt"), "w") - file.close() - self.project.validate() - self.assertEqual(1, len(self.project.get_files())) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,6 +2,7 @@ - self.project = testutils.sample_project( - ignored_resources=["myfile.txt"], ropefolder=None - ) -- myfile = self.project.root.create_file("myfile.txt") # noqa -+ myfile = self.project.root.create_file("myfile.txt") - self.assertEqual(0, len(self.project.get_files())) -+ self.assertTrue(myfile is not None) - -@language python - -def test_ignored_resources_and_get_files2(self): - self.project = testutils.sample_project( - ignored_resources=["myfile.txt"], ropefolder=None - ) - myfile = self.project.root.create_file("myfile.txt") # noqa - self.assertEqual(0, len(self.project.get_files())) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,5 +4,6 @@ - ) - mod = testutils.create_module(self.project, "mod") - mod.write("xyz print") -- pymod = self.project.get_pymodule(mod) # noqa -+ pymod = self.project.get_pymodule(mod) -+ self.assertTrue(pymod is not None) - -@language python - -def test_ignoring_syntax_errors(self): - self.project = testutils.sample_project( - ropefolder=None, ignore_syntax_errors=True - ) - mod = testutils.create_module(self.project, "mod") - mod.write("xyz print") - pymod = self.project.get_pymodule(mod) # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -31,18 +31,19 @@ - - def test_nested_modules(self): - pkg = testutils.create_package(self.project, "pkg") -- mod = testutils.create_module(self.project, "mod", pkg) # noqa -+ mod = testutils.create_module(self.project, "mod", pkg) - package = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), package.get_type()) - self.assertEqual(1, len(package.get_attributes())) - module = package["mod"].get_object() - self.assertEqual(get_base_type("Module"), module.get_type()) -- -+ self.assertTrue(mod is not None) - def test_package(self): - pkg = testutils.create_package(self.project, "pkg") -- mod = testutils.create_module(self.project, "mod", pkg) # noqa -+ mod = testutils.create_module(self.project, "mod", pkg) - result = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), result.type) -+ self.assertTrue(mod is not None) - - def test_simple_class(self): - mod = testutils.create_module(self.project, "mod") -@@ -101,7 +102,8 @@ - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["SampleClass"].get_object() -- var = sample_class["var"] # noqa -+ var = sample_class["var"] -+ self.assertTrue(var is not None) - - def test_class_attributes_set_in_init(self): - mod = testutils.create_module(self.project, "mod") -@@ -112,7 +114,8 @@ - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["C"].get_object() -- var = sample_class["var"] # noqa -+ var = sample_class["var"] -+ self.assertTrue(var is not None) - - def test_class_attributes_set_in_init_overwriting_a_defined(self): - mod = testutils.create_module(self.project, "mod") -@@ -174,7 +177,8 @@ - - def test_get_string_module_with_extra_spaces(self): - code = "a = 10\n " -- mod = libutils.get_string_module(self.project, code) # noqa -+ mod = libutils.get_string_module(self.project, code) -+ self.assertTrue(mod is not None) - - def test_parameter_info_for_functions(self): - code = dedent("""\ -@@ -264,9 +268,10 @@ - self.assertEqual(self.project.get_resource("module.py"), new_module) - - def test_packaged_module_creation(self): -- package = self.project.root.create_folder("package") # noqa -+ package = self.project.root.create_folder("package") - new_module = testutils.create_module(self.project, "package.module") - self.assertEqual(self.project.get_resource("package/module.py"), new_module) -+ self.assertTrue(package is not None) - - def test_packaged_module_creation_with_nested_src(self): - src = self.project.root.create_folder("src") -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,9 @@ - def test_nested_modules(self): - pkg = testutils.create_package(self.project, "pkg") -- mod = testutils.create_module(self.project, "mod", pkg) # noqa -+ mod = testutils.create_module(self.project, "mod", pkg) - package = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), package.get_type()) - self.assertEqual(1, len(package.get_attributes())) - module = package["mod"].get_object() - self.assertEqual(get_base_type("Module"), module.get_type()) -- -+ self.assertTrue(mod is not None) -@language python - -def test_nested_modules(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) # noqa - package = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), package.get_type()) - self.assertEqual(1, len(package.get_attributes())) - module = package["mod"].get_object() - self.assertEqual(get_base_type("Module"), module.get_type()) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,7 @@ - def test_package(self): - pkg = testutils.create_package(self.project, "pkg") -- mod = testutils.create_module(self.project, "mod", pkg) # noqa -+ mod = testutils.create_module(self.project, "mod", pkg) - result = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), result.type) -+ self.assertTrue(mod is not None) - -@language python - -def test_package(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) # noqa - result = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), result.type) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,5 +6,6 @@ - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["SampleClass"].get_object() -- var = sample_class["var"] # noqa -+ var = sample_class["var"] -+ self.assertTrue(var is not None) - -@language python - -def test_class_variables(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - class SampleClass(object): - var = 10 - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["SampleClass"].get_object() - var = sample_class["var"] # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -7,5 +7,6 @@ - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["C"].get_object() -- var = sample_class["var"] # noqa -+ var = sample_class["var"] -+ self.assertTrue(var is not None) - -@language python - -def test_class_attributes_set_in_init(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - class C(object): - def __init__(self): - self.var = 20 - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["C"].get_object() - var = sample_class["var"] # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,5 @@ - def test_get_string_module_with_extra_spaces(self): - code = "a = 10\n " -- mod = libutils.get_string_module(self.project, code) # noqa -+ mod = libutils.get_string_module(self.project, code) -+ self.assertTrue(mod is not None) - -@language python - -def test_get_string_module_with_extra_spaces(self): - code = "a = 10\n " - mod = libutils.get_string_module(self.project, code) # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,6 @@ - def test_packaged_module_creation(self): -- package = self.project.root.create_folder("package") # noqa -+ package = self.project.root.create_folder("package") - new_module = testutils.create_module(self.project, "package.module") - self.assertEqual(self.project.get_resource("package/module.py"), new_module) -+ self.assertTrue(package is not None) - -@language python - -def test_packaged_module_creation(self): - package = self.project.root.create_folder("package") # noqa - new_module = testutils.create_module(self.project, "package.module") - self.assertEqual(self.project.get_resource("package/module.py"), new_module) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -53,6 +53,7 @@ - get_base_type("Type"), - sample_func_scope["SampleClass"].get_object().get_type(), - ) -+ self.assertTrue(sample_func_scope is not None) - - def test_list_comprehension_scope_inside_assignment(self): - code = "a_var = [b_var + d_var for b_var, c_var in e_var]\n" -@@ -468,12 +469,13 @@ - """) - scope = libutils.get_string_scope(self.project, code) - -- a_scope = scope["A"].get_object().get_scope() # noqa -+ a_scope = scope["A"].get_object().get_scope() - b_scope = scope["B"].get_object().get_scope() - self.assertTrue("a" in b_scope.get_names()) - self.assertTrue("b" in b_scope.get_names()) - self.assertTrue("a" not in b_scope.get_defined_names()) - self.assertTrue("b" in b_scope.get_defined_names()) -+ self.assertTrue(a_scope is not None) - - def test_getting_defined_names_for_modules(self): - code = dedent("""\ -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -12,4 +12,5 @@ - get_base_type("Type"), - sample_func_scope["SampleClass"].get_object().get_type(), - ) -+ self.assertTrue(sample_func_scope is not None) - -@language python - -def test_classes_inside_function_scopes(self): - code = dedent("""\ - def sample_func(): - class SampleClass(object): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(1, len(scope.get_scopes())) - sample_func_scope = scope.get_scopes()[0] - self.assertEqual( - get_base_type("Type"), - sample_func_scope["SampleClass"].get_object().get_type(), - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -9,10 +9,11 @@ - """) - scope = libutils.get_string_scope(self.project, code) - -- a_scope = scope["A"].get_object().get_scope() # noqa -+ a_scope = scope["A"].get_object().get_scope() - b_scope = scope["B"].get_object().get_scope() - self.assertTrue("a" in b_scope.get_names()) - self.assertTrue("b" in b_scope.get_names()) - self.assertTrue("a" not in b_scope.get_defined_names()) - self.assertTrue("b" in b_scope.get_defined_names()) -+ self.assertTrue(a_scope is not None) - -@language python - -def test_getting_defined_names_for_classes(self): - code = dedent("""\ - class A(object): - def a(self): - pass - class B(A): - def b(self): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - a_scope = scope["A"].get_object().get_scope() # noqa - b_scope = scope["B"].get_object().get_scope() - self.assertTrue("a" in b_scope.get_names()) - self.assertTrue("b" in b_scope.get_names()) - self.assertTrue("a" not in b_scope.get_defined_names()) - self.assertTrue("b" in b_scope.get_defined_names()) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,23 +4,12 @@ - - import rope.base.taskhandle - import rope.refactor.introduce_parameter --import ropetest.refactor.extracttest --import ropetest.refactor.importutilstest --import ropetest.refactor.inlinetest --import ropetest.refactor.movetest --import ropetest.refactor.multiprojecttest --import ropetest.refactor.patchedasttest --import ropetest.refactor.renametest --import ropetest.refactor.restructuretest --import ropetest.refactor.suitestest --import ropetest.refactor.usefunctiontest - from rope.base.exceptions import RefactoringError, InterruptedTaskError - from rope.refactor.encapsulate_field import EncapsulateField - from rope.refactor.introduce_factory import IntroduceFactory - from rope.refactor.localtofield import LocalToField - from rope.refactor.method_object import MethodObject - from ropetest import testutils --from ropetest.refactor import change_signature_test, similarfindertest - - - class MethodObjectTest(unittest.TestCase): -@@ -1093,8 +1082,9 @@ - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) -- jobs = handle.create_jobset() # noqa -+ jobs = handle.create_jobset() - self.assertEqual(1, observer.called) -+ self.assertTrue(jobs is not None) - - def test_calling_the_observer_when_starting_and_finishing_jobs(self): - handle = rope.base.taskhandle.TaskHandle() -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,23 +5,12 @@ - - import rope.base.taskhandle - import rope.refactor.introduce_parameter --import ropetest.refactor.extracttest --import ropetest.refactor.importutilstest --import ropetest.refactor.inlinetest --import ropetest.refactor.movetest --import ropetest.refactor.multiprojecttest --import ropetest.refactor.patchedasttest --import ropetest.refactor.renametest --import ropetest.refactor.restructuretest --import ropetest.refactor.suitestest --import ropetest.refactor.usefunctiontest - from rope.base.exceptions import RefactoringError, InterruptedTaskError - from rope.refactor.encapsulate_field import EncapsulateField - from rope.refactor.introduce_factory import IntroduceFactory - from rope.refactor.localtofield import LocalToField - from rope.refactor.method_object import MethodObject - from ropetest import testutils --from ropetest.refactor import change_signature_test, similarfindertest - - - class MethodObjectTest(unittest.TestCase): -@@ -1094,8 +1083,9 @@ - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) -- jobs = handle.create_jobset() # noqa -+ jobs = handle.create_jobset() - self.assertEqual(1, observer.called) -+ self.assertTrue(jobs is not None) - - def test_calling_the_observer_when_starting_and_finishing_jobs(self): - handle = rope.base.taskhandle.TaskHandle() -@language python - -@path C:/Repos/ekr-rope/rope/ -from textwrap import dedent - -import unittest - -import rope.base.taskhandle -import rope.refactor.introduce_parameter -import ropetest.refactor.extracttest -import ropetest.refactor.importutilstest -import ropetest.refactor.inlinetest -import ropetest.refactor.movetest -import ropetest.refactor.multiprojecttest -import ropetest.refactor.patchedasttest -import ropetest.refactor.renametest -import ropetest.refactor.restructuretest -import ropetest.refactor.suitestest -import ropetest.refactor.usefunctiontest -from rope.base.exceptions import RefactoringError, InterruptedTaskError -from rope.refactor.encapsulate_field import EncapsulateField -from rope.refactor.introduce_factory import IntroduceFactory -from rope.refactor.localtofield import LocalToField -from rope.refactor.method_object import MethodObject -from ropetest import testutils -from ropetest.refactor import change_signature_test, similarfindertest - - -class MethodObjectTest(unittest.TestCase): - def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - def test_empty_method(self): - code = dedent("""\ - def func(): - pass - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __call__(self): - pass - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_trivial_return(self): - code = dedent("""\ - def func(): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_multi_line_header(self): - code = dedent("""\ - def func( - ): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_a_single_parameter(self): - code = dedent("""\ - def func(param): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, param): - self.param = param - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_self_parameter(self): - code = dedent("""\ - def func(self): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, host): - self.self = host - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_simple_using_passed_parameters(self): - code = dedent("""\ - def func(param): - return param - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, param): - self.param = param - - def __call__(self): - return self.param - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_self_keywords_and_args_parameters(self): - code = dedent("""\ - def func(arg, *args, **kwds): - result = arg + args[0] + kwds[arg] - return result - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, arg, args, kwds): - self.arg = arg - self.args = args - self.kwds = kwds - - def __call__(self): - result = self.arg + self.args[0] + self.kwds[self.arg] - return result - """) - self.assertEqual(expected, replacer.get_new_class("_New")) - - def test_performing_on_not_a_function(self): - code = dedent("""\ - my_var = 10 - """) - self.mod.write(code) - with self.assertRaises(RefactoringError): - MethodObject(self.project, self.mod, code.index("my_var")) - - def test_changing_the_module(self): - code = dedent("""\ - def func(): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - self.project.do(replacer.get_changes("_New")) - expected = dedent("""\ - def func(): - return _New()() - - - class _New(object): - - def __call__(self): - return 1 - """) - self.assertEqual(expected, self.mod.read()) - - def test_changing_the_module_and_class_methods(self): - code = dedent("""\ - class C(object): - - def a_func(self): - return 1 - - def another_func(self): - pass - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - self.project.do(replacer.get_changes("_New")) - expected = dedent("""\ - class C(object): - - def a_func(self): - return _New(self)() - - def another_func(self): - pass - - - class _New(object): - - def __init__(self, host): - self.self = host - - def __call__(self): - return 1 - """) - self.assertEqual(expected, self.mod.read()) - - -class IntroduceFactoryTest(unittest.TestCase): - def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - - def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - def _introduce_factory(self, resource, offset, *args, **kwds): - factory_introducer = IntroduceFactory(self.project, resource, offset) - changes = factory_introducer.get_changes(*args, **kwds) - self.project.do(changes) - - def test_adding_the_method(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - def test_changing_occurrences_in_the_main_module(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - a_var = AClass()""") - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - a_var = AClass.create()""") - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - def test_changing_occurrences_with_arguments(self): - code = dedent("""\ - class AClass(object): - def __init__(self, arg): - pass - a_var = AClass(10) - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - def __init__(self, arg): - pass - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - a_var = AClass.create(10) - """) - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - def test_changing_occurrences_in_other_modules(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("import mod1\na_var = mod1.AClass()\n") - self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = dedent("""\ - import mod1 - a_var = mod1.AClass.create() - """) - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - def test_raising_exception_for_non_classes(self): - mod = testutils.create_module(self.project, "mod") - mod.write("def a_func():\n pass\n") - with self.assertRaises(RefactoringError): - self._introduce_factory(mod, mod.read().index("a_func") + 1, "create") - - def test_undoing_introduce_factory(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - code1 = dedent("""\ - class AClass(object): - an_attr = 10 - """) - mod1.write(code1) - code2 = dedent("""\ - from mod1 import AClass - a_var = AClass() - """) - mod2.write(code2) - self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") - self.project.history.undo() - self.assertEqual(code1, mod1.read()) - self.assertEqual(code2, mod2.read()) - - def test_using_on_an_occurrence_outside_the_main_module(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("import mod1\na_var = mod1.AClass()\n") - self._introduce_factory(mod2, mod2.read().index("AClass") + 1, "create") - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = "import mod1\n" "a_var = mod1.AClass.create()\n" - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - def test_introduce_factory_in_nested_scopes(self): - code = dedent("""\ - def create_var(): - class AClass(object): - an_attr = 10 - return AClass() - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - def create_var(): - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - return AClass.create() - """) - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - def test_adding_factory_for_global_factories(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - self._introduce_factory( - mod, mod.read().index("AClass") + 1, "create", global_factory=True - ) - self.assertEqual(expected, mod.read()) - - def test_get_name_for_factories(self): - code = dedent("""\ - class C(object): - pass - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - factory = IntroduceFactory(self.project, mod, mod.read().index("C") + 1) - self.assertEqual("C", factory.get_name()) - - def test_raising_exception_for_global_factory_for_nested_classes(self): - code = dedent("""\ - def create_var(): - class AClass(object): - an_attr = 10 - return AClass() - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - with self.assertRaises(RefactoringError): - self._introduce_factory( - mod, mod.read().index("AClass") + 1, "create", global_factory=True - ) - - def test_changing_occurrences_in_the_main_module_for_global_factories(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - a_var = AClass()""") - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - a_var = create()""") - self._introduce_factory( - mod, mod.read().index("AClass") + 1, "create", global_factory=True - ) - self.assertEqual(expected, mod.read()) - - def test_changing_occurrences_in_other_modules_for_global_factories(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("import mod1\na_var = mod1.AClass()\n") - self._introduce_factory( - mod1, mod1.read().index("AClass") + 1, "create", global_factory=True - ) - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = "import mod1\n" "a_var = mod1.create()\n" - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - def test_import_if_necessary_in_other_mods_for_global_factories(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("from mod1 import AClass\npair = AClass(), AClass\n") - self._introduce_factory( - mod1, mod1.read().index("AClass") + 1, "create", global_factory=True - ) - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = dedent("""\ - from mod1 import AClass, create - pair = create(), AClass - """) - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - def test_changing_occurrences_for_renamed_classes(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - a_class = AClass - a_var = a_class()""") - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - a_class = AClass - a_var = a_class()""") - self._introduce_factory(mod, mod.read().index("a_class") + 1, "create") - self.assertEqual(expected, mod.read()) - - def test_changing_occurrs_in_the_same_module_with_conflict_ranges(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - def create(self): - return C() - """) - mod.write(code) - self._introduce_factory(mod, mod.read().index("C"), "create_c", True) - expected = dedent("""\ - class C(object): - def create(self): - return create_c() - """) - self.assertTrue(mod.read().startswith(expected)) - - def _transform_module_to_package(self, resource): - self.project.do( - rope.refactor.ModuleToPackage(self.project, resource).get_changes() - ) - - def test_transform_module_to_package(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write("import mod2\nfrom mod2 import AClass\n") - mod2 = testutils.create_module(self.project, "mod2") - mod2.write("class AClass(object):\n pass\n") - self._transform_module_to_package(mod2) - mod2 = self.project.get_resource("mod2") - root_folder = self.project.root - self.assertFalse(root_folder.has_child("mod2.py")) - self.assertEqual( - "class AClass(object):\n pass\n", - root_folder.get_child("mod2").get_child("__init__.py").read(), - ) - - def test_transform_module_to_package_undoing(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) - self._transform_module_to_package(mod) - self.assertFalse(pkg.has_child("mod.py")) - self.assertTrue(pkg.get_child("mod").has_child("__init__.py")) - self.project.history.undo() - self.assertTrue(pkg.has_child("mod.py")) - self.assertFalse(pkg.has_child("mod")) - - def test_transform_module_to_package_with_relative_imports(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod1.write("import mod2\nfrom mod2 import AClass\n") - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod2.write("class AClass(object):\n pass\n") - self._transform_module_to_package(mod1) - new_init = self.project.get_resource("pkg/mod1/__init__.py") - self.assertEqual( - "import pkg.mod2\nfrom pkg.mod2 import AClass\n", new_init.read() - ) - - def test_resources_parameter(self): - code = dedent("""\ - class A(object): - an_attr = 10 - """) - code1 = dedent("""\ - import mod - a = mod.A() - """) - mod = testutils.create_module(self.project, "mod") - mod1 = testutils.create_module(self.project, "mod1") - mod.write(code) - mod1.write(code1) - expected = dedent("""\ - class A(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return A(*args, **kwds) - """) - self._introduce_factory( - mod, mod.read().index("A") + 1, "create", resources=[mod] - ) - self.assertEqual(expected, mod.read()) - self.assertEqual(code1, mod1.read()) - - -class EncapsulateFieldTest(unittest.TestCase): - def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - self.mod1 = testutils.create_module(self.project, "mod1") - self.a_class = dedent("""\ - class A(object): - def __init__(self): - self.attr = 1 - """) - self.added_methods = ( - "\n" - " def get_attr(self):\n" - " return self.attr\n\n" - " def set_attr(self, value):\n" - " self.attr = value\n" - ) - self.encapsulated = self.a_class + self.added_methods - - def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - def _encapsulate(self, resource, offset, **args): - changes = EncapsulateField(self.project, resource, offset).get_changes(**args) - self.project.do(changes) - - def test_adding_getters_and_setters(self): - code = self.a_class - self.mod.write(code) - self._encapsulate(self.mod, code.index("attr") + 1) - self.assertEqual(self.encapsulated, self.mod.read()) - - def test_changing_getters_in_other_modules(self): - code = dedent("""\ - import mod - a_var = mod.A() - range(a_var.attr) - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - range(a_var.get_attr()) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_setters_in_other_modules(self): - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(1) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_getters_in_setters(self): - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 + a_var.attr - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(1 + a_var.get_attr()) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_appending_to_class_end(self): - self.mod1.write(self.a_class + "a_var = A()\n") - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - self.assertEqual(self.encapsulated + "a_var = A()\n", self.mod1.read()) - - def test_performing_in_other_modules(self): - code = dedent("""\ - import mod - a_var = mod.A() - range(a_var.attr) - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - self.assertEqual(self.encapsulated, self.mod.read()) - expected = dedent("""\ - import mod - a_var = mod.A() - range(a_var.get_attr()) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_main_module_occurrences(self): - code = self.a_class + "a_var = A()\n" "a_var.attr = a_var.attr * 2\n" - self.mod1.write(code) - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - expected = ( - self.encapsulated + "a_var = A()\n" "a_var.set_attr(a_var.get_attr() * 2)\n" - ) - self.assertEqual(expected, self.mod1.read()) - - def test_raising_exception_when_performed_on_non_attributes(self): - self.mod1.write("attr = 10") - with self.assertRaises(RefactoringError): - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - - def test_raising_exception_on_tuple_assignments(self): - self.mod.write(self.a_class) - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 - a_var.attr, b = 1, 2 - """) - self.mod1.write(code) - with self.assertRaises(RefactoringError): - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - - def test_raising_exception_on_tuple_assignments2(self): - self.mod.write(self.a_class) - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 - b, a_var.attr = 1, 2 - """) - self.mod1.write(code) - with self.assertRaises(RefactoringError): - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - - def test_tuple_assignments_and_function_calls(self): - code = dedent("""\ - import mod - def func(a1=0, a2=0): - pass - a_var = mod.A() - func(a_var.attr, a2=2) - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - def func(a1=0, a2=0): - pass - a_var = mod.A() - func(a_var.get_attr(), a2=2) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_tuple_assignments(self): - code = dedent("""\ - import mod - a_var = mod.A() - a, b = a_var.attr, 1 - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a, b = a_var.get_attr(), 1 - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_augmented_assignments(self): - code = "import mod\n" "a_var = mod.A()\n" "a_var.attr += 1\n" - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(a_var.get_attr() + 1) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_augmented_assignments2(self): - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr <<= 1 - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(a_var.get_attr() << 1) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_occurrences_inside_the_class(self): - new_class = ( - self.a_class + "\n" " def a_func(self):\n" " self.attr = 1\n" - ) - self.mod.write(new_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = ( - self.a_class + "\n" - " def a_func(self):\n" - " self.set_attr(1)\n" + self.added_methods - ) - self.assertEqual(expected, self.mod.read()) - - def test_getter_and_setter_parameters(self): - self.mod.write(self.a_class) - self._encapsulate( - self.mod, - self.mod.read().index("attr") + 1, - getter="getAttr", - setter="setAttr", - ) - new_methods = self.added_methods.replace("get_attr", "getAttr").replace( - "set_attr", "setAttr" - ) - expected = self.a_class + new_methods - self.assertEqual(expected, self.mod.read()) - - def test_using_resources_parameter(self): - self.mod1.write("import mod\na = mod.A()\nvar = a.attr\n") - self.mod.write(self.a_class) - self._encapsulate( - self.mod, self.mod.read().index("attr") + 1, resources=[self.mod] - ) - self.assertEqual("import mod\na = mod.A()\nvar = a.attr\n", self.mod1.read()) - expected = self.a_class + self.added_methods - self.assertEqual(expected, self.mod.read()) - - -class LocalToFieldTest(unittest.TestCase): - def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - def _perform_convert_local_variable_to_field(self, resource, offset): - changes = LocalToField(self.project, resource, offset).get_changes() - self.project.do(changes) - - def test_simple_local_to_field(self): - code = dedent("""\ - class A(object): - def a_func(self): - var = 10 - """) - self.mod.write(code) - self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) - expected = dedent("""\ - class A(object): - def a_func(self): - self.var = 10 - """) - self.assertEqual(expected, self.mod.read()) - - def test_raising_exception_when_performed_on_a_global_var(self): - self.mod.write("var = 10\n") - with self.assertRaises(RefactoringError): - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().index("var") + 1 - ) - - def test_raising_exception_when_performed_on_field(self): - code = dedent("""\ - class A(object): - def a_func(self): - self.var = 10 - """) - self.mod.write(code) - with self.assertRaises(RefactoringError): - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().index("var") + 1 - ) - - def test_raising_exception_when_performed_on_a_parameter(self): - code = dedent("""\ - class A(object): - def a_func(self, var): - a = var - """) - self.mod.write(code) - with self.assertRaises(RefactoringError): - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().index("var") + 1 - ) - - # NOTE: This situation happens alot and is normally not an error - # @testutils.assert_raises(RefactoringError) - def test_not_rais_exception_when_there_is_a_field_with_the_same_name(self): - code = dedent("""\ - class A(object): - def __init__(self): - self.var = 1 - def a_func(self): - var = 10 - """) - self.mod.write(code) - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().rindex("var") + 1 - ) - - def test_local_to_field_with_self_renamed(self): - code = dedent("""\ - class A(object): - def a_func(myself): - var = 10 - """) - self.mod.write(code) - self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) - expected = dedent("""\ - class A(object): - def a_func(myself): - myself.var = 10 - """) - self.assertEqual(expected, self.mod.read()) - - -class IntroduceParameterTest(unittest.TestCase): - def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - def _introduce_parameter(self, offset, name): - rope.refactor.introduce_parameter.IntroduceParameter( - self.project, self.mod, offset - ).get_changes(name).do() - - def test_simple_case(self): - code = dedent("""\ - var = 1 - def f(): - b = var - """) - self.mod.write(code) - offset = self.mod.read().rindex("var") - self._introduce_parameter(offset, "var") - expected = dedent("""\ - var = 1 - def f(var=var): - b = var - """) - self.assertEqual(expected, self.mod.read()) - - def test_changing_function_body(self): - code = dedent("""\ - var = 1 - def f(): - b = var - """) - self.mod.write(code) - offset = self.mod.read().rindex("var") - self._introduce_parameter(offset, "p1") - expected = dedent("""\ - var = 1 - def f(p1=var): - b = p1 - """) - self.assertEqual(expected, self.mod.read()) - - def test_unknown_variables(self): - self.mod.write("def f():\n b = var + c\n") - offset = self.mod.read().rindex("var") - with self.assertRaises(RefactoringError): - self._introduce_parameter(offset, "p1") - self.assertEqual("def f(p1=var):\n b = p1 + c\n", self.mod.read()) - - def test_failing_when_not_inside(self): - self.mod.write("var = 10\nb = var\n") - offset = self.mod.read().rindex("var") - with self.assertRaises(RefactoringError): - self._introduce_parameter(offset, "p1") - - def test_attribute_accesses(self): - code = dedent("""\ - class C(object): - a = 10 - c = C() - def f(): - b = c.a - """) - self.mod.write(code) - offset = self.mod.read().rindex("a") - self._introduce_parameter(offset, "p1") - expected = dedent("""\ - class C(object): - a = 10 - c = C() - def f(p1=c.a): - b = p1 - """) - self.assertEqual(expected, self.mod.read()) - - def test_introducing_parameters_for_methods(self): - code = dedent("""\ - var = 1 - class C(object): - def f(self): - b = var - """) - self.mod.write(code) - offset = self.mod.read().rindex("var") - self._introduce_parameter(offset, "p1") - expected = dedent("""\ - var = 1 - class C(object): - def f(self, p1=var): - b = p1 - """) - self.assertEqual(expected, self.mod.read()) - - -class _MockTaskObserver: - def __init__(self): - self.called = 0 - - def __call__(self): - self.called += 1 - - -class TaskHandleTest(unittest.TestCase): - def test_trivial_case(self): - handle = rope.base.taskhandle.TaskHandle() - self.assertFalse(handle.is_stopped()) - - def test_stopping(self): - handle = rope.base.taskhandle.TaskHandle() - handle.stop() - self.assertTrue(handle.is_stopped()) - - def test_job_sets(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset() - self.assertEqual([jobs], handle.get_jobsets()) - - def test_starting_and_finishing_jobs(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset(name="test job set", count=1) - jobs.started_job("job1") - jobs.finished_job() - - def test_test_checking_status(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset() - handle.stop() - with self.assertRaises(InterruptedTaskError): - jobs.check_status() - - def test_test_checking_status_when_starting(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset() - handle.stop() - with self.assertRaises(InterruptedTaskError): - jobs.started_job("job1") - - def test_calling_the_observer_after_stopping(self): - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) - handle.stop() - self.assertEqual(1, observer.called) - - def test_calling_the_observer_after_creating_job_sets(self): - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) - jobs = handle.create_jobset() # noqa - self.assertEqual(1, observer.called) - - def test_calling_the_observer_when_starting_and_finishing_jobs(self): - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) - jobs = handle.create_jobset(name="test job set", count=1) - jobs.started_job("job1") - jobs.finished_job() - self.assertEqual(3, observer.called) - - def test_job_set_get_percent_done(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset(name="test job set", count=2) - self.assertEqual(0, jobs.get_percent_done()) - jobs.started_job("job1") - jobs.finished_job() - self.assertEqual(50, jobs.get_percent_done()) - jobs.started_job("job2") - jobs.finished_job() - self.assertEqual(100, jobs.get_percent_done()) - - def test_getting_job_name(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset(name="test job set", count=1) - # recommended name/job_name attribute - self.assertEqual("test job set", jobs.name) - self.assertEqual(None, jobs.job_name) - # deprecated getters - self.assertEqual("test job set", jobs.get_name()) - self.assertEqual(None, jobs.get_active_job_name()) - jobs.started_job("job1") - # recommended name/job_name attribute - self.assertEqual("test job set", jobs.get_name()) - # deprecated getters - self.assertEqual("job1", jobs.get_active_job_name()) -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -21,8 +21,10 @@ - p1 = testutils.create_package(self.project, "p1") - p2 = testutils.create_package(self.project, "p2", p1) - p3 = testutils.create_package(self.project, "p3", p2) -- m1 = testutils.create_module(self.project, "m1", p3) # noqa -- l = testutils.create_module(self.project, "l", p3) # noqa -+ m1 = testutils.create_module(self.project, "m1", p3) -+ mod_l = testutils.create_module(self.project, "l", p3) -+ self.assertTrue(m1 is not None) -+ self.assertTrue(mod_l is not None) - - def tearDown(self): - testutils.remove_project(self.project) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -24,7 +24,6 @@ - "", - ")", - ]) -- - - @testutils.only_for_versions_higher("3.10") - def test_match_node_with_match_mapping_match_as(self): -@@ -54,5 +53,3 @@ - "", - "}", - ]) -- -- -@language python - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name(self): - source = dedent("""\ - match x: - case Foo(x) as b: - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "MatchClass", - " ", - "as", - " ", - "b", - ]) - checker.check_children("MatchClass", [ - "Name", - "", - "(", - "", - "MatchAs", - "", - ")", - ]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_mapping_match_as(self): - source = dedent("""\ - match x: - case {"a": b} as c: - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "MatchMapping", - " ", - "as", - " ", - "c", - ]) - checker.check_children("MatchMapping", [ - "{", - "", - "Constant", - "", - ":", - " ", - "MatchAs", - "", - "}", - ]) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,12 +2,12 @@ - import shutil - import sys - import logging -- --logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) - import unittest - - import rope.base.project - from rope.contrib import generate -+ -+logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) - - - def sample_project(root=None, foldername=None, **kwds): -@@ -51,7 +51,7 @@ - - # windows sometimes raises exceptions instead of removing files - if os.name == "nt" or sys.platform == "cygwin": -- for i in range(12): -+ for _i in range(12): - try: - _remove_recursively(path) - except OSError as e: -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -3,13 +3,13 @@ - import shutil - import sys - import logging -- --logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) - import unittest - - import rope.base.project - from rope.contrib import generate - -+logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) -+ - - @others - @language python -@language python - -@path C:/Repos/ekr-rope/ropetest/ -import os.path -import shutil -import sys -import logging - -logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) -import unittest - -import rope.base.project -from rope.contrib import generate - - -@others -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -3,7 +3,7 @@ - - # windows sometimes raises exceptions instead of removing files - if os.name == "nt" or sys.platform == "cygwin": -- for i in range(12): -+ for _i in range(12): - try: - _remove_recursively(path) - except OSError as e: -@language python - -def remove_recursively(path): - import time - - # windows sometimes raises exceptions instead of removing files - if os.name == "nt" or sys.platform == "cygwin": - for i in range(12): - try: - _remove_recursively(path) - except OSError as e: - if e.errno not in (13, 16, 32): - raise - time.sleep(0.3) - else: - break - else: - _remove_recursively(path) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,3 +1,3 @@ - from setuptools import setup - --setup()+setup() - - - - - - -@ignore -@nosearch - - -def _Name(self, node): - self.result = self.scope.lookup(node.id) - - -def _Attribute(self, node): - pyname = eval_node(self.scope, node.value) - if pyname is None: - pyname = rope.base.pynames.UnboundName() - self.old_result = pyname - if pyname.get_object() != rope.base.pyobjects.get_unknown(): - try: - self.result = pyname.get_object()[node.attr] - except exceptions.AttributeNotFoundError: - self.result = None - - -def _Call(self, node): - primary, pyobject = self._get_primary_and_object_for_node(node.func) - if pyobject is None: - return - - def _get_returned(pyobject): - args = arguments.create_arguments(primary, pyobject, node, self.scope) - return pyobject.get_returned_object(args) - - if isinstance(pyobject, rope.base.pyobjects.AbstractClass): - result = None - if "__new__" in pyobject: - new_function = pyobject["__new__"].get_object() - result = _get_returned(new_function) - if result is None or result == rope.base.pyobjects.get_unknown(): - result = rope.base.pyobjects.PyObject(pyobject) - self.result = rope.base.pynames.UnboundName(pyobject=result) - return - - pyfunction = None - if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): - pyfunction = pyobject - elif "__call__" in pyobject: - pyfunction = pyobject["__call__"].get_object() - if pyfunction is not None: - self.result = rope.base.pynames.UnboundName( - pyobject=_get_returned(pyfunction) - ) - - -def _Str(self, node): - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_str() - ) - - -def _Num(self, node): - type_name = type(node.n).__name__ - self.result = self._get_builtin_name(type_name) - - -def _Constant(self, node): - type_name = type(node.n).__name__ - try: - self.result = self._get_builtin_name(type_name) - except exceptions.AttributeNotFoundError: - # XXX: Right way to fix this is to add missing NoneType to builtins? - pass - - -def _get_builtin_name(self, type_name): - pytype = rope.base.builtins.builtins[type_name].get_object() - return rope.base.pynames.UnboundName(rope.base.pyobjects.PyObject(pytype)) - - -def _BinOp(self, node): - self.result = rope.base.pynames.UnboundName( - self._get_object_for_node(node.left) - ) - - -def _BoolOp(self, node): - pyobject = self._get_object_for_node(node.values[0]) - if pyobject is None: - pyobject = self._get_object_for_node(node.values[1]) - self.result = rope.base.pynames.UnboundName(pyobject) - - -def _Repr(self, node): - self.result = self._get_builtin_name("str") - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - @path C:/Repos/ekr-rope/rope/base/ - @nopyflakes --import ast --from ast import * -+import ast # noqu -+from ast import * # noqa - - from rope.base import fscommands - -@language python - -def _UnaryOp(self, node): - self.result = rope.base.pynames.UnboundName( - self._get_object_for_node(node.operand) - ) - - -def _Compare(self, node): - self.result = self._get_builtin_name("bool") - - -def _Dict(self, node): - keys = None - values = None - if node.keys and node.keys[0]: - keys, values = next( - iter(filter(itemgetter(0), zip(node.keys, node.values))), (None, None) - ) - if keys: - keys = self._get_object_for_node(keys) - if values: - values = self._get_object_for_node(values) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_dict(keys, values) - ) - - -def _List(self, node): - holding = None - if node.elts: - holding = self._get_object_for_node(node.elts[0]) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_list(holding) - ) - - -def _ListComp(self, node): - pyobject = self._what_does_comprehension_hold(node) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_list(pyobject) - ) - - -def _GeneratorExp(self, node): - pyobject = self._what_does_comprehension_hold(node) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_iterator(pyobject) - ) - - -def _what_does_comprehension_hold(self, node): - scope = self._make_comprehension_scope(node) - pyname = eval_node(scope, node.elt) - return pyname.get_object() if pyname is not None else None - - -def _make_comprehension_scope(self, node): - scope = self.scope - module = scope.pyobject.get_module() - names = {} - for comp in node.generators: - new_names = _get_evaluated_names( - comp.target, comp.iter, module, ".__iter__().next()", node.lineno - ) - names.update(new_names) - return rope.base.pyscopes.TemporaryScope(scope.pycore, scope, names) - - -def _Tuple(self, node): - objects = [] - if len(node.elts) < 4: - for stmt in node.elts: - pyobject = self._get_object_for_node(stmt) - objects.append(pyobject) - else: - objects.append(self._get_object_for_node(node.elts[0])) - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.get_tuple(*objects) - ) - - -def _get_object_for_node(self, stmt): - pyname = eval_node(self.scope, stmt) - pyobject = None - if pyname is not None: - pyobject = pyname.get_object() - return pyobject - - -@path C:/Repos/ekr-rope/rope/base/ -@nopyflakes -import ast -from ast import * - -from rope.base import fscommands - - -@others -@language python -@tabwidth -4 - -def _get_primary_and_object_for_node(self, stmt): - primary, pyname = eval_node2(self.scope, stmt) - pyobject = None - if pyname is not None: - pyobject = pyname.get_object() - return primary, pyobject - - -def _Subscript(self, node): - if isinstance(node.slice, ast.Index): - self._call_function(node.value, "__getitem__", [node.slice.value]) - elif isinstance(node.slice, ast.Slice): - self._call_function(node.value, "__getitem__", [node.slice]) - elif isinstance(node.slice, ast.expr): - self._call_function(node.value, "__getitem__", [node.value]) - - -def _Slice(self, node): - self.result = self._get_builtin_name("slice") - - -def _call_function(self, node, function_name, other_args=None): - pyname = eval_node(self.scope, node) - if pyname is not None: - pyobject = pyname.get_object() - else: - return - if function_name in pyobject: - called = pyobject[function_name].get_object() - if not called or not isinstance(called, pyobjects.AbstractFunction): - return - args = [node] - if other_args: - args += other_args - arguments_ = arguments.Arguments(args, self.scope) - self.result = rope.base.pynames.UnboundName( - pyobject=called.get_returned_object(arguments_) - ) - - -def _Lambda(self, node): - self.result = rope.base.pynames.UnboundName( - pyobject=rope.base.builtins.Lambda(node, self.scope) - ) - - - -def _get_evaluated_names(targets, assigned, module, evaluation, lineno): - result = {} - for name, levels in astutils.get_name_levels(targets): - assignment = rope.base.pynames.AssignmentValue(assigned, levels, evaluation) - # XXX: this module should not access `rope.base.pynamesdef`! - pyname = rope.base.pynamesdef.AssignedName(lineno, module) - pyname.assignments.append(assignment) - result[name] = pyname - return result - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,4 +6,4 @@ - - - @method(symbol("[")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa -@language python - - if parser.token.name != ",": - break - parser.advance(",") - parser.advance("]") - return self - - -@method(symbol("[")) -def evaluate(self, pyobject): - -def eval_str2(holding_scope, name): - try: - # parenthesizing for handling cases like 'a_var.\nattr' - node = ast.parse("(%s)" % name) - except SyntaxError: - raise BadIdentifierError("Not a resolvable python identifier selected.") - return eval_node2(holding_scope, node) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - @method(symbol("(")) --def nud(self, parser): -+def nud(self, parser): # noqa - self.second = [] - if parser.token.name != ")": - while 1: -@language python - -@path C:/Repos/ekr-rope/rope/base/ -@nopyflakes -import ast -from ast import * - -from rope.base import fscommands - - -@others -@language python -@tabwidth -4 - -@method(symbol("(")) -def nud(self, parser): -self.second = [] -if parser.token.name != ")": - while 1: - self.second.append(parser.expression()) - if parser.token.name != ",": - break - parser.advance(",") -parser.advance(")") -parser.advance("->") -self.third = parser.expression(symbol("->").lbp + 0.1) -return self - - -# Function Calls - -def _is_defined_in_class_body(self, holding_scope, offset, lineno): - if ( - lineno == holding_scope.get_start() - and holding_scope.parent is not None - and holding_scope.parent.get_kind() == "Class" - and self.worder.is_a_class_or_function_name_in_header(offset) - ): - return True - if ( - lineno != holding_scope.get_start() - and holding_scope.get_kind() == "Class" - and self.worder.is_name_assigned_in_class_body(offset) - ): - return True - return False - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - @method(symbol("(")) --def led(self, left, parser): -+def led(self, left, parser): # noqa - self.first = left - self.second = [] - if parser.token.name != ")": -@language python - -@method(symbol("(")) -def led(self, left, parser): -self.first = left -self.second = [] -if parser.token.name != ")": - while 1: - self.second.append(parser.expression()) - -def _is_function_name_in_function_header(self, scope, offset, lineno): - return ( - scope.get_start() <= lineno <= scope.get_body_start() - and scope.get_kind() == "Function" - and self.worder.is_a_class_or_function_name_in_header(offset) - ) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,14 +5,14 @@ - - - @method(symbol("(")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa - # TODO: Implement me - raise NotImplementedError - - - @method(symbol("or")) - @method(symbol("|")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa - # TODO: Implement me - raise NotImplementedError - -@language python - -parser.advance(")") -parser.advance("->") -self.third = parser.expression(symbol("->").lbp + 0.1) -return self - - -@method(symbol("(")) -def evaluate(self, pyobject): -# TODO: Implement me -raise NotImplementedError - - -@method(symbol("or")) -@method(symbol("|")) -def evaluate(self, pyobject): -# TODO: Implement me -raise NotImplementedError - - -class Compiler: - -parser_factory = Parser -lexer_factory = Lexer -symbol_table = symbol_table - -def _make_parser(self): - return self.parser_factory(self.lexer_factory(self.symbol_table)) - -@base_utils.cached(500) -def __call__(self, program): - """ - :type program: str - :rtype: rope.base.oi.type_hinting.evaluate.SymbolBase - """ - return self._make_parser().parse(program) - - -compile = Compiler() - - -class Evaluator: - -compile = compile - -def get_primary_and_pyname_at( - self, - offset: int, -) -> Tuple[Optional[rope.base.pynames.PyName], Optional[rope.base.pynames.PyName]]: - lineno = self.lines.get_line_number(offset) - holding_scope = self.module_scope.get_inner_scope_for_offset(offset) - # function keyword parameter - if self.worder.is_function_keyword_parameter(offset): - keyword_name = self.worder.get_word_at(offset) - pyobject = self.get_enclosing_function(offset) - if isinstance(pyobject, pyobjectsdef.PyFunction): - parameter_name = pyobject.get_parameters().get(keyword_name, None) - return (None, parameter_name) - elif isinstance(pyobject, pyobjects.AbstractFunction): - parameter_name = rope.base.pynames.ParameterName() - return (None, parameter_name) - # class body - if self._is_defined_in_class_body(holding_scope, offset, lineno): - class_scope = holding_scope - if lineno == holding_scope.get_start(): - class_scope = holding_scope.parent - name = self.worder.get_primary_at(offset).strip() - try: - return (None, class_scope.pyobject[name]) - except rope.base.exceptions.AttributeNotFoundError: - return (None, None) - # function header - if self._is_function_name_in_function_header(holding_scope, offset, lineno): - name = self.worder.get_primary_at(offset).strip() - return (None, holding_scope.parent[name]) - # module in a from statement or an imported name that is aliased - if self.worder.is_from_statement_module( - offset - ) or self.worder.is_import_statement_aliased_module(offset): - module = self.worder.get_primary_at(offset) - module_pyname = self._find_module(module) - return (None, module_pyname) - if self.worder.is_from_aliased(offset): - name = self.worder.get_from_aliased(offset) - else: - name = self.worder.get_primary_at(offset) - return eval_str2(holding_scope, name) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -9,4 +9,4 @@ - return ast.evaluate(pyobject) - - --evaluate = Evaluator() -+evaluate = Evaluator() # noqa -@language python - - -def __call__(self, program, pyobject): - """Evaluates the program string or AST - - :type program: str or rope.base.oi.type_hinting.evaluate.SymbolBase - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - ast = self.compile(program) if isinstance(program, str) else program - return ast.evaluate(pyobject) - - -evaluate = Evaluator() - -def parse(source, filename="<string>"): - # NOTE: the raw string should be given to `compile` function - if isinstance(source, str): - source = fscommands.unicode_to_file_data(source) - if b"\r" in source: - source = source.replace(b"\r\n", b"\n").replace(b"\r", b"\n") - if not source.endswith(b"\n"): - source += b"\n" - try: - return ast.parse(source, filename="<unknown>") - except (TypeError, ValueError) as e: - error = SyntaxError() - error.lineno = 1 - error.filename = filename - error.msg = str(e) - raise error - - - -def get_enclosing_function(self, offset): - function_parens = self.worder.find_parens_start_from_inside(offset) - try: - function_pyname = self.get_pyname_at(function_parens - 1) - except BadIdentifierError: - function_pyname = None - if function_pyname is not None: - pyobject = function_pyname.get_object() - if isinstance(pyobject, pyobjects.AbstractFunction): - return pyobject - elif ( - isinstance(pyobject, pyobjects.AbstractClass) and "__init__" in pyobject - ): - return pyobject["__init__"].get_object() - elif "__call__" in pyobject: - return pyobject["__call__"].get_object() - return None - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - import re --from rope.base.oi.type_hinting import utils -+ - from rope.base.oi.type_hinting.providers import interfaces -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,6 @@ - @path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ - import re --from rope.base.oi.type_hinting import utils -+ - from rope.base.oi.type_hinting.providers import interfaces - - -@language python - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ -import re -from rope.base.oi.type_hinting import utils -from rope.base.oi.type_hinting.providers import interfaces - - -@others -@language python -@tabwidth -4 - -@path C:/Repos/ekr-rope/rope/base/oi/type_hinting/providers/ -import re -from rope.base.oi.type_hinting import utils -from rope.base.oi.type_hinting.providers import interfaces - - -@others -@language python -@tabwidth -4 - -class AssignmentProvider(interfaces.IAssignmentProvider): - @others - -def __init__(self, resolver): - """ - :type resolver: rope.base.oi.type_hinting.resolvers.interfaces.IResolver - """ - self._resolve = resolver - - -PEP0484_TYPE_COMMENT_PATTERNS = (re.compile(r"type:\s*([^\n]+)"),) - - -def __call__(self, pyname): - """ - :type pyname: rope.base.pynamesdef.AssignedName - :rtype: rope.base.pyobjects.PyDefinedObject | rope.base.pyobjects.PyObject or None - """ - from rope.base.oi.soi import _get_lineno_for_node - - lineno = _get_lineno_for_node(pyname.assignments[0].ast_node) - holding_scope = pyname.module.get_scope().get_inner_scope_for_line(lineno) - line = holding_scope._get_global_scope()._scope_finder.lines.get_line(lineno) - if "#" in line: - type_strs = self._search_type_in_type_comment(line.split("#", 1)[1]) - if type_strs: - return self._resolve(type_strs[0], holding_scope.pyobject) - - -def walk(node, walker) -> None: - """Walk the syntax tree""" - method_name = "_" + node.__class__.__name__ - method = getattr(walker, method_name, None) - if method is not None: - if isinstance(node, ast.ImportFrom) and node.module is None: - # In python < 2.7 ``node.module == ''`` for relative imports - # but for python 2.7 it is None. Generalizing it to ''. - node.module = "" - method(node) - return - for child in get_child_nodes(node): - walk(child, walker) - - - -def _search_type_in_type_comment(self, code): - """For more info see: - https://www.python.org/dev/peps/pep-0484/#type-comments - - >>> AssignmentProvider()._search_type_in_type_comment('type: int') - ['int'] - """ - for p in self.PEP0484_TYPE_COMMENT_PATTERNS: - match = p.search(code) - if match: - return [match.group(1)] - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,14 +1,10 @@ - import logging -+from typing import Optional, Union - --try: -- from typing import Union, Optional --except ImportError: -- pass - import rope.base.utils as base_utils - from rope.base import evaluate - from rope.base.exceptions import AttributeNotFoundError - from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject --from rope.base.utils import pycompat - - - def get_super_func(pyfunc): -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,15 +1,11 @@ - @path C:/Repos/ekr-rope/rope/base/ - import logging -+from typing import Optional, Union - --try: -- from typing import Union, Optional --except ImportError: -- pass - import rope.base.utils as base_utils - from rope.base import evaluate - from rope.base.exceptions import AttributeNotFoundError - from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject --from rope.base.utils import pycompat - - - @others -@language python - -@path C:/Repos/ekr-rope/rope/base/ -import logging - -try: - from typing import Union, Optional -except ImportError: - pass -import rope.base.utils as base_utils -from rope.base import evaluate -from rope.base.exceptions import AttributeNotFoundError -from rope.base.pyobjects import PyClass, PyDefinedObject, PyFunction, PyObject -from rope.base.utils import pycompat - - -@others -@language python -@tabwidth -4 - -@path C:/Repos/ekr-rope/rope/base/ -"""A few useful functions for using rope as a library""" -import os.path - -import rope.base.project -import rope.base.pycore -from rope.base import pyobjectsdef -from rope.base import utils -from rope.base import taskhandle - - -@others -@language python -@tabwidth -4 - -def path_to_resource(project, path, type=None): - """Get the resource at path - - You only need to specify `type` if `path` does not exist. It can - be either 'file' or 'folder'. If the type is `None` it is assumed - that the resource already exists. - - Note that this function uses `Project.get_resource()`, - `Project.get_file()`, and `Project.get_folder()` methods. - - """ - project_path = path_relative_to_project_root(project, path) - if project_path is None: - project_path = rope.base.project._realpath(path) - project = rope.base.project.get_no_project() - if type is None: - return project.get_resource(project_path) - if type == "file": - return project.get_file(project_path) - if type == "folder": - return project.get_folder(project_path) - return None - - - -def path_relative_to_project_root(project, path): - return relative(project.address, path) - - - -@utils.deprecated() -def relative(root, path): - root = rope.base.project._realpath(root).replace(os.path.sep, "/") - path = rope.base.project._realpath(path).replace(os.path.sep, "/") - if path == root: - return "" - if path.startswith(root + "/"): - return path[len(root) + 1 :] - - - -def report_change(project, path, old_content): - """Report that the contents of file at `path` was changed - - The new contents of file is retrieved by reading the file. - - """ - resource = path_to_resource(project, path) - if resource is None: - return - for observer in list(project.observers): - observer.resource_changed(resource) - if project.pycore.automatic_soa: - rope.base.pycore.perform_soa_on_changed_scopes(project, resource, old_content) - - - -def get_child_nodes(node): - if isinstance(node, ast.Module): - return node.body - result = [] - if node._fields is not None: - for name in node._fields: - child = getattr(node, name) - if isinstance(child, list): - for entry in child: - if isinstance(entry, ast.AST): - result.append(entry) - if isinstance(child, ast.AST): - result.append(child) - return result - - - -def analyze_module(project, resource): - """Perform static object analysis on a python file in the project - - Note that this might be really time consuming. - """ - project.pycore.analyze_module(resource) - - - -def analyze_modules(project, task_handle=taskhandle.NullTaskHandle()): - """Perform static object analysis on all python files in the project - - Note that this might be really time consuming. - """ - resources = project.get_python_files() - job_set = task_handle.create_jobset("Analyzing Modules", len(resources)) - for resource in resources: - job_set.started_job(resource.path) - analyze_module(project, resource) - job_set.finished_job() - - - -def get_string_module(project, code, resource=None, force_errors=False): - """Returns a `PyObject` object for the given code - - If `force_errors` is `True`, `exceptions.ModuleSyntaxError` is - raised if module has syntax errors. This overrides - ``ignore_syntax_errors`` project config. - - """ - return pyobjectsdef.PyModule( - project.pycore, code, resource, force_errors=force_errors - ) - - - -def get_string_scope(project, code, resource=None): - """Returns a `Scope` object for the given code""" - return get_string_module(project, code, resource).get_scope() - - - -def is_python_file(project, resource): - return project.pycore.is_python_file(resource) - - - -def modname(resource): - if resource.is_folder(): - module_name = resource.name - source_folder = resource.parent - elif resource.name == "__init__.py": - module_name = resource.parent.name - source_folder = resource.parent.parent - else: - module_name = resource.name[:-3] - source_folder = resource.parent - - while source_folder != source_folder.parent and source_folder.has_child( - "__init__.py" - ): - module_name = source_folder.name + "." + module_name - source_folder = source_folder.parent - - return module_name - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,5 @@ - import bisect - import difflib --import sys - import warnings - - import rope.base.libutils -@@ -15,7 +14,6 @@ - from rope.base import stdmods - from rope.base import taskhandle - from rope.base import utils --from rope.base.exceptions import ModuleNotFoundError - - - class PyCore: -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,6 @@ - @path C:/Repos/ekr-rope/rope/base/ - import bisect - import difflib --import sys - import warnings - - import rope.base.libutils -@@ -16,7 +15,6 @@ - from rope.base import stdmods - from rope.base import taskhandle - from rope.base import utils --from rope.base.exceptions import ModuleNotFoundError - - - @others -@language python - -@path C:/Repos/ekr-rope/rope/base/ -import bisect -import difflib -import sys -import warnings - -import rope.base.libutils -import rope.base.resourceobserver -import rope.base.resources -import rope.base.oi.doa -import rope.base.oi.objectinfo -import rope.base.oi.soa -from rope.base import builtins -from rope.base import exceptions -from rope.base import pyobjectsdef -from rope.base import stdmods -from rope.base import taskhandle -from rope.base import utils -from rope.base.exceptions import ModuleNotFoundError - - -@others -@language python -@tabwidth -4 - -def call_for_nodes(node, callback, recursive=False): - """If callback returns `True` the child nodes are skipped""" - result = callback(node) - if recursive and not result: - for child in get_child_nodes(node): - call_for_nodes(child, callback, recursive) - - - -@path C:/Repos/ekr-rope/rope/base/ -import bisect -import difflib -import sys -import warnings - -import rope.base.libutils -import rope.base.resourceobserver -import rope.base.resources -import rope.base.oi.doa -import rope.base.oi.objectinfo -import rope.base.oi.soa -from rope.base import builtins -from rope.base import exceptions -from rope.base import pyobjectsdef -from rope.base import stdmods -from rope.base import taskhandle -from rope.base import utils -from rope.base.exceptions import ModuleNotFoundError - - -@others -@language python -@tabwidth -4 - -class PyCore: - @others - -def __init__(self, project): - self.project = project - self._init_resource_observer() - self.cache_observers = [] - self.module_cache = _ModuleCache(self) - self.extension_cache = _ExtensionCache(self) - self.object_info = rope.base.oi.objectinfo.ObjectInfoManager(project) - self._init_python_files() - self._init_automatic_soa() - - -def _init_python_files(self): - self.python_matcher = None - patterns = self.project.prefs.get("python_files", None) - if patterns is not None: - self.python_matcher = rope.base.resources._ResourceMatcher() - self.python_matcher.set_patterns(patterns) - - -def _init_resource_observer(self): - callback = self._invalidate_resource_cache - observer = rope.base.resourceobserver.ResourceObserver( - changed=callback, moved=callback, removed=callback - ) - self.observer = rope.base.resourceobserver.FilteredResourceObserver(observer) - self.project.add_observer(self.observer) - - -def _init_automatic_soa(self): - if not self.automatic_soa: - return - callback = self._file_changed_for_soa - observer = rope.base.resourceobserver.ResourceObserver( - changed=callback, moved=callback, removed=callback - ) - self.project.add_observer(observer) - - -@property -def automatic_soa(self): - auto_soa = self.project.prefs.get("automatic_soi", None) - return self.project.prefs.get("automatic_soa", auto_soa) - - -def _file_changed_for_soa(self, resource, new_resource=None): - old_contents = self.project.history.contents_before_current_change(resource) - if old_contents is not None: - perform_soa_on_changed_scopes(self.project, resource, old_contents) - - -def is_python_file(self, resource): - if resource.is_folder(): - return False - if self.python_matcher is None: - return resource.name.endswith(".py") - return self.python_matcher.does_match(resource) - - -@utils.deprecated("Use `project.get_module` instead") -def get_module(self, name, folder=None): - """Returns a `PyObject` if the module was found.""" - return self.project.get_module(name, folder) - - -def get_children(node): - result = [] - if node._fields is not None: - for name in node._fields: - if name in ["lineno", "col_offset"]: - continue - child = getattr(node, name) - result.append(child) - return result - -def _builtin_submodules(self, modname): - result = {} - for extension in self.extension_modules: - if extension.startswith(modname + "."): - name = extension[len(modname) + 1 :] - if "." not in name: - result[name] = self.builtin_module(extension) - return result - - -def builtin_module(self, name): - return self.extension_cache.get_pymodule(name) - - -@utils.deprecated("Use `project.get_relative_module` instead") -def get_relative_module(self, name, folder, level): - return self.project.get_relative_module(name, folder, level) - - -@utils.deprecated("Use `libutils.get_string_module` instead") -def get_string_module(self, code, resource=None, force_errors=False): - """Returns a `PyObject` object for the given code - - If `force_errors` is `True`, `exceptions.ModuleSyntaxError` is - raised if module has syntax errors. This overrides - ``ignore_syntax_errors`` project config. - - """ - return pyobjectsdef.PyModule(self, code, resource, force_errors=force_errors) - - -@utils.deprecated("Use `libutils.get_string_scope` instead") -def get_string_scope(self, code, resource=None): - """Returns a `Scope` object for the given code""" - return rope.base.libutils.get_string_scope(code, resource) - - -def _invalidate_resource_cache(self, resource, new_resource=None): - for observer in self.cache_observers: - observer(resource) - - -@utils.deprecated("Use `project.get_python_path_folders` instead") -def get_python_path_folders(self): - return self.project.get_python_path_folders() - - -@utils.deprecated("Use `project.find_module` instead") -def find_module(self, modname, folder=None): - """Returns a resource corresponding to the given module - - returns None if it can not be found - """ - return self.project.find_module(modname, folder) - - -@utils.deprecated("Use `project.find_relative_module` instead") -def find_relative_module(self, modname, folder, level): - return self.project.find_relative_module(modname, folder, level) - - -# INFO: It was decided not to cache source folders, since: -# - Does not take much time when the root folder contains -# packages, that is most of the time -# - We need a separate resource observer; `self.observer` -# does not get notified about module and folder creations -@utils.deprecated("Use `project.get_source_folders` instead") -def get_source_folders(self): - """Returns project source folders""" - return self.project.get_source_folders() - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -10,8 +10,6 @@ - import os - import shutil - import subprocess -- --import rope.base.utils.pycompat as pycompat - import typing -@language python - -def resource_to_pyobject(self, resource, force_errors=False): - return self.module_cache.get_pymodule(resource, force_errors) - - -@utils.deprecated("Use `project.get_python_files` instead") -def get_python_files(self): - """Returns all python files available in the project""" - return self.project.get_python_files() - - -def _is_package(self, folder): - return ( - folder.has_child("__init__.py") - and not folder.get_child("__init__.py").is_folder() - ) - - -def _find_source_folders(self, folder): - for resource in folder.get_folders(): - if self._is_package(resource): - return [folder] - result = [] - for resource in folder.get_files(): - if resource.name.endswith(".py"): - result.append(folder) - break - for resource in folder.get_folders(): - result.extend(self._find_source_folders(resource)) - return result - - -def run_module(self, resource, args=None, stdin=None, stdout=None): - """Run `resource` module - - Returns a `rope.base.oi.doa.PythonFileRunner` object for - controlling the process. - - """ - perform_doa = self.project.prefs.get("perform_doi", True) - perform_doa = self.project.prefs.get("perform_doa", perform_doa) - receiver = self.object_info.doa_data_received - if not perform_doa: - receiver = None - runner = rope.base.oi.doa.PythonFileRunner( - self, resource, args, stdin, stdout, receiver - ) - runner.add_finishing_observer(self.module_cache.forget_all_data) - runner.run() - return runner - - -def analyze_module( - self, - resource, - should_analyze=lambda py: True, - search_subscopes=lambda py: True, - followed_calls=None, -): - """Analyze `resource` module for static object inference - - This function forces rope to analyze this module to collect - information about function calls. `should_analyze` is a - function that is called with a `PyDefinedObject` argument. If - it returns `True` the element is analyzed. If it is `None` or - returns `False` the element is not analyzed. - - `search_subscopes` is like `should_analyze`; The difference is - that if it returns `False` the sub-scopes are all ignored. - That is it is assumed that `should_analyze` returns `False` - for all of its subscopes. - - `followed_calls` override the value of ``soa_followed_calls`` - project config. - """ - if followed_calls is None: - followed_calls = self.project.prefs.get("soa_followed_calls", 0) - pymodule = self.resource_to_pyobject(resource) - self.module_cache.forget_all_data() - rope.base.oi.soa.analyze_module( - self, pymodule, should_analyze, search_subscopes, followed_calls - ) - - -def get_classes(self, task_handle=taskhandle.NullTaskHandle()): - warnings.warn( - "`PyCore.get_classes()` is deprecated", DeprecationWarning, stacklevel=2 - ) - return [] - - -def __str__(self): - return str(self.module_cache) + str(self.object_info) - - -@utils.deprecated("Use `libutils.modname` instead") -def modname(self, resource): - return rope.base.libutils.modname(resource) - - -@property -@utils.cacheit -def extension_modules(self): - result = set(self.project.prefs.get("extension_modules", [])) - if self.project.prefs.get("import_dynload_stdmods", False): - result.update(stdmods.dynload_modules()) - return result - - - - - -class _ModuleCache: - @others - -def __init__(self, pycore): - self.pycore = pycore - self.module_map = {} - self.pycore.cache_observers.append(self._invalidate_resource) - self.observer = self.pycore.observer - - -def _invalidate_resource(self, resource): - if resource in self.module_map: - self.forget_all_data() - self.observer.remove_resource(resource) - del self.module_map[resource] - - -def get_pymodule(self, resource, force_errors=False): - if resource in self.module_map: - return self.module_map[resource] - if resource.is_folder(): - result = pyobjectsdef.PyPackage( - self.pycore, - resource, - force_errors=force_errors, - ) - else: - result = pyobjectsdef.PyModule( - self.pycore, - resource=resource, - force_errors=force_errors, - ) - if result.has_errors: - return result - self.module_map[resource] = result - self.observer.add_resource(resource) - return result - - -def forget_all_data(self): - for pymodule in self.module_map.values(): - pymodule._forget_concluded_data() - - -def __str__(self): - return "PyCore caches %d PyModules\n" % len(self.module_map) - - - -class _ExtensionCache: - @others - -def __init__(self, pycore): - self.pycore = pycore - self.extensions = {} - - -def get_pymodule(self, name): - if name == "__builtin__": - return builtins.builtins - allowed = self.pycore.extension_modules - if name not in self.extensions and name in allowed: - self.extensions[name] = builtins.BuiltinModule(name, self.pycore) - return self.extensions.get(name) - - - -def perform_soa_on_changed_scopes(project, resource, old_contents): - pycore = project.pycore - if resource.exists() and pycore.is_python_file(resource): - try: - new_contents = resource.read() - # detecting changes in new_contents relative to old_contents - detector = _TextChangeDetector(new_contents, old_contents) - - def search_subscopes(pydefined): - scope = pydefined.get_scope() - return detector.is_changed(scope.get_start(), scope.get_end()) - - def should_analyze(pydefined): - scope = pydefined.get_scope() - start = scope.get_start() - end = scope.get_end() - return detector.consume_changes(start, end) - - pycore.analyze_module(resource, should_analyze, search_subscopes) - except exceptions.ModuleSyntaxError: - pass - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -11,8 +11,6 @@ - import os - import shutil - import subprocess -- --import rope.base.utils.pycompat as pycompat - import typing - - -@language python - -class _TextChangeDetector: - @others - -def __init__(self, old, new): - self.old = old - self.new = new - self._set_diffs() - - -def _set_diffs(self): - differ = difflib.Differ() - self.lines = [] - lineno = 0 - for line in differ.compare( - self.old.splitlines(True), self.new.splitlines(True) - ): - if line.startswith(" "): - lineno += 1 - elif line.startswith("-"): - lineno += 1 - self.lines.append(lineno) - - -def is_changed(self, start, end): - """Tell whether any of start till end lines have changed - - The end points are inclusive and indices start from 1. - """ - left, right = self._get_changed(start, end) - return left < right - - -def consume_changes(self, start, end): - """Clear the changed status of lines from start till end""" - left, right = self._get_changed(start, end) - if left < right: - del self.lines[left:right] - return left < right - - -def _get_changed(self, start, end): - left = bisect.bisect_left(self.lines, start) - right = bisect.bisect_right(self.lines, end) - return left, right - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,3 @@ --from rope.base.pynames import DefinedName - import rope.base.builtins - import rope.base.codeanalyze - import rope.base.evaluate -@@ -461,9 +460,7 @@ - pass - - def _For(self, node): -- names = self._update_evaluated( -- node.target, node.iter, ".__iter__().next()" # noqa -- ) -+ self._update_evaluated(node.target, node.iter, ".__iter__().next()") - for child in node.body + node.orelse: - ast.walk(child, self) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,3 @@ --from rope.base.pynames import DefinedName - import rope.base.builtins - import rope.base.codeanalyze - import rope.base.evaluate -@language python - -from rope.base.pynames import DefinedName -import rope.base.builtins -import rope.base.codeanalyze -import rope.base.evaluate -import rope.base.libutils -import rope.base.oi.soi -import rope.base.pyscopes -from rope.base import ( - pynamesdef as pynames, - exceptions, - ast, - astutils, - pyobjects, - fscommands, - arguments, - utils, -) -from rope.base.utils import pycompat - - - -@path C:/Repos/ekr-rope/rope/base/ -"""Project file system commands. - -This modules implements file system operations used by rope. Different -version control systems can be supported by implementing the interface -provided by `FileSystemCommands` class. See `SubversionCommands` and -`MercurialCommands` for example. - -""" -import re -import os -import shutil -import subprocess - -import rope.base.utils.pycompat as pycompat -import typing - - -FileContent = typing.NewType("FileContent", bytes) - - -@others -@language python -@tabwidth -4 - -import rope.base.builtins -import rope.base.codeanalyze -import rope.base.evaluate -import rope.base.libutils -import rope.base.oi.soi -import rope.base.pyscopes -from rope.base import ( - pynamesdef as pynames, - exceptions, - ast, - astutils, - pyobjects, - fscommands, - arguments, - utils, -) -from rope.base.utils import pycompat - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,5 @@ - def _For(self, node): -- names = self._update_evaluated( -- node.target, node.iter, ".__iter__().next()" # noqa -- ) -+ self._update_evaluated(node.target, node.iter, ".__iter__().next()") - for child in node.body + node.orelse: - ast.walk(child, self) - -@language python - -def _For(self, node): - names = self._update_evaluated( - node.target, node.iter, ".__iter__().next()" # noqa - ) - for child in node.body + node.orelse: - ast.walk(child, self) - - -def _For(self, node): - self._update_evaluated(node.target, node.iter, ".__iter__().next()") - for child in node.body + node.orelse: - ast.walk(child, self) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,6 @@ - from itertools import chain - - from rope.base import ast --from rope.base.utils import pycompat - - - def find_visible(node, lines): -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,6 @@ - from itertools import chain - - from rope.base import ast --from rope.base.utils import pycompat - - - @others -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -from itertools import chain - -from rope.base import ast -from rope.base.utils import pycompat - - -@others -@language python -@tabwidth -4 - -@path C:/Repos/ekr-rope/rope/refactor/ -from itertools import chain - -from rope.base import ast -from rope.base.utils import pycompat - - -@others -@language python -@tabwidth -4 - -def find_visible(node, lines): - """Return the line which is visible from all `lines`""" - root = ast_suite_tree(node) - return find_visible_for_suite(root, lines) - - - -@path C:/Repos/ekr-rope/rope/base/ -"""Project file system commands. - -This modules implements file system operations used by rope. Different -version control systems can be supported by implementing the interface -provided by `FileSystemCommands` class. See `SubversionCommands` and -`MercurialCommands` for example. - -""" -import re -import os -import shutil -import subprocess - -import rope.base.utils.pycompat as pycompat -import typing - - -FileContent = typing.NewType("FileContent", bytes) - - -@others -@language python -@tabwidth -4 - -def find_visible_for_suite(root, lines): - if len(lines) == 1: - return lines[0] - line1 = lines[0] - line2 = find_visible_for_suite(root, lines[1:]) - suite1 = root.find_suite(line1) - suite2 = root.find_suite(line2) - - @others - if valid(suite1) and not valid(suite2): - return line1 - if not valid(suite1) and valid(suite2): - return line2 - if not valid(suite1) and not valid(suite2): - return None - while suite1 != suite2 and suite1.parent != suite2.parent: - if suite1._get_level() < suite2._get_level(): - line2 = suite2.get_start() - suite2 = suite2.parent - elif suite1._get_level() > suite2._get_level(): - line1 = suite1.get_start() - suite1 = suite1.parent - else: - line1 = suite1.get_start() - line2 = suite2.get_start() - suite1 = suite1.parent - suite2 = suite2.parent - if suite1 == suite2: - return min(line1, line2) - return min(suite1.get_start(), suite2.get_start()) - - - -def valid(suite): - return suite is not None and not suite.ignored - - -def ast_suite_tree(node): - if hasattr(node, "lineno"): - lineno = node.lineno - else: - lineno = 1 - return Suite(node.body, lineno) - - - -class Suite: - @others - -def __init__(self, child_nodes, lineno, parent=None, ignored=False): - self.parent = parent - self.lineno = lineno - self.child_nodes = child_nodes - self._children = None - self.ignored = ignored - - -def get_start(self): - if self.parent is None: - if self.child_nodes: - return self.local_start() - else: - return 1 - return self.lineno - - -def get_children(self): - if self._children is None: - walker = _SuiteWalker(self) - for child in self.child_nodes: - ast.walk(child, walker) - self._children = walker.suites - return self._children - - -def local_start(self): - return self.child_nodes[0].lineno - - -def local_end(self): - end = self.child_nodes[-1].lineno - if self.get_children(): - end = max(end, self.get_children()[-1].local_end()) - return end - - -def find_suite(self, line): - if line is None: - return None - for child in self.get_children(): - if child.local_start() <= line <= child.local_end(): - return child.find_suite(line) - return self - - -def create_fscommands(root): - dirlist = os.listdir(root) - commands = { - ".hg": MercurialCommands, - ".svn": SubversionCommands, - ".git": GITCommands, - "_svn": SubversionCommands, - "_darcs": DarcsCommands, - } - for key in commands: - if key in dirlist: - try: - return commands[key](root) - except (ImportError, OSError): - pass - return FileSystemCommands() - - - -def _get_level(self): - if self.parent is None: - return 0 - return self.parent._get_level() + 1 - - - -class _SuiteWalker: - @others - -def __init__(self, suite): - self.suite = suite - self.suites = [] - - -def _If(self, node): - self._add_if_like_node(node) - - -def _For(self, node): - self._add_if_like_node(node) - - -def _While(self, node): - self._add_if_like_node(node) - - -def _With(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - - -def _AsyncWith(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - - -def _Match(self, node): - case_bodies = list( - chain.from_iterable([[case.pattern] + case.body for case in node.cases]) - ) - self.suites.append(Suite(case_bodies, node.lineno, self.suite)) - - -def _TryFinally(self, node): - proceed_to_except_handler = False - if len(node.finalbody) == 1: - try: - proceed_to_except_handler = isinstance( - node.handlers[0], ast.ExceptHandler - ) - except IndexError: - pass - if proceed_to_except_handler: - self._TryExcept(node) - else: - self.suites.append(Suite(node.body, node.lineno, self.suite)) - self.suites.append(Suite(node.finalbody, node.lineno, self.suite)) - - -class FileSystemCommands: - @others - -def _Try(self, node): - if len(node.finalbody) == 1: - self._TryFinally(node) - else: - self._TryExcept(node) - - -def _TryExcept(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - for handler in node.handlers: - self.suites.append(Suite(handler.body, node.lineno, self.suite)) - if node.orelse: - self.suites.append(Suite(node.orelse, node.lineno, self.suite)) - - -def _add_if_like_node(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite)) - if node.orelse: - self.suites.append(Suite(node.orelse, node.lineno, self.suite)) - - -def _FunctionDef(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) - - -def _AsyncFunctionDef(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) - - -def _ClassDef(self, node): - self.suites.append(Suite(node.body, node.lineno, self.suite, ignored=True)) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,12 +1,9 @@ - from textwrap import dedent -+import unittest - - from rope.base.builtins import Str -- --import unittest -- - import rope.base.libutils - import rope.base.oi --from rope.base.utils import pycompat - from ropetest import testutils - - -@@ -1052,9 +1049,10 @@ - l = {} - v = l["key"] - """)) -- pymod1 = self.project.get_pymodule(mod1) # noqa -- var = pymod1["v"].get_object() # noqa -- -+ pymod1 = self.project.get_pymodule(mod1) -+ var = pymod1["v"].get_object() -+ self.assertTrue(pymod1 is not None) -+ self.assertTrue(var is not None) - def test_always_returning_containing_class_for_selfs(self): - code = dedent("""\ - class A(object): -@@ -1100,3 +1098,4 @@ - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - x_var = pymod["x"].pyobject.get() -+ self.assertTrue(x_var is not None) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,13 +1,10 @@ - @path C:/Repos/ekr-rope/ropetest/ - from textwrap import dedent -+import unittest - - from rope.base.builtins import Str -- --import unittest -- - import rope.base.libutils - import rope.base.oi --from rope.base.utils import pycompat - from ropetest import testutils - - -@language python - -def create_file(self, path): - open(path, "w").close() - - -@path C:/Repos/ekr-rope/ropetest/ -from textwrap import dedent - -from rope.base.builtins import Str - -import unittest - -import rope.base.libutils -import rope.base.oi -from rope.base.utils import pycompat -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -@path C:/Repos/ekr-rope/ropetest/ -from textwrap import dedent - -from rope.base.builtins import Str - -import unittest - -import rope.base.libutils -import rope.base.oi -from rope.base.utils import pycompat -from ropetest import testutils - - -@others -@language python -@tabwidth -4 - -class DynamicOITest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project(validate_objectdb=True) - self.pycore = self.project.pycore - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_simple_dti(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - return eval("arg") - a_var = a_func(a_func) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - self.assertEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) - - -def test_module_dti(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - code = dedent("""\ - import mod1 - def a_func(arg): - return eval("arg") - a_var = a_func(mod1) - """) - mod2.write(code) - self.pycore.run_module(mod2).wait_process() - pymod2 = self.project.get_pymodule(mod2) - self.assertEqual(self.project.get_pymodule(mod1), pymod2["a_var"].get_object()) - - -def test_class_from_another_module_dti(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - code1 = dedent("""\ - class AClass(object): - pass - """) - code2 = dedent("""\ - from mod1 import AClass - - def a_func(arg): - return eval("arg") - a_var = a_func(AClass) - """) - mod1.write(code1) - mod2.write(code2) - self.pycore.run_module(mod2).wait_process() - # pymod1 = self.project.get_pymodule(mod1) - pymod2 = self.project.get_pymodule(mod2) - self.assertEqual(pymod2["AClass"].get_object(), pymod2["a_var"].get_object()) - - -def test_class_dti(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class AClass(object): - pass - - def a_func(arg): - return eval("arg") - a_var = a_func(AClass) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - self.assertEqual(pymod["AClass"].get_object(), pymod["a_var"].get_object()) - - -def test_instance_dti(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class AClass(object): - pass - - def a_func(arg): - return eval("arg()") - a_var = a_func(AClass) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - self.assertEqual( - pymod["AClass"].get_object(), pymod["a_var"].get_object().get_type() - ) - - -def create_folder(self, path): - os.mkdir(path) - - -def test_method_dti(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class AClass(object): - def a_method(self, arg): - return eval("arg()") - an_instance = AClass() - a_var = an_instance.a_method(AClass) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - self.assertEqual( - pymod["AClass"].get_object(), pymod["a_var"].get_object().get_type() - ) - - -def test_function_argument_dti(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - pass - a_func(a_func) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pyscope = self.project.get_pymodule(mod).get_scope() - self.assertEqual( - pyscope["a_func"].get_object(), pyscope.get_scopes()[0]["arg"].get_object() - ) - - -def test_classes_with_the_same_name(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - class AClass(object): - pass - return eval("arg") - class AClass(object): - pass - a_var = a_func(AClass) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - self.assertEqual(pymod["AClass"].get_object(), pymod["a_var"].get_object()) - - -def test_nested_classes(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(): - class AClass(object): - pass - return AClass - def another_func(arg): - return eval("arg") - a_var = another_func(a_func()) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pyscope = self.project.get_pymodule(mod).get_scope() - self.assertEqual( - pyscope.get_scopes()[0]["AClass"].get_object(), - pyscope["a_var"].get_object(), - ) - - -def test_function_argument_dti2(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg, a_builtin_type): - pass - a_func(a_func, []) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pyscope = self.project.get_pymodule(mod).get_scope() - self.assertEqual( - pyscope["a_func"].get_object(), pyscope.get_scopes()[0]["arg"].get_object() - ) - - -def test_dti_and_concluded_data_invalidation(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - return eval("arg") - a_var = a_func(a_func) - """) - mod.write(code) - pymod = self.project.get_pymodule(mod) - pymod["a_var"].get_object() - self.pycore.run_module(mod).wait_process() - self.assertEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) - - -def test_list_objects_and_dynamicoi(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - pass - def a_func(arg): - return eval("arg") - a_var = a_func([C()])[0] - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_for_loops_and_dynamicoi(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - pass - def a_func(arg): - return eval("arg") - for c in a_func([C()]): - a_var = c - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_dict_objects_and_dynamicoi(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - pass - def a_func(arg): - return eval("arg") - a_var = a_func({1: C()})[1] - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_dict_keys_and_dynamicoi(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - pass - def a_func(arg): - return eval("arg") - a_var = list(a_func({C(): 1}))[0] - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def move(self, path, new_location): - shutil.move(path, new_location) - - -def test_dict_keys_and_dynamicoi2(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(arg): - return eval("arg") - a, b = a_func((C1(), C2())) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_strs_and_dynamicoi(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - return eval("arg") - a_var = a_func("hey") - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - a_var = pymod["a_var"].get_object() - self.assertTrue(isinstance(a_var.get_type(), rope.base.builtins.Str)) - - -def test_textual_transformations(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - pass - def f(): - pass - a_var = C() - a_list = [C()] - a_str = "hey" - a_file = open("file.txt") - """) - mod.write(code) - to_pyobject = rope.base.oi.transform.TextualToPyObject(self.project) - to_textual = rope.base.oi.transform.PyObjectToTextual(self.project) - pymod = self.project.get_pymodule(mod) - - def complex_to_textual(pyobject): - return to_textual.transform( - to_pyobject.transform(to_textual.transform(pyobject)) - ) - - test_variables = [ - ("C", ("defined", "mod.py", "C")), - ("f", ("defined", "mod.py", "f")), - ("a_var", ("instance", ("defined", "mod.py", "C"))), - ("a_list", ("builtin", "list", ("instance", ("defined", "mod.py", "C")))), - ("a_str", ("builtin", "str")), - ("a_file", ("builtin", "file")), - ] - test_cases = [(pymod[v].get_object(), r) for v, r in test_variables] - test_cases += [ - (pymod, ("defined", "mod.py")), - ( - rope.base.builtins.builtins["enumerate"].get_object(), - ("builtin", "function", "enumerate"), - ), - ] - for var, result in test_cases: - self.assertEqual(to_textual.transform(var), result) - self.assertEqual(complex_to_textual(var), result) - - -def test_arguments_with_keywords(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(arg): - return eval("arg") - a = a_func(arg=C1()) - b = a_func(arg=C2()) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_a_function_with_different_returns(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(arg): - return eval("arg") - a = a_func(C1()) - b = a_func(C2()) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_a_function_with_different_returns2(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(p): - if p == C1: - return C1() - else: - return C2() - a = a_func(C1) - b = a_func(C2) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_ignoring_star_args(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(p, *args): - if p == C1: - return C1() - else: - return C2() - a = a_func(C1, 1) - b = a_func(C2, 2) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_ignoring_double_star_args(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(p, *kwds, **args): - if p == C1: - return C1() - else: - return C2() - a = a_func(C1, kwd=1) - b = a_func(C2, kwd=2) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - pymod = self.project.get_pymodule(mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_invalidating_data_after_changing(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - def a_func(arg): - return eval("arg") - a_var = a_func(a_func) - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - mod.write(code.replace("a_func", "newfunc")) - mod.write(code) - pymod = self.project.get_pymodule(mod) - self.assertNotEqual(pymod["a_func"].get_object(), pymod["a_var"].get_object()) - - -def test_invalidating_data_after_moving(self): - mod2 = testutils.create_module(self.project, "mod2") - mod2.write("class C(object):\n pass\n") - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - import mod2 - def a_func(arg): - return eval(arg) - a_var = a_func("mod2.C") - """) - mod.write(code) - self.pycore.run_module(mod).wait_process() - mod.move("newmod.py") - pymod = self.project.get_module("newmod") - pymod2 = self.project.get_pymodule(mod2) - self.assertEqual(pymod2["C"].get_object(), pymod["a_var"].get_object()) - - - -def remove(self, path): - if os.path.isfile(path): - os.remove(path) - else: - shutil.rmtree(path) - - -class NewStaticOITest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = testutils.sample_project(validate_objectdb=True) - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_static_oi_for_simple_function_calls(self): - code = dedent("""\ - class C(object): - pass - def f(p): - pass - f(C()) - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - f_scope = pymod["f"].get_object().get_scope() - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(c_class, p_type) - - -def test_static_oi_not_failing_when_callin_callables(self): - code = dedent("""\ - class C(object): - pass - C() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - - -def test_static_oi_for_nested_calls(self): - code = dedent("""\ - class C(object): - pass - def f(p): - pass - def g(p): - return p - f(g(C())) - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - f_scope = pymod["f"].get_object().get_scope() - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(c_class, p_type) - - -def test_static_oi_class_methods(self): - code = dedent("""\ - class C(object): - def f(self, p): - pass - C().f(C())""") - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - f_scope = c_class["f"].get_object().get_scope() - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(c_class, p_type) - - -def test_static_oi_preventing_soi_maximum_recursion_exceptions(self): - code = dedent("""\ - item = {} - for item in item.keys(): - pass - """) - self.mod.write(code) - try: - self.pycore.analyze_module(self.mod) - except RuntimeError as e: - self.fail(str(e)) - - -def test_static_oi_for_infer_return_typs_from_funcs_based_on_params(self): - code = dedent("""\ - class C(object): - pass - def func(p): - return p - a_var = func(C()) - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_a_function_with_different_returns(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - def a_func(arg): - return arg - a = a_func(C1()) - b = a_func(C2()) - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -927,7 +927,7 @@ - break - else: - self._skip_comment() -- except (ValueError, TypeError) as e: -+ except (ValueError, TypeError): - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) -@language python - -def write(self, path, data): - file_ = open(path, "wb") - try: - file_.write(data) - finally: - file_.close() - - -def test_not_reporting_out_of_date_information(self): - code = dedent("""\ - class C1(object): - pass - def f(arg): - return C1() - a_var = f() - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - - self.mod.write(code.replace("C1", "C2")) - pymod = self.project.get_pymodule(self.mod) - c2_class = pymod["C2"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c2_class, a_var.get_type()) - - -def test_invalidating_concluded_data_in_a_function(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write(dedent("""\ - def func(arg): - temp = arg - return temp - """)) - mod2.write(dedent("""\ - import mod1 - class C1(object): - pass - class C2(object): - pass - a_var = mod1.func(C1()) - """)) - pymod2 = self.project.get_pymodule(mod2) - c1_class = pymod2["C1"].get_object() - a_var = pymod2["a_var"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - - mod2.write(mod2.read()[: mod2.read().rfind("C1()")] + "C2())\n") - pymod2 = self.project.get_pymodule(mod2) - c2_class = pymod2["C2"].get_object() - a_var = pymod2["a_var"].get_object() - self.assertEqual(c2_class, a_var.get_type()) - - -def test_handling_generator_functions_for_strs(self): - self.mod.write(dedent("""\ - class C(object): - pass - def f(p): - yield p() - for c in f(C): - a_var = c - """)) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -# TODO: Returning a generator for functions that yield unknowns -@unittest.skip("Returning a generator that yields unknowns") -def xxx_test_handl_generator_functions_when_unknown_type_is_yielded(self): - self.mod.write(dedent("""\ - class C(object): - pass - def f(): - yield eval("C()") - a_var = f() - """)) - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["a_var"].get_object() - self.assertTrue(isinstance(a_var.get_type(), rope.base.builtins.Generator)) - - -def test_static_oi_for_lists_depending_on_append_function(self): - code = dedent("""\ - class C(object): - pass - l = list() - l.append(C()) - a_var = l.pop() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_static_oi_for_lists_per_object_for_get_item(self): - code = dedent("""\ - class C(object): - pass - l = list() - l.append(C()) - a_var = l[0] - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_static_oi_for_lists_per_object_for_fields(self): - code = dedent("""\ - class C(object): - pass - class A(object): - def __init__(self): - self.l = [] - def set(self): - self.l.append(C()) - a = A() - a.set() - a_var = a.l[0] - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_static_oi_for_lists_per_object_for_set_item(self): - code = dedent("""\ - class C(object): - pass - l = [None] - l[0] = C() - a_var = l[0] - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_static_oi_for_lists_per_object_for_extending_lists(self): - code = dedent("""\ - class C(object): - pass - l = [] - l.append(C()) - l2 = [] - l2.extend(l) - a_var = l2[0] - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_static_oi_for_lists_per_object_for_iters(self): - code = dedent("""\ - class C(object): - pass - l = [] - l.append(C()) - for c in l: - a_var = c - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def read(self, path): - with open(path, "rb") as handle: - return handle.read() - - - -def test_static_oi_for_dicts_depending_on_append_function(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {} - d[C1()] = C2() - a, b = d.popitem() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_static_oi_for_dicts_depending_on_for_loops(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {} - d[C1()] = C2() - for k, v in d.items(): - a = k - b = v - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_static_oi_for_dicts_depending_on_update(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {} - d[C1()] = C2() - d2 = {} - d2.update(d) - a, b = d2.popitem() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_static_oi_for_dicts_depending_on_update_on_seqs(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - pass - d = {} - d.update([(C1(), C2())]) - a, b = d.popitem() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - c2_class = pymod["C2"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertEqual(c2_class, b_var.get_type()) - - -def test_static_oi_for_sets_per_object_for_set_item(self): - code = dedent("""\ - class C(object): - pass - s = set() - s.add(C()) - a_var = s.pop() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c_class, a_var.get_type()) - - -def test_properties_and_calling_get_property(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - c1 = C1() - def get_c1(self): - return self.c1 - p = property(get_c1) - c2 = C2() - a_var = c2.p - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - - -def test_soi_on_constructors(self): - code = dedent("""\ - class C1(object): - pass - class C2(object): - def __init__(self, arg): - self.attr = arg - c2 = C2(C1()) - a_var = c2.attr""") - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a_var"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - - -def test_soi_on_literal_assignment(self): - code = 'a_var = ""' - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["a_var"].get_object() - self.assertEqual(Str, type(a_var.get_type())) - - -@testutils.only_for_versions_higher("3.6") -def test_soi_on_typed_assignment(self): - code = "a_var: str" - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - a_var = pymod["a_var"].get_object() - self.assertEqual(Str, type(a_var.get_type())) - - -def test_not_saving_unknown_function_returns(self): - mod2 = testutils.create_module(self.project, "mod2") - self.mod.write(dedent("""\ - class C(object): - pass - l = [] - l.append(C()) - """)) - mod2.write(dedent("""\ - import mod - def f(): - return mod.l.pop() - a_var = f() - """)) - pymod = self.project.get_pymodule(self.mod) - pymod2 = self.project.get_pymodule(mod2) - c_class = pymod["C"].get_object() - a_var = pymod2["a_var"] - - self.pycore.analyze_module(mod2) - self.assertNotEqual(c_class, a_var.get_object().get_type()) - - self.pycore.analyze_module(self.mod) - self.assertEqual(c_class, a_var.get_object().get_type()) - - -class SubversionCommands: - @others - -def test_using_the_best_callinfo(self): - code = dedent("""\ - class C1(object): - pass - def f(arg1, arg2, arg3): - pass - f("", None, C1()) - f("", C1(), None) - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - f_scope = pymod["f"].get_object().get_scope() - arg2 = f_scope["arg2"].get_object() - self.assertEqual(c1_class, arg2.get_type()) - - -def test_call_function_and_parameters(self): - code = dedent("""\ - class A(object): - def __call__(self, p): - pass - A()("") - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - scope = self.project.get_pymodule(self.mod).get_scope() - p_object = scope.get_scopes()[0].get_scopes()[0]["p"].get_object() - self.assertTrue(isinstance(p_object.get_type(), rope.base.builtins.Str)) - - -def test_report_change_in_libutils(self): - self.project.prefs["automatic_soa"] = True - code = dedent("""\ - class C(object): - pass - def f(p): - pass - f(C()) - """) - with open(self.mod.real_path, "w") as mod_file: - mod_file.write(code) - - rope.base.libutils.report_change(self.project, self.mod.real_path, "") - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - f_scope = pymod["f"].get_object().get_scope() - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(c_class, p_type) - - -def test_report_libutils_and_analyze_all_modules(self): - code = dedent("""\ - class C(object): - pass - def f(p): - pass - f(C()) - """) - self.mod.write(code) - rope.base.libutils.analyze_modules(self.project) - pymod = self.project.get_pymodule(self.mod) - c_class = pymod["C"].get_object() - f_scope = pymod["f"].get_object().get_scope() - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(c_class, p_type) - - -def test_validation_problems_for_objectdb_retrievals(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write(dedent("""\ - l = [] - var = l.pop() - """)) - mod2.write(dedent("""\ - import mod1 - - class C(object): - pass - mod1.l.append(C()) - """)) - self.pycore.analyze_module(mod2) - - pymod2 = self.project.get_pymodule(mod2) - c_class = pymod2["C"].get_object() - pymod1 = self.project.get_pymodule(mod1) - var_pyname = pymod1["var"] - self.assertEqual(c_class, var_pyname.get_object().get_type()) - mod2.write(dedent("""\ - import mod1 - - mod1.l.append("") - """)) - self.assertNotEqual( - c_class, var_pyname.get_object().get_type(), "Class `C` no more exists" - ) - - -def test_always_returning_containing_class_for_selfs(self): - code = dedent("""\ - class A(object): - def f(p): - return p - class B(object): - pass - b = B() - b.f() - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod) - pymod = self.project.get_pymodule(self.mod) - a_class = pymod["A"].get_object() - f_scope = a_class.get_scope().get_scopes()[0] - p_type = f_scope["p"].get_object().get_type() - self.assertEqual(a_class, p_type) - - -def test_following_function_calls_when_asked_to(self): - code = dedent("""\ - class A(object): - pass - class C(object): - def __init__(self, arg): - self.attr = arg - def f(p): - return C(p) - c = f(A()) - x = c.attr - """) - self.mod.write(code) - self.pycore.analyze_module(self.mod, followed_calls=1) - pymod = self.project.get_pymodule(self.mod) - a_class = pymod["A"].get_object() - x_var = pymod["x"].get_object().get_type() - self.assertEqual(a_class, x_var) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -10,6 +10,7 @@ - l = {} - v = l["key"] - """)) -- pymod1 = self.project.get_pymodule(mod1) # noqa -- var = pymod1["v"].get_object() # noqa -- -+ pymod1 = self.project.get_pymodule(mod1) -+ var = pymod1["v"].get_object() -+ self.assertTrue(pymod1 is not None) -+ self.assertTrue(var is not None) -@language python - -def __init__(self, *args): - self.normal_actions = FileSystemCommands() - import pysvn - - self.client = pysvn.Client() - - -def test_validation_problems_for_changing_builtin_types(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - l = [] - l.append("") - """)) - self.pycore.analyze_module(mod1) - - mod1.write(dedent("""\ - l = {} - v = l["key"] - """)) - pymod1 = self.project.get_pymodule(mod1) # noqa - var = pymod1["v"].get_object() # noqa - - -def test_validation_problems_for_changing_builtin_types(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write(dedent("""\ - l = [] - l.append("") - """)) - self.pycore.analyze_module(mod1) - - mod1.write(dedent("""\ - l = {} - v = l["key"] - """)) - pymod1 = self.project.get_pymodule(mod1) # noqa - var = pymod1["v"].get_object() # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,3 +6,4 @@ - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - x_var = pymod["x"].pyobject.get() -+ self.assertTrue(x_var is not None) -@language python - -def test_set_comprehension(self): - code = dedent("""\ - x = {s.strip() for s in X()} - x.add('x') - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - x_var = pymod["x"].pyobject.get() - -def test_set_comprehension(self): - code = dedent("""\ - x = {s.strip() for s in X()} - x.add('x') - """) - self.mod.write(code) - pymod = self.project.get_pymodule(self.mod) - x_var = pymod["x"].pyobject.get() - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,6 +2,7 @@ - from .pickle import AutoImport as _PickleAutoImport - from .sqlite import AutoImport as _SqliteAutoImport - -+assert _SqliteAutoImport # Workaround for an apparent pyflakes bug. - - AutoImport = _PickleAutoImport -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -3,6 +3,7 @@ - from .pickle import AutoImport as _PickleAutoImport - from .sqlite import AutoImport as _SqliteAutoImport - -+assert _SqliteAutoImport # Workaround for an apparent pyflakes bug. - - AutoImport = _PickleAutoImport - -@language python - -@path C:/Repos/ekr-rope/rope/ -"""AutoImport module for rope.""" -from .pickle import AutoImport as _PickleAutoImport -from .sqlite import AutoImport as _SqliteAutoImport - - -AutoImport = _PickleAutoImport - -__all__ = ["AutoImport"] -@language python -@tabwidth -4 - -def create_file(self, path): - self.normal_actions.create_file(path) - self.client.add(path, force=True) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -45,8 +45,11 @@ - monitoring the progress of refactorings. - - """ --from rope.refactor.importutils import ImportOrganizer # noqa --from rope.refactor.topackage import ModuleToPackage # noqa -+from rope.refactor.importutils import ImportOrganizer # essential. -+from rope.refactor.topackage import ModuleToPackage # essential. -+ -+assert ImportOrganizer -+assert ModuleToPackage - - - __all__ = [ -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -46,8 +46,11 @@ - monitoring the progress of refactorings. - - """ --from rope.refactor.importutils import ImportOrganizer # noqa --from rope.refactor.topackage import ModuleToPackage # noqa -+from rope.refactor.importutils import ImportOrganizer # essential. -+from rope.refactor.topackage import ModuleToPackage # essential. -+ -+assert ImportOrganizer -+assert ModuleToPackage - - - __all__ = [ -@language python - -@path C:/Repos/ekr-rope/rope/ -"""rope refactor package - -This package contains modules that perform python refactorings. -Refactoring classes perform refactorings in 4 steps: - -1. Collect some data for performing the refactoring and use them - to construct a refactoring class. Like:: - - renamer = Rename(project, resource, offset) - -2. Some refactorings give you useful information about the - refactoring after their construction. Like:: - - print(renamer.get_old_name()) - -3. Give the refactoring class more information about how to - perform the refactoring and get the changes this refactoring is - going to make. This is done by calling `get_changes` method of the - refactoring class. Like:: - - changes = renamer.get_changes(new_name) - -4. You can commit the changes. Like:: - - project.do(changes) - -These steps are like the steps IDEs usually do for performing a -refactoring. These are the things an IDE does in each step: - -1. Construct a refactoring object by giving it information like - resource, offset and ... . Some of the refactoring problems (like - performing rename refactoring on language keywords) can be reported - here. -2. Print some information about the refactoring and ask the user - about the information that are necessary for completing the - refactoring (like new name). -3. Call the `get_changes` by passing it information asked from - the user (if necessary) and get and preview the changes returned by - it. -4. perform the refactoring. - -From ``0.5m5`` release the `get_changes()` method of some time- -consuming refactorings take an optional `rope.base.taskhandle. -TaskHandle` parameter. You can use this object for stopping or -monitoring the progress of refactorings. - -""" -from rope.refactor.importutils import ImportOrganizer # noqa -from rope.refactor.topackage import ModuleToPackage # noqa - - -__all__ = [ - "rename", - "move", - "inline", - "extract", - "restructure", - "topackage", - "importutils", - "usefunction", - "change_signature", - "encapsulate_field", - "introduce_factory", - "introduce_parameter", - "localtofield", - "method_object", - "multiproject", -] -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -22,7 +22,6 @@ - import rope.base.exceptions - import rope.refactor.functionutils - from rope.base import ( -- ast, - pynames, - pyobjects, - codeanalyze, -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -23,7 +23,6 @@ - import rope.base.exceptions - import rope.refactor.functionutils - from rope.base import ( -- ast, - pynames, - pyobjects, - codeanalyze, -@language python - -@path C:/Repos/ekr-rope/rope/refactor/ -# Known Bugs when inlining a function/method -# The values passed to function are inlined using _inlined_variable. -# This may cause two problems, illustrated in the examples below -# -# def foo(var1): -# var1 = var1*10 -# return var1 -# -# If a call to foo(20) is inlined, the result of inlined function is 20, -# but it should be 200. -# -# def foo(var1): -# var2 = var1*10 -# return var2 -# -# 2- If a call to foo(10+10) is inlined the result of inlined function is 110 -# but it should be 200. - -import re -from typing import List - -import rope.base.exceptions -import rope.refactor.functionutils -from rope.base import ( - ast, - pynames, - pyobjects, - codeanalyze, - taskhandle, - evaluate, - worder, - utils, - libutils, -) -from rope.base.change import ChangeSet, ChangeContents -from rope.refactor import ( - occurrences, - rename, - sourceutils, - importutils, - move, - change_signature, -) - - -@others -@language python -@tabwidth -4 - -def create_folder(self, path): - self.normal_actions.create_folder(path) - self.client.add(path, force=True) - - -@path C:/Repos/ekr-rope/rope/refactor/ -# Known Bugs when inlining a function/method -# The values passed to function are inlined using _inlined_variable. -# This may cause two problems, illustrated in the examples below -# -# def foo(var1): -# var1 = var1*10 -# return var1 -# -# If a call to foo(20) is inlined, the result of inlined function is 20, -# but it should be 200. -# -# def foo(var1): -# var2 = var1*10 -# return var2 -# -# 2- If a call to foo(10+10) is inlined the result of inlined function is 110 -# but it should be 200. - -import re -from typing import List - -import rope.base.exceptions -import rope.refactor.functionutils -from rope.base import ( - ast, - pynames, - pyobjects, - codeanalyze, - taskhandle, - evaluate, - worder, - utils, - libutils, -) -from rope.base.change import ChangeSet, ChangeContents -from rope.refactor import ( - occurrences, - rename, - sourceutils, - importutils, - move, - change_signature, -) - - -@others -@language python -@tabwidth -4 - -def unique_prefix(): - n = 0 - while True: - yield "__" + str(n) + "__" - n += 1 - - - -def create_inline(project, resource, offset): - """Create a refactoring object for inlining - - Based on `resource` and `offset` it returns an instance of - `InlineMethod`, `InlineVariable` or `InlineParameter`. - - """ - pyname = _get_pyname(project, resource, offset) - message = ( - "Inline refactoring should be performed on " - "a method, local variable or parameter." - ) - if pyname is None: - raise rope.base.exceptions.RefactoringError(message) - if isinstance(pyname, pynames.ImportedName): - pyname = pyname._get_imported_pyname() - if isinstance(pyname, pynames.AssignedName): - return InlineVariable(project, resource, offset) - if isinstance(pyname, pynames.ParameterName): - return InlineParameter(project, resource, offset) - if isinstance(pyname.get_object(), pyobjects.PyFunction): - return InlineMethod(project, resource, offset) - else: - raise rope.base.exceptions.RefactoringError(message) - - - -class _Inliner: - @others - -def __init__(self, project, resource, offset): - self.project = project - self.pyname = _get_pyname(project, resource, offset) - range_finder = worder.Worder(resource.read(), True) - self.region = range_finder.get_primary_range(offset) - self.name = range_finder.get_word_at(offset) - self.offset = offset - self.original = resource - - -def get_changes(self, *args, **kwds): - pass - - -def get_kind(self): - """Return either 'variable', 'method' or 'parameter'""" - - - -class InlineMethod(_Inliner): - @others - -def __init__(self, *args, **kwds): - super().__init__(*args, **kwds) - self.pyfunction = self.pyname.get_object() - self.pymodule = self.pyfunction.get_module() - self.resource = self.pyfunction.get_module().get_resource() - self.occurrence_finder = occurrences.create_finder( - self.project, self.name, self.pyname - ) - self.normal_generator = _DefinitionGenerator(self.project, self.pyfunction) - self._init_imports() - - -def _init_imports(self): - body = sourceutils.get_body(self.pyfunction) - body, imports = move.moving_code_with_imports(self.project, self.resource, body) - self.imports = imports - self.others_generator = _DefinitionGenerator( - self.project, self.pyfunction, body=body - ) - - -def move(self, path, new_location): - self.client.move(path, new_location, force=True) - - -def _get_scope_range(self): - scope = self.pyfunction.get_scope() - lines = self.pymodule.lines - start_line = scope.get_start() - if self.pyfunction.decorators: - decorators = self.pyfunction.decorators - if hasattr(decorators[0], "lineno"): - start_line = decorators[0].lineno - start_offset = lines.get_line_start(start_line) - end_offset = min( - lines.get_line_end(scope.end) + 1, len(self.pymodule.source_code) - ) - return (start_offset, end_offset) - - -def get_changes( - self, - remove=True, - only_current=False, - resources=None, - task_handle=taskhandle.NullTaskHandle(), -): - """Get the changes this refactoring makes - - If `remove` is `False` the definition will not be removed. If - `only_current` is `True`, the the current occurrence will be - inlined, only. - """ - changes = ChangeSet("Inline method <%s>" % self.name) - if resources is None: - resources = self.project.get_python_files() - if only_current: - resources = [self.original] - if remove: - resources.append(self.resource) - job_set = task_handle.create_jobset("Collecting Changes", len(resources)) - for file in resources: - job_set.started_job(file.path) - if file == self.resource: - changes.add_change( - self._defining_file_changes( - changes, remove=remove, only_current=only_current - ) - ) - else: - aim = None - if only_current and self.original == file: - aim = self.offset - handle = _InlineFunctionCallsForModuleHandle( - self.project, file, self.others_generator, aim - ) - result = move.ModuleSkipRenamer( - self.occurrence_finder, file, handle - ).get_changed_module() - if result is not None: - result = _add_imports(self.project, result, file, self.imports) - if remove: - result = _remove_from(self.project, self.pyname, result, file) - changes.add_change(ChangeContents(file, result)) - job_set.finished_job() - return changes - - -def _get_removed_range(self): - scope = self.pyfunction.get_scope() - lines = self.pymodule.lines - start, end = self._get_scope_range() - end_line = scope.get_end() - for i in range(end_line + 1, lines.length()): - if lines.get_line(i).strip() == "": - end_line = i - else: - break - end = min(lines.get_line_end(end_line) + 1, len(self.pymodule.source_code)) - return (start, end) - - -def _defining_file_changes(self, changes, remove, only_current): - start_offset, end_offset = self._get_removed_range() - aim = None - if only_current: - if self.resource == self.original: - aim = self.offset - else: - # we don't want to change any of them - aim = len(self.resource.read()) + 100 - handle = _InlineFunctionCallsForModuleHandle( - self.project, self.resource, self.normal_generator, aim_offset=aim - ) - replacement = None - if remove: - replacement = self._get_method_replacement() - result = move.ModuleSkipRenamer( - self.occurrence_finder, - self.resource, - handle, - start_offset, - end_offset, - replacement, - ).get_changed_module() - return ChangeContents(self.resource, result) - - -def _get_method_replacement(self): - if self._is_the_last_method_of_a_class(): - indents = sourceutils.get_indents( - self.pymodule.lines, self.pyfunction.get_scope().get_start() - ) - return " " * indents + "pass\n" - return "" - - -def _is_the_last_method_of_a_class(self): - pyclass = self.pyfunction.parent - if not isinstance(pyclass, pyobjects.PyClass): - return False - class_start, class_end = sourceutils.get_body_region(pyclass) - source = self.pymodule.source_code - func_start, func_end = self._get_scope_range() - return ( - source[class_start:func_start].strip() == "" - and source[func_end:class_end].strip() == "" - ) - - -def get_kind(self): - return "method" - - - -class InlineVariable(_Inliner): - @others - -def __init__(self, *args, **kwds): - super().__init__(*args, **kwds) - self.pymodule = self.pyname.get_definition_location()[0] - self.resource = self.pymodule.get_resource() - self._check_exceptional_conditions() - self._init_imports() - - -def _check_exceptional_conditions(self): - if len(self.pyname.assignments) != 1: - raise rope.base.exceptions.RefactoringError( - "Local variable should be assigned once for inlining." - ) - - -def remove(self, path): - self.client.remove(path, force=True) - - -def get_changes( - self, - remove=True, - only_current=False, - resources=None, - docs=False, - task_handle=taskhandle.NullTaskHandle(), -): - if resources is None: - if rename._is_local(self.pyname): - resources = [self.resource] - else: - resources = self.project.get_python_files() - if only_current: - resources = [self.original] - if remove and self.original != self.resource: - resources.append(self.resource) - changes = ChangeSet("Inline variable <%s>" % self.name) - jobset = task_handle.create_jobset("Calculating changes", len(resources)) - - for resource in resources: - jobset.started_job(resource.path) - if resource == self.resource: - source = self._change_main_module(remove, only_current, docs) - changes.add_change(ChangeContents(self.resource, source)) - else: - result = self._change_module(resource, remove, only_current) - if result is not None: - result = _add_imports(self.project, result, resource, self.imports) - changes.add_change(ChangeContents(resource, result)) - jobset.finished_job() - return changes - - -def _change_main_module(self, remove, only_current, docs): - region = None - if only_current and self.original == self.resource: - region = self.region - return _inline_variable( - self.project, - self.pymodule, - self.pyname, - self.name, - remove=remove, - region=region, - docs=docs, - ) - - -def _init_imports(self): - vardef = _getvardef(self.pymodule, self.pyname) - self.imported, self.imports = move.moving_code_with_imports( - self.project, self.resource, vardef - ) - - -def _change_module(self, resource, remove, only_current): - filters = [occurrences.NoImportsFilter(), occurrences.PyNameFilter(self.pyname)] - if only_current and resource == self.original: - - @others - filters.insert(0, check_aim) - finder = occurrences.Finder(self.project, self.name, filters=filters) - changed = rename.rename_in_module( - finder, self.imported, resource=resource, replace_primary=True - ) - if changed and remove: - changed = _remove_from(self.project, self.pyname, changed, resource) - return changed - - -def check_aim(occurrence): - start, end = occurrence.get_primary_range() - if self.offset < start or end < self.offset: - return False - - -def get_kind(self): - return "variable" - - - -class InlineParameter(_Inliner): - @others - -def __init__(self, *args, **kwds): - super().__init__(*args, **kwds) - resource, offset = self._function_location() - index = self.pyname.index - self.changers = [change_signature.ArgumentDefaultInliner(index)] - self.signature = change_signature.ChangeSignature( - self.project, resource, offset - ) - - -def _function_location(self): - pymodule, lineno = self.pyname.get_definition_location() - resource = pymodule.get_resource() - start = pymodule.lines.get_line_start(lineno) - word_finder = worder.Worder(pymodule.source_code) - offset = word_finder.find_function_offset(start) - return resource, offset - - -def get_changes(self, **kwds): - """Get the changes needed by this refactoring - - See `rope.refactor.change_signature.ChangeSignature.get_changes()` - for arguments. - """ - return self.signature.get_changes(self.changers, **kwds) - - -def write(self, path, data): - self.normal_actions.write(path, data) - - -def get_kind(self): - return "parameter" - - - -def _join_lines(lines: List[str]) -> str: - return "\n".join(lines) - - -class _ComplexExpressionVisitor: - def __init__(self): - self.is_complex_expression = False - - def _Set(self, node): - self.is_complex_expression = True - - def _List(self, node): - self.is_complex_expression = True - - def _Tuple(self, node): - self.is_complex_expression = True - - def _Dict(self, node): - self.is_complex_expression = True - - - -class _DefinitionGenerator: - unique_prefix = unique_prefix() - - @others - -def __init__(self, project, pyfunction, body=None): - self.project = project - self.pyfunction = pyfunction - self.pymodule = pyfunction.get_module() - self.resource = self.pymodule.get_resource() - self.definition_info = self._get_definition_info() - self.definition_params = self._get_definition_params() - self._calculated_definitions = {} - if body is not None: - self.body = body - else: - self.body = sourceutils.get_body(self.pyfunction) - - -def _get_definition_info(self): - return rope.refactor.functionutils.DefinitionInfo.read(self.pyfunction) - - -def _get_definition_params(self): - definition_info = self.definition_info - paramdict = dict([pair for pair in definition_info.args_with_defaults]) - if ( - definition_info.args_arg is not None - or definition_info.keywords_arg is not None - ): - raise rope.base.exceptions.RefactoringError( - "Cannot inline functions with list and keyword arguements." - ) - if self.pyfunction.get_kind() == "classmethod": - paramdict[ - definition_info.args_with_defaults[0][0] - ] = self.pyfunction.parent.get_name() - return paramdict - - -def get_function_name(self): - return self.pyfunction.get_name() - - -def get_definition(self, primary, pyname, call, host_vars=[], returns=False): - # caching already calculated definitions - return self._calculate_definition(primary, pyname, call, host_vars, returns) - - -def _calculate_header(self, primary, pyname, call): - # A header is created which initializes parameters - # to the values passed to the function. - call_info = rope.refactor.functionutils.CallInfo.read( - primary, pyname, self.definition_info, call - ) - paramdict = self.definition_params - mapping = rope.refactor.functionutils.ArgumentMapping( - self.definition_info, call_info - ) - for param_name, value in mapping.param_dict.items(): - paramdict[param_name] = value - header = "" - to_be_inlined = [] - for name, value in paramdict.items(): - if name != value and value is not None: - header += name + " = " + value.replace("\n", " ") + "\n" - to_be_inlined.append(name) - return header, to_be_inlined - - -def _calculate_definition(self, primary, pyname, call, host_vars, returns): - - header, to_be_inlined = self._calculate_header(primary, pyname, call) - - source = header + self.body - mod = libutils.get_string_module(self.project, source) - name_dict = mod.get_scope().get_names() - all_names = [ - x - for x in name_dict - if not isinstance(name_dict[x], rope.base.builtins.BuiltinName) - ] - - # If there is a name conflict, all variable names - # inside the inlined function are renamed - if len(set(all_names).intersection(set(host_vars))) > 0: - - prefix = next(_DefinitionGenerator.unique_prefix) - guest = libutils.get_string_module(self.project, source, self.resource) - - to_be_inlined = [prefix + item for item in to_be_inlined] - for item in all_names: - pyname = guest[item] - occurrence_finder = occurrences.create_finder( - self.project, item, pyname - ) - source = rename.rename_in_module( - occurrence_finder, prefix + item, pymodule=guest - ) - guest = libutils.get_string_module(self.project, source, self.resource) - - # parameters not reassigned inside the functions are now inlined. - for name in to_be_inlined: - pymodule = libutils.get_string_module(self.project, source, self.resource) - pyname = pymodule[name] - source = _inline_variable(self.project, pymodule, pyname, name) - - return self._replace_returns_with(source, returns) - - -def read(self, path): - return self.normal_actions.read(path) - - - -def _replace_returns_with(self, source, returns): - result = [] - returned = None - last_changed = 0 - for match in _DefinitionGenerator._get_return_pattern().finditer(source): - for key, value in match.groupdict().items(): - if value and key == "return": - result.append(source[last_changed : match.start("return")]) - if returns: - self._check_nothing_after_return(source, match.end("return")) - beg_idx = match.end("return") - returned = _join_lines( - source[beg_idx : len(source)].lstrip().splitlines(), - ) - last_changed = len(source) - else: - current = match.end("return") - while current < len(source) and source[current] in " \t": - current += 1 - last_changed = current - if current == len(source) or source[current] == "\n": - result.append("pass") - result.append(source[last_changed:]) - return "".join(result), returned - - -def _check_nothing_after_return(self, source, offset): - lines = codeanalyze.SourceLinesAdapter(source) - lineno = lines.get_line_number(offset) - logical_lines = codeanalyze.LogicalLineFinder(lines) - lineno = logical_lines.logical_line_in(lineno)[1] - if source[lines.get_line_end(lineno) : len(source)].strip() != "": - raise rope.base.exceptions.RefactoringError( - "Cannot inline functions with statements " + "after return statement." - ) - - -@classmethod -def _get_return_pattern(cls): - if not hasattr(cls, "_return_pattern"): - - @others - comment_pattern = named_pattern("comment", [r"#[^\n]*"]) - string_pattern = named_pattern("string", [codeanalyze.get_string_pattern()]) - return_pattern = r"\b(?P<return>return)\b" - cls._return_pattern = re.compile( - comment_pattern + "|" + string_pattern + "|" + return_pattern - ) - return cls._return_pattern - - - -def named_pattern(name, list_): - return "(?P<%s>" % name + "|".join(list_) + ")" - - -class _InlineFunctionCallsForModuleHandle: - @others - -def __init__(self, project, resource, definition_generator, aim_offset=None): - """Inlines occurrences - - If `aim` is not `None` only the occurrences that intersect - `aim` offset will be inlined. - - """ - self.project = project - self.generator = definition_generator - self.resource = resource - self.aim = aim_offset - - -def occurred_inside_skip(self, change_collector, occurrence): - if not occurrence.is_defined(): - raise rope.base.exceptions.RefactoringError( - "Cannot inline functions that reference themselves" - ) - - -def occurred_outside_skip(self, change_collector, occurrence): - start, end = occurrence.get_primary_range() - # we remove out of date imports later - if occurrence.is_in_import_statement(): - return - # the function is referenced outside an import statement - if not occurrence.is_called(): - raise rope.base.exceptions.RefactoringError( - "Reference to inlining function other than function call" - " in <file: %s, offset: %d>" % (self.resource.path, start) - ) - if self.aim is not None and (self.aim < start or self.aim > end): - return - end_parens = self._find_end_parens(self.source, end - 1) - lineno = self.lines.get_line_number(start) - start_line, end_line = self.pymodule.logical_lines.logical_line_in(lineno) - line_start = self.lines.get_line_start(start_line) - line_end = self.lines.get_line_end(end_line) - - returns = ( - self.source[line_start:start].strip() != "" - or self.source[end_parens:line_end].strip() != "" - ) - indents = sourceutils.get_indents(self.lines, start_line) - primary, pyname = occurrence.get_primary_and_pyname() - - host = self.pymodule - scope = host.scope.get_inner_scope_for_line(lineno) - definition, returned = self.generator.get_definition( - primary, - pyname, - self.source[start:end_parens], - scope.get_names(), - returns=returns, - ) - - end = min(line_end + 1, len(self.source)) - change_collector.add_change( - line_start, end, sourceutils.fix_indentation(definition, indents) - ) - if returns: - name = returned - if name is None: - name = "None" - change_collector.add_change( - line_end, - end, - self.source[line_start:start] + name + self.source[end_parens:end], - ) - - -def _find_end_parens(self, source, offset): - finder = worder.Worder(source) - return finder.get_word_parens_range(offset)[1] - - -@property -@utils.saveit -def pymodule(self): - return self.project.get_pymodule(self.resource) - - - -class MercurialCommands: - @others - -@property -@utils.saveit -def source(self): - if self.resource is not None: - return self.resource.read() - else: - return self.pymodule.source_code - - -@property -@utils.saveit -def lines(self): - return self.pymodule.lines - - - -def _inline_variable( - project, pymodule, pyname, name, remove=True, region=None, docs=False -): - definition = _getvardef(pymodule, pyname) - start, end = _assigned_lineno(pymodule, pyname) - - occurrence_finder = occurrences.create_finder(project, name, pyname, docs=docs) - changed_source = rename.rename_in_module( - occurrence_finder, - definition, - pymodule=pymodule, - replace_primary=True, - writes=False, - region=region, - ) - if changed_source is None: - changed_source = pymodule.source_code - if remove: - lines = codeanalyze.SourceLinesAdapter(changed_source) - source = ( - changed_source[: lines.get_line_start(start)] - + changed_source[lines.get_line_end(end) + 1 :] - ) - else: - source = changed_source - return source - - - -def _getvardef(pymodule, pyname): - assignment = pyname.assignments[0] - lines = pymodule.lines - start, end = _assigned_lineno(pymodule, pyname) - definition_with_assignment = _join_lines( - [lines.get_line(n) for n in range(start, end + 1)], - ) - if assignment.levels: - raise rope.base.exceptions.RefactoringError("Cannot inline tuple assignments.") - definition = definition_with_assignment[ - definition_with_assignment.index("=") + 1 : - ].strip() - return definition - - - -def _assigned_lineno(pymodule, pyname): - definition_line = pyname.assignments[0].ast_node.lineno - return pymodule.logical_lines.logical_line_in(definition_line) - - - -def _add_imports(project, source, resource, imports): - if not imports: - return source - pymodule = libutils.get_string_module(project, source, resource) - module_import = importutils.get_module_imports(project, pymodule) - for import_info in imports: - module_import.add_import(import_info) - source = module_import.get_changed_source() - pymodule = libutils.get_string_module(project, source, resource) - import_tools = importutils.ImportTools(project) - return import_tools.organize_imports(pymodule, unused=False, sort=False) - - - -def _get_pyname(project, resource, offset): - pymodule = project.get_pymodule(resource) - pyname = evaluate.eval_location(pymodule, offset) - if isinstance(pyname, pynames.ImportedName): - pyname = pyname._get_imported_pyname() - return pyname - - - -def _remove_from(project, pyname, source, resource): - pymodule = libutils.get_string_module(project, source, resource) - module_import = importutils.get_module_imports(project, pymodule) - module_import.remove_pyname(pyname) - return module_import.get_changed_source() - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -485,8 +485,9 @@ - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a"].get_object() -- b_var = pymod["b"].get_object() # noqa -+ b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) -+ self.assertTrue(b_var is not None) - - def test_enumerate_builtin_function(self): - self.mod.write(dedent("""\ -@language python - - -def __init__(self, root): - self.hg = self._import_mercurial() - self.normal_actions = FileSystemCommands() - try: - self.ui = self.hg.ui.ui( - verbose=False, - debug=False, - quiet=True, - interactive=False, - traceback=False, - report_untrusted=False, - ) - except: - self.ui = self.hg.ui.ui() - self.ui.setconfig("ui", "interactive", "no") - self.ui.setconfig("ui", "debug", "no") - self.ui.setconfig("ui", "traceback", "no") - self.ui.setconfig("ui", "verbose", "no") - self.ui.setconfig("ui", "report_untrusted", "no") - self.ui.setconfig("ui", "quiet", "yes") - - self.repo = self.hg.hg.repository(self.ui, root) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -8,6 +8,7 @@ - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a"].get_object() -- b_var = pymod["b"].get_object() # noqa -+ b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) -+ self.assertTrue(b_var is not None) - -@language python - -def test_wrong_arguments_to_zip_function(self): - self.mod.write(dedent("""\ - class C1(object): - pass - c1_list = [C1()] - a, b = zip(c1_list, 1)[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() # noqa - self.assertEqual(c1_class, a_var.get_type()) - - -def test_wrong_arguments_to_zip_function(self): - self.mod.write(dedent("""\ - class C1(object): - pass - c1_list = [C1()] - a, b = zip(c1_list, 1)[0] - """)) - pymod = self.project.get_pymodule(self.mod) - c1_class = pymod["C1"].get_object() - a_var = pymod["a"].get_object() - b_var = pymod["b"].get_object() - self.assertEqual(c1_class, a_var.get_type()) - self.assertTrue(b_var is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -335,7 +335,8 @@ - - def test_getting_primary_and_strings_at_the_end_of_line(self): - code = "f('\\'')\n" -- result = self._find_primary(code, len(code) - 1) # noqa -+ result = self._find_primary(code, len(code) - 1) -+ self.assertTrue(result is not None) - - def test_getting_primary_and_not_crossing_newlines(self): - code = "\na = (b + c)\n(4 + 1).x\n" -@@ -753,7 +754,7 @@ - mod1 = testutils.create_module(self.project, "mod1") - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) -- mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa -+ mod2 = testutils.create_module(self.project, "mod2", pkg2) - mod1.write("import pkg1.pkg2.mod2") - - mod1_scope = self.project.get_pymodule(mod1).get_scope() -@@ -761,6 +762,7 @@ - pkg2_pyobject = self.project.get_pymodule(pkg2) - found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) - self.assertEqual(pkg2_pyobject, found_pyname.get_object()) -+ self.assertTrue(mod2 is not None) - - def test_get_pyname_at_on_language_keywords(self): - code = dedent("""\ -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,5 @@ - def test_getting_primary_and_strings_at_the_end_of_line(self): - code = "f('\\'')\n" -- result = self._find_primary(code, len(code) - 1) # noqa -+ result = self._find_primary(code, len(code) - 1) -+ self.assertTrue(result is not None) - -@language python - -def test_getting_primary_and_strings_at_the_end_of_line(self): - code = "f('\\'')\n" - result = self._find_primary(code, len(code) - 1) # noqa - - -def test_getting_primary_and_strings_at_the_end_of_line(self): - code = "f('\\'')\n" - result = self._find_primary(code, len(code) - 1) - self.assertTrue(result is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,7 @@ - mod1 = testutils.create_module(self.project, "mod1") - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) -- mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa -+ mod2 = testutils.create_module(self.project, "mod2", pkg2) - mod1.write("import pkg1.pkg2.mod2") - - mod1_scope = self.project.get_pymodule(mod1).get_scope() -@@ -10,4 +10,5 @@ - pkg2_pyobject = self.project.get_pymodule(pkg2) - found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) - self.assertEqual(pkg2_pyobject, found_pyname.get_object()) -+ self.assertTrue(mod2 is not None) - -@language python - -def test_relative_modules_after_from_statements2(self): - mod1 = testutils.create_module(self.project, "mod1") - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) - mod2 = testutils.create_module(self.project, "mod2", pkg2) # noqa - mod1.write("import pkg1.pkg2.mod2") - - mod1_scope = self.project.get_pymodule(mod1).get_scope() - name_finder = rope.base.evaluate.ScopeNameFinder(mod1_scope.pyobject) - pkg2_pyobject = self.project.get_pymodule(pkg2) - found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) - self.assertEqual(pkg2_pyobject, found_pyname.get_object()) - - -def _import_mercurial(self): - import mercurial.commands - import mercurial.hg - import mercurial.ui - - return mercurial - - -def test_relative_modules_after_from_statements2(self): - mod1 = testutils.create_module(self.project, "mod1") - pkg1 = testutils.create_package(self.project, "pkg1") - pkg2 = testutils.create_package(self.project, "pkg2", pkg1) - mod2 = testutils.create_module(self.project, "mod2", pkg2) - mod1.write("import pkg1.pkg2.mod2") - - mod1_scope = self.project.get_pymodule(mod1).get_scope() - name_finder = rope.base.evaluate.ScopeNameFinder(mod1_scope.pyobject) - pkg2_pyobject = self.project.get_pymodule(pkg2) - found_pyname = name_finder.get_pyname_at(mod1.read().index("pkg2") + 1) - self.assertEqual(pkg2_pyobject, found_pyname.get_object()) - self.assertTrue(mod2 is not None) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,4 @@ - """Tests for autoimport utility functions, written in pytest""" -- --from sys import platform -- --import pytest - - from rope.contrib.autoimport import utils - from rope.contrib.autoimport.defs import Package, PackageType, Source -@@ -59,5 +55,5 @@ - def test_get_package_tuple_compiled(compiled_lib): - lib_name, lib_path = compiled_lib - assert Package( -- lib_name, Source.STANDARD, lib_path, PackageType.COMPILED -+ lib_name, Source.STANDARD, lib_path, PackageType.COMPILED - ) == utils.get_package_tuple(lib_path) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,5 @@ - @path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ - """Tests for autoimport utility functions, written in pytest""" -- --from sys import platform -- --import pytest - - from rope.contrib.autoimport import utils - from rope.contrib.autoimport.defs import Package, PackageType, Source -@language python - -@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ -"""Tests for autoimport utility functions, written in pytest""" - -from sys import platform - -import pytest - -from rope.contrib.autoimport import utils -from rope.contrib.autoimport.defs import Package, PackageType, Source - - -@others -@language python -@tabwidth -4 - -@path C:/Repos/ekr-rope/ropetest/contrib/autoimport/ -"""Tests for autoimport utility functions, written in pytest""" - -from sys import platform - -import pytest - -from rope.contrib.autoimport import utils -from rope.contrib.autoimport.defs import Package, PackageType, Source - - -@others -@language python -@tabwidth -4 - -def test_get_package_source(mod1_path, project): - assert utils.get_package_source(mod1_path, project, "") == Source.PROJECT - - - -def test_get_package_source_not_project(mod1_path): - assert utils.get_package_source(mod1_path, None, "") == Source.UNKNOWN - - - -def test_get_package_source_pytest(build_path): - # pytest is not installed as part of the standard library - # but should be installed into site_packages, - # so it should return Source.SITE_PACKAGE - assert utils.get_package_source(build_path, None, "build") == Source.SITE_PACKAGE - - - -def create_file(self, path): - self.normal_actions.create_file(path) - self.hg.commands.add(self.ui, self.repo, path) - - -def test_get_package_source_typing(typing_path): - - assert utils.get_package_source(typing_path, None, "typing") == Source.STANDARD - - - -def test_get_modname_project_no_add(mod1_path, project_path): - - assert utils.get_modname_from_path(mod1_path, project_path, False) == "mod1" - - - -def test_get_modname_single_file(typing_path): - - assert utils.get_modname_from_path(typing_path, typing_path) == "typing" - - - -def test_get_modname_folder(build_path, build_env_path): - - assert utils.get_modname_from_path(build_env_path, build_path) == "build.env" - - - -def test_get_package_tuple_sample(project_path): - assert Package( - "sample_project", Source.UNKNOWN, project_path, PackageType.STANDARD - ) == utils.get_package_tuple(project_path) - - - -def test_get_package_tuple_typing(typing_path): - - assert Package( - "typing", Source.STANDARD, typing_path, PackageType.SINGLE_FILE - ) == utils.get_package_tuple(typing_path) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def test_get_package_tuple_compiled(compiled_lib): - lib_name, lib_path = compiled_lib - assert Package( -- lib_name, Source.STANDARD, lib_path, PackageType.COMPILED -+ lib_name, Source.STANDARD, lib_path, PackageType.COMPILED - ) == utils.get_package_tuple(lib_path) -@language python - -def test_get_package_tuple_compiled(compiled_lib): - lib_name, lib_path = compiled_lib - assert Package( - lib_name, Source.STANDARD, lib_path, PackageType.COMPILED - ) == utils.get_package_tuple(lib_path) - -def test_get_package_tuple_compiled(compiled_lib): - lib_name, lib_path = compiled_lib - assert Package( - lib_name, Source.STANDARD, lib_path, PackageType.COMPILED - ) == utils.get_package_tuple(lib_path) - -def create_folder(self, path): - self.normal_actions.create_folder(path) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -718,7 +718,8 @@ - pass - my_""") - result = self._assist(code) -- proposals = sorted_proposals(result, typepref=["function"]) # noqa -+ proposals = sorted_proposals(result, typepref=["function"]) -+ self.assertTrue(proposals is not None) - - def test_get_pydoc_unicode(self): - src = dedent('''\ -@@ -824,7 +825,8 @@ - s = "hey" - s.replace() - """) -- doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa -+ doc = get_doc(self.project, src, src.rindex("replace") + 1) -+ self.assertTrue(doc is not None) - - def test_proposing_variables_defined_till_the_end_of_scope(self): - code = dedent("""\ -@@ -928,7 +930,8 @@ - except: - pass - """) -- result = self._assist(code, code.index("."), maxfixes=1) # noqa -+ result = self._assist(code, code.index("."), maxfixes=1) -+ self.assertTrue(result is not None) - - def test_nested_blocks(self): - code = dedent("""\ -@@ -951,7 +954,8 @@ - code = dedent("""\ - f = 1 - f(p""") -- result = self._assist(code) # noqa -+ result = self._assist(code) -+ self.assertTrue(result is not None) - - def test_proposing_function_keywords_when_calling_extra_spaces(self): - code = dedent("""\ -@@ -1337,7 +1341,8 @@ - """) - samplemod.write(code) - package = testutils.create_package(self.project, "package") -- nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa -+ nestedmod = testutils.create_module(self.project, "nestedmod", package) -+ self.assertTrue(nestedmod is not None) - - def tearDown(self): - testutils.remove_project(self.project) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,5 +5,6 @@ - pass - my_""") - result = self._assist(code) -- proposals = sorted_proposals(result, typepref=["function"]) # noqa -+ proposals = sorted_proposals(result, typepref=["function"]) -+ self.assertTrue(proposals is not None) - -@language python - -def test_proposals_sorter_and_missing_type_in_typepref(self): - code = dedent("""\ - my_global_var = 1 - def my_global_func(): - pass - my_""") - result = self._assist(code) - proposals = sorted_proposals(result, typepref=["function"]) # noqa - - -def test_proposals_sorter_and_missing_type_in_typepref(self): - code = dedent("""\ - my_global_var = 1 - def my_global_func(): - pass - my_""") - result = self._assist(code) - proposals = sorted_proposals(result, typepref=["function"]) - self.assertTrue(proposals is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,5 +4,6 @@ - s = "hey" - s.replace() - """) -- doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa -+ doc = get_doc(self.project, src, src.rindex("replace") + 1) -+ self.assertTrue(doc is not None) - -@language python - -def test_commenting_errors_before_offset(self): - src = dedent("""\ - lsjd lsjdf - s = "hey" - s.replace() - """) - doc = get_doc(self.project, src, src.rindex("replace") + 1) # noqa - - -def test_commenting_errors_before_offset(self): - src = dedent("""\ - lsjd lsjdf - s = "hey" - s.replace() - """) - doc = get_doc(self.project, src, src.rindex("replace") + 1) - self.assertTrue(doc is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,5 +5,6 @@ - except: - pass - """) -- result = self._assist(code, code.index("."), maxfixes=1) # noqa -+ result = self._assist(code, code.index("."), maxfixes=1) -+ self.assertTrue(result is not None) - -@language python - -def test_and_normal_complete_blocks_and_single_fixing(self): - code = dedent("""\ - try: - range. - except: - pass - """) - result = self._assist(code, code.index("."), maxfixes=1) # noqa - - -def move(self, path, new_location): - self.hg.commands.rename(self.ui, self.repo, path, new_location, after=False) - - -def test_and_normal_complete_blocks_and_single_fixing(self): - code = dedent("""\ - try: - range. - except: - pass - """) - result = self._assist(code, code.index("."), maxfixes=1) - self.assertTrue(result is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,5 +2,6 @@ - code = dedent("""\ - f = 1 - f(p""") -- result = self._assist(code) # noqa -+ result = self._assist(code) -+ self.assertTrue(result is not None) - -@language python - -def test_proposing_function_keywords_when_calling_for_non_functions(self): - code = dedent("""\ - f = 1 - f(p""") - result = self._assist(code) # noqa - - -def test_proposing_function_keywords_when_calling_for_non_functions(self): - code = dedent("""\ - f = 1 - f(p""") - result = self._assist(code) - self.assertTrue(result is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -18,5 +18,6 @@ - """) - samplemod.write(code) - package = testutils.create_package(self.project, "package") -- nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa -+ nestedmod = testutils.create_module(self.project, "nestedmod", package) -+ self.assertTrue(nestedmod is not None) - -@language python - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - samplemod = testutils.create_module(self.project, "samplemod") - code = dedent("""\ - class SampleClass(object): - def sample_method(): - pass - - def sample_func(): - pass - sample_var = 10 - - def _underlined_func(): - pass - - """) - samplemod.write(code) - package = testutils.create_package(self.project, "package") - nestedmod = testutils.create_module(self.project, "nestedmod", package) # noqa - - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - samplemod = testutils.create_module(self.project, "samplemod") - code = dedent("""\ - class SampleClass(object): - def sample_method(): - pass - - def sample_func(): - pass - sample_var = 10 - - def _underlined_func(): - pass - - """) - samplemod.write(code) - package = testutils.create_package(self.project, "package") - nestedmod = testutils.create_module(self.project, "nestedmod", package) - self.assertTrue(nestedmod is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -42,11 +42,12 @@ - - def test_handling_nested_modules(self): - pkg = create_package(self.project, "xkg") -- mod = create_module(self.project, "xkg.xod") # noqa -+ mod = create_module(self.project, "xkg.xod") - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - self.assertFalse(pkg.exists()) - self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) - self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) -+ self.assertTrue(mod is not None) - - - def _fixer(name): -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,10 @@ - def test_handling_nested_modules(self): - pkg = create_package(self.project, "xkg") -- mod = create_module(self.project, "xkg.xod") # noqa -+ mod = create_module(self.project, "xkg.xod") - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - self.assertFalse(pkg.exists()) - self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) - self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) -+ self.assertTrue(mod is not None) - - -@language python - -def remove(self, path): - self.hg.commands.remove(self.ui, self.repo, path) - - -def test_handling_nested_modules(self): - pkg = create_package(self.project, "xkg") - mod = create_module(self.project, "xkg.xod") # noqa - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - self.assertFalse(pkg.exists()) - self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) - self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) - - - -def test_handling_nested_modules(self): - pkg = create_package(self.project, "xkg") - mod = create_module(self.project, "xkg.xod") - self.project.do(FixModuleNames(self.project).get_changes(_fixer)) - self.assertFalse(pkg.exists()) - self.assertTrue(self.project.get_resource("_kg/__init__.py").exists()) - self.assertTrue(self.project.get_resource("_kg/_od.py").exists()) - self.assertTrue(mod is not None) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -373,7 +373,7 @@ - self.assertFalse(myfile.exists()) - - def test_writing_and_reading_history(self): -- history_file = self.project.get_file("history.pickle") # noqa -+ history_file = self.project.get_file("history.pickle") - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") -@@ -383,9 +383,10 @@ - history = rope.base.history.History(self.project) - history.undo() - self.assertFalse(myfile.exists()) -+ self.assertTrue(history_file is not None) - - def test_writing_and_reading_history2(self): -- history_file = self.project.get_file("history.pickle") # noqa -+ history_file = self.project.get_file("history.pickle") - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") -@@ -396,3 +397,4 @@ - history = rope.base.history.History(self.project) - history.redo() - self.assertTrue(myfile.exists()) -+ self.assertTrue(history_file is not None) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def test_writing_and_reading_history(self): -- history_file = self.project.get_file("history.pickle") # noqa -+ history_file = self.project.get_file("history.pickle") - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") -@@ -9,4 +9,5 @@ - history = rope.base.history.History(self.project) - history.undo() - self.assertFalse(myfile.exists()) -+ self.assertTrue(history_file is not None) - -@language python - -def test_writing_and_reading_history(self): - history_file = self.project.get_file("history.pickle") # noqa - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") - history.do(rope.base.change.CreateResource(myfile)) - history.write() - - history = rope.base.history.History(self.project) - history.undo() - self.assertFalse(myfile.exists()) - - -def test_writing_and_reading_history(self): - history_file = self.project.get_file("history.pickle") - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") - history.do(rope.base.change.CreateResource(myfile)) - history.write() - - history = rope.base.history.History(self.project) - history.undo() - self.assertFalse(myfile.exists()) - self.assertTrue(history_file is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def test_writing_and_reading_history2(self): -- history_file = self.project.get_file("history.pickle") # noqa -+ history_file = self.project.get_file("history.pickle") - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") -@@ -10,3 +10,4 @@ - history = rope.base.history.History(self.project) - history.redo() - self.assertTrue(myfile.exists()) -+ self.assertTrue(history_file is not None) -@language python - -def test_writing_and_reading_history2(self): - history_file = self.project.get_file("history.pickle") # noqa - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") - history.do(rope.base.change.CreateResource(myfile)) - history.undo() - history.write() - - history = rope.base.history.History(self.project) - history.redo() - self.assertTrue(myfile.exists()) - -def test_writing_and_reading_history2(self): - history_file = self.project.get_file("history.pickle") - self.project.set("save_history", True) - history = rope.base.history.History(self.project) - myfile = self.project.get_file("myfile.txt") - history.do(rope.base.change.CreateResource(myfile)) - history.undo() - history.write() - - history = rope.base.history.History(self.project) - history.redo() - self.assertTrue(myfile.exists()) - self.assertTrue(history_file is not None) - -def write(self, path, data): - self.normal_actions.write(path, data) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -285,7 +285,8 @@ - """) - mod = libutils.get_string_module(self.project, code) - -- a = mod["a"].get_object() # noqa -+ a = mod["a"].get_object() -+ self.assertTrue(a is not None) - - def test_handling_generator_functions(self): - code = dedent("""\ -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,5 +5,6 @@ - """) - mod = libutils.get_string_module(self.project, code) - -- a = mod["a"].get_object() # noqa -+ a = mod["a"].get_object() -+ self.assertTrue(a is not None) - -@language python - -def test_empty_tuples(self): - code = dedent("""\ - t = () - a, b = t - """) - mod = libutils.get_string_module(self.project, code) - - a = mod["a"].get_object() # noqa - - -def test_empty_tuples(self): - code = dedent("""\ - t = () - a, b = t - """) - mod = libutils.get_string_module(self.project, code) - - a = mod["a"].get_object() - self.assertTrue(a is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,8 +1,7 @@ - import os.path - import shutil - from textwrap import dedent -- --import pytest -+import unittest - - from rope.base.exceptions import RopeError, ResourceNotFoundError - from rope.base.fscommands import FileSystemCommands -@@ -10,9 +9,6 @@ - from rope.base.project import Project, NoProject, _realpath - from rope.base.resourceobserver import FilteredResourceObserver - from ropetest import testutils -- -- --import unittest - - - class ProjectTest(unittest.TestCase): -@@ -705,7 +701,7 @@ - def test_revalidating_folders(self): - root = self.project.root - my_folder = root.create_folder("myfolder") -- my_file = my_folder.create_file("myfile.txt") # noqa -+ my_file = my_folder.create_file("myfile.txt") - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [my_folder]) -@@ -714,6 +710,7 @@ - self.project.validate(root) - self.assertEqual(my_folder, sample_observer.last_removed) - self.assertEqual(1, sample_observer.change_count) -+ self.assertTrue(my_file is not None) - - def test_removing_and_adding_resources_to_filtered_observer(self): - my_file = self.project.root.create_file("my_file.txt") -@@ -812,7 +809,7 @@ - self.assertEqual(1, sample_observer.change_count) - - def test_changes_and_adding_resources(self): -- root = self.project.root # noqa -+ # root = self.project.root - file1 = self.project.get_file("file1.txt") - file2 = self.project.get_file("file2.txt") - file1.create() -@@ -826,7 +823,7 @@ - self.assertEqual((file1, file2), sample_observer.last_moved) - - def test_validating_get_files_list(self): -- root = self.project.root # noqa -+ # root = self.project.root - self.assertEqual(0, len(self.project.get_files())) - file = open(os.path.join(self.project.address, "myfile.txt"), "w") - file.close() -@@ -1040,8 +1037,9 @@ - self.project = testutils.sample_project( - ignored_resources=["myfile.txt"], ropefolder=None - ) -- myfile = self.project.root.create_file("myfile.txt") # noqa -+ myfile = self.project.root.create_file("myfile.txt") - self.assertEqual(0, len(self.project.get_files())) -+ self.assertTrue(myfile is not None) - - def test_setting_ignored_resources_patterns(self): - self.project = testutils.sample_project(ignored_resources=["m?file.*"]) -@@ -1162,7 +1160,8 @@ - ) - mod = testutils.create_module(self.project, "mod") - mod.write("xyz print") -- pymod = self.project.get_pymodule(mod) # noqa -+ pymod = self.project.get_pymodule(mod) -+ self.assertTrue(pymod is not None) - - def test_compressed_history(self): - self.project = testutils.sample_project(compress_history=True) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,8 +2,7 @@ - import os.path - import shutil - from textwrap import dedent -- --import pytest -+import unittest - - from rope.base.exceptions import RopeError, ResourceNotFoundError - from rope.base.fscommands import FileSystemCommands -@@ -13,9 +12,6 @@ - from ropetest import testutils - - --import unittest -- -- - @others - @language python - @tabwidth -4 -@language python - -@path C:/Repos/ekr-rope/ropetest/ -import os.path -import shutil -from textwrap import dedent - -import pytest - -from rope.base.exceptions import RopeError, ResourceNotFoundError -from rope.base.fscommands import FileSystemCommands -from rope.base.libutils import path_to_resource -from rope.base.project import Project, NoProject, _realpath -from rope.base.resourceobserver import FilteredResourceObserver -from ropetest import testutils - - -import unittest - - -@others -@language python -@tabwidth -4 - -@path C:/Repos/ekr-rope/ropetest/ -import os.path -import shutil -from textwrap import dedent - -import pytest - -from rope.base.exceptions import RopeError, ResourceNotFoundError -from rope.base.fscommands import FileSystemCommands -from rope.base.libutils import path_to_resource -from rope.base.project import Project, NoProject, _realpath -from rope.base.resourceobserver import FilteredResourceObserver -from ropetest import testutils - - -import unittest - - -@others -@language python -@tabwidth -4 - -def read(self, path): - return self.normal_actions.read(path) - - - -class ProjectTest(unittest.TestCase): - @others - -def setUp(self): - unittest.TestCase.setUp(self) - self.project = testutils.sample_project( - foldername="sampleproject", ropefolder=None - ) - self.project_root = self.project.address - self._make_sample_project() - self.no_project = NoProject() - - -def _make_sample_project(self): - self.sample_file = "sample_file.txt" - self.sample_path = os.path.join(self.project_root, "sample_file.txt") - if not os.path.exists(self.project_root): - os.mkdir(self.project_root) - self.sample_folder = "sample_folder" - os.mkdir(os.path.join(self.project_root, self.sample_folder)) - sample = open(self.sample_path, "w") - sample.write("sample text\n") - sample.close() - - -def tearDown(self): - testutils.remove_project(self.project) - unittest.TestCase.tearDown(self) - - -def test_project_creation(self): - self.assertEqual(_realpath(self.project_root), self.project.address) - - -def test_getting_project_file(self): - project_file = self.project.get_resource(self.sample_file) - self.assertTrue(project_file is not None) - - -def test_project_file_reading(self): - projectFile = self.project.get_resource(self.sample_file) - self.assertEqual("sample text\n", projectFile.read()) - - -def test_getting_not_existing_project_file(self): - with self.assertRaises(ResourceNotFoundError): - self.project.get_resource("DoesNotExistFile.txt") - - -def test_writing_in_project_files(self): - project_file = self.project.get_resource(self.sample_file) - project_file.write("another text\n") - self.assertEqual("another text\n", project_file.read()) - - -def test_creating_files(self): - project_file = "newfile.txt" - self.project.root.create_file(project_file) - newFile = self.project.get_resource(project_file) - self.assertTrue(newFile is not None) - - -class GITCommands: - @others - -def test_creating_files_that_already_exist(self): - with self.assertRaises(RopeError): - self.project.root.create_file(self.sample_file) - - -def test_making_root_folder_if_it_does_not_exist(self): - project = Project("sampleproject2") - try: - self.assertTrue( - os.path.exists("sampleproject2") and os.path.isdir("sampleproject2") - ) - finally: - testutils.remove_project(project) - - -def test_failure_when_project_root_exists_and_is_a_file(self): - project_root = "sampleproject2" - try: - open(project_root, "w").close() - with self.assertRaises(RopeError): - Project(project_root) - finally: - testutils.remove_recursively(project_root) - - -def test_creating_folders(self): - folderName = "SampleFolder" - self.project.root.create_folder(folderName) - folderPath = os.path.join(self.project.address, folderName) - self.assertTrue(os.path.exists(folderPath) and os.path.isdir(folderPath)) - - -def test_making_folder_that_already_exists(self): - folderName = "SampleFolder" - with self.assertRaises(RopeError): - self.project.root.create_folder(folderName) - self.project.root.create_folder(folderName) - - -def test_failing_if_creating_folder_while_file_already_exists(self): - folderName = "SampleFolder" - with self.assertRaises(RopeError): - self.project.root.create_file(folderName) - self.project.root.create_folder(folderName) - - -def test_creating_file_inside_folder(self): - folder_name = "sampleFolder" - file_name = "sample2.txt" - file_path = folder_name + "/" + file_name - parent_folder = self.project.root.create_folder(folder_name) - parent_folder.create_file(file_name) - file = self.project.get_resource(file_path) - file.write("sample notes") - self.assertEqual(file_path, file.path) - self.assertEqual( - "sample notes", open(os.path.join(self.project.address, file_path)).read() - ) - - -def test_failing_when_creating_file_inside_non_existent_folder(self): - with self.assertRaises(ResourceNotFoundError): - self.project.root.create_file("NonexistentFolder/SomeFile.txt") - - -def test_nested_directories(self): - folder_name = "SampleFolder" - parent = self.project.root.create_folder(folder_name) - parent.create_folder(folder_name) - folder_path = os.path.join(self.project.address, folder_name, folder_name) - self.assertTrue(os.path.exists(folder_path) and os.path.isdir(folder_path)) - - -def test_removing_files(self): - self.assertTrue(os.path.exists(self.sample_path)) - self.project.get_resource(self.sample_file).remove() - self.assertFalse(os.path.exists(self.sample_path)) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,7 +6,7 @@ - break - else: - self._skip_comment() -- except (ValueError, TypeError) as e: -+ except (ValueError, TypeError): - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) -@language python - -def __init__(self, root): - self.root = root - self._do(["version"]) - self.normal_actions = FileSystemCommands() - - -def test_removing_files_invalidating_in_project_resource_pool(self): - root_folder = self.project.root - my_file = root_folder.create_file("my_file.txt") - my_file.remove() - self.assertFalse(root_folder.has_child("my_file.txt")) - - -def test_removing_directories(self): - self.assertTrue( - os.path.exists(os.path.join(self.project.address, self.sample_folder)) - ) - self.project.get_resource(self.sample_folder).remove() - self.assertFalse( - os.path.exists(os.path.join(self.project.address, self.sample_folder)) - ) - - -def test_removing_non_existent_files(self): - with self.assertRaises(ResourceNotFoundError): - self.project.get_resource("NonExistentFile.txt").remove() - - -def test_removing_nested_files(self): - file_name = self.sample_folder + "/sample_file.txt" - self.project.root.create_file(file_name) - self.project.get_resource(file_name).remove() - self.assertTrue( - os.path.exists(os.path.join(self.project.address, self.sample_folder)) - ) - self.assertTrue( - not os.path.exists(os.path.join(self.project.address, file_name)) - ) - - -def test_file_get_name(self): - file = self.project.get_resource(self.sample_file) - self.assertEqual(self.sample_file, file.name) - file_name = "nestedFile.txt" - parent = self.project.get_resource(self.sample_folder) - filePath = self.sample_folder + "/" + file_name - parent.create_file(file_name) - nestedFile = self.project.get_resource(filePath) - self.assertEqual(file_name, nestedFile.name) - - -def test_folder_get_name(self): - folder = self.project.get_resource(self.sample_folder) - self.assertEqual(self.sample_folder, folder.name) - - -def test_file_get_path(self): - file = self.project.get_resource(self.sample_file) - self.assertEqual(self.sample_file, file.path) - fileName = "nestedFile.txt" - parent = self.project.get_resource(self.sample_folder) - filePath = self.sample_folder + "/" + fileName - parent.create_file(fileName) - nestedFile = self.project.get_resource(filePath) - self.assertEqual(filePath, nestedFile.path) - - -def test_folder_get_path(self): - folder = self.project.get_resource(self.sample_folder) - self.assertEqual(self.sample_folder, folder.path) - - -def test_is_folder(self): - self.assertTrue(self.project.get_resource(self.sample_folder).is_folder()) - self.assertTrue(not self.project.get_resource(self.sample_file).is_folder()) - - -def testget_children(self): - children = self.project.get_resource(self.sample_folder).get_children() - self.assertEqual([], children) - - -def create_file(self, path): - self.normal_actions.create_file(path) - self._do(["add", self._in_dir(path)]) - - -def test_nonempty_get_children(self): - file_name = "nestedfile.txt" - filePath = self.sample_folder + "/" + file_name - parent = self.project.get_resource(self.sample_folder) - parent.create_file(file_name) - children = parent.get_children() - self.assertEqual(1, len(children)) - self.assertEqual(filePath, children[0].path) - - -def test_nonempty_get_children2(self): - file_name = "nestedfile.txt" - folder_name = "nestedfolder.txt" - filePath = self.sample_folder + "/" + file_name - folderPath = self.sample_folder + "/" + folder_name - parent = self.project.get_resource(self.sample_folder) - parent.create_file(file_name) - parent.create_folder(folder_name) - children = parent.get_children() - self.assertEqual(2, len(children)) - self.assertTrue(filePath == children[0].path or filePath == children[1].path) - self.assertTrue( - folderPath == children[0].path or folderPath == children[1].path - ) - - -def test_does_not_fail_for_permission_denied(self): - bad_dir = os.path.join(self.sample_folder, "bad_dir") - os.makedirs(bad_dir) - self.addCleanup(shutil.rmtree, bad_dir) - os.chmod(bad_dir, 0o000) - try: - parent = self.project.get_resource(self.sample_folder) - - parent.get_children() - - finally: - os.chmod(bad_dir, 0o755) - - -def test_getting_files(self): - files = self.project.root.get_files() - self.assertEqual(1, len(files)) - self.assertTrue(self.project.get_resource(self.sample_file) in files) - - -def test_getting_folders(self): - folders = self.project.root.get_folders() - self.assertEqual(1, len(folders)) - self.assertTrue(self.project.get_resource(self.sample_folder) in folders) - - -def test_nested_folder_get_files(self): - parent = self.project.root.create_folder("top") - parent.create_file("file1.txt") - parent.create_file("file2.txt") - files = parent.get_files() - self.assertEqual(2, len(files)) - self.assertTrue(self.project.get_resource("top/file2.txt") in files) - self.assertEqual(0, len(parent.get_folders())) - - -def test_nested_folder_get_folders(self): - parent = self.project.root.create_folder("top") - parent.create_folder("dir1") - parent.create_folder("dir2") - folders = parent.get_folders() - self.assertEqual(2, len(folders)) - self.assertTrue(self.project.get_resource("top/dir1") in folders) - self.assertEqual(0, len(parent.get_files())) - - -def test_root_folder(self): - root_folder = self.project.root - self.assertEqual(2, len(root_folder.get_children())) - self.assertEqual("", root_folder.path) - self.assertEqual("", root_folder.name) - - -def test_get_all_files(self): - files = tuple(self.project.get_files()) - self.assertEqual(1, len(files)) - self.assertEqual(self.sample_file, files[0].name) - - -def test_get_all_files_after_changing(self): - self.assertEqual(1, len(self.project.get_files())) - myfile = self.project.root.create_file("myfile.txt") - self.assertEqual(2, len(self.project.get_files())) - myfile.move("newfile.txt") - self.assertEqual(2, len(self.project.get_files())) - self.project.get_file("newfile.txt").remove() - self.assertEqual(1, len(self.project.get_files())) - - -def create_folder(self, path): - self.normal_actions.create_folder(path) - - -def test_multifile_get_all_files(self): - fileName = "nestedFile.txt" - parent = self.project.get_resource(self.sample_folder) - parent.create_file(fileName) - files = list(self.project.get_files()) - self.assertEqual(2, len(files)) - self.assertTrue(fileName == files[0].name or fileName == files[1].name) - - -def test_ignoring_dot_pyc_files_in_get_files(self): - root = self.project.address - src_folder = os.path.join(root, "src") - os.mkdir(src_folder) - test_pyc = os.path.join(src_folder, "test.pyc") - open(test_pyc, "w").close() - for x in self.project.get_files(): - self.assertNotEqual("src/test.pyc", x.path) - - -def test_folder_creating_files(self): - projectFile = "NewFile.txt" - self.project.root.create_file(projectFile) - new_file = self.project.get_resource(projectFile) - self.assertTrue(new_file is not None and not new_file.is_folder()) - - -def test_folder_creating_nested_files(self): - project_file = "NewFile.txt" - parent_folder = self.project.get_resource(self.sample_folder) - parent_folder.create_file(project_file) - new_file = self.project.get_resource(self.sample_folder + "/" + project_file) - self.assertTrue(new_file is not None and not new_file.is_folder()) - - -def test_folder_creating_files2(self): - projectFile = "newfolder" - self.project.root.create_folder(projectFile) - new_folder = self.project.get_resource(projectFile) - self.assertTrue(new_folder is not None and new_folder.is_folder()) - - -def test_folder_creating_nested_files2(self): - project_file = "newfolder" - parent_folder = self.project.get_resource(self.sample_folder) - parent_folder.create_folder(project_file) - new_folder = self.project.get_resource(self.sample_folder + "/" + project_file) - self.assertTrue(new_folder is not None and new_folder.is_folder()) - - -def test_folder_get_child(self): - folder = self.project.root - folder.create_file("myfile.txt") - folder.create_folder("myfolder") - self.assertEqual( - self.project.get_resource("myfile.txt"), folder.get_child("myfile.txt") - ) - self.assertEqual( - self.project.get_resource("myfolder"), folder.get_child("myfolder") - ) - - -def test_folder_get_child_nested(self): - root = self.project.root - folder = root.create_folder("myfolder") - folder.create_file("myfile.txt") - folder.create_folder("myfolder") - self.assertEqual( - self.project.get_resource("myfolder/myfile.txt"), - folder.get_child("myfile.txt"), - ) - self.assertEqual( - self.project.get_resource("myfolder/myfolder"), folder.get_child("myfolder") - ) - - -def test_project_root_is_root_folder(self): - self.assertEqual("", self.project.root.path) - - -def test_moving_files(self): - root_folder = self.project.root - my_file = root_folder.create_file("my_file.txt") - my_file.move("my_other_file.txt") - self.assertFalse(my_file.exists()) - root_folder.get_child("my_other_file.txt") - - -def move(self, path, new_location): - self._do(["mv", self._in_dir(path), self._in_dir(new_location)]) - - -def test_moving_folders(self): - root_folder = self.project.root - my_folder = root_folder.create_folder("my_folder") - my_file = my_folder.create_file("my_file.txt") - my_folder.move("new_folder") - self.assertFalse(root_folder.has_child("my_folder")) - self.assertFalse(my_file.exists()) - self.assertTrue(root_folder.get_child("new_folder") is not None) - - -def test_moving_destination_folders(self): - root_folder = self.project.root - my_folder = root_folder.create_folder("my_folder") - my_file = root_folder.create_file("my_file.txt") - my_file.move("my_folder") - self.assertFalse(root_folder.has_child("my_file.txt")) - self.assertFalse(my_file.exists()) - my_folder.get_child("my_file.txt") - - -def test_moving_files_and_resource_objects(self): - root_folder = self.project.root - my_file = root_folder.create_file("my_file.txt") - old_hash = hash(my_file) - my_file.move("my_other_file.txt") - self.assertEqual(old_hash, hash(my_file)) - - -def test_file_encoding_reading(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = ( - b"# -*- coding: utf-8 -*-\n" - + br"#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" - ).decode("utf8") - file = open(sample_file.real_path, "wb") - file.write(contents.encode("utf-8")) - file.close() - self.assertEqual(contents, sample_file.read()) - - -def test_file_encoding_writing(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = ( - b"# -*- coding: utf-8 -*-\n" + br"\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" - ).decode("utf8") - sample_file.write(contents) - self.assertEqual(contents, sample_file.read()) - - -def test_using_utf8_when_writing_in_case_of_errors(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = br"\n\N{LATIN SMALL LETTER I WITH DIAERESIS}\n".decode("utf8") - sample_file.write(contents) - self.assertEqual(contents, sample_file.read()) - - -def test_encoding_declaration_in_the_second_line(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"\n# -*- coding: latin-1 -*-\n\xa9\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertEqual(contents, sample_file.read().encode("latin-1")) - - -def test_not_an_encoding_declaration(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"def my_method(self, encoding='latin-1'):\n var = {}\n\xc2\xa9\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertEqual(contents, sample_file.read().encode("utf-8")) - self.assertNotEqual(contents, sample_file.read().encode("latin-1")) - - -def test_read_bytes(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"\n# -*- coding: latin-1 -*-\n\xa9\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertEqual(contents, sample_file.read_bytes()) - - -def test_file_with_unix_line_ending(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"1\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertIsNone(sample_file.newlines) - self.assertEqual("1\n", sample_file.read()) - self.assertEqual("\n", sample_file.newlines) - - sample_file.write("1\n") - self.assertEqual(b"1\n", sample_file.read_bytes()) - - -def remove(self, path): - self._do(["rm", self._in_dir(path)]) - - -def test_file_with_dos_line_ending(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"1\r\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertIsNone(sample_file.newlines) - self.assertEqual("1\n", sample_file.read()) - self.assertEqual("\r\n", sample_file.newlines) - - sample_file.write("1\n") - self.assertEqual(b"1\r\n", sample_file.read_bytes()) - - -def test_file_with_mac_line_ending(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"1\r" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertIsNone(sample_file.newlines) - self.assertEqual("1\n", sample_file.read()) - self.assertEqual("\r", sample_file.newlines) - - sample_file.write("1\n") - self.assertEqual(b"1\r", sample_file.read_bytes()) - - -def test_file_binary(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"1\r\n" - file = open(sample_file.real_path, "wb") - file.write(contents) - file.close() - self.assertIsNone(sample_file.newlines) - self.assertEqual(b"1\r\n", sample_file.read_bytes()) - self.assertIsNone(sample_file.newlines) - - sample_file.write(b"1\nx\r") - self.assertEqual((b"1\nx\r"), sample_file.read_bytes()) - - -# TODO: Detecting utf-16 encoding -def xxx_test_using_utf16(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = b"# -*- coding: utf-16 -*-\n# This is a sample file ...\n" - file = open(sample_file.real_path, "w") - file.write(contents.encode("utf-16")) - file.close() - sample_file.write(contents) - self.assertEqual(contents, sample_file.read()) - - -# XXX: supporting utf_8_sig -def xxx_test_file_encoding_reading_for_notepad_styles(self): - sample_file = self.project.root.create_file("my_file.txt") - contents = "#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n" - file = open(sample_file.real_path, "w") - # file.write('\xef\xbb\xbf') - file.write(contents.encode("utf-8-sig")) - file.close() - self.assertEqual(contents, sample_file.read()) - - -def test_using_project_get_file(self): - myfile = self.project.get_file(self.sample_file) - self.assertTrue(myfile.exists()) - - -def test_using_file_create(self): - myfile = self.project.get_file("myfile.txt") - self.assertFalse(myfile.exists()) - myfile.create() - self.assertTrue(myfile.exists()) - self.assertFalse(myfile.is_folder()) - - -def test_using_folder_create(self): - myfolder = self.project.get_folder("myfolder") - self.assertFalse(myfolder.exists()) - myfolder.create() - self.assertTrue(myfolder.exists()) - self.assertTrue(myfolder.is_folder()) - - -def test_exception_when_creating_twice(self): - with self.assertRaises(RopeError): - myfile = self.project.get_file("myfile.txt") - myfile.create() - myfile.create() - - -def test_exception_when_parent_does_not_exist(self): - with self.assertRaises(ResourceNotFoundError): - myfile = self.project.get_file("myfolder/myfile.txt") - myfile.create() - - -def write(self, path, data): - # XXX: should we use ``git add``? - self.normal_actions.write(path, data) - - -def test_simple_path_to_resource(self): - myfile = self.project.root.create_file("myfile.txt") - self.assertEqual(myfile, path_to_resource(self.project, myfile.real_path)) - self.assertEqual( - myfile, path_to_resource(self.project, myfile.real_path, type="file") - ) - myfolder = self.project.root.create_folder("myfolder") - self.assertEqual(myfolder, path_to_resource(self.project, myfolder.real_path)) - self.assertEqual( - myfolder, path_to_resource(self.project, myfolder.real_path, type="folder") - ) - - -@testutils.skipNotPOSIX() -def test_ignoring_symlinks_inside_project(self): - project2 = testutils.sample_project(folder_name="sampleproject2") - mod = project2.root.create_file("mod.py") - try: - path = os.path.join(self.project.address, "linkedfile.txt") - os.symlink(mod.real_path, path) - files = self.project.root.get_files() - self.assertEqual(1, len(files)) - finally: - testutils.remove_project(project2) - - -def test_getting_empty_source_folders(self): - self.assertEqual([], self.project.get_source_folders()) - - -def test_root_source_folder(self): - self.project.root.create_file("sample.py") - source_folders = self.project.get_source_folders() - self.assertEqual(1, len(source_folders)) - self.assertTrue(self.project.root in source_folders) - - -def test_root_source_folder2(self): - self.project.root.create_file("mod1.py") - self.project.root.create_file("mod2.py") - source_folders = self.project.get_source_folders() - self.assertEqual(1, len(source_folders)) - self.assertTrue(self.project.root in source_folders) - - -def test_src_source_folder(self): - src = self.project.root.create_folder("src") - src.create_file("sample.py") - source_folders = self.project.get_source_folders() - self.assertEqual(1, len(source_folders)) - self.assertTrue(self.project.get_resource("src") in source_folders) - - -def test_packages(self): - src = self.project.root.create_folder("src") - pkg = src.create_folder("package") - pkg.create_file("__init__.py") - source_folders = self.project.get_source_folders() - self.assertEqual(1, len(source_folders)) - self.assertTrue(src in source_folders) - - -def test_multi_source_folders(self): - src = self.project.root.create_folder("src") - package = src.create_folder("package") - package.create_file("__init__.py") - test = self.project.root.create_folder("test") - test.create_file("alltests.py") - source_folders = self.project.get_source_folders() - self.assertEqual(2, len(source_folders)) - self.assertTrue(src in source_folders) - self.assertTrue(test in source_folders) - - -def test_multi_source_folders2(self): - testutils.create_module(self.project, "mod1") - src = self.project.root.create_folder("src") - package = testutils.create_package(self.project, "package", src) - testutils.create_module(self.project, "mod2", package) - source_folders = self.project.get_source_folders() - self.assertEqual(2, len(source_folders)) - self.assertTrue(self.project.root in source_folders and src in source_folders) - - - -class ResourceObserverTest(unittest.TestCase): - @others - -def read(self, path): - return self.normal_actions.read(path) - - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - - -def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - -def test_resource_change_observer(self): - sample_file = self.project.root.create_file("my_file.txt") - sample_file.write("a sample file version 1") - sample_observer = _SampleObserver() - self.project.add_observer(sample_observer) - sample_file.write("a sample file version 2") - self.assertEqual(1, sample_observer.change_count) - self.assertEqual(sample_file, sample_observer.last_changed) - - -def test_resource_change_observer_after_removal(self): - sample_file = self.project.root.create_file("my_file.txt") - sample_file.write("text") - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [sample_file]) - ) - sample_file.remove() - self.assertEqual(1, sample_observer.change_count) - self.assertEqual(sample_file, sample_observer.last_removed) - - -def test_resource_change_observer2(self): - sample_file = self.project.root.create_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(sample_observer) - self.project.remove_observer(sample_observer) - sample_file.write("a sample file version 2") - self.assertEqual(0, sample_observer.change_count) - - -def test_resource_change_observer_for_folders(self): - root_folder = self.project.root - my_folder = root_folder.create_folder("my_folder") - my_folder_observer = _SampleObserver() - root_folder_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(my_folder_observer, [my_folder]) - ) - self.project.add_observer( - FilteredResourceObserver(root_folder_observer, [root_folder]) - ) - my_file = my_folder.create_file("my_file.txt") - self.assertEqual(1, my_folder_observer.change_count) - my_file.move("another_file.txt") - self.assertEqual(2, my_folder_observer.change_count) - self.assertEqual(1, root_folder_observer.change_count) - self.project.get_resource("another_file.txt").remove() - self.assertEqual(2, my_folder_observer.change_count) - self.assertEqual(2, root_folder_observer.change_count) - - -def test_resource_change_observer_after_moving(self): - sample_file = self.project.root.create_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(sample_observer) - sample_file.move("new_file.txt") - self.assertEqual(1, sample_observer.change_count) - self.assertEqual( - (sample_file, self.project.get_resource("new_file.txt")), - sample_observer.last_moved, - ) - - -def test_revalidating_files(self): - root = self.project.root - my_file = root.create_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) - os.remove(my_file.real_path) - self.project.validate(root) - self.assertEqual(my_file, sample_observer.last_removed) - self.assertEqual(1, sample_observer.change_count) - - -def test_revalidating_files_and_no_changes2(self): - root = self.project.root - my_file = root.create_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) - self.project.validate(root) - self.assertEqual(None, sample_observer.last_moved) - self.assertEqual(0, sample_observer.change_count) - - -def _do(self, args): - _execute(["git"] + args, cwd=self.root) - - -def test_removing_and_adding_resources_to_filtered_observer(self): - my_file = self.project.root.create_file("my_file.txt") - sample_observer = _SampleObserver() - filtered_observer = FilteredResourceObserver(sample_observer) - self.project.add_observer(filtered_observer) - my_file.write("1") - self.assertEqual(0, sample_observer.change_count) - filtered_observer.add_resource(my_file) - my_file.write("2") - self.assertEqual(1, sample_observer.change_count) - filtered_observer.remove_resource(my_file) - my_file.write("3") - self.assertEqual(1, sample_observer.change_count) - - -def test_validation_and_changing_files(self): - my_file = self.project.root.create_file("my_file.txt") - sample_observer = _SampleObserver() - timekeeper = _MockChangeIndicator() - filtered_observer = FilteredResourceObserver( - sample_observer, [my_file], timekeeper=timekeeper - ) - self.project.add_observer(filtered_observer) - self._write_file(my_file.real_path) - timekeeper.set_indicator(my_file, 1) - self.project.validate(self.project.root) - self.assertEqual(1, sample_observer.change_count) - - -def test_validation_and_changing_files2(self): - my_file = self.project.root.create_file("my_file.txt") - sample_observer = _SampleObserver() - timekeeper = _MockChangeIndicator() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [my_file], timekeeper=timekeeper) - ) - timekeeper.set_indicator(my_file, 1) - my_file.write("hey") - self.assertEqual(1, sample_observer.change_count) - self.project.validate(self.project.root) - self.assertEqual(1, sample_observer.change_count) - - -def test_not_reporting_multiple_changes_to_folders(self): - root = self.project.root - file1 = root.create_file("file1.txt") - file2 = root.create_file("file2.txt") - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [root, file1, file2]) - ) - os.remove(file1.real_path) - os.remove(file2.real_path) - self.assertEqual(0, sample_observer.change_count) - self.project.validate(self.project.root) - self.assertEqual(3, sample_observer.change_count) - - -def _write_file(self, path): - my_file = open(path, "w") - my_file.write("\n") - my_file.close() - - -def test_moving_and_being_interested_about_a_folder_and_a_child(self): - my_folder = self.project.root.create_folder("my_folder") - my_file = my_folder.create_file("my_file.txt") - sample_observer = _SampleObserver() - filtered_observer = FilteredResourceObserver( - sample_observer, [my_folder, my_file] - ) - self.project.add_observer(filtered_observer) - my_folder.move("new_folder") - self.assertEqual(2, sample_observer.change_count) - - -def test_contains_for_folders(self): - folder1 = self.project.root.create_folder("folder") - folder2 = self.project.root.create_folder("folder2") - self.assertFalse(folder1.contains(folder2)) - - -def test_validating_when_created(self): - root = self.project.root - my_file = self.project.get_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) - open(my_file.real_path, "w").close() - self.project.validate(root) - self.assertEqual(my_file, sample_observer.last_created) - self.assertEqual(1, sample_observer.change_count) - - -def test_validating_twice_when_created(self): - root = self.project.root - my_file = self.project.get_file("my_file.txt") - sample_observer = _SampleObserver() - self.project.add_observer(FilteredResourceObserver(sample_observer, [my_file])) - open(my_file.real_path, "w").close() - self.project.validate(root) - self.project.validate(root) - self.assertEqual(my_file, sample_observer.last_created) - self.assertEqual(1, sample_observer.change_count) - - -def _in_dir(self, path): - if path.startswith(self.root): - return path[len(self.root) + 1 :] - return self.root - - - -def test_clear_observered_resources_for_filtered_observers(self): - sample_file = self.project.root.create_file("myfile.txt") - sample_observer = _SampleObserver() - filtered = FilteredResourceObserver(sample_observer) - self.project.add_observer(filtered) - filtered.add_resource(sample_file) - filtered.clear_resources() - sample_file.write("1") - self.assertEqual(0, sample_observer.change_count) - - - -class _MockChangeIndicator: - @others - -def __init__(self): - self.times = {} - - -def set_indicator(self, resource, time): - self.times[resource] = time - - -def get_indicator(self, resource): - return self.times.get(resource, 0) - - - -class _SampleObserver: - @others - -def __init__(self): - self.change_count = 0 - self.last_changed = None - self.last_moved = None - self.last_created = None - self.last_removed = None - - -def resource_changed(self, resource): - self.last_changed = resource - self.change_count += 1 - - -def resource_moved(self, resource, new_resource): - self.last_moved = (resource, new_resource) - self.change_count += 1 - - -class DarcsCommands: - @others - -def resource_created(self, resource): - self.last_created = resource - self.change_count += 1 - - -def resource_removed(self, resource): - self.last_removed = resource - self.change_count += 1 - - - -class OutOfProjectTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.test_directory = "temp_test_directory" - testutils.remove_recursively(self.test_directory) - os.mkdir(self.test_directory) - self.project = testutils.sample_project() - self.no_project = NoProject() - - -def tearDown(self): - testutils.remove_project(self.project) - testutils.remove_recursively(self.test_directory) - super().tearDown() - - -def test_simple_out_of_project_file(self): - sample_file_path = os.path.join(self.test_directory, "sample.txt") - sample_file = open(sample_file_path, "w") - sample_file.write("sample content\n") - sample_file.close() - sample_resource = self.no_project.get_resource(sample_file_path) - self.assertEqual("sample content\n", sample_resource.read()) - - -def test_simple_out_of_project_folder(self): - sample_folder_path = os.path.join(self.test_directory, "sample_folder") - os.mkdir(sample_folder_path) - sample_folder = self.no_project.get_resource(sample_folder_path) - self.assertEqual([], sample_folder.get_children()) - - sample_file_path = os.path.join(sample_folder_path, "sample.txt") - open(sample_file_path, "w").close() - sample_resource = self.no_project.get_resource(sample_file_path) - self.assertEqual(sample_resource, sample_folder.get_children()[0]) - - -def test_using_absolute_path(self): - sample_file_path = os.path.join(self.test_directory, "sample.txt") - open(sample_file_path, "w").close() - normal_sample_resource = self.no_project.get_resource(sample_file_path) - absolute_sample_resource = self.no_project.get_resource( - os.path.abspath(sample_file_path) - ) - self.assertEqual(normal_sample_resource, absolute_sample_resource) - - -def test_folder_get_child(self): - sample_folder_path = os.path.join(self.test_directory, "sample_folder") - os.mkdir(sample_folder_path) - sample_folder = self.no_project.get_resource(sample_folder_path) - self.assertEqual([], sample_folder.get_children()) - - sample_file_path = os.path.join(sample_folder_path, "sample.txt") - open(sample_file_path, "w").close() - sample_resource = self.no_project.get_resource(sample_file_path) - self.assertTrue(sample_folder.has_child("sample.txt")) - self.assertFalse(sample_folder.has_child("doesnothave.txt")) - self.assertEqual(sample_resource, sample_folder.get_child("sample.txt")) - - -def test_out_of_project_files_and_path_to_resource(self): - sample_file_path = os.path.join(self.test_directory, "sample.txt") - sample_file = open(sample_file_path, "w") - sample_file.write("sample content\n") - sample_file.close() - sample_resource = self.no_project.get_resource(sample_file_path) - self.assertEqual( - sample_resource, path_to_resource(self.project, sample_file_path) - ) - - - -def consume(self, token, skip_comment=True): - try: - while True: - new_offset = self.source.index(token, self.offset) - if self._good_token(token, new_offset) or not skip_comment: - break - else: - self._skip_comment() - except (ValueError, TypeError) as e: - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) - self.offset = new_offset + len(token) - return (new_offset, self.offset) - - -def __init__(self, root): - self.root = root - self.normal_actions = FileSystemCommands() - - -class _MockFSCommands: - @others - -def __init__(self): - self.log = "" - self.fscommands = FileSystemCommands() - - -def create_file(self, path): - self.log += "create_file " - self.fscommands.create_file(path) - - -def create_folder(self, path): - self.log += "create_folder " - self.fscommands.create_folder(path) - - -def move(self, path, new_location): - self.log += "move " - self.fscommands.move(path, new_location) - - -def remove(self, path): - self.log += "remove " - self.fscommands.remove(path) - - -def read(self, path): - self.log += "read " - return self.fscommands.read(path) - - - -class _DeprecatedFSCommands: - @others - -def __init__(self): - self.log = "" - self.fscommands = FileSystemCommands() - - -def create_file(self, path): - self.log += "create_file " - self.fscommands.create_file(path) - - -def create_file(self, path): - self.normal_actions.create_file(path) - self._do(["add", path]) - - -def create_folder(self, path): - self.log += "create_folder " - self.fscommands.create_folder(path) - - -def move(self, path, new_location): - self.log += "move " - self.fscommands.move(path, new_location) - - -def remove(self, path): - self.log += "remove " - self.fscommands.remove(path) - - - -class RopeFolderTest(unittest.TestCase): - @others - -def setUp(self): - super().setUp() - self.project = None - - -def tearDown(self): - if self.project: - testutils.remove_project(self.project) - super().tearDown() - - -def test_none_project_rope_folder(self): - self.project = testutils.sample_project(ropefolder=None) - self.assertTrue(self.project.ropefolder is None) - - -def test_getting_project_rope_folder(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - self.assertTrue(self.project.ropefolder.exists()) - self.assertTrue(".ropeproject", self.project.ropefolder.path) - - -def test_setting_ignored_resources(self): - self.project = testutils.sample_project(ignored_resources=["myfile.txt"]) - myfile = self.project.get_file("myfile.txt") - file2 = self.project.get_file("file2.txt") - self.assertTrue(self.project.is_ignored(myfile)) - self.assertFalse(self.project.is_ignored(file2)) - - -def test_ignored_folders(self): - self.project = testutils.sample_project(ignored_resources=["myfolder"]) - myfolder = self.project.root.create_folder("myfolder") - self.assertTrue(self.project.is_ignored(myfolder)) - myfile = myfolder.create_file("myfile.txt") - self.assertTrue(self.project.is_ignored(myfile)) - - -def create_folder(self, path): - self.normal_actions.create_folder(path) - self._do(["add", path]) - - -def test_ignored_resources_and_get_files(self): - self.project = testutils.sample_project( - ignored_resources=["myfile.txt"], ropefolder=None - ) - myfile = self.project.get_file("myfile.txt") - self.assertEqual(0, len(self.project.get_files())) - myfile.create() - self.assertEqual(0, len(self.project.get_files())) - - -def test_setting_ignored_resources_patterns(self): - self.project = testutils.sample_project(ignored_resources=["m?file.*"]) - myfile = self.project.get_file("myfile.txt") - file2 = self.project.get_file("file2.txt") - self.assertTrue(self.project.is_ignored(myfile)) - self.assertFalse(self.project.is_ignored(file2)) - - -def test_star_should_not_include_slashes(self): - self.project = testutils.sample_project(ignored_resources=["f*.txt"]) - folder = self.project.root.create_folder("folder") - file1 = folder.create_file("myfile.txt") - file2 = folder.create_file("file2.txt") - self.assertFalse(self.project.is_ignored(file1)) - self.assertTrue(self.project.is_ignored(file2)) - - -def test_normal_fscommands(self): - fscommands = _MockFSCommands() - self.project = testutils.sample_project(fscommands=fscommands) - myfile = self.project.get_file("myfile.txt") - myfile.create() - self.assertTrue("create_file ", fscommands.log) - - -def test_fscommands_and_ignored_resources(self): - fscommands = _MockFSCommands() - self.project = testutils.sample_project( - fscommands=fscommands, ignored_resources=["myfile.txt"], ropefolder=None - ) - myfile = self.project.get_file("myfile.txt") - myfile.create() - self.assertEqual("", fscommands.log) - - -def test_deprecated_fscommands(self): - fscommands = _DeprecatedFSCommands() - self.project = testutils.sample_project(fscommands=fscommands) - myfile = self.project.get_file("myfile.txt") - myfile.create() - self.assertTrue("create_file ", fscommands.log) - - -def test_ignored_resources_and_prefixes(self): - self.project = testutils.sample_project(ignored_resources=[".hg"]) - myfile = self.project.root.create_file(".hgignore") - self.assertFalse(self.project.is_ignored(myfile)) - - -def test_loading_config_dot_py(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - config = self.project.get_file(".ropeproject/config.py") - if not config.exists(): - config.create() - config.write(dedent("""\ - def set_prefs(prefs): - prefs["ignored_resources"] = ["myfile.txt"] - def project_opened(project): - project.root.create_file("loaded") - """)) - self.project.close() - self.project = Project(self.project.address, ropefolder=".ropeproject") - self.assertTrue(self.project.get_file("loaded").exists()) - myfile = self.project.get_file("myfile.txt") - self.assertTrue(self.project.is_ignored(myfile)) - - -def test_loading_pyproject(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - config = self.project.get_file("pyproject.toml") - if not config.exists(): - config.create() - config.write(dedent("""\ - [tool.rope] - ignored_resources=["pyproject.py"] - """)) - self.project.close() - self.project = Project(self.project.address, ropefolder=".ropeproject") - myfile = self.project.get_file("pyproject.py") - self.assertTrue(self.project.is_ignored(myfile)) - - -def move(self, path, new_location): - self._do(["mv", path, new_location]) - - -def test_loading_pyproject_empty_file(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - config = self.project.get_file("pyproject.toml") - if not config.exists(): - config.create() - config.write("") - self.project.close() - self.project = Project(self.project.address, ropefolder=".ropeproject") - myfile = self.project.get_file("pyproject.py") - self.assertFalse(self.project.is_ignored(myfile)) - - -def test_loading_pyproject_no_tool_section(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - config = self.project.get_file("pyproject.toml") - if not config.exists(): - config.create() - config.write(dedent("""\ - [project] - name = 'testproject' - """)) - self.project.close() - self.project = Project(self.project.address, ropefolder=".ropeproject") - myfile = self.project.get_file("pyproject.py") - self.assertFalse(self.project.is_ignored(myfile)) - - -def test_loading_pyproject_no_tool_rope_section(self): - self.project = testutils.sample_project(ropefolder=".ropeproject") - config = self.project.get_file("pyproject.toml") - if not config.exists(): - config.create() - config.write(dedent("""\ - [tool.anothertool] - name = 'testproject' - """)) - self.project.close() - self.project = Project(self.project.address, ropefolder=".ropeproject") - myfile = self.project.get_file("pyproject.py") - self.assertFalse(self.project.is_ignored(myfile)) - - -def test_compressed_history(self): - self.project = testutils.sample_project(compress_history=True) - mod = testutils.create_module(self.project, "mod") - mod.write("") - - -def test_compressed_objectdb(self): - self.project = testutils.sample_project(compress_objectdb=True) - mod = testutils.create_module(self.project, "mod") - self.project.pycore.analyze_module(mod) - - -def test_nested_dot_ropeproject_folder(self): - self.project = testutils.sample_project(ropefolder=".f1/f2") - ropefolder = self.project.ropefolder - self.assertEqual(".f1/f2", ropefolder.path) - self.assertTrue(ropefolder.exists()) - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,7 @@ - def test_revalidating_folders(self): - root = self.project.root - my_folder = root.create_folder("myfolder") -- my_file = my_folder.create_file("myfile.txt") # noqa -+ my_file = my_folder.create_file("myfile.txt") - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [my_folder]) -@@ -10,4 +10,5 @@ - self.project.validate(root) - self.assertEqual(my_folder, sample_observer.last_removed) - self.assertEqual(1, sample_observer.change_count) -+ self.assertTrue(my_file is not None) - -@language python - -def test_revalidating_folders(self): - root = self.project.root - my_folder = root.create_folder("myfolder") - my_file = my_folder.create_file("myfile.txt") # noqa - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [my_folder]) - ) - testutils.remove_recursively(my_folder.real_path) - self.project.validate(root) - self.assertEqual(my_folder, sample_observer.last_removed) - self.assertEqual(1, sample_observer.change_count) - - -def test_revalidating_folders(self): - root = self.project.root - my_folder = root.create_folder("myfolder") - my_file = my_folder.create_file("myfile.txt") # noqa - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [my_folder]) - ) - testutils.remove_recursively(my_folder.real_path) - self.project.validate(root) - self.assertEqual(my_folder, sample_observer.last_removed) - self.assertEqual(1, sample_observer.change_count) - - -def remove(self, path): - self.normal_actions.remove(path) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def test_changes_and_adding_resources(self): -- root = self.project.root # noqa -+ # root = self.project.root - file1 = self.project.get_file("file1.txt") - file2 = self.project.get_file("file2.txt") - file1.create() -@language python - -def test_changes_and_adding_resources(self): - root = self.project.root # noqa - file1 = self.project.get_file("file1.txt") - file2 = self.project.get_file("file2.txt") - file1.create() - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [file1, file2]) - ) - file1.move(file2.path) - self.assertEqual(2, sample_observer.change_count) - self.assertEqual(file2, sample_observer.last_created) - self.assertEqual((file1, file2), sample_observer.last_moved) - - -def test_changes_and_adding_resources(self): - root = self.project.root # noqa - file1 = self.project.get_file("file1.txt") - file2 = self.project.get_file("file2.txt") - file1.create() - sample_observer = _SampleObserver() - self.project.add_observer( - FilteredResourceObserver(sample_observer, [file1, file2]) - ) - file1.move(file2.path) - self.assertEqual(2, sample_observer.change_count) - self.assertEqual(file2, sample_observer.last_created) - self.assertEqual((file1, file2), sample_observer.last_moved) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ - def test_validating_get_files_list(self): -- root = self.project.root # noqa -+ # root = self.project.root - self.assertEqual(0, len(self.project.get_files())) - file = open(os.path.join(self.project.address, "myfile.txt"), "w") - file.close() -@language python - -def test_validating_get_files_list(self): - root = self.project.root # noqa - self.assertEqual(0, len(self.project.get_files())) - file = open(os.path.join(self.project.address, "myfile.txt"), "w") - file.close() - self.project.validate() - self.assertEqual(1, len(self.project.get_files())) - - -def test_validating_get_files_list(self): - root = self.project.root # noqa - self.assertEqual(0, len(self.project.get_files())) - file = open(os.path.join(self.project.address, "myfile.txt"), "w") - file.close() - self.project.validate() - self.assertEqual(1, len(self.project.get_files())) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,6 +2,7 @@ - self.project = testutils.sample_project( - ignored_resources=["myfile.txt"], ropefolder=None - ) -- myfile = self.project.root.create_file("myfile.txt") # noqa -+ myfile = self.project.root.create_file("myfile.txt") - self.assertEqual(0, len(self.project.get_files())) -+ self.assertTrue(myfile is not None) - -@language python - -def test_ignored_resources_and_get_files2(self): - self.project = testutils.sample_project( - ignored_resources=["myfile.txt"], ropefolder=None - ) - myfile = self.project.root.create_file("myfile.txt") # noqa - self.assertEqual(0, len(self.project.get_files())) - - -def test_ignored_resources_and_get_files2(self): - self.project = testutils.sample_project( - ignored_resources=["myfile.txt"], ropefolder=None - ) - myfile = self.project.root.create_file("myfile.txt") # noqa - self.assertEqual(0, len(self.project.get_files())) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,5 +4,6 @@ - ) - mod = testutils.create_module(self.project, "mod") - mod.write("xyz print") -- pymod = self.project.get_pymodule(mod) # noqa -+ pymod = self.project.get_pymodule(mod) -+ self.assertTrue(pymod is not None) - -@language python - -def read(self, path): - return self.normal_actions.read(path) - - -def test_ignoring_syntax_errors(self): - self.project = testutils.sample_project( - ropefolder=None, ignore_syntax_errors=True - ) - mod = testutils.create_module(self.project, "mod") - mod.write("xyz print") - pymod = self.project.get_pymodule(mod) # noqa - - -def test_ignoring_syntax_errors(self): - self.project = testutils.sample_project( - ropefolder=None, ignore_syntax_errors=True - ) - mod = testutils.create_module(self.project, "mod") - mod.write("xyz print") - pymod = self.project.get_pymodule(mod) # noqa - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -31,18 +31,19 @@ - - def test_nested_modules(self): - pkg = testutils.create_package(self.project, "pkg") -- mod = testutils.create_module(self.project, "mod", pkg) # noqa -+ mod = testutils.create_module(self.project, "mod", pkg) - package = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), package.get_type()) - self.assertEqual(1, len(package.get_attributes())) - module = package["mod"].get_object() - self.assertEqual(get_base_type("Module"), module.get_type()) -- -+ self.assertTrue(mod is not None) - def test_package(self): - pkg = testutils.create_package(self.project, "pkg") -- mod = testutils.create_module(self.project, "mod", pkg) # noqa -+ mod = testutils.create_module(self.project, "mod", pkg) - result = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), result.type) -+ self.assertTrue(mod is not None) - - def test_simple_class(self): - mod = testutils.create_module(self.project, "mod") -@@ -101,7 +102,8 @@ - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["SampleClass"].get_object() -- var = sample_class["var"] # noqa -+ var = sample_class["var"] -+ self.assertTrue(var is not None) - - def test_class_attributes_set_in_init(self): - mod = testutils.create_module(self.project, "mod") -@@ -112,7 +114,8 @@ - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["C"].get_object() -- var = sample_class["var"] # noqa -+ var = sample_class["var"] -+ self.assertTrue(var is not None) - - def test_class_attributes_set_in_init_overwriting_a_defined(self): - mod = testutils.create_module(self.project, "mod") -@@ -174,7 +177,8 @@ - - def test_get_string_module_with_extra_spaces(self): - code = "a = 10\n " -- mod = libutils.get_string_module(self.project, code) # noqa -+ mod = libutils.get_string_module(self.project, code) -+ self.assertTrue(mod is not None) - - def test_parameter_info_for_functions(self): - code = dedent("""\ -@@ -264,9 +268,10 @@ - self.assertEqual(self.project.get_resource("module.py"), new_module) - - def test_packaged_module_creation(self): -- package = self.project.root.create_folder("package") # noqa -+ package = self.project.root.create_folder("package") - new_module = testutils.create_module(self.project, "package.module") - self.assertEqual(self.project.get_resource("package/module.py"), new_module) -+ self.assertTrue(package is not None) - - def test_packaged_module_creation_with_nested_src(self): - src = self.project.root.create_folder("src") -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,9 +1,9 @@ - def test_nested_modules(self): - pkg = testutils.create_package(self.project, "pkg") -- mod = testutils.create_module(self.project, "mod", pkg) # noqa -+ mod = testutils.create_module(self.project, "mod", pkg) - package = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), package.get_type()) - self.assertEqual(1, len(package.get_attributes())) - module = package["mod"].get_object() - self.assertEqual(get_base_type("Module"), module.get_type()) -- -+ self.assertTrue(mod is not None) -@language python - -def test_nested_modules(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) # noqa - package = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), package.get_type()) - self.assertEqual(1, len(package.get_attributes())) - module = package["mod"].get_object() - self.assertEqual(get_base_type("Module"), module.get_type()) - - -def test_nested_modules(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) - package = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), package.get_type()) - self.assertEqual(1, len(package.get_attributes())) - module = package["mod"].get_object() - self.assertEqual(get_base_type("Module"), module.get_type()) - self.assertTrue(mod is not None) - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,6 +1,7 @@ - def test_package(self): - pkg = testutils.create_package(self.project, "pkg") -- mod = testutils.create_module(self.project, "mod", pkg) # noqa -+ mod = testutils.create_module(self.project, "mod", pkg) - result = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), result.type) -+ self.assertTrue(mod is not None) - -@language python - -def test_package(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) # noqa - result = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), result.type) - - -def test_package(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) - result = self.project.get_module("pkg") - self.assertEqual(get_base_type("Module"), result.type) - self.assertTrue(mod is not None) - - -def write(self, path, data): - self.normal_actions.write(path, data) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -6,5 +6,6 @@ - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["SampleClass"].get_object() -- var = sample_class["var"] # noqa -+ var = sample_class["var"] -+ self.assertTrue(var is not None) - -@language python - -def test_class_variables(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - class SampleClass(object): - var = 10 - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["SampleClass"].get_object() - var = sample_class["var"] # noqa - - -def test_class_variables(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - class SampleClass(object): - var = 10 - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["SampleClass"].get_object() - var = sample_class["var"] - self.assertTrue(var is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -7,5 +7,6 @@ - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["C"].get_object() -- var = sample_class["var"] # noqa -+ var = sample_class["var"] -+ self.assertTrue(var is not None) - -@language python - -def test_class_attributes_set_in_init(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - class C(object): - def __init__(self): - self.var = 20 - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["C"].get_object() - var = sample_class["var"] # noqa - - -def test_class_attributes_set_in_init(self): - mod = testutils.create_module(self.project, "mod") - mod.write(dedent("""\ - class C(object): - def __init__(self): - self.var = 20 - """)) - mod_element = self.project.get_module("mod") - sample_class = mod_element["C"].get_object() - var = sample_class["var"] - self.assertTrue(var is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,4 +1,5 @@ - def test_get_string_module_with_extra_spaces(self): - code = "a = 10\n " -- mod = libutils.get_string_module(self.project, code) # noqa -+ mod = libutils.get_string_module(self.project, code) -+ self.assertTrue(mod is not None) - -@language python - -def test_get_string_module_with_extra_spaces(self): - code = "a = 10\n " - mod = libutils.get_string_module(self.project, code) # noqa - - -def test_get_string_module_with_extra_spaces(self): - code = "a = 10\n " - mod = libutils.get_string_module(self.project, code) - self.assertTrue(mod is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,6 @@ - def test_packaged_module_creation(self): -- package = self.project.root.create_folder("package") # noqa -+ package = self.project.root.create_folder("package") - new_module = testutils.create_module(self.project, "package.module") - self.assertEqual(self.project.get_resource("package/module.py"), new_module) -+ self.assertTrue(package is not None) - -@language python - -def _do(self, args): - _execute(["darcs"] + args, cwd=self.root) - - - -def test_packaged_module_creation(self): - package = self.project.root.create_folder("package") # noqa - new_module = testutils.create_module(self.project, "package.module") - self.assertEqual(self.project.get_resource("package/module.py"), new_module) - - -def test_packaged_module_creation(self): - package = self.project.root.create_folder("package") - new_module = testutils.create_module(self.project, "package.module") - self.assertEqual(self.project.get_resource("package/module.py"), new_module) - self.assertTrue(package is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -53,6 +53,7 @@ - get_base_type("Type"), - sample_func_scope["SampleClass"].get_object().get_type(), - ) -+ self.assertTrue(sample_func_scope is not None) - - def test_list_comprehension_scope_inside_assignment(self): - code = "a_var = [b_var + d_var for b_var, c_var in e_var]\n" -@@ -468,12 +469,13 @@ - """) - scope = libutils.get_string_scope(self.project, code) - -- a_scope = scope["A"].get_object().get_scope() # noqa -+ a_scope = scope["A"].get_object().get_scope() - b_scope = scope["B"].get_object().get_scope() - self.assertTrue("a" in b_scope.get_names()) - self.assertTrue("b" in b_scope.get_names()) - self.assertTrue("a" not in b_scope.get_defined_names()) - self.assertTrue("b" in b_scope.get_defined_names()) -+ self.assertTrue(a_scope is not None) - - def test_getting_defined_names_for_modules(self): - code = dedent("""\ -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -12,4 +12,5 @@ - get_base_type("Type"), - sample_func_scope["SampleClass"].get_object().get_type(), - ) -+ self.assertTrue(sample_func_scope is not None) - -@language python - -def test_classes_inside_function_scopes(self): - code = dedent("""\ - def sample_func(): - class SampleClass(object): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(1, len(scope.get_scopes())) - sample_func_scope = scope.get_scopes()[0] - self.assertEqual( - get_base_type("Type"), - sample_func_scope["SampleClass"].get_object().get_type(), - ) - - -def test_classes_inside_function_scopes(self): - code = dedent("""\ - def sample_func(): - class SampleClass(object): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - self.assertEqual(1, len(scope.get_scopes())) - sample_func_scope = scope.get_scopes()[0] - self.assertEqual( - get_base_type("Type"), - sample_func_scope["SampleClass"].get_object().get_type(), - ) - self.assertTrue(sample_func_scope is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -9,10 +9,11 @@ - """) - scope = libutils.get_string_scope(self.project, code) - -- a_scope = scope["A"].get_object().get_scope() # noqa -+ a_scope = scope["A"].get_object().get_scope() - b_scope = scope["B"].get_object().get_scope() - self.assertTrue("a" in b_scope.get_names()) - self.assertTrue("b" in b_scope.get_names()) - self.assertTrue("a" not in b_scope.get_defined_names()) - self.assertTrue("b" in b_scope.get_defined_names()) -+ self.assertTrue(a_scope is not None) - -@language python - -def test_getting_defined_names_for_classes(self): - code = dedent("""\ - class A(object): - def a(self): - pass - class B(A): - def b(self): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - a_scope = scope["A"].get_object().get_scope() # noqa - b_scope = scope["B"].get_object().get_scope() - self.assertTrue("a" in b_scope.get_names()) - self.assertTrue("b" in b_scope.get_names()) - self.assertTrue("a" not in b_scope.get_defined_names()) - self.assertTrue("b" in b_scope.get_defined_names()) - - -def test_getting_defined_names_for_classes(self): - code = dedent("""\ - class A(object): - def a(self): - pass - class B(A): - def b(self): - pass - """) - scope = libutils.get_string_scope(self.project, code) - - a_scope = scope["A"].get_object().get_scope() - b_scope = scope["B"].get_object().get_scope() - self.assertTrue("a" in b_scope.get_names()) - self.assertTrue("b" in b_scope.get_names()) - self.assertTrue("a" not in b_scope.get_defined_names()) - self.assertTrue("b" in b_scope.get_defined_names()) - self.assertTrue(a_scope is not None) - - -def _execute(args, cwd=None): - process = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE) - process.wait() - return process.returncode - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -4,23 +4,12 @@ - - import rope.base.taskhandle - import rope.refactor.introduce_parameter --import ropetest.refactor.extracttest --import ropetest.refactor.importutilstest --import ropetest.refactor.inlinetest --import ropetest.refactor.movetest --import ropetest.refactor.multiprojecttest --import ropetest.refactor.patchedasttest --import ropetest.refactor.renametest --import ropetest.refactor.restructuretest --import ropetest.refactor.suitestest --import ropetest.refactor.usefunctiontest - from rope.base.exceptions import RefactoringError, InterruptedTaskError - from rope.refactor.encapsulate_field import EncapsulateField - from rope.refactor.introduce_factory import IntroduceFactory - from rope.refactor.localtofield import LocalToField - from rope.refactor.method_object import MethodObject - from ropetest import testutils --from ropetest.refactor import change_signature_test, similarfindertest - - - class MethodObjectTest(unittest.TestCase): -@@ -1093,8 +1082,9 @@ - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) -- jobs = handle.create_jobset() # noqa -+ jobs = handle.create_jobset() - self.assertEqual(1, observer.called) -+ self.assertTrue(jobs is not None) - - def test_calling_the_observer_when_starting_and_finishing_jobs(self): - handle = rope.base.taskhandle.TaskHandle() -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -5,23 +5,12 @@ - - import rope.base.taskhandle - import rope.refactor.introduce_parameter --import ropetest.refactor.extracttest --import ropetest.refactor.importutilstest --import ropetest.refactor.inlinetest --import ropetest.refactor.movetest --import ropetest.refactor.multiprojecttest --import ropetest.refactor.patchedasttest --import ropetest.refactor.renametest --import ropetest.refactor.restructuretest --import ropetest.refactor.suitestest --import ropetest.refactor.usefunctiontest - from rope.base.exceptions import RefactoringError, InterruptedTaskError - from rope.refactor.encapsulate_field import EncapsulateField - from rope.refactor.introduce_factory import IntroduceFactory - from rope.refactor.localtofield import LocalToField - from rope.refactor.method_object import MethodObject - from ropetest import testutils --from ropetest.refactor import change_signature_test, similarfindertest - - - class MethodObjectTest(unittest.TestCase): -@@ -1094,8 +1083,9 @@ - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) -- jobs = handle.create_jobset() # noqa -+ jobs = handle.create_jobset() - self.assertEqual(1, observer.called) -+ self.assertTrue(jobs is not None) - - def test_calling_the_observer_when_starting_and_finishing_jobs(self): - handle = rope.base.taskhandle.TaskHandle() -@language python - -@path C:/Repos/ekr-rope/rope/ -from textwrap import dedent - -import unittest - -import rope.base.taskhandle -import rope.refactor.introduce_parameter -import ropetest.refactor.extracttest -import ropetest.refactor.importutilstest -import ropetest.refactor.inlinetest -import ropetest.refactor.movetest -import ropetest.refactor.multiprojecttest -import ropetest.refactor.patchedasttest -import ropetest.refactor.renametest -import ropetest.refactor.restructuretest -import ropetest.refactor.suitestest -import ropetest.refactor.usefunctiontest -from rope.base.exceptions import RefactoringError, InterruptedTaskError -from rope.refactor.encapsulate_field import EncapsulateField -from rope.refactor.introduce_factory import IntroduceFactory -from rope.refactor.localtofield import LocalToField -from rope.refactor.method_object import MethodObject -from ropetest import testutils -from ropetest.refactor import change_signature_test, similarfindertest - - -class MethodObjectTest(unittest.TestCase): - def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - def test_empty_method(self): - code = dedent("""\ - def func(): - pass - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __call__(self): - pass - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_trivial_return(self): - code = dedent("""\ - def func(): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_multi_line_header(self): - code = dedent("""\ - def func( - ): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_a_single_parameter(self): - code = dedent("""\ - def func(param): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, param): - self.param = param - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_self_parameter(self): - code = dedent("""\ - def func(self): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, host): - self.self = host - - def __call__(self): - return 1 - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_simple_using_passed_parameters(self): - code = dedent("""\ - def func(param): - return param - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, param): - self.param = param - - def __call__(self): - return self.param - """) - self.assertEqual( - expected, - replacer.get_new_class("_New"), - ) - - def test_self_keywords_and_args_parameters(self): - code = dedent("""\ - def func(arg, *args, **kwds): - result = arg + args[0] + kwds[arg] - return result - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - expected = dedent("""\ - class _New(object): - - def __init__(self, arg, args, kwds): - self.arg = arg - self.args = args - self.kwds = kwds - - def __call__(self): - result = self.arg + self.args[0] + self.kwds[self.arg] - return result - """) - self.assertEqual(expected, replacer.get_new_class("_New")) - - def test_performing_on_not_a_function(self): - code = dedent("""\ - my_var = 10 - """) - self.mod.write(code) - with self.assertRaises(RefactoringError): - MethodObject(self.project, self.mod, code.index("my_var")) - - def test_changing_the_module(self): - code = dedent("""\ - def func(): - return 1 - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - self.project.do(replacer.get_changes("_New")) - expected = dedent("""\ - def func(): - return _New()() - - - class _New(object): - - def __call__(self): - return 1 - """) - self.assertEqual(expected, self.mod.read()) - - def test_changing_the_module_and_class_methods(self): - code = dedent("""\ - class C(object): - - def a_func(self): - return 1 - - def another_func(self): - pass - """) - self.mod.write(code) - replacer = MethodObject(self.project, self.mod, code.index("func")) - self.project.do(replacer.get_changes("_New")) - expected = dedent("""\ - class C(object): - - def a_func(self): - return _New(self)() - - def another_func(self): - pass - - - class _New(object): - - def __init__(self, host): - self.self = host - - def __call__(self): - return 1 - """) - self.assertEqual(expected, self.mod.read()) - - -class IntroduceFactoryTest(unittest.TestCase): - def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - - def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - def _introduce_factory(self, resource, offset, *args, **kwds): - factory_introducer = IntroduceFactory(self.project, resource, offset) - changes = factory_introducer.get_changes(*args, **kwds) - self.project.do(changes) - - def test_adding_the_method(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - def test_changing_occurrences_in_the_main_module(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - a_var = AClass()""") - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - a_var = AClass.create()""") - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - def test_changing_occurrences_with_arguments(self): - code = dedent("""\ - class AClass(object): - def __init__(self, arg): - pass - a_var = AClass(10) - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - def __init__(self, arg): - pass - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - a_var = AClass.create(10) - """) - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - def test_changing_occurrences_in_other_modules(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("import mod1\na_var = mod1.AClass()\n") - self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = dedent("""\ - import mod1 - a_var = mod1.AClass.create() - """) - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - def test_raising_exception_for_non_classes(self): - mod = testutils.create_module(self.project, "mod") - mod.write("def a_func():\n pass\n") - with self.assertRaises(RefactoringError): - self._introduce_factory(mod, mod.read().index("a_func") + 1, "create") - - def test_undoing_introduce_factory(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - code1 = dedent("""\ - class AClass(object): - an_attr = 10 - """) - mod1.write(code1) - code2 = dedent("""\ - from mod1 import AClass - a_var = AClass() - """) - mod2.write(code2) - self._introduce_factory(mod1, mod1.read().index("AClass") + 1, "create") - self.project.history.undo() - self.assertEqual(code1, mod1.read()) - self.assertEqual(code2, mod2.read()) - - def test_using_on_an_occurrence_outside_the_main_module(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("import mod1\na_var = mod1.AClass()\n") - self._introduce_factory(mod2, mod2.read().index("AClass") + 1, "create") - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = "import mod1\n" "a_var = mod1.AClass.create()\n" - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - def test_introduce_factory_in_nested_scopes(self): - code = dedent("""\ - def create_var(): - class AClass(object): - an_attr = 10 - return AClass() - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - def create_var(): - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - return AClass.create() - """) - self._introduce_factory(mod, mod.read().index("AClass") + 1, "create") - self.assertEqual(expected, mod.read()) - - def test_adding_factory_for_global_factories(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - self._introduce_factory( - mod, mod.read().index("AClass") + 1, "create", global_factory=True - ) - self.assertEqual(expected, mod.read()) - - def test_get_name_for_factories(self): - code = dedent("""\ - class C(object): - pass - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - factory = IntroduceFactory(self.project, mod, mod.read().index("C") + 1) - self.assertEqual("C", factory.get_name()) - - def test_raising_exception_for_global_factory_for_nested_classes(self): - code = dedent("""\ - def create_var(): - class AClass(object): - an_attr = 10 - return AClass() - """) - mod = testutils.create_module(self.project, "mod") - mod.write(code) - with self.assertRaises(RefactoringError): - self._introduce_factory( - mod, mod.read().index("AClass") + 1, "create", global_factory=True - ) - - def test_changing_occurrences_in_the_main_module_for_global_factories(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - a_var = AClass()""") - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - a_var = create()""") - self._introduce_factory( - mod, mod.read().index("AClass") + 1, "create", global_factory=True - ) - self.assertEqual(expected, mod.read()) - - def test_changing_occurrences_in_other_modules_for_global_factories(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("import mod1\na_var = mod1.AClass()\n") - self._introduce_factory( - mod1, mod1.read().index("AClass") + 1, "create", global_factory=True - ) - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = "import mod1\n" "a_var = mod1.create()\n" - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - def test_import_if_necessary_in_other_mods_for_global_factories(self): - mod1 = testutils.create_module(self.project, "mod1") - mod2 = testutils.create_module(self.project, "mod2") - mod1.write("class AClass(object):\n an_attr = 10\n") - mod2.write("from mod1 import AClass\npair = AClass(), AClass\n") - self._introduce_factory( - mod1, mod1.read().index("AClass") + 1, "create", global_factory=True - ) - expected1 = dedent("""\ - class AClass(object): - an_attr = 10 - - def create(*args, **kwds): - return AClass(*args, **kwds) - """) - expected2 = dedent("""\ - from mod1 import AClass, create - pair = create(), AClass - """) - self.assertEqual(expected1, mod1.read()) - self.assertEqual(expected2, mod2.read()) - - def test_changing_occurrences_for_renamed_classes(self): - code = dedent("""\ - class AClass(object): - an_attr = 10 - a_class = AClass - a_var = a_class()""") - mod = testutils.create_module(self.project, "mod") - mod.write(code) - expected = dedent("""\ - class AClass(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return AClass(*args, **kwds) - a_class = AClass - a_var = a_class()""") - self._introduce_factory(mod, mod.read().index("a_class") + 1, "create") - self.assertEqual(expected, mod.read()) - - def test_changing_occurrs_in_the_same_module_with_conflict_ranges(self): - mod = testutils.create_module(self.project, "mod") - code = dedent("""\ - class C(object): - def create(self): - return C() - """) - mod.write(code) - self._introduce_factory(mod, mod.read().index("C"), "create_c", True) - expected = dedent("""\ - class C(object): - def create(self): - return create_c() - """) - self.assertTrue(mod.read().startswith(expected)) - - def _transform_module_to_package(self, resource): - self.project.do( - rope.refactor.ModuleToPackage(self.project, resource).get_changes() - ) - - def test_transform_module_to_package(self): - mod1 = testutils.create_module(self.project, "mod1") - mod1.write("import mod2\nfrom mod2 import AClass\n") - mod2 = testutils.create_module(self.project, "mod2") - mod2.write("class AClass(object):\n pass\n") - self._transform_module_to_package(mod2) - mod2 = self.project.get_resource("mod2") - root_folder = self.project.root - self.assertFalse(root_folder.has_child("mod2.py")) - self.assertEqual( - "class AClass(object):\n pass\n", - root_folder.get_child("mod2").get_child("__init__.py").read(), - ) - - def test_transform_module_to_package_undoing(self): - pkg = testutils.create_package(self.project, "pkg") - mod = testutils.create_module(self.project, "mod", pkg) - self._transform_module_to_package(mod) - self.assertFalse(pkg.has_child("mod.py")) - self.assertTrue(pkg.get_child("mod").has_child("__init__.py")) - self.project.history.undo() - self.assertTrue(pkg.has_child("mod.py")) - self.assertFalse(pkg.has_child("mod")) - - def test_transform_module_to_package_with_relative_imports(self): - pkg = testutils.create_package(self.project, "pkg") - mod1 = testutils.create_module(self.project, "mod1", pkg) - mod1.write("import mod2\nfrom mod2 import AClass\n") - mod2 = testutils.create_module(self.project, "mod2", pkg) - mod2.write("class AClass(object):\n pass\n") - self._transform_module_to_package(mod1) - new_init = self.project.get_resource("pkg/mod1/__init__.py") - self.assertEqual( - "import pkg.mod2\nfrom pkg.mod2 import AClass\n", new_init.read() - ) - - def test_resources_parameter(self): - code = dedent("""\ - class A(object): - an_attr = 10 - """) - code1 = dedent("""\ - import mod - a = mod.A() - """) - mod = testutils.create_module(self.project, "mod") - mod1 = testutils.create_module(self.project, "mod1") - mod.write(code) - mod1.write(code1) - expected = dedent("""\ - class A(object): - an_attr = 10 - - @staticmethod - def create(*args, **kwds): - return A(*args, **kwds) - """) - self._introduce_factory( - mod, mod.read().index("A") + 1, "create", resources=[mod] - ) - self.assertEqual(expected, mod.read()) - self.assertEqual(code1, mod1.read()) - - -class EncapsulateFieldTest(unittest.TestCase): - def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - self.mod1 = testutils.create_module(self.project, "mod1") - self.a_class = dedent("""\ - class A(object): - def __init__(self): - self.attr = 1 - """) - self.added_methods = ( - "\n" - " def get_attr(self):\n" - " return self.attr\n\n" - " def set_attr(self, value):\n" - " self.attr = value\n" - ) - self.encapsulated = self.a_class + self.added_methods - - def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - def _encapsulate(self, resource, offset, **args): - changes = EncapsulateField(self.project, resource, offset).get_changes(**args) - self.project.do(changes) - - def test_adding_getters_and_setters(self): - code = self.a_class - self.mod.write(code) - self._encapsulate(self.mod, code.index("attr") + 1) - self.assertEqual(self.encapsulated, self.mod.read()) - - def test_changing_getters_in_other_modules(self): - code = dedent("""\ - import mod - a_var = mod.A() - range(a_var.attr) - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - range(a_var.get_attr()) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_setters_in_other_modules(self): - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(1) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_getters_in_setters(self): - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 + a_var.attr - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(1 + a_var.get_attr()) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_appending_to_class_end(self): - self.mod1.write(self.a_class + "a_var = A()\n") - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - self.assertEqual(self.encapsulated + "a_var = A()\n", self.mod1.read()) - - def test_performing_in_other_modules(self): - code = dedent("""\ - import mod - a_var = mod.A() - range(a_var.attr) - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - self.assertEqual(self.encapsulated, self.mod.read()) - expected = dedent("""\ - import mod - a_var = mod.A() - range(a_var.get_attr()) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_main_module_occurrences(self): - code = self.a_class + "a_var = A()\n" "a_var.attr = a_var.attr * 2\n" - self.mod1.write(code) - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - expected = ( - self.encapsulated + "a_var = A()\n" "a_var.set_attr(a_var.get_attr() * 2)\n" - ) - self.assertEqual(expected, self.mod1.read()) - - def test_raising_exception_when_performed_on_non_attributes(self): - self.mod1.write("attr = 10") - with self.assertRaises(RefactoringError): - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - - def test_raising_exception_on_tuple_assignments(self): - self.mod.write(self.a_class) - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 - a_var.attr, b = 1, 2 - """) - self.mod1.write(code) - with self.assertRaises(RefactoringError): - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - - def test_raising_exception_on_tuple_assignments2(self): - self.mod.write(self.a_class) - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr = 1 - b, a_var.attr = 1, 2 - """) - self.mod1.write(code) - with self.assertRaises(RefactoringError): - self._encapsulate(self.mod1, self.mod1.read().index("attr") + 1) - - def test_tuple_assignments_and_function_calls(self): - code = dedent("""\ - import mod - def func(a1=0, a2=0): - pass - a_var = mod.A() - func(a_var.attr, a2=2) - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - def func(a1=0, a2=0): - pass - a_var = mod.A() - func(a_var.get_attr(), a2=2) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_tuple_assignments(self): - code = dedent("""\ - import mod - a_var = mod.A() - a, b = a_var.attr, 1 - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a, b = a_var.get_attr(), 1 - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_augmented_assignments(self): - code = "import mod\n" "a_var = mod.A()\n" "a_var.attr += 1\n" - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(a_var.get_attr() + 1) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_augmented_assignments2(self): - code = dedent("""\ - import mod - a_var = mod.A() - a_var.attr <<= 1 - """) - self.mod1.write(code) - self.mod.write(self.a_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = dedent("""\ - import mod - a_var = mod.A() - a_var.set_attr(a_var.get_attr() << 1) - """) - self.assertEqual(expected, self.mod1.read()) - - def test_changing_occurrences_inside_the_class(self): - new_class = ( - self.a_class + "\n" " def a_func(self):\n" " self.attr = 1\n" - ) - self.mod.write(new_class) - self._encapsulate(self.mod, self.mod.read().index("attr") + 1) - expected = ( - self.a_class + "\n" - " def a_func(self):\n" - " self.set_attr(1)\n" + self.added_methods - ) - self.assertEqual(expected, self.mod.read()) - - def test_getter_and_setter_parameters(self): - self.mod.write(self.a_class) - self._encapsulate( - self.mod, - self.mod.read().index("attr") + 1, - getter="getAttr", - setter="setAttr", - ) - new_methods = self.added_methods.replace("get_attr", "getAttr").replace( - "set_attr", "setAttr" - ) - expected = self.a_class + new_methods - self.assertEqual(expected, self.mod.read()) - - def test_using_resources_parameter(self): - self.mod1.write("import mod\na = mod.A()\nvar = a.attr\n") - self.mod.write(self.a_class) - self._encapsulate( - self.mod, self.mod.read().index("attr") + 1, resources=[self.mod] - ) - self.assertEqual("import mod\na = mod.A()\nvar = a.attr\n", self.mod1.read()) - expected = self.a_class + self.added_methods - self.assertEqual(expected, self.mod.read()) - - -class LocalToFieldTest(unittest.TestCase): - def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - def _perform_convert_local_variable_to_field(self, resource, offset): - changes = LocalToField(self.project, resource, offset).get_changes() - self.project.do(changes) - - def test_simple_local_to_field(self): - code = dedent("""\ - class A(object): - def a_func(self): - var = 10 - """) - self.mod.write(code) - self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) - expected = dedent("""\ - class A(object): - def a_func(self): - self.var = 10 - """) - self.assertEqual(expected, self.mod.read()) - - def test_raising_exception_when_performed_on_a_global_var(self): - self.mod.write("var = 10\n") - with self.assertRaises(RefactoringError): - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().index("var") + 1 - ) - - def test_raising_exception_when_performed_on_field(self): - code = dedent("""\ - class A(object): - def a_func(self): - self.var = 10 - """) - self.mod.write(code) - with self.assertRaises(RefactoringError): - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().index("var") + 1 - ) - - def test_raising_exception_when_performed_on_a_parameter(self): - code = dedent("""\ - class A(object): - def a_func(self, var): - a = var - """) - self.mod.write(code) - with self.assertRaises(RefactoringError): - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().index("var") + 1 - ) - - # NOTE: This situation happens alot and is normally not an error - # @testutils.assert_raises(RefactoringError) - def test_not_rais_exception_when_there_is_a_field_with_the_same_name(self): - code = dedent("""\ - class A(object): - def __init__(self): - self.var = 1 - def a_func(self): - var = 10 - """) - self.mod.write(code) - self._perform_convert_local_variable_to_field( - self.mod, self.mod.read().rindex("var") + 1 - ) - - def test_local_to_field_with_self_renamed(self): - code = dedent("""\ - class A(object): - def a_func(myself): - var = 10 - """) - self.mod.write(code) - self._perform_convert_local_variable_to_field(self.mod, code.index("var") + 1) - expected = dedent("""\ - class A(object): - def a_func(myself): - myself.var = 10 - """) - self.assertEqual(expected, self.mod.read()) - - -class IntroduceParameterTest(unittest.TestCase): - def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.pycore = self.project.pycore - self.mod = testutils.create_module(self.project, "mod") - - def tearDown(self): - testutils.remove_project(self.project) - super().tearDown() - - def _introduce_parameter(self, offset, name): - rope.refactor.introduce_parameter.IntroduceParameter( - self.project, self.mod, offset - ).get_changes(name).do() - - def test_simple_case(self): - code = dedent("""\ - var = 1 - def f(): - b = var - """) - self.mod.write(code) - offset = self.mod.read().rindex("var") - self._introduce_parameter(offset, "var") - expected = dedent("""\ - var = 1 - def f(var=var): - b = var - """) - self.assertEqual(expected, self.mod.read()) - - def test_changing_function_body(self): - code = dedent("""\ - var = 1 - def f(): - b = var - """) - self.mod.write(code) - offset = self.mod.read().rindex("var") - self._introduce_parameter(offset, "p1") - expected = dedent("""\ - var = 1 - def f(p1=var): - b = p1 - """) - self.assertEqual(expected, self.mod.read()) - - def test_unknown_variables(self): - self.mod.write("def f():\n b = var + c\n") - offset = self.mod.read().rindex("var") - with self.assertRaises(RefactoringError): - self._introduce_parameter(offset, "p1") - self.assertEqual("def f(p1=var):\n b = p1 + c\n", self.mod.read()) - - def test_failing_when_not_inside(self): - self.mod.write("var = 10\nb = var\n") - offset = self.mod.read().rindex("var") - with self.assertRaises(RefactoringError): - self._introduce_parameter(offset, "p1") - - def test_attribute_accesses(self): - code = dedent("""\ - class C(object): - a = 10 - c = C() - def f(): - b = c.a - """) - self.mod.write(code) - offset = self.mod.read().rindex("a") - self._introduce_parameter(offset, "p1") - expected = dedent("""\ - class C(object): - a = 10 - c = C() - def f(p1=c.a): - b = p1 - """) - self.assertEqual(expected, self.mod.read()) - - def test_introducing_parameters_for_methods(self): - code = dedent("""\ - var = 1 - class C(object): - def f(self): - b = var - """) - self.mod.write(code) - offset = self.mod.read().rindex("var") - self._introduce_parameter(offset, "p1") - expected = dedent("""\ - var = 1 - class C(object): - def f(self, p1=var): - b = p1 - """) - self.assertEqual(expected, self.mod.read()) - - -class _MockTaskObserver: - def __init__(self): - self.called = 0 - - def __call__(self): - self.called += 1 - - -class TaskHandleTest(unittest.TestCase): - def test_trivial_case(self): - handle = rope.base.taskhandle.TaskHandle() - self.assertFalse(handle.is_stopped()) - - def test_stopping(self): - handle = rope.base.taskhandle.TaskHandle() - handle.stop() - self.assertTrue(handle.is_stopped()) - - def test_job_sets(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset() - self.assertEqual([jobs], handle.get_jobsets()) - - def test_starting_and_finishing_jobs(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset(name="test job set", count=1) - jobs.started_job("job1") - jobs.finished_job() - - def test_test_checking_status(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset() - handle.stop() - with self.assertRaises(InterruptedTaskError): - jobs.check_status() - - def test_test_checking_status_when_starting(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset() - handle.stop() - with self.assertRaises(InterruptedTaskError): - jobs.started_job("job1") - - def test_calling_the_observer_after_stopping(self): - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) - handle.stop() - self.assertEqual(1, observer.called) - - def test_calling_the_observer_after_creating_job_sets(self): - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) - jobs = handle.create_jobset() # noqa - self.assertEqual(1, observer.called) - - def test_calling_the_observer_when_starting_and_finishing_jobs(self): - handle = rope.base.taskhandle.TaskHandle() - observer = _MockTaskObserver() - handle.add_observer(observer) - jobs = handle.create_jobset(name="test job set", count=1) - jobs.started_job("job1") - jobs.finished_job() - self.assertEqual(3, observer.called) - - def test_job_set_get_percent_done(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset(name="test job set", count=2) - self.assertEqual(0, jobs.get_percent_done()) - jobs.started_job("job1") - jobs.finished_job() - self.assertEqual(50, jobs.get_percent_done()) - jobs.started_job("job2") - jobs.finished_job() - self.assertEqual(100, jobs.get_percent_done()) - - def test_getting_job_name(self): - handle = rope.base.taskhandle.TaskHandle() - jobs = handle.create_jobset(name="test job set", count=1) - # recommended name/job_name attribute - self.assertEqual("test job set", jobs.name) - self.assertEqual(None, jobs.job_name) - # deprecated getters - self.assertEqual("test job set", jobs.get_name()) - self.assertEqual(None, jobs.get_active_job_name()) - jobs.started_job("job1") - # recommended name/job_name attribute - self.assertEqual("test job set", jobs.get_name()) - # deprecated getters - self.assertEqual("job1", jobs.get_active_job_name()) -@language python -@tabwidth -4 - -@path C:/Repos/ekr-rope/rope/ -"""rope, a python refactoring library""" - -from pkg_resources import get_distribution, DistributionNotFound - -try: - VERSION = get_distribution("rope").version -except DistributionNotFound: - - def get_fallback_version(): - import re - import pathlib - - pyproject = ( - pathlib.Path(__file__).resolve().parent.parent / "pyproject.toml" - ).read_text() - version = re.search("version.*=.*'(.*)'", pyproject) - return version.group(1) if version else None - - VERSION = get_fallback_version() - - -INFO = __doc__ -COPYRIGHT = """\ -Copyright (C) 2021-2022 Lie Ryan -Copyright (C) 2019-2021 Matej Cepl -Copyright (C) 2015-2018 Nicholas Smith -Copyright (C) 2014-2015 Matej Cepl -Copyright (C) 2006-2012 Ali Gholami Rudi -Copyright (C) 2009-2012 Anton Gritsay - -This program is free software: you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation, either -version 3 of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this program. If not, see -<https://www.gnu.org/licenses/>.""" -@language python -@tabwidth -4 - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -21,8 +21,10 @@ - p1 = testutils.create_package(self.project, "p1") - p2 = testutils.create_package(self.project, "p2", p1) - p3 = testutils.create_package(self.project, "p3", p2) -- m1 = testutils.create_module(self.project, "m1", p3) # noqa -- l = testutils.create_module(self.project, "l", p3) # noqa -+ m1 = testutils.create_module(self.project, "m1", p3) -+ mod_l = testutils.create_module(self.project, "l", p3) -+ self.assertTrue(m1 is not None) -+ self.assertTrue(mod_l is not None) - - def tearDown(self): - testutils.remove_project(self.project) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -12,6 +12,8 @@ - p1 = testutils.create_package(self.project, "p1") - p2 = testutils.create_package(self.project, "p2", p1) - p3 = testutils.create_package(self.project, "p3", p2) -- m1 = testutils.create_module(self.project, "m1", p3) # noqa -- l = testutils.create_module(self.project, "l", p3) # noqa -+ m1 = testutils.create_module(self.project, "m1", p3) -+ mod_l = testutils.create_module(self.project, "l", p3) -+ self.assertTrue(m1 is not None) -+ self.assertTrue(mod_l is not None) - -@language python - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.import_tools = ImportTools(self.project) - - self.mod = testutils.create_module(self.project, "mod") - self.pkg1 = testutils.create_package(self.project, "pkg1") - self.mod1 = testutils.create_module(self.project, "mod1", self.pkg1) - self.pkg2 = testutils.create_package(self.project, "pkg2") - self.mod2 = testutils.create_module(self.project, "mod2", self.pkg2) - self.mod3 = testutils.create_module(self.project, "mod3", self.pkg2) - p1 = testutils.create_package(self.project, "p1") - p2 = testutils.create_package(self.project, "p2", p1) - p3 = testutils.create_package(self.project, "p3", p2) - m1 = testutils.create_module(self.project, "m1", p3) # noqa - l = testutils.create_module(self.project, "l", p3) # noqa - - -def setUp(self): - super().setUp() - self.project = testutils.sample_project() - self.import_tools = ImportTools(self.project) - - self.mod = testutils.create_module(self.project, "mod") - self.pkg1 = testutils.create_package(self.project, "pkg1") - self.mod1 = testutils.create_module(self.project, "mod1", self.pkg1) - self.pkg2 = testutils.create_package(self.project, "pkg2") - self.mod2 = testutils.create_module(self.project, "mod2", self.pkg2) - self.mod3 = testutils.create_module(self.project, "mod3", self.pkg2) - p1 = testutils.create_package(self.project, "p1") - p2 = testutils.create_package(self.project, "p2", p1) - p3 = testutils.create_package(self.project, "p3", p2) - m1 = testutils.create_module(self.project, "m1", p3) - mod_l = testutils.create_module(self.project, "l", p3) - self.assertTrue(m1 is not None) - self.assertTrue(mod_l is not None) - - -def unicode_to_file_data(contents: str, encoding=None, newlines=None) -> FileContent: - assert isinstance(contents, str) - if newlines and newlines != "\n": - contents = contents.replace("\n", newlines) - if encoding is None: - encoding = read_str_coding(contents) - if encoding is not None: - return FileContent(contents.encode(encoding)) - try: - return FileContent(contents.encode()) - except UnicodeEncodeError: - return FileContent(contents.encode("utf-8")) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -314,6 +314,7 @@ - mover = move.create_move( - self.project, self.mod1, code.index("CONSTANT") + 1 - ) -+ self.assertTrue(mover is not None) - - def test_raising_exception_for_mov_glob_elemnts_to_the_same_module(self): - self.mod1.write("def a_func():\n pass\n") -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -8,4 +8,5 @@ - mover = move.create_move( - self.project, self.mod1, code.index("CONSTANT") + 1 - ) -+ self.assertTrue(mover is not None) - -@language python - -def test_raising_an_exception_for_moving_non_global_variable(self): - code = dedent("""\ - class TestClass: - CONSTANT = 5 - """) - self.mod1.write(code) - with self.assertRaises(exceptions.RefactoringError): - mover = move.create_move( - self.project, self.mod1, code.index("CONSTANT") + 1 - ) - - -def test_raising_an_exception_for_moving_non_global_variable(self): - code = dedent("""\ - class TestClass: - CONSTANT = 5 - """) - self.mod1.write(code) - with self.assertRaises(exceptions.RefactoringError): - mover = move.create_move( - self.project, self.mod1, code.index("CONSTANT") + 1 - ) - self.assertTrue(mover is not None) - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1558,7 +1558,6 @@ - ")", - ]) - -- - @testutils.only_for_versions_higher("3.10") - def test_match_node_with_match_mapping_match_as(self): - source = dedent("""\ -@@ -1587,8 +1586,6 @@ - "", - "}", - ]) -- -- - class _ResultChecker: - def __init__(self, test_case, ast): - self.test_case = test_case -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -24,7 +24,6 @@ - "", - ")", - ]) -- - - @testutils.only_for_versions_higher("3.10") - def test_match_node_with_match_mapping_match_as(self): -@@ -54,5 +53,3 @@ - "", - "}", - ]) -- -- -@language python - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name(self): - source = dedent("""\ - match x: - case Foo(x) as b: - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "MatchClass", - " ", - "as", - " ", - "b", - ]) - checker.check_children("MatchClass", [ - "Name", - "", - "(", - "", - "MatchAs", - "", - ")", - ]) - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_mapping_match_as(self): - source = dedent("""\ - match x: - case {"a": b} as c: - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "MatchMapping", - " ", - "as", - " ", - "c", - ]) - checker.check_children("MatchMapping", [ - "{", - "", - "Constant", - "", - ":", - " ", - "MatchAs", - "", - "}", - ]) - - - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_class_match_as_capture_pattern_with_explicit_name(self): - source = dedent("""\ - match x: - case Foo(x) as b: - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "MatchClass", - " ", - "as", - " ", - "b", - ]) - checker.check_children("MatchClass", [ - "Name", - "", - "(", - "", - "MatchAs", - "", - ")", - ]) - -@testutils.only_for_versions_higher("3.10") -def test_match_node_with_match_mapping_match_as(self): - source = dedent("""\ - match x: - case {"a": b} as c: - print(x) - """) - ast_frag = patchedast.get_patched_ast(source, True) - checker = _ResultChecker(self, ast_frag) - self.assert_single_case_match_block(checker, "MatchAs") - checker.check_children("MatchAs", [ - "MatchMapping", - " ", - "as", - " ", - "c", - ]) - checker.check_children("MatchMapping", [ - "{", - "", - "Constant", - "", - ":", - " ", - "MatchAs", - "", - "}", - ]) - -def consume(self, token, skip_comment=True): - try: - while True: - new_offset = self.source.index(token, self.offset) - if self._good_token(token, new_offset) or not skip_comment: - break - else: - self._skip_comment() - except (ValueError, TypeError): - raise MismatchedTokenError( - "Token <{}> at {} cannot be matched".format(token, self._get_location()) - ) - self.offset = new_offset + len(token) - return (new_offset, self.offset) - - -def file_data_to_unicode(data, encoding=None): - result = _decode_data(data, encoding) - newline = "\n" - if "\r\n" in result: - result = result.replace("\r\n", "\n") - newline = "\r\n" - if "\r" in result: - result = result.replace("\r", "\n") - newline = "\r" - return result, newline - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,12 +2,12 @@ - import shutil - import sys - import logging -- --logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) - import unittest - - import rope.base.project - from rope.contrib import generate -+ -+logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) - - - def sample_project(root=None, foldername=None, **kwds): -@@ -51,7 +51,7 @@ - - # windows sometimes raises exceptions instead of removing files - if os.name == "nt" or sys.platform == "cygwin": -- for i in range(12): -+ for _i in range(12): - try: - _remove_recursively(path) - except OSError as e: -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -3,13 +3,13 @@ - import shutil - import sys - import logging -- --logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) - import unittest - - import rope.base.project - from rope.contrib import generate - -+logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) -+ - - @others - @language python -@language python - -@path C:/Repos/ekr-rope/ropetest/ -import os.path -import shutil -import sys -import logging - -logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) -import unittest - -import rope.base.project -from rope.contrib import generate - - -@others -@language python -@tabwidth -4 - -@path C:/Repos/ekr-rope/ropetest/ -import os.path -import shutil -import sys -import logging - -logging.basicConfig(format="%(levelname)s:%(funcName)s:%(message)s", level=logging.INFO) -import unittest - -import rope.base.project -from rope.contrib import generate - - -@others -@language python -@tabwidth -4 - -def sample_project(root=None, foldername=None, **kwds): - if root is None: - root = "sample_project" - if foldername: - root = foldername - # HACK: Using ``/dev/shm/`` for faster tests - if os.name == "posix": - if os.path.isdir("/dev/shm") and os.access("/dev/shm", os.W_OK): - root = "/dev/shm/" + root - elif os.path.isdir("/tmp") and os.access("/tmp", os.W_OK): - root = "/tmp/" + root - logging.debug("Using %s as root of the project.", root) - # Using these prefs for faster tests - prefs = { - "save_objectdb": False, - "save_history": False, - "validate_objectdb": False, - "automatic_soa": False, - "ignored_resources": [".ropeproject", "*.pyc"], - "import_dynload_stdmods": False, - } - prefs.update(kwds) - remove_recursively(root) - project = rope.base.project.Project(root, **prefs) - return project - - - -create_module = generate.create_module -create_package = generate.create_package - - - -def remove_project(project): - project.close() - remove_recursively(project.address) - - - -def _remove_recursively(path): - if not os.path.exists(path): - return - if os.path.isfile(path): - os.remove(path) - else: - shutil.rmtree(path) - - - -def _decode_data(data, encoding): - if isinstance(data, str): - return data - if encoding is None: - encoding = read_str_coding(data) - if encoding is None: - # there is no encoding tip, we need to guess. - # PEP263 says that "encoding not explicitly defined" means it is ascii, - # but we will use utf8 instead since utf8 fully covers ascii and btw is - # the only non-latin sane encoding. - encoding = "utf-8" - try: - return data.decode(encoding) - except (UnicodeError, LookupError): - # fallback to latin1: it should never fail - return data.decode("latin1") - - - -def parse_version(version): - return tuple(map(int, version.split("."))) - - - -def only_for(version): - """Should be used as a decorator for a unittest.TestCase test method""" - return unittest.skipIf( - sys.version_info < parse_version(version), - "This test requires at least {0} version of Python.".format(version), - ) - - - -def only_for_versions_lower(version): - """Should be used as a decorator for a unittest.TestCase test method""" - return unittest.skipIf( - sys.version_info > parse_version(version), - "This test requires version of Python lower than {0}".format(version), - ) - - - -def only_for_versions_higher(version): - """Should be used as a decorator for a unittest.TestCase test method""" - return unittest.skipIf( - sys.version_info < parse_version(version), - "This test requires version of Python higher than {0}".format(version), - ) - - - -def skipNotPOSIX(): - return unittest.skipIf(os.name != "posix", "This test works only on POSIX") - - - -def time_limit(timeout): - if not any(procname in sys.argv[0] for procname in {"pytest", "py.test"}): - # no-op when running tests without pytest - return lambda *args, **kwargs: lambda func: func - - # do a local import so we don't import pytest when running without pytest - import pytest - - # this prevents infinite loop/recursion from taking forever in CI - return pytest.mark.time_limit(timeout) - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -3,7 +3,7 @@ - - # windows sometimes raises exceptions instead of removing files - if os.name == "nt" or sys.platform == "cygwin": -- for i in range(12): -+ for _i in range(12): - try: - _remove_recursively(path) - except OSError as e: -@language python - -def remove_recursively(path): - import time - - # windows sometimes raises exceptions instead of removing files - if os.name == "nt" or sys.platform == "cygwin": - for i in range(12): - try: - _remove_recursively(path) - except OSError as e: - if e.errno not in (13, 16, 32): - raise - time.sleep(0.3) - else: - break - else: - _remove_recursively(path) - - - -def remove_recursively(path): - import time - - # windows sometimes raises exceptions instead of removing files - if os.name == "nt" or sys.platform == "cygwin": - for i in range(12): - try: - _remove_recursively(path) - except OSError as e: - if e.errno not in (13, 16, 32): - raise - time.sleep(0.3) - else: - break - else: - _remove_recursively(path) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,3 +1,3 @@ - from setuptools import setup - --setup()+setup() - -def read_str_coding(source): - # as defined by PEP-263 (https://www.python.org/dev/peps/pep-0263/) - CODING_LINE_PATTERN = b"^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)" - - if type(source) == bytes: - newline = b"\n" - CODING_LINE_PATTERN = re.compile(CODING_LINE_PATTERN) - else: - newline = "\n" - CODING_LINE_PATTERN = re.compile(CODING_LINE_PATTERN.decode("ascii")) - for line in source.split(newline, 2)[:2]: - if re.match(CODING_LINE_PATTERN, line): - return _find_coding(line) - else: - return - - - -def _find_coding(text): - if isinstance(text, str): - text = text.encode("utf-8") - coding = b"coding" - to_chr = chr - try: - start = text.index(coding) + len(coding) - if text[start] not in b"=:": - return - start += 1 - while start < len(text) and to_chr(text[start]).isspace(): - start += 1 - end = start - while end < len(text): - c = text[end] - if not to_chr(c).isalnum() and c not in b"-_": - break - end += 1 - result = text[start:end] - if isinstance(result, bytes): - result = result.decode("utf-8") - return result - except ValueError: - pass - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -30,9 +30,7 @@ - pycore, pyfunction, return_true, return_false, new_followed_calls - ) - -- if not followed_calls: -- _follow = None -- visitor = SOAVisitor(pycore, pydefined, _follow) -+ visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None) - for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): - rope.base.ast.walk(child, visitor) -@language python - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -14,9 +14,7 @@ - pycore, pyfunction, return_true, return_false, new_followed_calls - ) - -- if not followed_calls: -- _follow = None -- visitor = SOAVisitor(pycore, pydefined, _follow) -+ visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None) - for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): - rope.base.ast.walk(child, visitor) - -@language python - -def _analyze_node(pycore, pydefined, should_analyze, search_subscopes, followed_calls): - if search_subscopes(pydefined): - for scope in pydefined.get_scope().get_scopes(): - _analyze_node( - pycore, scope.pyobject, should_analyze, search_subscopes, followed_calls - ) - if should_analyze(pydefined): - new_followed_calls = max(0, followed_calls - 1) - return_true = lambda pydefined: True - return_false = lambda pydefined: False - - def _follow(pyfunction): - _analyze_node( - pycore, pyfunction, return_true, return_false, new_followed_calls - ) - - if not followed_calls: - _follow = None - visitor = SOAVisitor(pycore, pydefined, _follow) - for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): - rope.base.ast.walk(child, visitor) - - - -def _analyze_node(pycore, pydefined, should_analyze, search_subscopes, followed_calls): - if search_subscopes(pydefined): - for scope in pydefined.get_scope().get_scopes(): - _analyze_node( - pycore, scope.pyobject, should_analyze, search_subscopes, followed_calls - ) - if should_analyze(pydefined): - new_followed_calls = max(0, followed_calls - 1) - return_true = lambda pydefined: True - return_false = lambda pydefined: False - - def _follow(pyfunction): - _analyze_node( - pycore, pyfunction, return_true, return_false, new_followed_calls - ) - - visitor = SOAVisitor(pycore, pydefined, _follow if followed_calls else None) - for child in rope.base.ast.get_child_nodes(pydefined.get_ast()): - rope.base.ast.walk(child, visitor) - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,7 +1,6 @@ - # Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm - # and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py - import re --from rope.base.utils import pycompat - from rope.base.oi.type_hinting import utils - from rope.base import utils as base_utils - -@@ -268,7 +267,7 @@ - - - @method(symbol("[")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa - return utils.parametrize_type( - self.first.evaluate(pyobject), *[i.evaluate(pyobject) for i in self.second] - ) -@@ -276,7 +275,7 @@ - - # Anonymous Function Calls - @method(symbol("(")) --def nud(self, parser): -+def nud(self, parser): # noqa - self.second = [] - if parser.token.name != ")": - while 1: -@@ -292,7 +291,7 @@ - - # Function Calls - @method(symbol("(")) --def led(self, left, parser): -+def led(self, left, parser): # noqa - self.first = left - self.second = [] - if parser.token.name != ")": -@@ -308,14 +307,14 @@ - - - @method(symbol("(")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa - # TODO: Implement me - raise NotImplementedError - - - @method(symbol("or")) - @method(symbol("|")) --def evaluate(self, pyobject): -+def evaluate(self, pyobject): # noqa - # TODO: Implement me - raise NotImplementedError - -@@ -355,4 +354,4 @@ - return ast.evaluate(pyobject) - - --evaluate = Evaluator() -+evaluate = Evaluator() # noqa -@language python - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -2,7 +2,6 @@ - # Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm - # and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py - import re --from rope.base.utils import pycompat - from rope.base.oi.type_hinting import utils - from rope.base import utils as base_utils - -@language python - -@path C:/Repos/ekr-rope/rope/base/ -# Based on super lightweight Simple Top-Down Parser from http://effbot.org/zone/simple-top-down-parsing.htm -# and https://bitbucket.org/emacsway/sqlbuilder/src/default/sqlbuilder/smartsql/contrib/evaluate.py -import re -from rope.base.utils import pycompat -from rope.base.oi.type_hinting import utils -from rope.base import utils as base_utils - - -class SymbolBase: - - name = None # node/token type name - - def __init__(self): - self.value = None # used by name and literals - self.first = None - self.second = None - self.third = None # used by tree nodes - - def nud(self, parser): - raise SyntaxError("Syntax error (%r)." % self.name) - - def led(self, left, parser): - raise SyntaxError("Unknown operator (%r)." % self.name) - - def evaluate(self, pyobject): - raise NotImplementedError(self.name, self) - - def __repr__(self): - if self.name == "(name)": - return "({} {})".format(self.name[1:-1], self.value) - out = [repr(self.name), self.first, self.second, self.third] - out = [str(i) for i in out if i] - return "(" + " ".join(out) + ")" - - -class SymbolTable: - def multi(func): - def _inner(self, names, *a, **kw): - for name in names.split(): - func(self, name, *a, **kw) - - return _inner - - def __init__(self): - self.symbol_table = {} - - def get(self, name, default=None): - return self.symbol_table.get(name, default) - - def __getitem__(self, name): - return self.symbol_table[name] - - def __iter__(self): - return iter(self.symbol_table) - - def symbol(self, name, bp=0): - try: - s = self.symbol_table[name] - except KeyError: - - class S(SymbolBase): - pass - - s = S - s.__name__ = "symbol-" + name # for debugging - s.name = name - s.lbp = bp - self.symbol_table[name] = s - else: - s.lbp = max(bp, s.lbp) - return s - - @multi - def infix(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def led(self, left, parser): - self.first = left - self.second = parser.expression(bp) - return self - - @multi - def infix_r(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def led(self, left, parser): - self.first = left - self.second = parser.expression(bp - 0.1) - return self - - def ternary(self, name, name2, bp): - symbol = self.symbol(name, bp) - symbol2 = self.symbol(name2) - - @method(symbol) - def led(self, left, parser): - self.first = left - self.second = parser.expression(symbol2.lbp) - parser.advance(symbol2.name) - self.third = parser.expression(symbol2.lbp + 0.1) - return self - - @multi - def prefix(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def nud(self, parser): - self.first = parser.expression(bp) - return self - - @multi - def postfix(self, name, bp): - symbol = self.symbol(name, bp) - - @method(symbol) - def led(self, left, parser): - self.first = left - return self - - multi = staticmethod(multi) # Just for code checker - - -symbol_table = SymbolTable() - - -class Lexer: - - _token_pattern = re.compile( - r""" - \s* - (?: - ( - [,()\[\]|] - | -> - | (?<=\s)(?:or)\b - ) # operator - | ([a-zA-Z](?:\w|\.)*) # name - ) - """, - re.U | re.S | re.X, - ) - - def __init__(self, symbol_table): - self.symbol_table = symbol_table - - def tokenize(self, program): - for name, value in self._tokenize_expr(program): - symbol = symbol_table.get(value) - if symbol: - s = symbol() - elif name == "(name)": - symbol = symbol_table[name] - s = symbol() - s.value = value - else: - raise SyntaxError( - "Unknown operator ({}). Possible operators are {!r}".format( - value, list(self.symbol_table) - ) - ) - - yield s - - def _tokenize_expr(self, program): - if isinstance(program, bytes): - program = program.decode("utf-8") - # import pprint; pprint.pprint(self._token_pattern.findall(program)) - for operator, name in self._token_pattern.findall(program): - if operator: - yield "(operator)", operator - elif name: - yield "(name)", name - else: - raise SyntaxError - yield "(end)", "(end)" - - -class Parser: - - token = None - next = None - - def __init__(self, lexer): - self.lexer = lexer - - def parse(self, program): - generator = self.lexer.tokenize(program) - self.next = generator.__next__ - self.token = self.next() - return self.expression() - - def expression(self, rbp=0): - t = self.token - self.token = self.next() - left = t.nud(self) - while rbp < self.token.lbp: - t = self.token - self.token = self.next() - left = t.led(left, self) - return left - - def advance(self, name=None): - if name and self.token.name != name: - raise SyntaxError(f"Expected {name!r} but found {self.token.name!r}") - self.token = self.next() - - -def method(s): - assert issubclass(s, SymbolBase) - - def bind(fn): - setattr(s, fn.__name__, fn) - return fn - - return bind - - -symbol, infix, infix_r, prefix, postfix, ternary = ( - symbol_table.symbol, - symbol_table.infix, - symbol_table.infix_r, - symbol_table.prefix, - symbol_table.postfix, - symbol_table.ternary, -) - -symbol("(", 270) -symbol(")") -symbol("[", 250) # Parameters -symbol("]") -@others -@language python -@tabwidth -4 - -@path C:/Repos/ekr-rope/rope/base/ -from operator import itemgetter -from typing import Optional, Tuple - -import rope.base.builtins -import rope.base.pynames -import rope.base.pyobjects -from rope.base import ( - ast, - astutils, - exceptions, - pyobjects, - pyobjectsdef, - arguments, - worder, -) - - -BadIdentifierError = exceptions.BadIdentifierError - - -@others -@language python -@tabwidth -4 - -def eval_location(pymodule, offset): - """Find the pyname at the offset""" - return eval_location2(pymodule, offset)[1] - - - -def eval_location2(pymodule, offset): - """Find the primary and pyname at offset""" - pyname_finder = ScopeNameFinder(pymodule) - return pyname_finder.get_primary_and_pyname_at(offset) - - - -def eval_node(scope, node): - """Evaluate a `ast.AST` node and return a PyName - - Return `None` if the expression cannot be evaluated. - """ - return eval_node2(scope, node)[1] - - - -def eval_node2(scope, node): - evaluator = StatementEvaluator(scope) - ast.walk(node, evaluator) - return evaluator.old_result, evaluator.result - - - -def eval_str(holding_scope, name): - return eval_str2(holding_scope, name)[1] - - - -@ignore -@nosearch -@language patch ---- master -+++ HEAD -@@ -1,5 +1,5 @@ --import ast --from ast import * -+import ast # noqu -+from ast import * # noqa - - from rope.base import fscommands -@language python - -class ScopeNameFinder: - @others - -def __init__(self, pymodule): - self.module_scope = pymodule.get_scope() - self.lines = pymodule.lines - self.worder = worder.Worder(pymodule.source_code, True) - - -def get_pyname_at(self, offset): - return self.get_primary_and_pyname_at(offset)[1] - - -def _find_module(self, module_name): - dots = 0 - while module_name[dots] == ".": - dots += 1 - return rope.base.pynames.ImportedModule( - self.module_scope.pyobject, module_name[dots:], dots - ) - - - -class StatementEvaluator: - @others - -def __init__(self, scope): - self.scope = scope - self.result = None - self.old_result = None - - -@nosearch - -# Word, Head, Body - -# found 23 nodes -@nosearch - -# Word, Head, Body - -# found 6 nodes -@path C:/Repos/ekr-rope/rope/base/utils/ -import ast -import builtins - - -ast_arg_type = ast.arg - - -def execfile(fn, global_vars=None, local_vars=None): - with open(fn) as f: - code = compile(f.read(), fn, "exec") - exec(code, global_vars or {}, local_vars) - - -def get_ast_arg_arg(node): - if isinstance(node, str): # TODO: G21: Understand the Algorithm (Where it's used?) - return node - return node.arg - - -def get_ast_with_items(node): - return node.items - - - - From eba947cfe9d70b18901bf433d10a68bf0be2ad49 Mon Sep 17 00:00:00 2001 From: "Edward K. Ream" Date: Mon, 28 Nov 2022 06:29:53 -0600 Subject: [PATCH 3/4] Remove pycompat.py --- rope/base/utils/pycompat.py | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 rope/base/utils/pycompat.py diff --git a/rope/base/utils/pycompat.py b/rope/base/utils/pycompat.py deleted file mode 100644 index b96a0eeaf..000000000 --- a/rope/base/utils/pycompat.py +++ /dev/null @@ -1,21 +0,0 @@ -import ast -import builtins - - -ast_arg_type = ast.arg - - -def execfile(fn, global_vars=None, local_vars=None): - with open(fn) as f: - code = compile(f.read(), fn, "exec") - exec(code, global_vars or {}, local_vars) - - -def get_ast_arg_arg(node): - if isinstance(node, str): # TODO: G21: Understand the Algorithm (Where it's used?) - return node - return node.arg - - -def get_ast_with_items(node): - return node.items From f8d35870dc57f26b9b48b837a3588a4900e044f7 Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Tue, 29 Nov 2022 00:19:39 +1100 Subject: [PATCH 4/4] "Blacken" manually Black misses this since this file is excluded from it --- rope/base/prefs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rope/base/prefs.py b/rope/base/prefs.py index bc630f783..03d793f21 100644 --- a/rope/base/prefs.py +++ b/rope/base/prefs.py @@ -257,7 +257,7 @@ def _read(self) -> bool: } ) with open(config.real_path) as f: - code = compile(f.read(),config.real_path, 'exec') + code = compile(f.read(), config.real_path, "exec") exec(code, self.run_globals) return True