Index: tools/telemetry/third_party/rope/rope/base/resources.py |
diff --git a/tools/telemetry/third_party/rope/rope/base/resources.py b/tools/telemetry/third_party/rope/rope/base/resources.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..af8ac0a27698b73a6a3416f16f79c242a45c8dfb |
--- /dev/null |
+++ b/tools/telemetry/third_party/rope/rope/base/resources.py |
@@ -0,0 +1,243 @@ |
+"""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 |
+ |
+from rope.base import change |
+from rope.base import exceptions |
+from rope.base import fscommands |
+ |
+ |
+class Resource(object): |
+ """Represents files and folders in a project""" |
+ |
+ def __init__(self, project, path): |
+ self.project = project |
+ self._path = path |
+ |
+ def move(self, new_location): |
+ """Move resource to `new_location`""" |
+ self._perform_change(change.MoveResource(self, new_location), |
+ 'Moving <%s> to <%s>' % (self.path, new_location)) |
+ |
+ def remove(self): |
+ """Remove resource from the project""" |
+ self._perform_change(change.RemoveResource(self), |
+ 'Removing <%s>' % self.path) |
+ |
+ 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) |
+ |
+ def __eq__(self, obj): |
+ return self.__class__ == obj.__class__ and self.path == obj.path |
+ |
+ def __ne__(self, obj): |
+ return not self.__eq__(obj) |
+ |
+ 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""" |
+ |
+ def __init__(self, project, name): |
+ super(File, self).__init__(project, name) |
+ |
+ def read(self): |
+ data = self.read_bytes() |
+ try: |
+ return fscommands.file_data_to_unicode(data) |
+ except UnicodeDecodeError as e: |
+ raise exceptions.ModuleDecodeError(self.path, e.reason) |
+ |
+ def read_bytes(self): |
+ return open(self.real_path, 'rb').read() |
+ |
+ def write(self, contents): |
+ try: |
+ if contents == self.read(): |
+ return |
+ except IOError: |
+ 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""" |
+ |
+ def __init__(self, project, name): |
+ super(Folder, self).__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 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(object): |
+ |
+ def __init__(self): |
+ self.patterns = [] |
+ self._compiled_patterns = [] |
+ |
+ def set_patterns(self, patterns): |
+ """Specify which resources to match |
+ |
+ `patterns` is a `list` of `str`\s 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('/')) |
+ if os.path.islink(path): |
+ return True |
+ return False |
+ |
+ @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 |