Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: tools/telemetry/third_party/rope/rope/base/resourceobserver.py

Issue 1132103009: Example of refactoring using rope library. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 import os
2
3
4 class ResourceObserver(object):
5 """Provides the interface for observing resources
6
7 `ResourceObserver`\s can be registered using `Project.
8 add_observer()`. But most of the time `FilteredResourceObserver`
9 should be used. `ResourceObserver`\s report all changes passed
10 to them and they don't report changes to all resources. For
11 example if a folder is removed, it only calls `removed()` for that
12 folder and not its contents. You can use
13 `FilteredResourceObserver` if you are interested in changes only
14 to a list of resources. And you want changes to be reported on
15 individual resources.
16
17 """
18
19 def __init__(self, changed=None, moved=None, created=None,
20 removed=None, validate=None):
21 self.changed = changed
22 self.moved = moved
23 self.created = created
24 self.removed = removed
25 self._validate = validate
26
27 def resource_changed(self, resource):
28 """It is called when the resource changes"""
29 if self.changed is not None:
30 self.changed(resource)
31
32 def resource_moved(self, resource, new_resource):
33 """It is called when a resource is moved"""
34 if self.moved is not None:
35 self.moved(resource, new_resource)
36
37 def resource_created(self, resource):
38 """Is called when a new resource is created"""
39 if self.created is not None:
40 self.created(resource)
41
42 def resource_removed(self, resource):
43 """Is called when a new resource is removed"""
44 if self.removed is not None:
45 self.removed(resource)
46
47 def validate(self, resource):
48 """Validate the existence of this resource and its children.
49
50 This function is called when rope need to update its resource
51 cache about the files that might have been changed or removed
52 by other processes.
53
54 """
55 if self._validate is not None:
56 self._validate(resource)
57
58
59 class FilteredResourceObserver(object):
60 """A useful decorator for `ResourceObserver`
61
62 Most resource observers have a list of resources and are
63 interested only in changes to those files. This class satisfies
64 this need. It dispatches resource changed and removed messages.
65 It performs these tasks:
66
67 * Changes to files and folders are analyzed to check whether any
68 of the interesting resources are changed or not. If they are,
69 it reports these changes to `resource_observer` passed to the
70 constructor.
71 * When a resource is removed it checks whether any of the
72 interesting resources are contained in that folder and reports
73 them to `resource_observer`.
74 * When validating a folder it validates all of the interesting
75 files in that folder.
76
77 Since most resource observers are interested in a list of
78 resources that change over time, `add_resource` and
79 `remove_resource` might be useful.
80
81 """
82
83 def __init__(self, resource_observer, initial_resources=None,
84 timekeeper=None):
85 self.observer = resource_observer
86 self.resources = {}
87 if timekeeper is not None:
88 self.timekeeper = timekeeper
89 else:
90 self.timekeeper = ChangeIndicator()
91 if initial_resources is not None:
92 for resource in initial_resources:
93 self.add_resource(resource)
94
95 def add_resource(self, resource):
96 """Add a resource to the list of interesting resources"""
97 if resource.exists():
98 self.resources[resource] = self.timekeeper.get_indicator(resource)
99 else:
100 self.resources[resource] = None
101
102 def remove_resource(self, resource):
103 """Add a resource to the list of interesting resources"""
104 if resource in self.resources:
105 del self.resources[resource]
106
107 def clear_resources(self):
108 """Removes all registered resources"""
109 self.resources.clear()
110
111 def resource_changed(self, resource):
112 changes = _Changes()
113 self._update_changes_caused_by_changed(changes, resource)
114 self._perform_changes(changes)
115
116 def _update_changes_caused_by_changed(self, changes, changed):
117 if changed in self.resources:
118 changes.add_changed(changed)
119 if self._is_parent_changed(changed):
120 changes.add_changed(changed.parent)
121
122 def _update_changes_caused_by_moved(self, changes, resource,
123 new_resource=None):
124 if resource in self.resources:
125 changes.add_removed(resource, new_resource)
126 if new_resource in self.resources:
127 changes.add_created(new_resource)
128 if resource.is_folder():
129 for file in list(self.resources):
130 if resource.contains(file):
131 new_file = self._calculate_new_resource(
132 resource, new_resource, file)
133 changes.add_removed(file, new_file)
134 if self._is_parent_changed(resource):
135 changes.add_changed(resource.parent)
136 if new_resource is not None:
137 if self._is_parent_changed(new_resource):
138 changes.add_changed(new_resource.parent)
139
140 def _is_parent_changed(self, child):
141 return child.parent in self.resources
142
143 def resource_moved(self, resource, new_resource):
144 changes = _Changes()
145 self._update_changes_caused_by_moved(changes, resource, new_resource)
146 self._perform_changes(changes)
147
148 def resource_created(self, resource):
149 changes = _Changes()
150 self._update_changes_caused_by_created(changes, resource)
151 self._perform_changes(changes)
152
153 def _update_changes_caused_by_created(self, changes, resource):
154 if resource in self.resources:
155 changes.add_created(resource)
156 if self._is_parent_changed(resource):
157 changes.add_changed(resource.parent)
158
159 def resource_removed(self, resource):
160 changes = _Changes()
161 self._update_changes_caused_by_moved(changes, resource)
162 self._perform_changes(changes)
163
164 def _perform_changes(self, changes):
165 for resource in changes.changes:
166 self.observer.resource_changed(resource)
167 self.resources[resource] = self.timekeeper.get_indicator(resource)
168 for resource, new_resource in changes.moves.items():
169 self.resources[resource] = None
170 if new_resource is not None:
171 self.observer.resource_moved(resource, new_resource)
172 else:
173 self.observer.resource_removed(resource)
174 for resource in changes.creations:
175 self.observer.resource_created(resource)
176 self.resources[resource] = self.timekeeper.get_indicator(resource)
177
178 def validate(self, resource):
179 changes = _Changes()
180 for file in self._search_resource_moves(resource):
181 if file in self.resources:
182 self._update_changes_caused_by_moved(changes, file)
183 for file in self._search_resource_changes(resource):
184 if file in self.resources:
185 self._update_changes_caused_by_changed(changes, file)
186 for file in self._search_resource_creations(resource):
187 if file in self.resources:
188 changes.add_created(file)
189 self._perform_changes(changes)
190
191 def _search_resource_creations(self, resource):
192 creations = set()
193 if resource in self.resources and resource.exists() and \
194 self.resources[resource] is None:
195 creations.add(resource)
196 if resource.is_folder():
197 for file in self.resources:
198 if file.exists() and resource.contains(file) and \
199 self.resources[file] is None:
200 creations.add(file)
201 return creations
202
203 def _search_resource_moves(self, resource):
204 all_moved = set()
205 if resource in self.resources and not resource.exists():
206 all_moved.add(resource)
207 if resource.is_folder():
208 for file in self.resources:
209 if resource.contains(file):
210 if not file.exists():
211 all_moved.add(file)
212 moved = set(all_moved)
213 for folder in [file for file in all_moved if file.is_folder()]:
214 if folder in moved:
215 for file in list(moved):
216 if folder.contains(file):
217 moved.remove(file)
218 return moved
219
220 def _search_resource_changes(self, resource):
221 changed = set()
222 if resource in self.resources and self._is_changed(resource):
223 changed.add(resource)
224 if resource.is_folder():
225 for file in self.resources:
226 if file.exists() and resource.contains(file):
227 if self._is_changed(file):
228 changed.add(file)
229 return changed
230
231 def _is_changed(self, resource):
232 if self.resources[resource] is None:
233 return False
234 return self.resources[resource] != \
235 self.timekeeper.get_indicator(resource)
236
237 def _calculate_new_resource(self, main, new_main, resource):
238 if new_main is None:
239 return None
240 diff = resource.path[len(main.path):]
241 return resource.project.get_resource(new_main.path + diff)
242
243
244 class ChangeIndicator(object):
245
246 def get_indicator(self, resource):
247 """Return the modification time and size of a `Resource`."""
248 path = resource.real_path
249 # on dos, mtime does not change for a folder when files are added
250 if os.name != 'posix' and os.path.isdir(path):
251 return (os.path.getmtime(path),
252 len(os.listdir(path)),
253 os.path.getsize(path))
254 return (os.path.getmtime(path),
255 os.path.getsize(path))
256
257
258 class _Changes(object):
259
260 def __init__(self):
261 self.changes = set()
262 self.creations = set()
263 self.moves = {}
264
265 def add_changed(self, resource):
266 self.changes.add(resource)
267
268 def add_removed(self, resource, new_resource=None):
269 self.moves[resource] = new_resource
270
271 def add_created(self, resource):
272 self.creations.add(resource)
OLDNEW
« no previous file with comments | « tools/telemetry/third_party/rope/rope/base/pyscopes.py ('k') | tools/telemetry/third_party/rope/rope/base/resources.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698