Skip to content

Commit

Permalink
Merge from 5.x: PR #22244
Browse files Browse the repository at this point in the history
Fixes #21545
  • Loading branch information
ccordoba12 committed Jul 24, 2024
2 parents 05471ab + b610229 commit da6396b
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 31 deletions.
1 change: 1 addition & 0 deletions binder/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies:
- diff-match-patch >=20181111
- fcitx-qt5 >=1.2.7
- fzf >=0.42.0
- importlib-metadata >=4.6.0
- intervaltree >=3.0.2
- ipython >=8.13.0,<9.0.0,!=8.17.1
- jedi >=0.17.2,<0.20.0
Expand Down
13 changes: 9 additions & 4 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,18 @@ def reset_conf_before_test():
from spyder.plugins.completion.api import COMPLETION_ENTRYPOINT
from spyder.plugins.completion.plugin import CompletionPlugin

# See compatibility note on `group` keyword:
# https://docs.python.org/3/library/importlib.metadata.html#entry-points
if sys.version_info < (3, 10): # pragma: no cover
from importlib_metadata import entry_points
else: # pragma: no cover
from importlib.metadata import entry_points

# Restore completion clients default settings, since they
# don't have default values on the configuration.
from pkg_resources import iter_entry_points

provider_configurations = {}
for entry_point in iter_entry_points(COMPLETION_ENTRYPOINT):
Provider = entry_point.resolve()
for entry_point in entry_points(group=COMPLETION_ENTRYPOINT):
Provider = entry_point.load()
provider_name = Provider.COMPLETION_PROVIDER_NAME

