如何禁用将包上传到 PyPi 除非将 --public 传递给上传命令

2024-05-01

我正在开发包并将包的开发/测试/等版本上传到本地 devpi 服务器。

为了防止意外上传到PyPi,我采用了以下常见做法:

setup(...,
      classifiers=[
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 2.7",
        "Private :: Do not Upload"
     ],
     ...)

效果很好,但是当我最终准备好将包上传到 PyPi 时呢?

我想出了一个完全丑陋但简单的技巧,它要求我将分类器定义为 setup() 调用之外的全局变量,如下所示:

CLASSIFIERS = [
    "Programming Language :: Python",
    "Programming Language :: Python :: 2",
    "Programming Language :: Python :: 2.7"
]


if "--public" not in sys.argv:
     CLASSIFIERS.append("Private :: Do Not Upload")
else:
     sys.argv.remove("--public")

setup(...
      classifiers=CLASSIFIERS,
      ...)

另一个也许更简单的选择是仅仅注释掉“Private :: Do not Upload”,但这似乎并不比我的黑客更专业。

我会做什么like要做的就是创建一个名为上传命令的适当子类SafeUpload并让它检查--publiccmd 行选项。也许,由于在上传之前可能存在构建,SafeBuild可能是一个更好的选择。

不幸的是,我无法理解有关创建自定义命令的 setuptools 文档。

有谁知道如何实现这个?我不清楚自定义命令是否有权访问传递给的参数setup(),即它可以直接操纵classifiers传递给setup(),或者如果它要求命令的用户遵循将 CLASSIFIERS 定义为全局变量的约定yuck?


倒退你的问题;虽然它确实很广泛,但主题仍然足够有限。

我可以告诉你,分类器不是被操纵的,而是从 中读取然后写入PKG-INFO文件由egg_info命令,依次查找所有egg_info.writers入口点setuptools.command.egg_info:write_pkg_info https://github.com/pypa/setuptools/blob/master/setuptools/command/egg_info.py#L394函数将进行实际的写入。据我所知,尝试在外部利用该分类器并不是一个好方法,但是您可以覆盖一切 and anything你想要通过setuptools这样你就可以自己制作write_pkg_info函数,弄清楚如何读取元数据 https://docs.python.org/3/distutils/examples.html#reading-the-metadata(你可以在主窗口中看到distutils.command.upload:upload.upload_file https://github.com/python/cpython/blob/master/Lib/distutils/command/upload.py#L116方法)并在 upload_file 最终读取它之前进一步操作它。此时,您可能会认为操纵和使用这个系统会相当烦人。

正如我所提到的,一切都可以被覆盖。您可以创建一个带有公共标志的上传命令,如下所示:

from distutils.log import warn
from distutils.command.upload import upload as orig
# alternatively, for later versions of setuptools:
# from setuptools.command.upload import upload as orig

class upload(orig):
    description = "customized upload command"

    user_options = orig.user_options + [
        ('public', None,
         'make package public on pypi'),
    ]

    def initialize_options(self):
        orig.initialize_options(self)
        self.public = False

    def run(self):
        if not self.public:
            warn('not public, not uploading')
            return
        return orig.run(self)

陪同的setup.py可能看起来像这样。

from setuptools import setup

setup(
    name='my_pypi_uploader',
    version='0.0',
    description='"safer" pypi uploader',
    py_modules=['my_pypi_uploader'],  # assuming above file is my_py_uploader.py
    entry_points={
        'distutils.commands': [
            'upload = my_pypi_uploader:upload',
        ],
    },
)

将其作为包安装到您的环境中,上传命令将替换为您的版本。运行示例:

$ python setup.py upload
running upload
not public, not uploading

使用公共标志重试

$ python setup.py upload --public
running upload
error: No dist file created in earlier command

这很好,因为我根本没有创建任何 dist 文件。您当然可以通过重写来进一步扩展该命令upload_file https://github.com/python/cpython/blob/master/Lib/distutils/command/upload.py#L116方法(在代码中复制)并更改部分以在子类中执行您想要的操作(例如在那里注入私有分类器),由您决定。

您可能还想知道为什么类名是小写的(违反 pep8),这是由于遗留问题以及给定命令的帮助是如何生成的。

$ python setup.py upload --help
...
Options for 'upload' command:

使用“正确”命名的类(例如SafeUpload;记得还要更新entry_point in the setup.py指向这个新的类名)

$ python setup.py upload --help
...
Options for 'SafeUpload' command:

当然,如果此输出是意图,则可以使用标准类命名约定。

尽管说实话,您根本不应该在生产中指定上传,而应该在构建服务器上作为后推送挂钩的一部分执行此操作,因此当项目被推送(或标记)时,构建已完成并且文件被加载到您的私人服务器上,然后只有进一步的手动干预(或者如果推送特定标签则自动干预)才能将包上传到 pypi。但是,上面的示例应该可以帮助您开始执行最初打算做的事情。

最后一件事:你can只是改变self.repository到您的私人 devpi 位置,如果--public标志未设置。您可以在调用之前覆盖它orig.upload_file方法(通过您的定制版本),或者在run;因此,您的代码可以验证存储库 url 不是公共 PyPI 实例,而不是退出。或者,通过操作分布元数据(即分类器)self.distribution.metadata (selfupload实例)。您当然可以创建一个全新的命令来玩这个您喜欢的内容(通过创建一个新的Command子类,并为其添加一个新的入口点)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何禁用将包上传到 PyPi 除非将 --public 传递给上传命令 的相关文章

