创建 debtcollector

https://blueprints.launchpad.net/oslo.utils/+spec/adopt-debtcollector

这个库的目标是提供文档完善的面向开发者的弃用模式,从一个基本集合开始,并随着时间的推移扩展到更大的模式集合(它不会一开始就成为一个用于面向操作者的弃用功能的库,因为这已经在 oslo-incubator 中的 versionutils.py 模块中涵盖了)。

例如,可以考虑以下模式:

  • 弃用一个关键字参数,以便稍后用一个替换关键字参数替换(当稍后确定新名称比初始名称更好时很有用)。

  • 更改属性的名称以引用一个新的改进名称(当发现某个属性名称在一段时间后比初始属性名称更有意义时很有用)。

  • 移动一个类(无论是否破坏从旧位置继承的人);当一个类更适合位于一个不同的(可能更好命名、更有意义的)模块中时,这很有用(当初始位置被认为是一个好的位置时,但经过使用后,另一个位置会更有意义)。

这些模式的期望输出是 warnings 模块的应用,该模块将使用该模块提供的常用函数来发出 DeprecationWarningPendingDeprecationWarning 或类似的派生警告,以告知使用库(或潜在应用)的开发者未来的弃用情况。

由于 warnings 模块支持不同类型的操作,我们应该利用这种能力(或根据需要扩展它),以避免创建一堆垃圾消息,这些消息将出现在使用已弃用功能/功能的开发人员面前。

例如,提供的库/函数应该受到下面定义的/复制的警告模块的操作字符串的影响。

处置

error

将匹配的警告转换为异常

ignore

从不打印匹配的警告(python 2.7+ 中的默认设置)

总是

总是打印匹配的警告

default

打印每个发出警告的位置的匹配警告的首次出现

模块

打印每个模块的匹配警告的首次出现

一次

打印匹配警告的首次出现,无论位置如何

适当使用这些设置预计可以帮助避免污染日志或 sys.stderr,这些消息可能会出现在其中(我们应该研究如何使这些消息在 OpenStack CI 系统中可见,并且在已发布库中不可见或不那么可见)。

为了帮助这个过程,挂接到以下内容可能有用(但这可以留待稍后讨论):

https://docs.pythonlang.cn/2/library/logging.html#logging.captureWarnings

根据未来的功能,我们可以让应用程序使用 logging.captureWarnings 函数,或者在 oslo.log 中提供它,或者做其他事情(关键在于 warnings 模块和支持 API 将是这些模式使用的入口点,应用程序或其他库如何适应/插件到 warnings 模块可以根据需要进行调整和修改)。

库名称

debtcollector

内容

  • debtcollector/__init__.py

  • debtcollector/utils.py(内部工具,不供公开使用)

  • debtcollector/moves.py(用于移动代码/类/属性的常见模式...)

  • debtcollector/renames.py(用于重命名代码/类/属性的常见模式...)

  • ...(随着模式的出现,其他模式)

早期采用者

  • Taskflow

  • 其他人?

公共 API

当前 API 想法(可能会随着新模式的出现而演变...)

  • debtcollector/moves.py

# Patterns devoted to 'moving' functions, methods, classes, arguments...

def moved_decorator(kind, new_attribute_name, message=None,
                    version=None, removal_version=None,
                    stacklevel=3)

 # Creates a decorator of the given kind for the given attribute name
 # with the provided message, version deprecated in, the version it will
 # be removed in and the given stacklevel (used to output the users code
 # location when this decorator is called).
 #
 # An example message:
 >>> kind = 'Property'
 >>> new_attribute_name = 'a'
 >>> what = "%s '%s' has moved to '%s" % (kind, 'b', new_attribute_name)
 >>> deprecation._generate_moved_message(what, message='sorry its going away', version='0.1', removal_version='0.2')
 "Property 'a' has moved to 'b' in version '0.1' and will be removed in version '0.2': sorry its going away"

 def moved_property(new_attribute_name, message=None,
                    version=None, removal_version=None, stacklevel=3):

 # Decorator specialization of moved_decorator that sets the kind to
 # a property instead of allowing it to be specified.

 def moved_class(new_class, old_class_name, old_module_name, message=None,
                 version=None, removal_version=None, stacklevel=3):

 # Same as moved_decorator but for classes, returns a class proxy that can
 # not be inherited from (useful for when the user of this is aware that no
 # inheritance is happening)

 def moved_class_inheritable(new_class, old_class_name, old_module_name, message=None,
                             version=None, removal_version=None, stacklevel=3):

 # Same as moved_class but for classes, returns a new-old class that can
 # be inherited from (useful for when the user of this is unaware if any
 # inheritance is happening)

 ...
  • debtcollector/renames.py

# Patterns devoted to 'renaming' functions, methods, classes, arguments...

def renamed_kwarg(old_name, new_name, message=None,
                  version=None, removal_version=None, stacklevel=3):

# Creates a decorator that can be applied to a keyword argument accepting
# method, function, callable that will warn the user of that function
# when they are using the old, to be removed keyword argument; creates
# an appropriate message telling the user this (in a similar format
# as mentioned above).

...
  • debtcollector/utils.py

# Generic *internal* library used utils...

def generate_message(prefix, postfix=None, message=None,
                     version=None, removal_version=None):

# Generates the messages for renames or moves in a common (share as much
# as possible manner) so that the messages look and feel like they are
# coming from a common library

...

实现

负责人

主要负责人

  • Harlowja

其他贡献者

  • 你?

主要维护者

主要维护者

  • Harlowja (@yahoo)

其他贡献者

  • Szhukov (@yahoo)

  • 你?

安全联系人

安全联系人:harlowja

里程碑

完成目标里程碑:kilo-2

工作项

  • 更改 Launchpad 项目的所有者(使其成为 Oslo 项目组的一部分)

  • 授予 openstackci 在 PyPI 上的 Owner 权限

  • 创建初始仓库

  • 让库做一些事情

  • 更新 README.rst

  • 发布 git 仓库

  • Oslo 团队审查新仓库

  • Infra 项目配置

  • 更新 Gerrit 组和 ACL

  • openstack-infra/devstack-gate 调整

  • openstack/requirements projects.txt 调整

  • 更新 docs.openstack.org 上的项目列表

  • 标记一个发布版本

  • 盈利!

采用说明

N/A

依赖项

需求

注意

所有当前计划的依赖项都在 requirements 仓库中。

参考资料

注意

本作品采用知识共享署名 3.0 非移植许可协议授权。 http://creativecommons.org/licenses/by/3.0/legalcode