(provider_conf_version,
Expand Down
2 changes: 1 addition & 1 deletion install_dev_repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
"""

import argparse
from importlib.metadata import PackageNotFoundError, distribution
import os
import sys
from logging import Formatter, StreamHandler, getLogger
from pathlib import Path
from subprocess import check_output

from importlib_metadata import PackageNotFoundError, distribution
from packaging.requirements import Requirement

# Remove current/script directory from sys.path[0] if added by the Python invocation,
Expand Down
2 changes: 2 additions & 0 deletions requirements/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ dependencies:
- cookiecutter >=1.6.0
- diff-match-patch >=20181111
- fzf >=0.42.0
# Need at least some compatibility with python 3.10 features
- importlib-metadata >=4.6.0
- intervaltree >=3.0.2
- ipython >=8.13.0,<9.0.0,!=8.17.1
- jedi >=0.17.2,<0.20.0
Expand Down
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ def run(self):
'cloudpickle>=0.5.0',
'cookiecutter>=1.6.0',
'diff-match-patch>=20181111',
# While this is only required for python <3.10, it is safe enough to
# install in all cases and helps the tests to pass.
'importlib-metadata>=4.6.0',
'intervaltree>=3.0.2',
'ipython>=8.12.2,<8.13.0; python_version=="3.8"',
'ipython>=8.13.0,<9.0.0,!=8.17.1; python_version>"3.8"',
Expand Down
29 changes: 16 additions & 13 deletions spyder/app/find_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@

import importlib
import logging
import sys
import traceback

import pkg_resources

from spyder.api.exceptions import SpyderAPIError
from spyder.api.plugins import Plugins
from spyder.api.utils import get_class_values
from spyder.config.base import STDERR

# See compatibility note on `group` keyword:
# https://docs.python.org/3/library/importlib.metadata.html#entry-points
if sys.version_info < (3, 10): # pragma: no cover
from importlib_metadata import entry_points
else: # pragma: no cover
from importlib.metadata import entry_points


logger = logging.getLogger(__name__)

Expand All @@ -28,16 +34,15 @@ def find_internal_plugins():
"""
internal_plugins = {}

entry_points = list(pkg_resources.iter_entry_points("spyder.plugins"))
internal_names = get_class_values(Plugins)

for entry_point in entry_points:
for entry_point in entry_points(group="spyder.plugins"):
name = entry_point.name
if name not in internal_names:
continue

class_name = entry_point.attrs[0]
mod = importlib.import_module(entry_point.module_name)
class_name = entry_point.attr
mod = importlib.import_module(entry_point.module)
plugin_class = getattr(mod, class_name, None)
internal_plugins[name] = plugin_class

Expand All @@ -56,21 +61,19 @@ def find_external_plugins():
Find available external plugins based on setuptools entry points.
"""
internal_names = get_class_values(Plugins)
plugins = list(pkg_resources.iter_entry_points("spyder.plugins"))
external_plugins = {}

for entry_point in plugins:
for entry_point in entry_points(group="spyder.plugins"):
name = entry_point.name
if name not in internal_names:
try:
class_name = entry_point.attrs[0]
mod = importlib.import_module(entry_point.module_name)
class_name = entry_point.attr
mod = importlib.import_module(entry_point.module)
plugin_class = getattr(mod, class_name, None)

# To display in dependencies dialog.
plugin_class._spyder_module_name = entry_point.module_name
plugin_class._spyder_package_name = (
entry_point.dist.project_name)
plugin_class._spyder_module_name = entry_point.module
plugin_class._spyder_package_name = entry_point.dist.name
plugin_class._spyder_version = entry_point.dist.version

external_plugins[name] = plugin_class
Expand Down
5 changes: 5 additions & 0 deletions spyder/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
CLOUDPICKLE_REQVER = '>=0.5.0'
COOKIECUTTER_REQVER = '>=1.6.0'
DIFF_MATCH_PATCH_REQVER = '>=20181111'
IMPORTLIB_METADATA_REQVER = '>=4.6.0'
INTERVALTREE_REQVER = '>=3.0.2'
IPYTHON_REQVER = ">=8.12.2,<8.13.0" if PY38 else ">=8.13.0,<9.0.0,!=8.17.1"
JEDI_REQVER = '>=0.17.2,<0.20.0'
Expand Down Expand Up @@ -129,6 +130,10 @@
'package_name': "diff-match-patch",
'features': _("Compute text file diff changes during edition"),
'required_version': DIFF_MATCH_PATCH_REQVER},
{'modname': 'importlib_metadata',
'package_name': 'importlib-metadata',
'features': _('Access the metadata for a Python package'),
'required_version': IMPORTLIB_METADATA_REQVER},
{'modname': "intervaltree",
'package_name': "intervaltree",
'features': _("Compute folding range nesting levels"),
Expand Down
13 changes: 10 additions & 3 deletions spyder/plugins/completion/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
import functools
import inspect
import logging
import sys
from typing import List, Union
import weakref

# Third-party imports
from packaging.version import parse
from pkg_resources import iter_entry_points
from qtpy.QtCore import QRecursiveMutex, QMutexLocker, QTimer, Slot, Signal

# Local imports
Expand All @@ -35,6 +35,13 @@
from spyder.plugins.completion.confpage import CompletionConfigPage
from spyder.plugins.completion.container import CompletionContainer

# See compatibility note on `group` keyword:
# https://docs.python.org/3/library/importlib.metadata.html#entry-points
if sys.version_info < (3, 10): # pragma: no cover
from importlib_metadata import entry_points
else: # pragma: no cover
from importlib.metadata import entry_points


logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -223,10 +230,10 @@ def __init__(self, parent, configuration=None):

# Find and instantiate all completion providers registered via
# entrypoints
for entry_point in iter_entry_points(COMPLETION_ENTRYPOINT):
for entry_point in entry_points(group=COMPLETION_ENTRYPOINT):
try:
logger.debug(f'Loading entry point: {entry_point}')
Provider = entry_point.resolve()
Provider = entry_point.load()
self._instantiate_and_register_provider(Provider)
except Exception as e:
logger.warning('Failed to load completion provider from entry '
Expand Down
14 changes: 5 additions & 9 deletions spyder/utils/programs.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@

# Standard library imports
from ast import literal_eval
from getpass import getuser
from textwrap import dedent
import glob
from getpass import getuser
import importlib
from importlib.metadata import PackageNotFoundError, version as package_version
import itertools
import os
import os.path as osp
import re
import subprocess
import sys
import tempfile
from textwrap import dedent
import threading
import time
import logging

# Third party imports
from packaging.version import parse
import pkg_resources
import psutil

# Local imports
Expand Down Expand Up @@ -1009,13 +1009,9 @@ def get_module_version(module_name, interpreter=None):

def get_package_version(package_name):
"""Return package version or None if version can't be retrieved."""

# When support for Python 3.7 and below is dropped, this can be replaced
# with the built-in importlib.metadata.version
try:
ver = pkg_resources.get_distribution(package_name).version
return ver
except pkg_resources.DistributionNotFound:
return package_version(package_name)
except PackageNotFoundError:
return None


Expand Down
2 changes: 1 addition & 1 deletion spyder/utils/tests/test_programs.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ def test_open_files_with_application(tmp_path):


def test_get_package_version():
# Primarily a test of pkg_resources/setuptools being installed properly
# Primarily a test of importlib.metadata being installed properly
assert get_package_version('IPython')
assert get_package_version('python_lsp_black')

Expand Down

0 comments on commit da6396b

Please sign in to comment.