随机推荐

  • .NET:对象头有什么用?

    在 NET 中 每个对象有 8 个字节的开销 4 个字节是指向对象类型的指针 另外 4 个字节 称为对象头 有何用途 注意 这个问题是在 2010 年提出的 并且是 32 位特定的 开销与位数相关 1 个指针大小用于 对象类型 方法表 1
  • 向元素添加类

    像这样 我有两个选项卡 所以当我单击其中一个选项卡时 它是活动的 逻辑的 现在我试图区分活动选项卡和非活动选项卡 但不是使用 css 属性 但我想向单击的选项卡添加特定的类 如下所示 tab1 addClass active 但是 没有什么
  • 如何避免 C 运行时 (crt*.o) 垃圾

    我有两个C源文件 foo1 c include
  • 条形图中的并排条形

    这是基于这个帖子 https stackoverflow com questions 26913954 make barplot in ggplot2 with summary statistics noredirect 1 comment
  • 如何更改matplotlib中填充线的线宽?

    有没有办法增加 matplotlib 中剖面线的宽度 例如 下面的代码通过指定linewidth仅改变边缘的宽度 我想更改用于填充的线的线宽 import matplotlib pyplot as plt import numpy as n
  • 在 WPF 中展开 TreeView 时显示“请稍候...”消息

    我的 TreeView 中有很多项目 而且项目也非常复杂 我不想使用虚拟化 展开 TreeView 有时需要花费大量时间 因此 是否有任何事件 例如 IsTreeViewExpanding 或类似的事件 我可以在其中显示 正在生成 Tree
  • 替换 lambda 表达式中的参数类型

    我正在尝试将 lambda 表达式中的参数类型从一种类型替换为另一种类型 我在 stackoverflow 上找到了其他答案 即this one https stackoverflow com questions 11159697 repl
  • 修改文本文件而不读入内存

    我试图找出一种修改文本文件 特别是删除特定行 的方法 而无需将文件的大部分读取到内存中或重写整个文件 这里讨论的是大于主内存约 15 50 Gigs 的文件 附 我正在使用Linux 你不会逃避创建一个新文件 所以就硬着头皮去做吧 使用gr
  • 在汇编中显示两位数? [复制]

    这个问题在这里已经有答案了 我对汇编编程完全陌生 在课堂作业的示例中 需要将两个数字相加并显示总和 我发现神秘的是当其是两位数时显示总和 这是我的代码 mov al num1 mov bl num2 add al bl add ax 303
  • 我应该为每个选项卡栏使用单独的 UINavigationController

    根据Apple https developer apple com library ios documentation WindowsViews Conceptual ViewControllerCatalog Chapters Combi
  • Node.js、EventEmitter 为什么使用它

    我有一个问题events EventEmitter在 Node js 中 为什么使用它 示例1和示例2有什么区别 我发现它们是相同的 是吗 什么时候可以实际使用它 let events require events let util req
  • 在 Libgdx 中实现简单运动模糊的意外结果

    在所附的两张图片中 libgdx 的桌面屏幕截图按预期运行 不幸的是 我的 Galaxy Nexus 的屏幕截图与预期不符 我正在尝试创建一个简单的运动模糊或轨迹效果 Rendering as I expected on my deskto
  • C++:输入和输出流运算符:结合性

    输入 输出流运算符理论上的结合性 左到右 例如 根据这个 圣玛丽大学网站 http cs smu ca porter csc ref cpp operators html 输入 输出流运算符结合性实践 include
  • 开源html解析类无法正确解析段落之间的空格

    我正在使用一种开源方法 将 html 文本解析为 NSString 生成的字符串在前几个段落之间有大量空格 但后续段落只有一行空格 这是输出的示例 Below is the method I m calling I ve only chan
  • 如何在 ASP.NET 中将下拉列表与字符串数组绑定?

    我可以通过这样做将下拉列表与字符串数组绑定 不确定这是否是正确的实现方法 string items 111 222 333 ddlSearch DataSource items ddlSearch DataBind 然而 我真正想要的是 当
  • 使用并发.futures.ProcessPoolExecutor 动态创建函数的限制

    我正在尝试使用我在其他函数中动态创建的函数进行一些多重处理 如果提供给 ProcessPoolExecutor 的函数是模块级的 我似乎可以运行这些 def make func a def dynamic func i return i i
  • 仅在一个 JTable 单元格中的复选框

    我想创建一个JTable有 2 列 看起来像一个调查 所以左边是问题 右边是用户可以给出他的答案 但在一行的右侧应该有一个复选框 以便用户只能回答是或否 这可以用JTable 我怎样才能做到这一点 regards 您在评论中指出 我用一列
  • 如何从 CloudFormation 中的 Elastic Beanstalk 环境中提取负载均衡器名称

    我使用以下代码片段在 CloudFormation 中创建了 Elastic Beanstalk 和 CloudWatch 警报 ElasticBeanstalkEnvironment Type AWS ElasticBeanstalk E
  • 使用 Mapstruct 将对象列表转换为长 ID 列表

    我在用MapStruct将实体转换为 DTO 我有一个实体 A 和实体 B 的列表 public class A List b bs 我想要 ADto 类中的 B id 列表 public class ADto List b
  • 如何禁用将包上传到 PyPi 除非将 --public 传递给上传命令

    我正在开发包并将包的开发 测试 等版本上传到本地 devpi 服务器 为了防止意外上传到PyPi 我采用了以下常见做法 setup classifiers Programming Language Python Programming La