New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: 推广基于 PEP 420 的命名空间插件 #535
Comments
可以参阅 https://v2.nonebot.dev/api/plugin.html#load-from-json-file-path-encoding-utf-8 https://v2.nonebot.dev/api/plugin.html#load-from-toml-file-path-encoding-utf-8 从配置文件加载插件 至于namespace这个暂时不会对用户开放,由于pip的包管理能力较差,容易导致混乱
建议和guido互怼 |
这两个函数我有提到:
|
不喜欢下划线的不止我,还有 PEP 8。 |
使用 |
顺便还有个问题 插件作者为什么要写成namespace插件,目前看来更多的是将自用插件发布到商店,然而namespace插件需要新建一个包结构,并且发布,相比目前的发布流程更复杂。 |
另外自动发现插件这个问题 你可以看看nonebot.plugin.manager |
就算采用了此规范,PyPI 的包名也仍然是 |
namespace问题+1:插件间冲突,插件编写混乱 namespace存在文件覆盖问题 怎么能把流氓放进家里 无法保证插件质量与规范的情况下不会这么干 当然你也可以强行这么干 |
立即使用 |
插件名也没强制你使用
|
是非常好的建议,非常感谢你花精力考虑改进 NoneBot 2,不过我个人认为
这些缺点确实相比带来的“遵守 PEP”这一个好处,成本还是有点高了。 有时候为了遵循标准而引入过多维护或升级开销,并不是很值得的,对于 NoneBot 这样的项目,用起来直观是最重要的,要让用户(包括插件开发者)的心智负担最小。 至于其他讨论,看其他活跃开发者吧~ |
非常抱歉,由于在外面前面的评论没有仔细整理。 你的方案在nonebot2早期开发中已经考虑过相似问题并否决了,存在的问题还有不少,暂时无法对这部分问题作出改动 我认为暂时的解决方案是使用 感谢你的建议! |
试了一下这个方法确实挺方便的。不过个人认为
写成 namespace 插件的原因我已经说过了。 发布流程更复杂的确也是一个缺点,但同时也带来了安装方便的优点。为什么会有这么多包管理器?明明开发者发布时需要考虑各个包管理器的安装,很麻烦,为什么不直接把源码发出来,让用户下载下来编译一下直接用?答案就是要方便用户。我的这个提议也是相同的道理。 此外,目前已经有许多插件发布在了 PyPI 上。我没有找到发布插件相关的文档,不清楚在不发包的情况下、是否同样能够发布插件。如果答案是否定的,那么也就没有了复杂这一说,只需要新建一两个文件夹,移动一下文件就行了。
这一问题的确没有考虑到。没有详细了解过这一问题,抱歉暂时无法给出解决方案。
完全可以采用
我也不清楚规定是什么,因为发布插件的文档目前是空的。但是目前的事实是,大多数插件都是如此命名的,在插件名前加上这个前缀已经是不成文的规定了。
如果是要避免意外的覆盖,可以要求每个插件需要有各自的目录,并且规定名字不能重复。 但如果是要避免故意的覆盖,或许可以想办法解决。如果各位开发者愿意,我们可以进一步讨论研究一下这个问题。
好处并不是遵守 PEP,而是解决我提出的后两个问题;在我看来,对于这一 PEP 甚至没有遵不遵守一说——它只是提供了一个新功能而已。我引用 PEP 的目的仅仅是为了说明这一方法有 python 的语言特性支持,而这也是我提议这种方式、而不是其他方式的原因。
我提议的这一改变虽然会加大插件开发者的负担,但会减少插件使用者的负担。参见前面的和包管理器的类比。 在我忙着回复的同时各位似乎已经定好了不采纳的结论。如果在看完我的回复后依然选择不采纳我会关闭 issue,但如果希望继续讨论、尝试解决各位指出的、这个提议的几个问题的话,我也愿意继续下去。 |
pypi发布的插件都是 你见过python import的时候使用 |
看你把之前那条删掉了,就没有回复这一点。 这里并没有涉及到 import,用户要么通过函数加载插件,要么按照提议自动加载插件,不需要考虑这一点。 Edit: 还是说你的意思是,即便是通过函数加载,也会遇到同样的问题?这样的话一个方法是直接自动加载,这样包名的问题就不再考虑,有下划线也无所谓;或者尝试让函数转换;或者放弃解决这一问题。 不过我本来也是没有说清楚,说下划线难看的意思是现在包名前面的前缀太难看了,并不是要针对下划线本身。 |
前面你发的pep8就规定了只能使用下划线 另外是为了保证插件可以被正常方式import |
并没有这种规定,见下方解释。
就拿 $ pip install nb-cli import nb_cli 下载时用的名字和导入时用的是两个不同的名字;插件名字里带有减号并不影响导入。同样见下方解释。 首先需要了解 module 和 package 的区别。假设有如下文件:
那么 由此可以发现插件属于 package,而 "Python packages should also have short, all-lowercase names, although the use of underscores is discouraged",因此在条件允许时,应尽力避免下划线。 其次,需要分清代码中 package 的名字,和 PyPI 上 package 的名字。前者适用 PEP 8,且需要遵守 python 语法(也就是说它必须是一个合法的标识符,像减号肯定就是不允许的);后者适用 PEP 508,不需要遵守 python 语法(请尝试运行 这两个名字不一定需要一样,例如在前者是 |
我再明确说一遍
最后
插件改名又没人拦着你,你自己改个名字不行嘛 下划线换成短横或者去掉不就行了吗 |
另外开发团队群里指出的其他问题
↑包括我之前所提到的 namespace 文件覆盖问题,也是我认为 namespace 不应该向用户开放的原因
|
PEP 420提供的是,package定义来自于上层(主包,如nonebot),而所有下层目录以子模块形式出现,发布时依赖于主模块的package定义(如nonebot.plugin.help, nonebot.plugin.test, nonebot.plugin.docs,他们的发布均需要依赖于nonebot2的模块定义),且这些子模块不是真正的完整package,目前无法被pypi搜索。 PEP 420更适合于:子模块的开发有统一的管理,使用者知晓每一个子模块,所有子模块从属于主模块,主模块甚至根据子模块的出现而变化自身的功能实现。 PEP 420不适合于:子模块的开发来自于社区分别开发,使用者需要查询子模块,子模块与主模块之间具有相对较大的独立性。 对于这种子模块插件的开发,由于发布时必须依赖主模块的定义,容易造成命名空间污染。 此外,由于这类子模块无法控制加载顺序,无法实现子模块互相依赖,必须提前获知子模块之间的依赖,本质上并不方便使用者。 由于命名空间的共享问题,是会出现如下情形的: # foo和bar两个包都在path内
# foo.name.first, bar.name.second为两个函数
import name.first
import name.second
# 正常生效,均import成功
# 此时,name空间实际上混合了foo.name和bar.name的内容,危险! |
@shniubobo 不可否认的是,nonebot2 相关文档的缺失,大伙都是看在眼里的 但是看起来目前本 Issue 的发展和最初的提问及建议存在出入,有一些应于现在明确的观点 作为同样不使用 nb-cli 的 nonebot2 项目和插件开发者,我认为
另外,本 Issue 目前的发展多围绕 PEP 标准进行讨论,表示理解但又没有完全理解。 因为我不明白的是,在您看来,命名空间到底能为 nonebot2 带来什么样的优势呢? |
很有道理,子模块并不特别适合 nonebot 的场景。
对于这一问题我先前有提出解决方法:“如果是要避免意外的覆盖,可以要求每个插件需要有各自的目录,并且规定名字不能重复。”具体来说规定这样的目录:
from nonebot.plugins import plugin_foo
from nonebot.plugins import plugin_bar
# plugin_foo.name.first 和 plugin_bar.name.second 没有混合
这同时涉及到第一和第三个问题。我提出的第一个问题并不是这一提议需要解决的重点,并且我也已经列出了现有的解决方案,这一问题几乎可以忽视。至于第三个问题,这可能和我的个人习惯有关。我习惯使用 不过考虑到这仅仅是我个人的习惯,的确会有很多人不总是加载所有安装了的插件,因此自动加载所有插件的功能并不适合所有人,同时也可能并不符合 nonebot 的设计理念。不过我也有提出过解决方法:“或者提供开关,控制是否自动加载。”或者也可以定义一个函数,允许用户调用后自动加载所有已安装的插件。请问这两种解决方法是否可以接受?
这里我想确认一点,目前大多插件采用的前缀是否是标准命名? 此外,即便旧的名字难以改变,也可以通过更改标准,确保新的名字好看。一个例子:
解决方案确实存在,但既然某些人(包括我)不认为它好用,那这个方法在这些人眼里自然就称不上“解决方案”。他们并不是无视了这个解决方案;对于他们来说,这不是解决方案。当然如果这些人的想法与 nonebot 的设计理念相悖,并因此决定不再提供更多解决方案,我认为这也完全可以接受。
我提到 PEP 的时候主要有这些原因:
优势就是解决了我一开始提到的那三个问题之中的后两个。 不过既然你会这么问,那么我认为或许这在你的眼中并不能算上优势。从其他各位开发者的回复来看,或许这一提议的优势也是微乎其微,并不能超过它带来的劣势。每个人的想法有所不同我认为很正常,虽然在各位眼中似乎这两个问题甚至可能称不上问题,在我眼中这两个问题的解决会是极大的优势。 最后,既然一片反对,是否应该继续讨论下去,还是说直接驳回这一提议? |
首先你先要把用户放在不可信的角度,你无法强制规定插件名称不同,也没有这个精力来审核每一个发布的插件。
我更希望用户插件能更加简单方便,直观。 另外poetry也无法代表一切,你无法保证每个人的环境都没有被污染,新手可能都无法理解依赖管理 所以你就是想偷懒自动加载 |
这是一种“约定俗成”,并不具有强制性。只要包名和项目名不与 PyPI 上的其他项目重复,怎么取都行。
插件开发者无法知道用户的环境里会不会有一个名为 logging 的包,所以为了保险起见就给插件加上了 nonebot 的前缀。 前缀并不是为了美观,而是一种保险。 |
需要明确一点,我从来没有认为需要去掉前缀,也没有认为前缀是为了美观。 |
现状
目前插件若通过
nonebot.load_plugin
与nonebot.load_plugins
加载,可能会导致出现这种代码:其中存在这样几个问题:
其中第一项虽然可以通过
nonebot.load_all_plugins
,nonebot.load_from_json
或nonebot.load_from_toml
解决,但剩余问题仍然存在。可能的解决方案
插件作者方面
依照 PEP 420 修改插件文件布局。例如:
框架方面
若需解决上述第二个问题
插件作者修改文件布局后,插件可以在通过
pip
安装后直接使用目前的nonebot.load_builtin_plugins
导入,例如:考虑到函数名的问题,以及多次调用同一函数带来的不便,可以定义以下函数:
若需进一步解决上述第三个问题
通过
pkgutil.iter_modules
等函数获得nonebot.plugins
下的所有模块,并自动加载。该解决方案的缺点
其中第一项随着时间的推移可以慢慢解决,且迁移仅需更改文件夹结构,难度较小。第二项难以避免,用户自行编写而没有发布的插件使用旧风格加载较为方便。第三项不需要考虑,为用户自身的问题;或者提供开关,控制是否自动加载。
参考
请项目维护者们考虑该提议是否可行,谢谢!
The text was updated successfully, but these errors were encountered: