summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/move.py
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/move.py')
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/move.py118
1 files changed, 118 insertions, 0 deletions
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/move.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/move.py
new file mode 100644
index 00000000000..6d0a7cb813e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/move.py
@@ -0,0 +1,118 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import functools
+import os
+import sys
+
+from py_utils import refactor
+
+
+def Run(sources, target, files_to_update):
+ """Move modules and update imports.
+
+ Args:
+ sources: List of source module or package paths.
+ target: Destination module or package path.
+ files_to_update: Modules whose imports we should check for changes.
+ """
+ # TODO(dtu): Support moving classes and functions.
+ moves = tuple(_Move(source, target) for source in sources)
+
+ # Update imports and references.
+ refactor.Transform(functools.partial(_Update, moves), files_to_update)
+
+ # Move files.
+ for move in moves:
+ os.rename(move.source_path, move.target_path)
+
+
+def _Update(moves, module):
+ for import_statement in module.FindAll(refactor.Import):
+ for move in moves:
+ try:
+ if move.UpdateImportAndReferences(module, import_statement):
+ break
+ except NotImplementedError as e:
+ print('Error updating %s: %s' % (module.file_path, e), file=sys.stderr)
+
+
+class _Move(object):
+
+ def __init__(self, source, target):
+ self._source_path = os.path.realpath(source)
+ self._target_path = os.path.realpath(target)
+
+ if os.path.isdir(self._target_path):
+ self._target_path = os.path.join(
+ self._target_path, os.path.basename(self._source_path))
+
+ @property
+ def source_path(self):
+ return self._source_path
+
+ @property
+ def target_path(self):
+ return self._target_path
+
+ @property
+ def source_module_path(self):
+ return _ModulePath(self._source_path)
+
+ @property
+ def target_module_path(self):
+ return _ModulePath(self._target_path)
+
+ def UpdateImportAndReferences(self, module, import_statement):
+ """Update an import statement in a module and all its references..
+
+ Args:
+ module: The refactor.Module to update.
+ import_statement: The refactor.Import to update.
+
+ Returns:
+ True if the import statement was updated, or False if the import statement
+ needed no updating.
+ """
+ statement_path_parts = import_statement.path.split('.')
+ source_path_parts = self.source_module_path.split('.')
+ if source_path_parts != statement_path_parts[:len(source_path_parts)]:
+ return False
+
+ # Update import statement.
+ old_name_parts = import_statement.name.split('.')
+ new_name_parts = ([self.target_module_path] +
+ statement_path_parts[len(source_path_parts):])
+ import_statement.path = '.'.join(new_name_parts)
+ new_name = import_statement.name
+
+ # Update references.
+ for reference in module.FindAll(refactor.Reference):
+ reference_parts = reference.value.split('.')
+ if old_name_parts != reference_parts[:len(old_name_parts)]:
+ continue
+
+ new_reference_parts = [new_name] + reference_parts[len(old_name_parts):]
+ reference.value = '.'.join(new_reference_parts)
+
+ return True
+
+
+def _BaseDir(module_path):
+ if not os.path.isdir(module_path):
+ module_path = os.path.dirname(module_path)
+
+ while '__init__.py' in os.listdir(module_path):
+ module_path = os.path.dirname(module_path)
+
+ return module_path
+
+
+def _ModulePath(module_path):
+ if os.path.split(module_path)[1] == '__init__.py':
+ module_path = os.path.dirname(module_path)
+ rel_path = os.path.relpath(module_path, _BaseDir(module_path))
+ return os.path.splitext(rel_path)[0].replace(os.sep, '.')