Commit 46d8917b authored by SVN-Git Migration's avatar SVN-Git Migration

Imported Upstream version 0.10.2

parent e258fdb4
include README.txt COPYING setup.py MANIFEST.in
include README.rst COPYING setup.py MANIFEST.in
recursive-include rope *.py
recursive-include docs *.txt
recursive-include docs *.rst
recursive-include ropetest *.py
Metadata-Version: 1.0
Metadata-Version: 1.1
Name: rope
Version: 0.9.2
Version: 0.10.2
Summary: a python refactoring library...
Home-page: http://rope.sf.net/
Author: Ali Gholami Rudi
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
========================================
rope, a python refactoring library ...
rope, a python refactoring library ...
========================================
......@@ -23,37 +29,10 @@ Description:
New Features
============
* caching all sub-modules of a module in `rope.contrib.autoimport`
* fix recursion when creating modules
* added basic support for setuptools
* extract method handles conditional variable updates
* added `rope.contrib.codeassist.CompletionProposal.parameters`
The `rope.contrib.autoimport.AutoImport.generate_module_cache()` has
been changed to handle module names that end with ``.*``. Now one can
use ``rope.*`` to mean `rope` and all of its sub-modules.
Extract method now handles variable updates better. For instance in::
def f(a):
if 0:
a = 1
print(a)
When extracting the first two lines of `f()`, `a` should be passed to
`g()`. Although these lines don't read `a`, if the conditional write
(like in ``if`` or ``while`` blocks) does not happen, it results in an
error. So the outcome will be::
def f(a):
a = g(a)
print(a)
def g(a):
if 0:
a = 1
return a
* Under new management! Matěj Cepl <mcepl@cepl.eu> takes it hesitantly
over
* Merged all availables pull requests and patches to the main codebase
* Tests are green again
Platform: UNKNOWN
......
**Note:** *Please note that this project has been moved to* `GitHub python-rope / rope`_
.. _GitHub python-rope / rope: https://github.com/python-rope/rope
========================================
rope, a python refactoring library ...
========================================
......@@ -14,45 +20,18 @@ Overview
New Features
============
* caching all sub-modules of a module in `rope.contrib.autoimport`
* fix recursion when creating modules
* added basic support for setuptools
* extract method handles conditional variable updates
* added `rope.contrib.codeassist.CompletionProposal.parameters`
The `rope.contrib.autoimport.AutoImport.generate_module_cache()` has
been changed to handle module names that end with ``.*``. Now one can
use ``rope.*`` to mean `rope` and all of its sub-modules.
Extract method now handles variable updates better. For instance in::
def f(a):
if 0:
a = 1
print(a)
When extracting the first two lines of `f()`, `a` should be passed to
`g()`. Although these lines don't read `a`, if the conditional write
(like in ``if`` or ``while`` blocks) does not happen, it results in an
error. So the outcome will be::
def f(a):
a = g(a)
print(a)
def g(a):
if 0:
a = 1
return a
* Under new management! Matěj Cepl <mcepl@cepl.eu> takes it hesitantly
over
* Merged all availables pull requests and patches to the main codebase
* Tests are green again
Getting Started
===============
* List of features: `docs/rope.txt`_
* Overview of some of rope's features: `docs/overview.txt`_
* Using as a library: `docs/library.txt`_
* Contributing: `docs/contributing.txt`_
* List of features: `<docs/rope.rst>`_
* Overview of some of rope's features: `<docs/overview.rst>`_
* Using as a library: `<docs/library.rst>`_
* Contributing: `<docs/contributing.rst>`_
To change your project preferences edit
``$PROJECT_ROOT/.ropeproject/config.py`` where ``$PROJECT_ROOT`` is
......@@ -76,7 +55,10 @@ This program is under the terms of GPL (GNU General Public License).
Have a look at ``COPYING`` file for more information.
.. _`docs/rope.txt`: docs/rope.html
.. _`docs/overview.txt`: docs/overview.html
.. _`docs/contributing.txt`: docs/contributing.html
.. _`docs/library.txt`: docs/library.html
.. _`docs/rope.rst`: docs/rope.html
.. _`docs/overview.rst`: docs/overview.html
.. _`docs/contributing.rst`: docs/contributing.html
.. _`docs/library.rst`: docs/library.html
.. image:: https://secure.travis-ci.org/python-rope/rope.png
:alt: Build Status
......@@ -34,13 +34,13 @@ googlegroups.com`_ mailing list. Here is only a list of suggestions.
Issues
------
The `dev/issues.txt`_ file is actually the main rope todo file. There
The `dev/issues.rst`_ file is actually the main rope todo file. There
is a section called "unresolved issues"; it contains almost every kind
of task. Most of them need some thought or discussion. Pickup
whichever you are most interested in. If you have ideas or questions
about them, don't hesitate to discuss it in the mailing list.
.. _`dev/issues.txt`: dev/issues.html
.. _`dev/issues.rst`: dev/issues.rst
Getting Ready For Python 3.0
----------------------------
......@@ -54,10 +54,10 @@ Write Plugins For Other IDEs
See ropemacs_, ropevim_, eric4_ and ropeide_.
.. _ropemacs: http://rope.sf.net/ropemacs.html
.. _ropevim: http://rope.sf.net/ropevim.html
.. _ropeide: http://rope.sf.net/ropeide.html
.. _eric4: http://www.die-offenbachs.de/eric/index.html
.. _ropemacs: http://rope.sf.net/ropemacs.rst
.. _ropevim: http://rope.sf.net/ropevim.rst
.. _ropeide: http://rope.sf.net/ropeide.rst
.. _eric4: http://www.die-offenbachs.de/eric/index.rst
Rope Structure
......@@ -69,10 +69,10 @@ Rope package structure:
* `rope.refactor`: refactorings and tools used in them
* `rope.contrib`: IDE helpers
Have a look at ``__init__.py`` of these packages or `library.txt`_ for
Have a look at ``__init__.py`` of these packages or `library.rst`_ for
more information.
.. _`library.txt`: library.html
.. _`library.rst`: library.rst
Source Repository
......
......@@ -2,7 +2,7 @@
TODO
======
See the `unresolved issues` section of ``issues.txt`` file for more.
See the `unresolved issues` section of ``issues.rst`` file for more.
> Public Release 1.0
......@@ -2,6 +2,42 @@
Done List
===========
> Public Release 0.10.0 : May 22, 2014
- Undre the new management! Matěj Cepl <mcepl@cepl.eu> takes hesitantly
over
- Merged all available pull requests and patches to the main codebase
- Tests are green again
> Public Release 0.9.3 : February 4, 2010
- codeassist: proposals scopes and types revised : January 26, 2010
- codeassist: handling "builtin unknowns" : January 06, 2010
- refactor: fixed arguments in extracted method : December 26, 2009
- pycore: fixed project's property `source_folders` : October 26, 2009
- codeassist: better handling of unicode docstrings : August 20, 2009
- setup.py: don't include docs as package data : July 18, 2009
- fscommands: handle hg crew ui changes : May 04, 2009
- patchedast: handle ExtSlice node : April 29, 2009
> Public Release 0.9.2 : February 19, 2009
......
......@@ -3,7 +3,7 @@
=========================
If you need other features, send a feature request. Have a look at
`contributing.txt`_.
`contributing.rst`_.
.. contents:: Table of Contents
......@@ -235,9 +235,9 @@ that points to that folder.
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.txt')`` returns
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.txt`` file.
``${projectroot}/my_folder/my_file.rst`` file.
Note that this method assumes the resource exists. If it does not
exist you can use `Project.get_file()` and `Project.get_folder()`
......@@ -524,7 +524,7 @@ Restructuring
-------------
The example for replacing occurrences of our `pow` function to ``**``
operator (see the restructuring section of `overview.txt`_)::
operator (see the restructuring section of `overview.rst`_)::
# Setting up the project
>>> from rope.base.project import Project
......@@ -557,8 +557,8 @@ operator (see the restructuring section of `overview.txt`_)::
See code documentation and test suites for more information.
.. _overview.txt: overview.html
.. _contributing.txt: contributing.html
.. _overview.rst: overview.rst
.. _contributing.rst: contributing.rst
Other Topics
......
......@@ -10,10 +10,10 @@ want to feel the power of rope try its features and see its unit
tests.
This file is more suitable for the users. Developers who plan to use
rope as a library might find library.txt_ more useful.
rope as a library might find library.rst_ more useful.
.. contents:: Table of Contents
.. _library.txt: library.html
.. _library.rst: library.rst
``.ropeproject`` Folder
......@@ -746,7 +746,7 @@ will match (for instance, if ``exact`` is specified , ``${name}``
matches ``name`` and ``x.name`` but not ``var`` nor ``(1 + 2)`` while
a normal ``${name}`` can match all of them).
For performing this refactoring using rope library see `library.txt`_.
For performing this refactoring using rope library see `library.rst`_.
Example 2
......@@ -1108,7 +1108,7 @@ there is no version control at all. Also don't forget to commit your
changes yourself, rope doesn't do that.
Adding support for other VCSs is easy; have a look at
`library.txt`_.
`library.rst`_.
.. _pysvn: http://pysvn.tigris.org
.. _Mercurial: http://selenic.com/mercurial
......
......@@ -45,10 +45,10 @@ Features implemented so far:
* Handling built-in container types
* Saving object information on disk and validating them
For more information see `overview.txt`_.
For more information see `overview.rst`_.
.. _overview.txt: overview.html
.. _overview.rst: overview.rst
.. _pysvn: http://pysvn.tigris.org
.. _Mercurial: http://selenic.com/mercurial
.. _GIT: http://git.or.cz
......
"""rope, a python refactoring library"""
INFO = __doc__
VERSION = '0.9.2'
VERSION = '0.10.2'
COPYRIGHT = """\
Copyright (C) 2006-2009 Ali Gholami Rudi
Copyright (C) 2006-2012 Ali Gholami Rudi
Copyright (C) 2009-2012 Anton Gritsay
This program is free software; you can redistribute it and/or modify it
under the terms of GNU General Public License as published by the
......
......@@ -72,6 +72,8 @@ class ObjectArguments(object):
def get_instance_pyname(self):
return self.pynames[0]
class MixedArguments(object):
def __init__(self, pyname, arguments, scope):
......
......@@ -27,6 +27,10 @@ def walk(node, walker):
method_name = '_' + node.__class__.__name__
method = getattr(walker, method_name, None)
if method is not None:
if isinstance(node, _ast.ImportFrom) and node.module is None:
# In python < 2.7 ``node.module == ''`` for relative imports
# but for python 2.7 it is None. Generalizing it to ''.
node.module = ''
return method(node)
for child in get_child_nodes(node):
walk(child, walker)
......
This diff is collapsed.
......@@ -2,7 +2,6 @@ import datetime
import difflib
import os
import time
import warnings
import rope.base.fscommands
from rope.base import taskhandle, exceptions, utils
......@@ -17,13 +16,13 @@ class Change(object):
def do(self, job_set=None):
"""Perform the change
.. note:: Do use this directly. Use `Project.do()` instead.
"""
def undo(self, job_set=None):
"""Perform the change
.. note:: Do use this directly. Use `History.undo()` instead.
"""
......@@ -97,7 +96,8 @@ class ChangeSet(Change):
date = datetime.datetime.fromtimestamp(self.time)
if date.date() == datetime.date.today():
string_date = 'today'
elif date.date() == (datetime.date.today() - datetime.timedelta(1)):
elif date.date() == (datetime.date.today() -
datetime.timedelta(1)):
string_date = 'yesterday'
elif date.year == datetime.date.today().year:
string_date = date.strftime('%b %d')
......@@ -257,7 +257,8 @@ class CreateFolder(CreateResource):
"""
def __init__(self, parent, name):
resource = parent.project.get_folder(self._get_child_path(parent, name))
resource = parent.project.get_folder(
self._get_child_path(parent, name))
super(CreateFolder, self).__init__(resource)
......@@ -309,6 +310,7 @@ def count_changes(change):
return result
return 1
def create_job_set(task_handle, change):
return task_handle.create_jobset(str(change), count_changes(change))
......
......@@ -18,6 +18,7 @@ class ChangeCollector(object):
def get_changed(self):
if not self.changes:
return None
def compare_changes(change1, change2):
return cmp(change1[:2], change2[:2])
self.changes.sort(compare_changes)
......@@ -131,6 +132,7 @@ class _CustomGenerator(object):
return result
_main_chars = re.compile(r'[\'|"|#|\\|\[|\]|\{|\}|\(|\)]')
def _analyze_line(self, line):
char = None
for match in self._main_chars.finditer(line):
......@@ -142,8 +144,8 @@ class _CustomGenerator(object):
if char * 3 == line[i:i + 3]:
self.in_string = char * 3
elif self.in_string == line[i:i + len(self.in_string)] and \
not (i > 0 and line[i - 1] == '\\' and
not (i > 1 and line[i - 2] == '\\')):
not (i > 0 and line[i - 1] == '\\' and
not (i > 1 and line[i - 2] == '\\')):
self.in_string = ''
if self.in_string:
continue
......@@ -158,6 +160,7 @@ class _CustomGenerator(object):
else:
self.continuation = False
def custom_generator(lines):
return _CustomGenerator(lines)()
......@@ -189,7 +192,6 @@ class LogicalLineFinder(object):
# XXX: `block_start` should be at a better position!
block_start = 1
readline = LinesToReadline(self.lines, block_start)
shifted = start_line - block_start + 1
try:
for start, end in self._logical_lines(readline):
real_start = start + block_start - 1
......@@ -199,7 +201,7 @@ class LogicalLineFinder(object):
real_end = end + block_start - 1
if real_start >= start_line:
yield (real_start, real_end)
except tokenize.TokenError, e:
except tokenize.TokenError:
pass
def _block_logical_line(self, block_start, line_number):
......@@ -254,6 +256,7 @@ class CachingLogicalLineFinder(object):
self._generate = generate
_starts = None
@property
def starts(self):
if self._starts is None:
......@@ -261,6 +264,7 @@ class CachingLogicalLineFinder(object):
return self._starts
_ends = None
@property
def ends(self):
if self._ends is None:
......@@ -326,6 +330,7 @@ def get_block_start(lines, lineno, maximum_indents=80):
_block_start_pattern = None
def get_block_start_patterns():
global _block_start_pattern
if not _block_start_pattern:
......@@ -354,5 +359,6 @@ def get_string_pattern():
return '|'.join([longstr, longstr.replace('"', "'"),
shortstr, shortstr.replace('"', "'")])
def get_comment_pattern():
return r'#[^\n]*'
......@@ -14,7 +14,7 @@ def set_prefs(prefs):
# 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
# 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',
'.hg', '.svn', '_svn', '.git']
'.hg', '.svn', '_svn', '.git', '.tox']
# Specifies which files should be considered python files. It is
# useful when you have scripts inside your project. Only files
......
......@@ -6,6 +6,7 @@ from rope.base import ast, astutils, exceptions, pyobjects, arguments, worder
BadIdentifierError = exceptions.BadIdentifierError
def eval_location(pymodule, offset):
"""Find the pyname at the offset"""
return eval_location2(pymodule, offset)[1]
......@@ -40,7 +41,8 @@ def eval_str2(holding_scope, name):
# parenthesizing for handling cases like 'a_var.\nattr'
node = ast.parse('(%s)' % name)
except SyntaxError:
raise BadIdentifierError('Not a resolvable python identifier selected.')
raise BadIdentifierError(
'Not a resolvable python identifier selected.')
return eval_node2(holding_scope, node)
......@@ -81,7 +83,8 @@ class ScopeNameFinder(object):
keyword_name = self.worder.get_word_at(offset)
pyobject = self.get_enclosing_function(offset)
if isinstance(pyobject, pyobjects.PyFunction):
return (None, pyobject.get_parameters().get(keyword_name, None))
return (None,
pyobject.get_parameters().get(keyword_name, None))
# class body
if self._is_defined_in_class_body(holding_scope, offset, lineno):
class_scope = holding_scope
......@@ -93,7 +96,8 @@ class ScopeNameFinder(object):
except rope.base.exceptions.AttributeNotFoundError:
return (None, None)
# function header
if self._is_function_name_in_function_header(holding_scope, offset, lineno):
if self._is_function_name_in_function_header(holding_scope,
offset, lineno):
name = self.worder.get_primary_at(offset).strip()
return (None, holding_scope.parent[name])
# from statement module
......@@ -118,7 +122,7 @@ class ScopeNameFinder(object):
if isinstance(pyobject, pyobjects.AbstractFunction):
return pyobject
elif isinstance(pyobject, pyobjects.AbstractClass) and \
'__init__' in pyobject:
'__init__' in pyobject:
return pyobject['__init__'].get_object()
elif '__call__' in pyobject:
return pyobject['__call__'].get_object()
......@@ -157,6 +161,7 @@ class StatementEvaluator(object):
primary, pyobject = self._get_primary_and_object_for_node(node.func)
if pyobject is None:
return
def _get_returned(pyobject):
args = arguments.create_arguments(primary, pyobject,
node, self.scope)
......@@ -199,8 +204,10 @@ class StatementEvaluator(object):
self._get_object_for_node(node.left))
def _BoolOp(self, node):
self.result = rope.base.pynames.UnboundName(
self._get_object_for_node(node.values[0]))
pyobject = self._get_object_for_node(node.values[0])
if pyobject is None:
pyobject = self._get_object_for_node(node.values[1])
self.result = rope.base.pynames.UnboundName(pyobject)
def _Repr(self, node):
self.result = self._get_builtin_name('str')
......@@ -292,13 +299,16 @@ class StatementEvaluator(object):
else:
return
if function_name in pyobject:
call_function = pyobject[function_name].get_object()
called = pyobject[function_name].get_object()
if not called or \
not isinstance(called, pyobjects.AbstractFunction):
return
args = [node]
if other_args:
args += other_args
arguments_ = arguments.Arguments(args, self.scope)
self.result = rope.base.pynames.UnboundName(
pyobject=call_function.get_returned_object(arguments_))
pyobject=called.get_returned_object(arguments_))
def _Lambda(self, node):
self.result = rope.base.pynames.UnboundName(
......
......@@ -82,9 +82,19 @@ class MercurialCommands(object):
def __init__(self, root):
self.hg = self._import_mercurial()
self.normal_actions = FileSystemCommands()
self.ui = self.hg.ui.ui(
verbose=False, debug=False, quiet=True,
interactive=False, traceback=False, report_untrusted=False)
try:
self.ui = self.hg.ui.ui(
verbose=False, debug=False, quiet=True,
interactive=False, traceback=False, report_untrusted=False)
except:
self.ui = self.hg.ui.ui()
self.ui.setconfig('ui', 'interactive', 'no')
self.ui.setconfig('ui', 'debug', 'no')
self.ui.setconfig('ui', 'traceback', 'no')
self.ui.setconfig('ui', 'verbose', 'no')
self.ui.setconfig('ui', 'report_untrusted', 'no')
self.ui.setconfig('ui', 'quiet', 'yes')
self.repo = self.hg.hg.repository(self.ui, root)
def _import_mercurial(self):
......@@ -189,29 +199,36 @@ def unicode_to_file_data(contents, encoding=None):
except UnicodeEncodeError:
return contents.encode('utf-8')
def file_data_to_unicode(data, encoding=None):
result = _decode_data(data, encoding)
if '\r' in result:
result = result.replace('\r\n', '\n').replace('\r', '\n')
return result
def _decode_data(data, encoding):
if isinstance(data, unicode):
return data
if encoding is None:
encoding = read_str_coding(data)
if encoding is None:
# there is no encoding tip, we need to guess.
# PEP263 says that "encoding not explicitly defined" means it is ascii,
# but we will use utf8 instead since utf8 fully covers ascii and btw is
# the only non-latin sane encoding.
encoding = 'utf-8'
try:
if encoding is not None:
return unicode(data, encoding)
return unicode(data)
except (UnicodeDecodeError, LookupError):
# Using ``utf-8`` if guessed encoding fails
return unicode(data, 'utf-8')
return data.decode(encoding)
except (UnicodeError, LookupError):
# fallback to latin1: it should never fail
return data.decode('latin1')
def read_file_coding(path):
file = open(path, 'b')
count = 0
result = []
buffsize = 10
while True:
current = file.read(10)
if not current:
......
......@@ -29,13 +29,15 @@ def path_to_resource(project, path, type=None):
return project.get_folder(project_path)
return None
def relative(root, path):
root = rope.base.project._realpath(root).replace(os.path.sep, '/')
path = rope.base.project._realpath(path).replace(os.path.sep, '/')
if path == root:
return ''
return ''
if path.startswith(root + '/'):
return path[len(root) + 1:]
return path[len(root) + 1:]
def report_change(project, path, old_content):
"""Report that the contents of file at `path` was changed
......@@ -52,6 +54,7 @@ def report_change(project, path, old_content):
rope.base.pycore.perform_soa_on_changed_scopes(project, resource,
old_content)
def analyze_modules(project, task_handle=taskhandle.NullTaskHandle()):
"""Perform static object analysis on all python files in the project
......
......@@ -26,7 +26,7 @@ class PythonFileRunner(object):
env = dict(os.environ)
file_path = self.file.real_path
path_folders = self.pycore.get_source_folders() + \
self.pycore.get_python_path_folders()
self.pycore.get_python_path_folders()
env['PYTHONPATH'] = os.pathsep.join(folder.real_path
for folder in path_folders)
runmod_path = self.pycore.find_module('rope.base.oi.runmod').real_path
......@@ -56,7 +56,8 @@ class PythonFileRunner(object):
self.receiver = _SocketReceiver()
else:
self.receiver = _FIFOReceiver()
self.receiving_thread = threading.Thread(target=self._receive_information)
self.receiving_thread = threading.Thread(
target=self._receive_information)
self.receiving_thread.setDaemon(True)
self.receiving_thread.start()
......@@ -114,7 +115,7 @@ class _SocketReceiver(_MessageReceiver):
try:
self.server_socket.bind(('', self.data_port))
break
except socket.error, e:
except socket.error:
self.data_port += 1
self.server_socket.listen(1)
......
......@@ -40,9 +40,9 @@ def __rope_start_everything():
def close(self):
self.my_file.close()
def _cached(func):
cache = {}
def newfunc(self, arg):
if arg in cache: