sopel-irc / sopel

:robot::speech_balloon: An easy-to-use and highly extensible IRC Bot framework. Formerly Willie.
https://sopel.chat
Other
951 stars 405 forks source link

Entrypoint plugins with non-equal 'project' and 'package' names cannot be reloaded #2593

Open SnoopJ opened 4 months ago

SnoopJ commented 4 months ago

Description

I have observed that an entrypoint-style Sopel plugin cannot be reloaded if its project name does not exactly match the top-level import name.

I believe this is caused by catching ValueError specifically in the get_version logic, where other exceptions may bubble up out of the importlib machinery.

Log error report

[2024-02-23 19:55:26,265] sopel.bot            ERROR    - Unexpected PackageNotFoundError (sopel_dummy) from SnoopJ. Message was: !reload dummy
Traceback (most recent call last):
  File "/var/lib/gitea/data/gitea-repositories/snoopj/sopel.git/sopel/bot.py", line 695, in call_rule
    rule.execute(sopel, trigger)
  File "/var/lib/gitea/data/gitea-repositories/snoopj/sopel.git/sopel/plugins/rules.py", line 1274, in execute
    exit_code = self._handler(bot, trigger)
  File "/var/lib/gitea/data/gitea-repositories/snoopj/sopel.git/sopel/plugin.py", line 1399, in guarded
    return function(bot, trigger, *args, **kwargs)
  File "/var/lib/gitea/data/gitea-repositories/snoopj/sopel.git/sopel/builtins/reload.py", line 109, in pm_f_reload
    f_reload(bot, trigger)
  File "/var/lib/gitea/data/gitea-repositories/snoopj/sopel.git/sopel/plugin.py", line 1640, in guarded
    return function(bot, trigger, *args, **kwargs)
  File "/var/lib/gitea/data/gitea-repositories/snoopj/sopel.git/sopel/builtins/reload.py", line 53, in f_reload
    bot.reload_plugin(name)
  File "/var/lib/gitea/data/gitea-repositories/snoopj/sopel.git/sopel/bot.py", line 365, in reload_plugin
    meta = plugin_handler.get_meta_description()
  File "/var/lib/gitea/data/gitea-repositories/snoopj/sopel.git/sopel/plugins/handlers.py", line 647, in get_meta_description
    data = super().get_meta_description()
  File "/var/lib/gitea/data/gitea-repositories/snoopj/sopel.git/sopel/plugins/handlers.py", line 321, in get_meta_description
    'version': self.get_version(),
  File "/var/lib/gitea/data/gitea-repositories/snoopj/sopel.git/sopel/plugins/handlers.py", line 620, in get_version
    version = importlib.metadata.version(self.module.__package__)
  File "/home/snoopjedi/.pyenv/versions/3.8.18/lib/python3.8/importlib/metadata.py", line 530, in version
    return distribution(distribution_name).version
  File "/home/snoopjedi/.pyenv/versions/3.8.18/lib/python3.8/importlib/metadata.py", line 503, in distribution
    return Distribution.from_name(distribution_name)
  File "/home/snoopjedi/.pyenv/versions/3.8.18/lib/python3.8/importlib/metadata.py", line 177, in from_name
    raise PackageNotFoundError(name)
importlib.metadata.PackageNotFoundError: sopel_dummy

Reproduction steps

Broken setup.cfg

For a plugin whose top-level import name is sopel_dummy

[metadata]                                                                                                                                                              
name = sopel-dummy-plugin                                                                                                                                               
version = 1.0.0                                                                                                                                                         
description = A dummy plugin for Sopel                                                                                                                                  
author = SnoopJ                                                                                                                                                         
author_email = snoopjedi@gmail.com                                                                                                                                                                                                                                                                
license = Eiffel Forum License, version 2                                                                                                                               
classifiers =                                                                                                                                                           
    Intended Audience :: Developers                                                                                                                                     
    Intended Audience :: System Administrators                                                                                                                          
    License :: Eiffel Forum License (EFL)                                                                                                                               
    License :: OSI Approved :: Eiffel Forum License                                                                                                                     
    Topic :: Communications :: Chat :: Internet Relay Chat                                                                                                              

[options]                                                                                                                                                               
packages = find:                                                                                                                                                        
zip_safe = false                                                                                                                                                        
include_package_data = true                                                                                                                                             
install_requires =                                                                                                                                                      
    sopel>=7.1                                                                                                                                                          

[options.entry_points]                                                                                                                                                  
sopel.plugins =                                                                                                                                                         
    dummy = sopel_dummy

Expected behavior

I expect the plugin to be reloaded

Relevant logs

No response

Notes

No response

Sopel version

973a489

Installation method

pip install

Python version

3.8.18

Operating system

Ubuntu 20.04

IRCd

No response

Relevant plugins

No response