Commit 835afd55 authored by Arnaud Fontaine's avatar Arnaud Fontaine

Import rope_0.10.3.orig.tar.gz

parent 46d8917b
Metadata-Version: 1.1
Name: rope
Version: 0.10.2
Version: 0.10.3
Summary: a python refactoring library...
Home-page: http://rope.sf.net/
Author: Ali Gholami Rudi
......@@ -8,8 +8,6 @@ Author-email: aligrudi@users.sourceforge.net
License: GNU GPL
Description:
**Note:** *Please note that this project has been moved to* `GitHub python-rope / rope`_
.. _GitHub python-rope / rope: https://github.com/python-rope/rope
......@@ -23,7 +21,7 @@ Description:
`Rope`_ is a python refactoring library.
.. _`rope`: http://rope.sf.net/
.. _`rope`: https://github.com/python-rope/rope
New Features
......
**Note:** *Please note that this project has been moved to* `GitHub python-rope / rope`_
.. _GitHub python-rope / rope: https://github.com/python-rope/rope
......@@ -14,7 +12,7 @@ Overview
`Rope`_ is a python refactoring library.
.. _`rope`: http://rope.sf.net/
.. _`rope`: https://github.com/python-rope/rope
New Features
......
......@@ -3,19 +3,19 @@
======================
Get Involved!
=============
Getting Involved!
=================
Rope's main goal is being a good refactoring tool for python. It also
provides some IDE helpers. If you like to contribute, you're welcome!
provides some IDE helpers. If you would like to contribute, you're
welcome to!
How to Help Rope?
=================
Rope mailing list is `rope-dev (at) googlegroups.com`_. You can send
a mail to ``rope-dev-subscribe (at) googlegroups [dot] com`` to
subscribe.
Rope's mailing list is `rope-dev (at) googlegroups.com`_. Click the
"Join group to post" button to subscribe. Then:
* Use rope
* Send bug reports and request features
......@@ -28,8 +28,8 @@ subscribe.
Wish List
=========
You are welcome to send your patches to `rope-dev (at)
googlegroups.com`_ mailing list. Here is only a list of suggestions.
You are welcome to send your patches to the `rope-dev (at)
googlegroups.com`_ mailing list. Here is a list of suggestions.
Issues
------
......@@ -78,12 +78,8 @@ more information.
Source Repository
=================
Rope uses Mercurial_ CMS:
* Rope main branch: http://bitbucket.org/agr/rope
* Rope py3k branch: http://bitbucket.org/agr/rope_py3k
.. _Mercurial: http://selenic.com/mercurial
Rope uses GitHub_. The repository exists at
`https://github.com/python-rope/rope`_.
Submitting patches
......@@ -91,11 +87,21 @@ Submitting patches
Patches are welcome.
Patch style
-----------
Programming Style
-----------------
* Follow :PEP:`8`.
* Use four spaces for indentation.
* Include good unit-tests if possible.
* Include good unit-tests when appropriate.
* Rope test suite should pass after patching
* Use ``hg export`` format to preserve your identity
Sending Patches
---------------
Follow the instructions on GitHub_ on how to setup Git and fork the
`python-rope/rope`_ repository. Once your changes are ready, send a
`pull request`_ for review.
.. _GitHub: http://github.com/
.. _`python-rope/rope`: https://github.com/python-rope/rope
.. _`pull request`: https://help.github.com/articles/using-pull-requests
......@@ -18,7 +18,9 @@ This section will help you get started as soon as possible.
Making A Project
----------------
The first thing you should do is to make a project::
The first thing you should do is make a project:
.. code-block:: python
import rope.base.project
......@@ -35,20 +37,20 @@ It's good to know that:
has been passed to them.
* Out of project modules that are imported from a module inside a
project are handled but never changed by refactorings.
* Rope makes a rope folder inside projects. By default the name of
this folder is ``.ropeproject`` but that can be changed using the
constructor's `ropefolder` parameter (passing `None` will prevent
rope from making this folder).
* Rope uses ``.ropeproject`` folder for things like saving object
* Rope makes a rope folder inside projects. By default the name of this
folder is ``.ropeproject``, but that can be changed using the
constructor's ``ropefolder`` parameter. Passing ``None`` prevents rope
from making this folder.
* Rope uses the ``.ropeproject`` folder for things like saving object
information and loading project configurations.
* Project preferences can be configured by passing options to the
constructor or in ``.ropeproject/config.py``. See the default
``config.py``, `rope.base.default_config` module, for more
``config.py``, ``rope.base.default_config`` module, for more
information.
* All configurations that are available in the ``config.py`` file can
be specified as keyword parameters to `Project` constructor. These
parameters override the ones in the ``config.py`` file.
* Each project has a set of ignored resource patterns; You can use it
be specified as keyword parameters to the ``Project`` constructor.
These parameters override the ones in the ``config.py`` file.
* Each project has a set of ignored resource patterns. You can use it
to tell rope to ignore files and folders matching certain patterns.
* The ``.ropeproject`` folder can be safely copied in other clones of
a project if you don't want to lose your objectdb and history.
......@@ -57,92 +59,110 @@ It's good to know that:
Library Utilities
-----------------
The `rope.base.libutils` module provides tools for making using rope
as a library easier. We'll talk more about this module later.
The `rope.base.libutils`_ module provides tools that make using rope as a
library easier. We'll talk more about this module later.
What Are These `Resource`\s?
----------------------------
In rope, files and folders in a project are accessed through
`rope.base.resources.Resource` objects. It has two subclasses `File`
and `Folder`. What we care about is that refactorings and `Change`\s
(we'll talk about them later) use resources.
``rope.base.resources.Resource`` objects. It has two subclasses
``File`` and ``Folder``. What we care about is that refactorings and
``Change``\s (we'll talk about them later) use resources.
There are two options for creating a ``Resource`` for a path in a project.
The first approach uses the `Project.get_resource()`_ method.
.. code-block:: python
from rope.base import project
myresource = myproject.get_resource('/path/to/resource')
In order to create a `Resource` for a path in a project we have two
options. The first approach uses the `Project` object (use
`Project.get_resource()`_ method). I prefer to describe the second
approach since it needs less to know.
However, it's preferable to use the ``libutils.path_to_resource()``
function, because it's more flexible and offers a unified way to create
resources. It takes a ``project`` and ``path`` as parameters with an
optional ``type``. The ``type`` parameter, with values ``file`` or
``folder``, can create a resource for an object that doesn't exist yet.
We can use `libutils` module. It has a function named
`path_to_resource()`. It takes a project and a path::
.. code-block:: python
from rope.base import libutils
myresource = libutils.path_to_resource(myproject, '/path/to/resource')
But this is only half of the answer. Consider we have a resource.
How can we know anything about it? The answer is to use its ``path``
and ``real_path`` fields. `Resource.real_path` is the absolute path
of the resource in the file-system. `Resource.path` field contains
the address of a resource relative to project root (the same format as
needed by `Project.get_resource()`_).
Consider we have a resource. How can we know anything about it? The
answer is to use its ``path`` and ``real_path`` attributes.
``Resource.real_path`` is the absolute path of the resource in the
file-system. The ``Resource.path`` attribute contains the address of a
resource relative to the project's root.
Performing Refactorings
-----------------------
There are examples at the end of this document. But as another
example we'll extract a variable in a file. First we need the
`Resource` object that points to a file in a project::
As a short example of performing refactorings, we'll show how to extract
a variable from a file. First we need the ``Resource`` object that
points to a file in a project:
.. code-block:: python
resource = libutils.path_to_resource(myproject, '/path/to/my/module.py')
So we can make our Refactoring class::
Now we can make our Refactoring class:
.. code-block:: python
from rope.refactor.extract import ExtractVariable
extractor = ExtractVariable(myproject, resource, start, end)
Where `start` and `end` are the offsets of the region to extract in
resource. Be careful when calculating the offsets. Dos line-endings
and multi-byte characters are considered to be only one character.
This is actually easier for IDEs, since most GUI libraries do that
when calculating offsets.
Where ``start`` and ``end`` are the offsets of the region to extract in
``resource``. Be careful when calculating the offsets. DOS
line-endings and multi-byte characters are considered to be one
character. This is actually easier for IDEs, since most GUI libraries
handle those cases for you.
Next, IDE's usually pop up a dialog for letting the user configure
refactoring options like the name of the extracted variable.
Next, the IDE ask the user to configure refactoring options, like
specifying the name of the extracted variable.
After that, we can calculate the changes::
After that, we can calculate the changes:
.. code-block:: python
changes = extractor.get_changes('extracted_variable')
`changes` holds the changes this refactoring makes. Calculating it
might be time consuming; See `rope.base.taskhandle.TaskHandle`_
section for measuring its progress or interrupting it.
Each refactoring returns a ``rope.base.change.Change`` object that holds
the changes it made. Calculating those changes can be time consuming.
See the `rope.base.taskhandle.TaskHandle`_ section for measuring its
progress or interrupting it.
Previewing And Performing Changes
---------------------------------
As mentioned in the last section each refactoring returns a
`rope.base.change.Change` object. Now how can we know what it
``rope.base.change.Change`` object. Now how can we know what it
contains and how to perform it?
*Previewing*:
``str(changes)`` returns a short description of the changes. You can
use ``changes.get_description()`` to get a preview; it is useful when
you don't care much about the format. Otherwise you can use the
You can use ``changes.get_description()`` to get a preview. It is useful
when you don't care much about the format. Otherwise you can use the
``changes`` object directly. See the documentation in
`rope.base.change` module.
``rope.base.change`` module.
*Performing*:
The easiest way for performing the refactoring is to use
`Project.do()`_ method::
The easiest way for performing the refactoring is to use the
`Project.do()`_ method:
.. code-block:: python
myproject.do(changes)
......@@ -150,14 +170,14 @@ If you want to perform the changes yourself, you have two options.
Note that the main reason for performing the changes manually is
handling version control systems that are not supported by rope.
The first approach is to use `rope.base.fscommands`_. See `Writing A
FileSystemCommands`_ section. The changes can be performed as before
using `Project.do()`.
1. The first approach is to use `rope.base.fscommands`_ (see `Writing A
FileSystemCommands`_). The changes can be performed as before using
`Project.do()`_.
The other is to perform the changes manually based on the returned
`changes` object (again see the documentation in `rope.base.change`
module). If this approach is used you cannot undo the refactoring
using ``project.history.undo()``.
2. The second approach is to perform the changes manually based on the
returned ``changes`` object (again see the documentation in
``rope.base.change`` module). If this approach is used you cannot undo
the refactoring using ``project.history.undo()``.
*Updating Open Buffers In IDEs*:
......@@ -172,139 +192,251 @@ Validating The Project
When using rope as a library, you probably change the files in it in
parallel (for example in IDEs). To force rope to invalidate cached
information about resources that have been removed or changed outside
rope you should call `Project.validate()`_ method. You can pass a
resource to this method. For example::
rope, you should call the `Project.validate()`_ method. You can pass a
resource to this method. For example:
myproject.validate()
.. code-block:: python
validates all files and directories in the project. So call this
function every time you want use rope (before performing refactorings,
for instance).
myproject.validate(resource)
This validates all files and directories in resource. Call this
function every time you want use rope (i.e., before performing
refactorings).
Activating Static Object Analysis
Performing Static Object Analysis
---------------------------------
One of the greatest strengths of rope is its static object analysis,
SOA. You can perform SOA on a module using `PyCore.analyze_module()`
method but performing SOA on a module is not cheap. So I decided that
the best time for performing SOA is when saving files and only
performing it on changed scopes.
One of the greatest strengths of rope is its Static Object Analysis
(SOA). It analyzes function calls and assignments to collect the types
of objects passed to the function. Rope uses the collected data to infer
the type of function parameters, return values, and the objects stored
in built-in containers. The function
``rope.base.libutils.analyze_modules()`` performs SOA on all modules in
the project. It is recommended that you call this function occasionally,
and especially before performing large refactorings. Note that analyzing
all modules of a project may take a long time.
If you have ``automatic_soa`` set, which instructs rop to analyze the
changed scopes of modules, then you should report the changes by calling
``rope.base.libutils.report_change()`` when saving files, as follows:
But since rope is not notified about the changes the IDE performs, you
should tell rope about the change. You can do so by using
`rope.base.libutils.report_change()`. That is, whenever you want to
change a module you can do something like::
.. code-block:: python
# Do the actual writing
old_contents = read(path)
write(path, new_content)
# Save the new contents.
old_contents = resource.read()
resource.write(new_contents)
# Inform rope about the change
# Inform rope about the change.
libutils.report_change(myproject, path, old_contents)
Where `read` and `write` stand for methods used for reading and
writing files.
Note, however, that the use of ``automatic_soa`` is discouraged, because it may
slow down saving considerably.
Closing The Project
-------------------
`Project.close()`_ closes project open resources. Always call this
function when you don't need a project anymore::
`Project.close()`_ closes a project's open resources. Always call this
function when you don't need a project anymore:
.. code-block:: python
myproject.close()
`rope.base.project.Project`
===========================
``rope.base.libutils``
======================
You can create a project by::
The ``rope.base.libutils`` module contains functions that make life
easier for building refactoring tools. In some cases, the functions
offer a unified way to access or create objects. You're encouraged to
use ``rope.base.libutils`` functions whenever possible, because the APIs
here may not be as volatile as class methods.
``libutils.analyze_module()``
------------------------------
Perform static object analysis on a Python file in the project. Note,
this may be a very time consuming task.
.. code-block:: python
libutils.analyze_module(myproject, resource)
project = Project(root_address)
Where the `root_address` is the root folder of your project.
``libutils.analyze_modules()``
------------------------------
Perform static object analysis on all Python files in the project. Note
that it might take a long time to finish.
.. code-block:: python
libutils.analyze_modules(myproject)
``libutils.get_string_module()``
--------------------------------
A project has some useful fields. `Project.address` is the address of
the root folder of a project. `Project.root` is a `Folder` object
that points to that folder.
Returns a ``rope.base.pyobjects.PyModule`` object for the code string.
An optional ``resource`` argument can be specified for the resource this
code is associated with. If ``force_errors` is ``True``, then
``rope.base.exceptions.ModuleSyntaxError`` is raised when the code has
syntax errors. Otherwise, syntax errors are silently ignored. Note that
``force_errors`` overrides the ``ignore_syntax_errors`` project
configuration flag.
.. code-block:: python
pymodule = libutils.get_string_module(myproject, source)
``libutils.get_string_scope()``
-------------------------------
Get the ``rope.base.pyscopes.GlobalScope`` object for the code string.
This is the outermost scope of the code encompassing the whole module.
.. code-block:: python
scope = libutils.get_string_scope(myproject, source)
``libutils.is_python_file()``
-----------------------------
Returns ``True`` if the resource is a Python file.
.. code-block:: python
libutils.is_python_file(myproject, resource)
``libutils.modname()``
----------------------
`Project.get_resource()`
------------------------
Retrieves the dotted path string to the module that contains that given
resource.
You can use this method for getting a resource (that is file or
folder) inside a project. Uses ``'/'``s for separating directories.
For instance ``project.get_resource('my_folder/my_file.rst')`` returns
a `rope.base.resources.File` object that points to
``${projectroot}/my_folder/my_file.rst`` file.
.. code-block:: python
Note that this method assumes the resource exists. If it does not
exist you can use `Project.get_file()` and `Project.get_folder()`
methods.
# If resource is 'path/to/resource.py' relative to the project's root
# directory, this returns the string: 'path.to.resource'.
module_name = libutils.modname(resource)
``libutils.path_relative_to_project_root()``
--------------------------------------------
Retrieve the path relative to the project's root directory.
.. code-block:: python
# Get the path relative to the project's root directory.
relpath = libutils.relative(myproject.address, path)
``libutils.path_to_resource()``
-------------------------------
Get the resource --- a file or folder --- at the given path. An optional
``type`` argument can be used if the resource doesn't yet exist. The
values for ``type`` are the strings ``'file'`` or ``'folder'``.
.. code-block:: python
# Resource for an existing file.
myfile = libutils.path_to_resource(myproject, '/path/to/file.py')
# Resource for a non-existing folder.
new_folder = libutils.path_to_resource(myproject, '/path/to/folder', type='folder')
``rope.base.project.Project``
=============================
You can create a project by:
.. code-block:: python
project = Project(root_address)
Where the ``root_address`` is the root folder of your project.
A project has some useful attributes. ``Project.address`` is the
address of the root folder of a project. ``Project.root`` is a
``Folder`` object that points to that folder.
`Project.do()`
--------------
For committing changes returned by refactorings.
Used to commit changes returned by refactorings:
.. code-block:: python
project.do(changes)
`Project.history`
-----------------
A `rope.base.history.History` object. You can use its `undo` and
`redo` methods for undoing or redoing changes. Note that you can use
it only if you have committed your changes using rope.
A ``rope.base.history.History`` object. You can use its ``undo`` and
``redo`` methods for undoing or redoing changes. Note that you can use
this only if you have committed your changes using rope.
`Project.validate()`
--------------------
When using rope as a library you probably change the files in that
project in parallel (for example in IDEs). To force rope to
invalidate cached information about resources that have been
removed or changed outside rope you should call `Project.validate`.
You should pass a resource to this method. For example::
When using rope as a library, you will probably change the files in that
project in parallel (for example in IDEs). To force rope to validate
cached information about resources that have been removed or changed
outside rope, you should call ``Project.validate()``. You should pass a
resource to this method. For example:
.. code-block:: python
project.validate(project.root)
validates all files and directories in the project.
This validates all files and directories in the project and clears the
cache of all recorded changes.
`Project.close()`
-----------------
Closes project open resources. Always call this function when you
Closes a project's open resources. Always call this function when you
don't need a project anymore. Currently it closes the files used for
storing object information and project history. Since some parts of
these files are in memory for efficiency not closing a project might
storing object information and project history. Because some parts of
these files are in memory for efficiency, not closing a project might
put them in an inconsistent state.
`rope.base.fscommands`
----------------------
======================
The `rope.base.fscommands` module implements the basic file system
The ``rope.base.fscommands`` module implements basic file system
operations that rope needs to perform. The main reason for the
existence of this module is supporting version control systems. Have
a look at `FileSystemCommands` and `SubversionCommands` in the same
existence of this module is supporting version control systems. Have a
look at ``FileSystemCommands`` and ``SubversionCommands`` in the same
module. If you need other version control systems you can write a new
class that provides this interface. `rope.base.project.Project`
accepts a ``fscommands`` argument. You can use this argument to force
class that provides this interface. ``rope.base.project.Project``
accepts an ``fscommands`` argument. You can use this argument to force
rope to use your new class.
``.ropeproject`` Folder
-----------------------
=======================
From version ``0.5``, rope makes a ``.ropeproject`` folder in the
project by default for saving project configurations and data. The
name of this folder is passed to the constructor if you want to change
that. Also you can force rope not to make such a folder by passing
`None`.
Since version ``0.5``, rope makes a ``.ropeproject`` folder in the
project by default for saving project configurations and data. The name
of this folder is passed to the constructor if you want to change that.
You can force rope not to make such a folder by passing ``None``.
If such a folder exists rope loads the ``config.py`` file in that
If such a folder exists, rope loads the ``config.py`` file in that
folder. It might also use it for storing object information and
history.
......@@ -312,15 +444,15 @@ history.
`rope.base.pycore.PyCore`
=========================
Provides useful methods for managing python modules and packages.
Each project has a `PyCore` that can be accessed using
`Project.pycore` attribute.
Provides useful methods for managing python modules and packages. Each
project has a ``PyCore`` that can be accessed using the
``Project.pycore`` attribute.
`PyCore.run_module()` runs a resource. When running, it collects type
``PyCore.run_module()`` runs a resource. When running, it collects type
information to do dynamic object inference. For this reason modules
run much slower.
Also `Pycore.analyze_module()` collects object information for a
Also ``Pycore.analyze_module()`` collects object information for a
module. The collected information can be used to enhance rope's
static object inference.
......@@ -328,27 +460,27 @@ static object inference.
`rope.base.taskhandle.TaskHandle`
=================================
Can be used for stopping and monitoring the progress of time consuming
tasks like some of refactorings. `Project.do()` and
`Refactoring.get_changes()` of most refactorings take a keyword
parameter called ``task_handle``. You can pass a `TaskHandle` object
to them. A `TaskHandle` can be used for interrupting or observing a
task.
A TaskHandle can be used for stopping and monitoring the progress of
time consuming tasks, like some refactorings. The ``Project.do()`` and
``Refactoring.get_changes()`` methods for most refactorings take a
keyword parameter called ``task_handle``. You can pass a ``TaskHandle``
object to them. A ``TaskHandle`` can be used for interrupting or
observing a task.
Always pass ``task_handle`` as keyword argument. It will always be the
last argument, and new arguments of the refactoring are added before it.
Always pass ``task_handle`` as keyword argument; it will always be the
last argument and new arguments of the refactoring are added before
it.
A task might consist of a few ``JobSet``\s. Each ``JobSet`` performs a
few jobs. For instance calculating the changes for renaming a method in
a class hierarchy has two job sets: one to find the classes for
constructing the class hierarchy and another to change the occurrences.
A task might consist of a few `JobSet`\s. Each `JobSet` does a few
jobs. For instance calculating the changes for renaming a method in a
class hierarchy has two job sets; We need to find the classes for
constructing the class hierarchy and then we need to change the
occurrences.
The ``TaskHandle.current_jobset()`` returns the most recent ``JobSet``
or ``None`` if none has been started. You can use the methods of
``JobSet`` for obtaining information about the current job. So you
might want to do something like:
The `TaskHandle.current_jobset()` returns the most recent `JobSet` or
`None` if none has been started. You can use the methods of `JobSet`
for obtaining information about the current job. So you might want to
do something like::
.. code-block:: python
import rope.base.taskhandle
......@@ -375,87 +507,93 @@ do something like::
changes = renamer.get_changes('new_name', task_handle=handle)
Also you can use something like this for stopping the task::
Also you can use something like this for stopping the task:
.. code-block:: python
def stop():
handle.stop()
After calling ``stop()``, the thread that is executing the task will
be interrupted by a `rope.base.exceptions.InterruptedTaskError`
be interrupted by a ``rope.base.exceptions.InterruptedTaskError``
exception.
Refactorings
============
Have a look at `rope.refactor` package and its sub-modules. For
example for performing a move refactoring you can create a
`Move` object like this::
Have a look at ``rope.refactor`` package and its sub-modules. For
example for performing a move refactoring you can create a ``Move``
object like this:
.. code-block:: python
mover = Move(project, resource, offset)
Where `resource` and `offset` is the location to perform the
Where ``resource`` and ``offset`` is the location to perform the
refactoring.
Then you can commit the changes by it using `get_changes()` method::
Then you can commit the changes by it using the ``get_changes()``
method:
.. code-block:: python
project.do(mover.get_changes(destination))
Where `destination` module/package is the destination resource for
move refactoring. Other refactorings classes have a similar
interface.
Where the ``destination`` module/package is the destination resource for
move refactoring. Other refactorings classes have a similar interface.