1
# -*- coding: utf-8 -*-
3
# Copyright © 2011 Pierre Raybaut
4
# Licensed under the terms of the MIT License
5
# (see spyderlib/__init__.py for details)
10
[1] For compatibility with Spyder's standalone version, build with py2exe or
13
[2] For better performances, see this thread:
14
http://groups.google.com/group/rope-dev/browse_thread/thread/57de5731f202537a
16
[3] To avoid considering folders without __init__.py as Python packages, thus
17
avoiding side effects as non-working introspection features on a Python module
18
or package when a folder in current directory has the same name.
20
http://groups.google.com/group/rope-dev/browse_thread/thread/924c4b5a6268e618
22
[4] To avoid rope adding a 2 spaces indent to every docstring it gets, because
23
it breaks the work of Sphinx on the Object Inspector.
27
"""Monkey patching rope
29
See [1], [2] and [3] in module docstring."""
31
if rope.VERSION not in ('0.9.4', '0.9.3', '0.9.2'):
32
raise ImportError, "rope %s can't be patched" % rope.VERSION
34
# [1] Patching project.Project for compatibility with py2exe/cx_Freeze
36
from spyderlib.baseconfig import is_py2exe_or_cx_Freeze
37
if is_py2exe_or_cx_Freeze():
38
from rope.base import project
39
class PatchedProject(project.Project):
40
def _default_config(self):
41
# py2exe/cx_Freeze distribution
42
from spyderlib.baseconfig import get_module_source_path
43
fname = get_module_source_path('spyderlib',
45
return open(fname, 'rb').read()
46
project.Project = PatchedProject
48
# Patching pycore.PyCore...
49
from rope.base import pycore
50
class PatchedPyCore(pycore.PyCore):
51
# [2] ...so that forced builtin modules (i.e. modules that were
52
# declared as 'extension_modules' in rope preferences) will be indeed
53
# recognized as builtins by rope, as expected
55
# This patch is included in rope 0.9.4+ but applying it anyway is ok
56
def get_module(self, name, folder=None):
57
"""Returns a `PyObject` if the module was found."""
58
# check if this is a builtin module
59
pymod = self._builtin_module(name)
62
module = self.find_module(name, folder)
64
raise pycore.ModuleNotFoundError(
65
'Module %s not found' % name)
66
return self.resource_to_pyobject(module)
67
# [3] ...to avoid considering folders without __init__.py as Python
69
def _find_module_in_folder(self, folder, modname):
71
packages = modname.split('.')
72
for pkg in packages[:-1]:
73
if module.is_folder() and module.has_child(pkg):
74
module = module.get_child(pkg)
77
if module.is_folder():
78
if module.has_child(packages[-1]) and \
79
module.get_child(packages[-1]).is_folder() and \
80
module.get_child(packages[-1]).has_child('__init__.py'):
81
return module.get_child(packages[-1])
82
elif module.has_child(packages[-1] + '.py') and \
83
not module.get_child(packages[-1] + '.py').is_folder():
84
return module.get_child(packages[-1] + '.py')
85
pycore.PyCore = PatchedPyCore
87
# [2] Patching BuiltinFunction for the calltip/doc functions to be
88
# able to retrieve the function signatures with forced builtins
89
from rope.base import builtins, pyobjects
90
from spyderlib.utils.dochelpers import getargs
91
class PatchedBuiltinFunction(builtins.BuiltinFunction):
92
def __init__(self, returned=None, function=None, builtin=None,
93
argnames=[], parent=None):
94
builtins._BuiltinElement.__init__(self, builtin, parent)
95
pyobjects.AbstractFunction.__init__(self)
96
self.argnames = argnames
97
if not argnames and builtin:
98
self.argnames = getargs(self.builtin)
99
if self.argnames is None:
101
self.returned = returned
102
self.function = function
103
builtins.BuiltinFunction = PatchedBuiltinFunction
105
# [2] Patching BuiltinName for the go to definition feature to simply work
106
# with forced builtins
107
from rope.base import libutils
109
class PatchedBuiltinName(builtins.BuiltinName):
112
while p.parent is not None:
114
if isinstance(p, builtins.BuiltinModule) and p.pycore is not None:
116
def get_definition_location(self):
117
if not inspect.isbuiltin(self.pyobject):
118
_lines, lineno = inspect.getsourcelines(self.pyobject.builtin)
119
path = inspect.getfile(self.pyobject.builtin)
120
pycore = self._pycore()
121
if pycore and pycore.project:
122
resource = libutils.path_to_resource(pycore.project, path)
123
module = pyobjects.PyModule(pycore, None, resource)
124
return (module, lineno)
126
builtins.BuiltinName = PatchedBuiltinName
128
# [4] Patching PyDocExtractor so that _get_class_docstring and
129
# _get_single_function_docstring don't add a 2 spaces indent to
130
# every docstring. The only value that we are modifying is the indent
131
# keyword, from 2 to 0.
132
from rope.contrib import codeassist
133
class PatchedPyDocExtractor(codeassist.PyDocExtractor):
134
def _get_class_docstring(self, pyclass):
135
contents = self._trim_docstring(pyclass.get_doc(), indents=0)
136
supers = [super.get_name() for super in pyclass.get_superclasses()]
137
doc = 'class %s(%s):\n\n' % (pyclass.get_name(), ', '.join(supers)) + contents
139
if '__init__' in pyclass:
140
init = pyclass['__init__'].get_object()
141
if isinstance(init, pyobjects.AbstractFunction):
142
doc += '\n\n' + self._get_single_function_docstring(init)
145
def _get_single_function_docstring(self, pyfunction):
146
signature = self._get_function_signature(pyfunction)
147
docs = pyfunction.get_doc()
148
docs = self._trim_docstring(pyfunction.get_doc(), indents=0)
150
return signature + ':\n\n' + docs
151
codeassist.PyDocExtractor = PatchedPyDocExtractor
1
# -*- coding: utf-8 -*-
3
# Copyright © 2011 Pierre Raybaut
4
# Licensed under the terms of the MIT License
5
# (see spyderlib/__init__.py for details)
10
[1] For compatibility with Spyder's standalone version, build with py2exe or
13
[2] For better performances, see this thread:
14
http://groups.google.com/group/rope-dev/browse_thread/thread/57de5731f202537a
16
[3] To avoid considering folders without __init__.py as Python packages, thus
17
avoiding side effects as non-working introspection features on a Python module
18
or package when a folder in current directory has the same name.
20
http://groups.google.com/group/rope-dev/browse_thread/thread/924c4b5a6268e618
22
[4] To avoid rope adding a 2 spaces indent to every docstring it gets, because
23
it breaks the work of Sphinx on the Object Inspector.
27
"""Monkey patching rope
29
See [1], [2] and [3] in module docstring."""
31
if rope.VERSION not in ('0.9.4', '0.9.3', '0.9.2'):
32
raise ImportError, "rope %s can't be patched" % rope.VERSION
34
# [1] Patching project.Project for compatibility with py2exe/cx_Freeze
36
from spyderlib.baseconfig import is_py2exe_or_cx_Freeze
37
if is_py2exe_or_cx_Freeze():
38
from rope.base import project
39
class PatchedProject(project.Project):
40
def _default_config(self):
41
# py2exe/cx_Freeze distribution
42
from spyderlib.baseconfig import get_module_source_path
43
fname = get_module_source_path('spyderlib',
45
return open(fname, 'rb').read()
46
project.Project = PatchedProject
48
# Patching pycore.PyCore...
49
from rope.base import pycore
50
class PatchedPyCore(pycore.PyCore):
51
# [2] ...so that forced builtin modules (i.e. modules that were
52
# declared as 'extension_modules' in rope preferences) will be indeed
53
# recognized as builtins by rope, as expected
55
# This patch is included in rope 0.9.4+ but applying it anyway is ok
56
def get_module(self, name, folder=None):
57
"""Returns a `PyObject` if the module was found."""
58
# check if this is a builtin module
59
pymod = self._builtin_module(name)
62
module = self.find_module(name, folder)
64
raise pycore.ModuleNotFoundError(
65
'Module %s not found' % name)
66
return self.resource_to_pyobject(module)
67
# [3] ...to avoid considering folders without __init__.py as Python
69
def _find_module_in_folder(self, folder, modname):
71
packages = modname.split('.')
72
for pkg in packages[:-1]:
73
if module.is_folder() and module.has_child(pkg):
74
module = module.get_child(pkg)
77
if module.is_folder():
78
if module.has_child(packages[-1]) and \
79
module.get_child(packages[-1]).is_folder() and \
80
module.get_child(packages[-1]).has_child('__init__.py'):
81
return module.get_child(packages[-1])
82
elif module.has_child(packages[-1] + '.py') and \
83
not module.get_child(packages[-1] + '.py').is_folder():
84
return module.get_child(packages[-1] + '.py')
85
pycore.PyCore = PatchedPyCore
87
# [2] Patching BuiltinFunction for the calltip/doc functions to be
88
# able to retrieve the function signatures with forced builtins
89
from rope.base import builtins, pyobjects
90
from spyderlib.utils.dochelpers import getargs
91
class PatchedBuiltinFunction(builtins.BuiltinFunction):
92
def __init__(self, returned=None, function=None, builtin=None,
93
argnames=[], parent=None):
94
builtins._BuiltinElement.__init__(self, builtin, parent)
95
pyobjects.AbstractFunction.__init__(self)
96
self.argnames = argnames
97
if not argnames and builtin:
98
self.argnames = getargs(self.builtin)
99
if self.argnames is None:
101
self.returned = returned
102
self.function = function
103
builtins.BuiltinFunction = PatchedBuiltinFunction
105
# [2] Patching BuiltinName for the go to definition feature to simply work
106
# with forced builtins
107
from rope.base import libutils
109
class PatchedBuiltinName(builtins.BuiltinName):
112
while p.parent is not None:
114
if isinstance(p, builtins.BuiltinModule) and p.pycore is not None:
116
def get_definition_location(self):
117
if not inspect.isbuiltin(self.pyobject):
118
_lines, lineno = inspect.getsourcelines(self.pyobject.builtin)
119
path = inspect.getfile(self.pyobject.builtin)
120
pycore = self._pycore()
121
if pycore and pycore.project:
122
resource = libutils.path_to_resource(pycore.project, path)
123
module = pyobjects.PyModule(pycore, None, resource)
124
return (module, lineno)
126
builtins.BuiltinName = PatchedBuiltinName
128
# [4] Patching PyDocExtractor so that _get_class_docstring and
129
# _get_single_function_docstring don't add a 2 spaces indent to
130
# every docstring. The only value that we are modifying is the indent
131
# keyword, from 2 to 0.
132
from rope.contrib import codeassist
133
class PatchedPyDocExtractor(codeassist.PyDocExtractor):
134
def _get_class_docstring(self, pyclass):
135
contents = self._trim_docstring(pyclass.get_doc(), indents=0)
136
supers = [super.get_name() for super in pyclass.get_superclasses()]
137
doc = 'class %s(%s):\n\n' % (pyclass.get_name(), ', '.join(supers)) + contents
139
if '__init__' in pyclass:
140
init = pyclass['__init__'].get_object()
141
if isinstance(init, pyobjects.AbstractFunction):
142
doc += '\n\n' + self._get_single_function_docstring(init)
145
def _get_single_function_docstring(self, pyfunction):
146
signature = self._get_function_signature(pyfunction)
147
docs = pyfunction.get_doc()
148
docs = self._trim_docstring(pyfunction.get_doc(), indents=0)
150
return signature + ':\n\n' + docs
151
codeassist.PyDocExtractor = PatchedPyDocExtractor