Skip to content

Commit

Permalink
Configurable preloaded modules (#367)
Browse files Browse the repository at this point in the history
  • Loading branch information
gatesn committed Jun 1, 2018
1 parent 077e1ae commit d294fe1
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 57 deletions.
34 changes: 34 additions & 0 deletions pyls/plugins/preload_imports.py
@@ -0,0 +1,34 @@
# Copyright 2017 Palantir Technologies, Inc.
import logging
from pyls import hookimpl

log = logging.getLogger(__name__)

MODULES = [
"OpenGL", "PIL",
"array", "audioop", "binascii", "cPickle", "cStringIO", "cmath", "collections",
"datetime", "errno", "exceptions", "gc", "imageop", "imp", "itertools",
"marshal", "math", "matplotlib", "mmap", "mpmath", "msvcrt", "networkx", "nose", "nt",
"numpy", "operator", "os", "os.path", "pandas", "parser", "rgbimg", "scipy", "signal",
"skimage", "sklearn", "statsmodels", "strop", "sympy", "sys", "thread", "time",
"wx", "xxsubtype", "zipimport", "zlib"
]


@hookimpl
def pyls_settings():
# Setup default modules to preload, and rope extension modules
return {
'plugins': {'preload': {'modules': MODULES}},
'rope': {'extensionModules': MODULES}
}


@hookimpl
def pyls_initialize(config):
for mod_name in config.plugin_settings('preload').get('modules', []):
try:
__import__(mod_name)
log.debug("Preloaded module %s", mod_name)
except ImportError:
pass
52 changes: 1 addition & 51 deletions pyls/workspace.py
Expand Up @@ -3,8 +3,6 @@
import logging
import os
import re
import imp
import pkgutil

import jedi

Expand All @@ -17,59 +15,11 @@
RE_END_WORD = re.compile('^[A-Za-z_0-9]*')


def get_submodules(mod):
"""Get all submodules of a given module"""
def catch_exceptions(_module):
pass

try:
m = __import__(mod)
submodules = [mod]
submods = pkgutil.walk_packages(m.__path__, m.__name__ + '.', catch_exceptions)
for sm in submods:
sm_name = sm[1]
submodules.append(sm_name)
except ImportError:
return []
except: # pylint: disable=bare-except
return [mod]
return submodules


def get_preferred_submodules():
mods = ['numpy', 'scipy', 'sympy', 'pandas',
'networkx', 'statsmodels', 'matplotlib', 'sklearn',
'skimage', 'mpmath', 'os', 'PIL',
'OpenGL', 'array', 'audioop', 'binascii', 'cPickle',
'cStringIO', 'cmath', 'collections', 'datetime',
'errno', 'exceptions', 'gc', 'imageop', 'imp',
'itertools', 'marshal', 'math', 'mmap', 'msvcrt',
'nt', 'operator', 'parser', 'rgbimg', 'signal',
'strop', 'sys', 'thread', 'time', 'wx', 'xxsubtype',
'zipimport', 'zlib', 'nose', 'os.path']

submodules = []
for mod in mods:
submods = get_submodules(mod)
submodules += submods

actual = []
for submod in submodules:
try:
imp.find_module(submod)
actual.append(submod)
except ImportError:
pass

return actual


class Workspace(object):

M_PUBLISH_DIAGNOSTICS = 'textDocument/publishDiagnostics'
M_APPLY_EDIT = 'workspace/applyEdit'
M_SHOW_MESSAGE = 'window/showMessage'
PRELOADED_MODULES = get_preferred_submodules()

def __init__(self, root_uri, endpoint):
self._root_uri = root_uri
Expand All @@ -89,7 +39,7 @@ def _rope_project_builder(self, rope_config):
if self.__rope is None or self.__rope_config != rope_config:
rope_folder = rope_config.get('ropeFolder')
self.__rope = Project(self._root_path, ropefolder=rope_folder)
self.__rope.prefs.set('extension_modules', self.PRELOADED_MODULES)
self.__rope.prefs.set('extension_modules', rope_config.get('extensionModules', []))
self.__rope.prefs.set('ignore_syntax_errors', True)
self.__rope.prefs.set('ignore_bad_imports', True)
self.__rope.validate()
Expand Down
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -80,6 +80,7 @@
'jedi_signature_help = pyls.plugins.signature',
'jedi_symbols = pyls.plugins.symbols',
'mccabe = pyls.plugins.mccabe_lint',
'preload = pyls.plugins.preload_imports',
'pycodestyle = pyls.plugins.pycodestyle_lint',
'pydocstyle = pyls.plugins.pydocstyle_lint',
'pyflakes = pyls.plugins.pyflakes_lint',
Expand Down
5 changes: 1 addition & 4 deletions test/plugins/test_completion.py
@@ -1,9 +1,8 @@
# Copyright 2017 Palantir Technologies, Inc.
import os
from rope.base.project import Project

from pyls import uris
from pyls.workspace import Document, get_preferred_submodules
from pyls.workspace import Document
from pyls.plugins.jedi_completion import pyls_completions as pyls_jedi_completions
from pyls.plugins.rope_completion import pyls_completions as pyls_rope_completions

Expand Down Expand Up @@ -47,8 +46,6 @@ def test_jedi_completion():
def test_rope_completion(config, workspace):
# Over 'i' in os.path.isabs(...)
com_position = {'line': 1, 'character': 15}
rope = Project(LOCATION)
rope.prefs.set('extension_modules', get_preferred_submodules())
workspace.put_document(DOC_URI, source=DOC)
doc = workspace.get_document(DOC_URI)
items = pyls_rope_completions(config, workspace, doc, com_position)
Expand Down
27 changes: 25 additions & 2 deletions vscode-client/package.json
Expand Up @@ -75,6 +75,20 @@
"default": 15,
"description": "The minimum threshold that triggers warnings about cyclomatic complexity."
},
"pyls.plugins.preload.enabled": {
"type": "boolean",
"default": true,
"description": "Enable or disable the plugin."
},
"pyls.plugins.preload.modules": {
"type": "array",
"default": null,
"items": {
"type": "string"
},
"uniqueItems": true,
"description": "List of modules to import on startup"
},
"pyls.plugins.pycodestyle.enabled": {
"type": "boolean",
"default": true,
Expand Down Expand Up @@ -201,10 +215,19 @@
"default": true,
"description": "Enable or disable the plugin."
},
"pyls.rope.ropeFolder": {
"pyls.rope.extensionModules": {
"type": "string",
"default": ".ropeproject",
"default": null,
"description": "The name of the folder in which rope stores project configurations and data. Pass `null` for not using such a folder at all."
},
"pyls.rope.ropeFolder": {
"type": "array",
"default": null,
"items": {
"type": "string"
},
"uniqueItems": true,
"description": "Builtin and c-extension modules that are allowed to be imported and inspected by rope."
}
}
}
Expand Down

0 comments on commit d294fe1

Please sign in to comment.