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

Side by Side Diff: tools/telemetry/third_party/rope/docs/library.rst

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 =========================
2 Using Rope As A Library
3 =========================
4
5 If you need other features, send a feature request. Have a look at
6 `contributing.rst`_.
7
8
9 .. contents:: Table of Contents
10
11
12 Quick Start
13 ===========
14
15 This section will help you get started as soon as possible.
16
17
18 Making A Project
19 ----------------
20
21 The first thing you should do is make a project:
22
23 .. code-block:: python
24
25 import rope.base.project
26
27
28 myproject = rope.base.project.Project('/path/to/myproject')
29
30 It's good to know that:
31
32 * A project is a folder in the file-system.
33 * It can contain anything.
34 * Rope searches for python modules and packages inside a project when
35 needed.
36 * Refactorings only change files and folders inside the project that
37 has been passed to them.
38 * Out of project modules that are imported from a module inside a
39 project are handled but never changed by refactorings.
40 * Rope makes a rope folder inside projects. By default the name of this
41 folder is ``.ropeproject``, but that can be changed using the
42 constructor's ``ropefolder`` parameter. Passing ``None`` prevents rope
43 from making this folder.
44 * Rope uses the ``.ropeproject`` folder for things like saving object
45 information and loading project configurations.
46 * Project preferences can be configured by passing options to the
47 constructor or in ``.ropeproject/config.py``. See the default
48 ``config.py``, ``rope.base.default_config`` module, for more
49 information.
50 * All configurations that are available in the ``config.py`` file can
51 be specified as keyword parameters to the ``Project`` constructor.
52 These parameters override the ones in the ``config.py`` file.
53 * Each project has a set of ignored resource patterns. You can use it
54 to tell rope to ignore files and folders matching certain patterns.
55 * The ``.ropeproject`` folder can be safely copied in other clones of
56 a project if you don't want to lose your objectdb and history.
57
58
59 Library Utilities
60 -----------------
61
62 The `rope.base.libutils`_ module provides tools that make using rope as a
63 library easier. We'll talk more about this module later.
64
65
66 What Are These `Resource`\s?
67 ----------------------------
68
69 In rope, files and folders in a project are accessed through
70 ``rope.base.resources.Resource`` objects. It has two subclasses
71 ``File`` and ``Folder``. What we care about is that refactorings and
72 ``Change``\s (we'll talk about them later) use resources.
73
74 There are two options for creating a ``Resource`` for a path in a project.
75 The first approach uses the `Project.get_resource()`_ method.
76
77 .. code-block:: python
78
79 from rope.base import project
80
81
82 myresource = myproject.get_resource('/path/to/resource')
83
84 However, it's preferable to use the ``libutils.path_to_resource()``
85 function, because it's more flexible and offers a unified way to create
86 resources. It takes a ``project`` and ``path`` as parameters with an
87 optional ``type``. The ``type`` parameter, with values ``file`` or
88 ``folder``, can create a resource for an object that doesn't exist yet.
89
90 .. code-block:: python
91
92 from rope.base import libutils
93
94
95 myresource = libutils.path_to_resource(myproject, '/path/to/resource')
96
97
98 Consider we have a resource. How can we know anything about it? The
99 answer is to use its ``path`` and ``real_path`` attributes.
100 ``Resource.real_path`` is the absolute path of the resource in the
101 file-system. The ``Resource.path`` attribute contains the address of a
102 resource relative to the project's root.
103
104
105 Performing Refactorings
106 -----------------------
107
108 As a short example of performing refactorings, we'll show how to extract
109 a variable from a file. First we need the ``Resource`` object that
110 points to a file in a project:
111
112 .. code-block:: python
113
114 resource = libutils.path_to_resource(myproject, '/path/to/my/module.py')
115
116 Now we can make our Refactoring class:
117
118 .. code-block:: python
119
120 from rope.refactor.extract import ExtractVariable
121
122
123 extractor = ExtractVariable(myproject, resource, start, end)
124
125 Where ``start`` and ``end`` are the offsets of the region to extract in
126 ``resource``. Be careful when calculating the offsets. DOS
127 line-endings and multi-byte characters are considered to be one
128 character. This is actually easier for IDEs, since most GUI libraries
129 handle those cases for you.
130
131 Next, the IDE ask the user to configure refactoring options, like
132 specifying the name of the extracted variable.
133
134 After that, we can calculate the changes:
135
136 .. code-block:: python
137
138 changes = extractor.get_changes('extracted_variable')
139
140 Each refactoring returns a ``rope.base.change.Change`` object that holds
141 the changes it made. Calculating those changes can be time consuming.
142 See the `rope.base.taskhandle.TaskHandle`_ section for measuring its
143 progress or interrupting it.
144
145
146 Previewing And Performing Changes
147 ---------------------------------
148
149 As mentioned in the last section each refactoring returns a
150 ``rope.base.change.Change`` object. Now how can we know what it
151 contains and how to perform it?
152
153 *Previewing*:
154
155 You can use ``changes.get_description()`` to get a preview. It is useful
156 when you don't care much about the format. Otherwise you can use the
157 ``changes`` object directly. See the documentation in
158 ``rope.base.change`` module.
159
160 *Performing*:
161
162 The easiest way for performing the refactoring is to use the
163 `Project.do()`_ method:
164
165 .. code-block:: python
166
167 myproject.do(changes)
168
169 If you want to perform the changes yourself, you have two options.
170 Note that the main reason for performing the changes manually is
171 handling version control systems that are not supported by rope.
172
173 1. The first approach is to use `rope.base.fscommands`_ (see `Writing A
174 FileSystemCommands`_). The changes can be performed as before using
175 `Project.do()`_.
176
177 2. The second approach is to perform the changes manually based on the
178 returned ``changes`` object (again see the documentation in
179 ``rope.base.change`` module). If this approach is used you cannot undo
180 the refactoring using ``project.history.undo()``.
181
182 *Updating Open Buffers In IDEs*:
183
184 Usually editors need to reload the files changed by rope. You can use
185 ``Change.get_changed_resources()`` to get the list of resources that
186 need to be reloaded.
187
188
189 Validating The Project
190 ----------------------
191
192 When using rope as a library, you probably change the files in it in
193 parallel (for example in IDEs). To force rope to invalidate cached
194 information about resources that have been removed or changed outside
195 rope, you should call the `Project.validate()`_ method. You can pass a
196 resource to this method. For example:
197
198 .. code-block:: python
199
200 myproject.validate(resource)
201
202 This validates all files and directories in resource. Call this
203 function every time you want use rope (i.e., before performing
204 refactorings).
205
206
207 Performing Static Object Analysis
208 ---------------------------------
209
210 One of the greatest strengths of rope is its Static Object Analysis
211 (SOA). It analyzes function calls and assignments to collect the types
212 of objects passed to the function. Rope uses the collected data to infer
213 the type of function parameters, return values, and the objects stored
214 in built-in containers. The function
215 ``rope.base.libutils.analyze_modules()`` performs SOA on all modules in
216 the project. It is recommended that you call this function occasionally,
217 and especially before performing large refactorings. Note that analyzing
218 all modules of a project may take a long time.
219
220 If you have ``automatic_soa`` set, which instructs rop to analyze the
221 changed scopes of modules, then you should report the changes by calling
222 ``rope.base.libutils.report_change()`` when saving files, as follows:
223
224 .. code-block:: python
225
226 # Save the new contents.
227 old_contents = resource.read()
228 resource.write(new_contents)
229
230 # Inform rope about the change.
231 libutils.report_change(myproject, path, old_contents)
232
233 Note, however, that the use of ``automatic_soa`` is discouraged, because it may
234 slow down saving considerably.
235
236
237 Closing The Project
238 -------------------
239
240 `Project.close()`_ closes a project's open resources. Always call this
241 function when you don't need a project anymore:
242
243 .. code-block:: python
244
245 myproject.close()
246
247
248 ``rope.base.libutils``
249 ======================
250
251 The ``rope.base.libutils`` module contains functions that make life
252 easier for building refactoring tools. In some cases, the functions
253 offer a unified way to access or create objects. You're encouraged to
254 use ``rope.base.libutils`` functions whenever possible, because the APIs
255 here may not be as volatile as class methods.
256
257
258 ``libutils.analyze_module()``
259 ------------------------------
260
261 Perform static object analysis on a Python file in the project. Note,
262 this may be a very time consuming task.
263
264 .. code-block:: python
265
266 libutils.analyze_module(myproject, resource)
267
268
269 ``libutils.analyze_modules()``
270 ------------------------------
271
272 Perform static object analysis on all Python files in the project. Note
273 that it might take a long time to finish.
274
275 .. code-block:: python
276
277 libutils.analyze_modules(myproject)
278
279
280 ``libutils.get_string_module()``
281 --------------------------------
282
283 Returns a ``rope.base.pyobjects.PyModule`` object for the code string.
284 An optional ``resource`` argument can be specified for the resource this
285 code is associated with. If ``force_errors` is ``True``, then
286 ``rope.base.exceptions.ModuleSyntaxError`` is raised when the code has
287 syntax errors. Otherwise, syntax errors are silently ignored. Note that
288 ``force_errors`` overrides the ``ignore_syntax_errors`` project
289 configuration flag.
290
291 .. code-block:: python
292
293 pymodule = libutils.get_string_module(myproject, source)
294
295
296 ``libutils.get_string_scope()``
297 -------------------------------
298
299 Get the ``rope.base.pyscopes.GlobalScope`` object for the code string.
300 This is the outermost scope of the code encompassing the whole module.
301
302 .. code-block:: python
303
304 scope = libutils.get_string_scope(myproject, source)
305
306
307 ``libutils.is_python_file()``
308 -----------------------------
309
310 Returns ``True`` if the resource is a Python file.
311
312 .. code-block:: python
313
314 libutils.is_python_file(myproject, resource)
315
316
317 ``libutils.modname()``
318 ----------------------
319
320 Retrieves the dotted path string to the module that contains that given
321 resource.
322
323 .. code-block:: python
324
325 # If resource is 'path/to/resource.py' relative to the project's root
326 # directory, this returns the string: 'path.to.resource'.
327 module_name = libutils.modname(resource)
328
329
330 ``libutils.path_relative_to_project_root()``
331 --------------------------------------------
332
333 Retrieve the path relative to the project's root directory.
334
335 .. code-block:: python
336
337 # Get the path relative to the project's root directory.
338 relpath = libutils.relative(myproject.address, path)
339
340
341 ``libutils.path_to_resource()``
342 -------------------------------
343
344 Get the resource --- a file or folder --- at the given path. An optional
345 ``type`` argument can be used if the resource doesn't yet exist. The
346 values for ``type`` are the strings ``'file'`` or ``'folder'``.
347
348 .. code-block:: python
349
350 # Resource for an existing file.
351 myfile = libutils.path_to_resource(myproject, '/path/to/file.py')
352
353 # Resource for a non-existing folder.
354 new_folder = libutils.path_to_resource(myproject, '/path/to/folder', type='fol der')
355
356
357 ``rope.base.project.Project``
358 =============================
359
360 You can create a project by:
361
362 .. code-block:: python
363
364 project = Project(root_address)
365
366 Where the ``root_address`` is the root folder of your project.
367
368 A project has some useful attributes. ``Project.address`` is the
369 address of the root folder of a project. ``Project.root`` is a
370 ``Folder`` object that points to that folder.
371
372
373 `Project.do()`
374 --------------
375
376 Used to commit changes returned by refactorings:
377
378 .. code-block:: python
379
380 project.do(changes)
381
382
383 `Project.history`
384 -----------------
385
386 A ``rope.base.history.History`` object. You can use its ``undo`` and
387 ``redo`` methods for undoing or redoing changes. Note that you can use
388 this only if you have committed your changes using rope.
389
390
391 `Project.validate()`
392 --------------------
393
394 When using rope as a library, you will probably change the files in that
395 project in parallel (for example in IDEs). To force rope to validate
396 cached information about resources that have been removed or changed
397 outside rope, you should call ``Project.validate()``. You should pass a
398 resource to this method. For example:
399
400 .. code-block:: python
401
402 project.validate(project.root)
403
404 This validates all files and directories in the project and clears the
405 cache of all recorded changes.
406
407
408 `Project.close()`
409 -----------------
410
411 Closes a project's open resources. Always call this function when you
412 don't need a project anymore. Currently it closes the files used for
413 storing object information and project history. Because some parts of
414 these files are in memory for efficiency, not closing a project might
415 put them in an inconsistent state.
416
417
418 `rope.base.fscommands`
419 ======================
420
421 The ``rope.base.fscommands`` module implements basic file system
422 operations that rope needs to perform. The main reason for the
423 existence of this module is supporting version control systems. Have a
424 look at ``FileSystemCommands`` and ``SubversionCommands`` in the same
425 module. If you need other version control systems you can write a new
426 class that provides this interface. ``rope.base.project.Project``
427 accepts an ``fscommands`` argument. You can use this argument to force
428 rope to use your new class.
429
430
431 ``.ropeproject`` Folder
432 =======================
433
434 Since version ``0.5``, rope makes a ``.ropeproject`` folder in the
435 project by default for saving project configurations and data. The name
436 of this folder is passed to the constructor if you want to change that.
437 You can force rope not to make such a folder by passing ``None``.
438
439 If such a folder exists, rope loads the ``config.py`` file in that
440 folder. It might also use it for storing object information and
441 history.
442
443
444 `rope.base.pycore.PyCore`
445 =========================
446
447 Provides useful methods for managing python modules and packages. Each
448 project has a ``PyCore`` that can be accessed using the
449 ``Project.pycore`` attribute.
450
451 ``PyCore.run_module()`` runs a resource. When running, it collects type
452 information to do dynamic object inference. For this reason modules
453 run much slower.
454
455 Also ``Pycore.analyze_module()`` collects object information for a
456 module. The collected information can be used to enhance rope's
457 static object inference.
458
459
460 `rope.base.taskhandle.TaskHandle`
461 =================================
462
463 A TaskHandle can be used for stopping and monitoring the progress of
464 time consuming tasks, like some refactorings. The ``Project.do()`` and
465 ``Refactoring.get_changes()`` methods for most refactorings take a
466 keyword parameter called ``task_handle``. You can pass a ``TaskHandle``
467 object to them. A ``TaskHandle`` can be used for interrupting or
468 observing a task.
469
470 Always pass ``task_handle`` as keyword argument. It will always be the
471 last argument, and new arguments of the refactoring are added before it.
472
473 A task might consist of a few ``JobSet``\s. Each ``JobSet`` performs a
474 few jobs. For instance calculating the changes for renaming a method in
475 a class hierarchy has two job sets: one to find the classes for
476 constructing the class hierarchy and another to change the occurrences.
477
478 The ``TaskHandle.current_jobset()`` returns the most recent ``JobSet``
479 or ``None`` if none has been started. You can use the methods of
480 ``JobSet`` for obtaining information about the current job. So you
481 might want to do something like:
482
483 .. code-block:: python
484
485 import rope.base.taskhandle
486
487
488 handle = rope.base.taskhandle.TaskHandle("Test Task")
489
490 def update_progress():
491 jobset = handle.current_jobsets()
492 if jobset:
493 text = ''
494 # getting current job set name
495 if jobset.get_name() is not None:
496 text += jobset.get_name()
497 # getting active job name
498 if jobset.get_active_job_name() is not None:
499 text += ' : ' + jobset.get_active_job_name()
500 # adding done percent
501 percent = jobset.get_percent_done()
502 if percent is not None:
503 text += ' ... %s percent done' % percent
504 print text
505
506 handle.add_observer(update_progress)
507
508 changes = renamer.get_changes('new_name', task_handle=handle)
509
510 Also you can use something like this for stopping the task:
511
512 .. code-block:: python
513
514 def stop():
515 handle.stop()
516
517 After calling ``stop()``, the thread that is executing the task will
518 be interrupted by a ``rope.base.exceptions.InterruptedTaskError``
519 exception.
520
521
522 Refactorings
523 ============
524
525 Have a look at ``rope.refactor`` package and its sub-modules. For
526 example for performing a move refactoring you can create a ``Move``
527 object like this:
528
529 .. code-block:: python
530
531 mover = Move(project, resource, offset)
532
533 Where ``resource`` and ``offset`` is the location to perform the
534 refactoring.
535
536 Then you can commit the changes by it using the ``get_changes()``
537 method:
538
539 .. code-block:: python
540
541 project.do(mover.get_changes(destination))
542
543 Where the ``destination`` module/package is the destination resource for
544 move refactoring. Other refactorings classes have a similar interface.
545
546
547 List Of Refactorings
548 --------------------
549
550 Here is the list of refactorings rope provides. (Note that this list
551 might be out of date.) For more information about these refactoring see
552 pydocs in their modules and the unit-tests in the ``ropetest/refactor/``
553 folder.
554
555 * ``rope.refactor.rename``:
556 Rename something in the project. See the example below.
557
558 * ``rope.refactor.move``:
559 Move a python element in the project.
560
561 * ``rope.refactor.restructure``:
562 Restructure code. See the example below.
563
564 * ``rope.refactor.extract``:
565 Extract methods/variables.
566
567 * ``rope.refactor.inline``:
568 Inline occurrences of a method/variable/parameter.
569
570 * ``rope.refactor.usefunction``:
571 Try to use a function wherever possible.
572
573 * ``rope.refactor.method_object``:
574 Transform a function or a method to a method object.
575
576 * ``rope.refactor.change_signature``:
577 Change the signature of a function/method.
578
579 * ``rope.refactor.introduce_factory``:
580 Introduce a factory for a class and changes all constructors to use
581 it.
582
583 * ``rope.refactor.introduce_parameter``:
584 Introduce a parameter in a function.
585
586 * ``rope.refactor.encapsulate_field``:
587 Generate a getter/setter for a field and changes its occurrences to
588 use them.
589
590 * ``rope.refactor.localtofield``:
591 Change a local variable to field.
592
593 * ``rope.refactor.topackage``:
594 Transform a module to a package with the same name.
595
596 * ``rope.refactor.importutils``:
597 Perform actions like organize imports.
598
599
600 Refactoring Resources Parameter
601 -------------------------------
602
603 Some refactorings, restructure and find occurrences accept an argument
604 called ``resources``. If it is a list of `File`\s, all other
605 resources in the project are ignored and the refactoring only analyzes
606 them. If it is ``None`` all python modules in the project will be
607 analyzed. Using this parameter, IDEs can let the user limit the files
608 on which a refactoring should be applied.
609
610
611 Examples
612 ========
613
614 Rename
615 ------
616
617 Using rename refactoring:
618
619 .. code-block:: python
620
621 # Creating a project
622 >>> from rope.base.project import Project
623 >>> project = Project('.')
624
625 # Working with files to create a module
626 >>> mod1 = project.root.create_file('mod1.py')
627 >>> mod1.write('a_var = 10\n')
628
629 # Alternatively you can use `generate` module.
630 # Creating modules and packages using `generate` module
631 >>> from rope.contrib import generate
632 >>> pkg = generate.create_package(project, 'pkg')
633 >>> mod2 = generate.create_module(project, 'mod2', pkg)
634 >>> mod2.write('import mod1\nprint mod1.a_var\n')
635
636 # We can use `Project.find_module` for finding modules, too
637 >>> assert mod2 == project.find_module('pkg.mod2')
638
639 # Performing rename refactoring on `mod1.a_var`
640 >>> from rope.refactor.rename import Rename
641 >>> changes = Rename(project, mod1, 1).get_changes('new_var')
642 >>> project.do(changes)
643 >>> mod1.read()
644 u'new_var = 10\n'
645 >>> mod2.read()
646 u'import mod1\nprint mod1.new_var\n'
647
648 # Undoing rename refactoring
649 >>> project.history.undo()
650 ...
651 >>> mod1.read()
652 u'a_var = 10\n'
653 >>> mod2.read()
654 u'import mod1\nprint mod1.a_var\n'
655
656 # Cleaning up
657 >>> pkg.remove()
658 >>> mod1.remove()
659 >>> project.close()
660
661
662 Restructuring
663 -------------
664
665 The example for replacing occurrences of our ``pow`` function to ``**``
666 operator (see the restructuring section of `overview.rst`_):
667
668 .. code-block:: python
669
670 # Setting up the project
671 >>> from rope.base.project import Project
672 >>> project = Project('.')
673
674 >>> mod1 = project.root.create_file('mod1.py')
675 >>> mod1.write('def pow(x, y):\n result = 1\n'
676 ... ' for i in range(y):\n result *= x\n'
677 ... ' return result\n')
678 >>> mod2 = project.root.create_file('mod2.py')
679 >>> mod2.write('import mod1\nprint(mod1.pow(2, 3))\n')
680
681 >>> from rope.refactor import restructure
682
683 >>> pattern = '${pow_func}(${param1}, ${param2})'
684 >>> goal = '${param1} ** ${param2}'
685 >>> args = {'pow_func': 'name=mod1.pow'}
686
687 >>> restructuring = restructure.Restructure(project, pattern, goal, args)
688
689 >>> project.do(restructuring.get_changes())
690 >>> mod2.read()
691 u'import mod1\nprint(2 ** 3)\n'
692
693 # Cleaning up
694 >>> mod1.remove()
695 >>> mod2.remove()
696 >>> project.close()
697
698
699 See code documentation and test suites for more information.
700
701 .. _overview.rst: overview.rst
702 .. _contributing.rst: contributing.rst
703
704
705 Other Topics
706 ============
707
708
709 Writing A `FileSystemCommands`
710 ------------------------------
711
712 The ``get_changes()`` method of refactoring classes return a
713 ``rope.base.change.Change`` object. You perform these changes by
714 calling ``Project.do()``. But as explained above some IDEs need to
715 perform the changes themselves.
716
717 Every change to the file-system in rope is commited using an object that
718 provides a ``rope.base.fscommands.FileSystemCommands`` interface. As
719 explained above in `rope.base.fscommands`_ section, rope uses this
720 interface to handle different VCSs.
721
722 You can implement your own fscommands object:
723
724 .. code-block:: python
725
726 class MyFileSystemCommands(object):
727
728 def create_file(self, path):
729 """Create a new file"""
730 # ...
731
732 def create_folder(self, path):
733 """Create a new folder"""
734 # ...
735
736 def move(self, path, new_location):
737 """Move resource at `path` to `new_location`"""
738 # ...
739
740 def remove(self, path):
741 """Remove resource"""
742 # ...
743
744 def write(self, path, data):
745 """Write `data` to file at `path`"""
746 # ...
747
748 And you can create a project like this:
749
750 .. code-block:: python
751
752 my_fscommands = MyFileSystemCommands()
753 project = rope.base.project.Project('~/myproject',
754 fscommands=my_fscommands)
755
756
757 `rope.contrib.codeassist`
758 -------------------------
759
760 The ``rope.contrib`` package contains modules that use rope base parts
761 and provide useful features. ``rope.contrib.codeassist`` module can be
762 used in IDEs:
763
764 .. code-block:: python
765
766 from rope.ide import codeassist
767
768
769 # Get the proposals; you might want to pass a Resource
770 proposals = codeassist.code_assist(project, source_code, offset)
771
772 # Sorting proposals; for changing the order see pydoc
773 proposals = codeassist.sorted_proposals(proposals)
774
775 # Where to insert the completions
776 starting_offset = codeassist.starting_offset(source_code, offset)
777
778 # Applying a proposal
779 proposal = proposals[x]
780 replacement = proposal.name
781
782 new_source_code = (source_code[:starting_offset] +
783 replacement + source_code[offset:])
784
785 ``maxfixes`` parameter of ``code_assist`` decides how many syntax errors
786 to fix. The default value is one. For instance:
787
788 .. code-block:: python
789
790 def f():
791 g(my^
792
793 myvariable = None
794
795 def g(p):
796 invalid syntax ...
797
798 will report ``myvariable``, only if ``maxfixes`` is greater than 1.
799
800 ``later_locals``, if ``True``, forces rope to propose names that are
801 defined later in current scope. It is ``True`` by default. For
802 instance:
803
804 .. code-block:: python
805
806 def f():
807 my^
808 myvariable = None
809
810 will not report ``myvariable``, if ``later_locals`` is ``False``.
811
812 See pydocs and source code for more information (other functions in
813 this module might be interesting, too; like ``get_doc``,
814 ``get_definition_location``).
815
816
817 `rope.contrib.findit`
818 ---------------------
819
820 ``findit`` module provides ``find_occurrences()`` for finding
821 occurrences of a name. Also the ``find_implementations()`` function
822 finds the places in which a method is overridden.
823
824
825 `rope.contrib.autoimport`
826 -------------------------
827
828 This module can be used to find the modules that provide a name. IDEs
829 can use this module to auto-import names. ``AutoImport.get_modules()``
830 returns the list of modules with the given global name.
831 ``AutoImport.import_assist()`` tries to find the modules that have a
832 global name that starts with the given prefix.
833
834
835 Cross-Project Refactorings
836 --------------------------
837
838 ``rope.refactor.multiproject`` can be used to perform a refactoring
839 across multiple projects.
840
841 Usually refactorings have a main project. That is the project that
842 contains the definition of the changing python name. Other projects
843 depend on the main one, and the uses of the changed name in them should
844 be updated.
845
846 Each refactoring changes only one project (the project passed to its
847 constructor). But we can use the ``MultiProjectRefactoring`` proxy to
848 perform a refactoring on other projects, too.
849
850 First we need to create a multi-project refactoring constructor. As
851 an example consider that we want to perform a rename refactoring:
852
853 .. code-block:: python
854
855 from rope.refactor import multiproject, rename
856
857
858 CrossRename = multiproject.MultiProjectRefactoring(rename.Rename,
859 projects)
860
861
862 Here ``projects`` is the list of dependant projects. It does not
863 include the main project. The first argument is the refactoring class
864 (such as ``Rename``) or factory function (like ``create_move``).
865
866 Next we can construct the refactoring:
867
868 .. code-block:: python
869
870 renamer = CrossRename(project, resource, offset)
871
872 We create the rename refactoring as we do for normal refactoings. Note
873 that ``project`` is the main project.
874
875 As mentioned above, other projects use the main project. Rope
876 automatically adds the main project to the python path of other
877 projects.
878
879 Finally we can calculate the changes. But instead of calling
880 ``get_changes()`` (which returns main project changes only), we can
881 call ``get_all_changes()`` with the same arguments. It returns a list
882 of ``(project, changes)`` tuples. You can perform them manually by
883 calling ``project.do(changes)`` for each tuple, or use
884 ``multiproject.perform()``:
885
886 .. code-block:: python
887
888 project_and_changes = renamer.get_all_changes('newname')
889
890 multiproject.perform(project_and_changes)
OLDNEW
« no previous file with comments | « tools/telemetry/third_party/rope/docs/done.rst ('k') | tools/telemetry/third_party/rope/docs/overview.rst » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698