vsc-install为UGent的HPC小组开发的python库提供共享的setuptools函数和类
项目描述
描述
vsc-install为UGent的HPC小组开发的python库提供共享的setuptools函数和类
常见问题
如果您的install_requires = 'setuptools',则bdist_rpm将失败,因为它将无法找到setuptools rpm。
export VSC_RPM_PYTHON=1
将确保在install_requires中为构建RPM的包添加python-前缀,因此将使用python-setuptools。
添加测试
测试是位于test目录中的python模块,它们是TestCase的子类,并且至少有一个以test_开头的方法。
建议使用
from vsc.install.testing import TestCase
(而不是来自unittest的基本TestCase)。
任何__main__
或suite()
都不需要( anymore)。
使用以下命令初始化测试目录
mkdir -p test
echo '' > test/__init__.py
echo 'from vsc.install.commontest import CommonTest' > test/00-import.py
当运行测试时,test
、lib
和bin
(如果相关)将添加到sys.path
中,因此不需要在测试模块中这样做。
运行测试
python setup.py test
使用-F
(测试模块名称)和-f
(测试方法名称)筛选测试
另请参阅
python setup.py test --help
依赖项将自动安装在.eggs
目录中。它将首先尝试安装到github.ugent.be
,然后是github.com
。与通过克隆原始存储库的方法相同(http、ssh等)。如果您需要私有依赖项,请始终使用ssh克隆。
如果出现以下错误,则表示有一个无法导入的测试模块XYZ
。
File "setup.py", line 499, in loadTestsFromModule
testsuites = ScanningLoader.loadTestsFromModule(self, module)
File "build/bdist.linux-x86_64/egg/setuptools/command/test.py", line 37, in loadTestsFromModule
File "/usr/lib64/python2.7/unittest/loader.py", line 100, in loadTestsFromName
parent, obj = obj, getattr(obj, part)
AttributeError: 'module' object has no attribute 'XYZ'
您可以通过尝试获取实际的导入错误来修复问题
python -c 'import sys;sys.path.insert(0, "test");import XYZ;'
修复失败的测试
-
缺少或不正确的
LICENSE
-
将适当的许可文件复制到项目目录下的
known_licenses
目录中,并将文件命名为LICENSE
-
缺少
README.md
-
创建一个包含至少一个
描述
部分的README.md
文件 -
按照https://github.com/hpcugent/vsc-install/blob/master/lib/vsc/install/headers.py 中的说明修复许可头
cd <project dir with .git folder> REPO_BASE_DIR=$PWD python -m vsc.install.headers path/to/file script_or_not
使用 find 一次性修复它们所有
find ./{lib,test} -type f -name '*.py' | REPO_BASE_DIR=$PWD xargs -I '{}' python -m vsc.install.headers '{}' find ./bin -type f -name '*.py' | REPO_BASE_DIR=$PWD xargs -I '{}' python -m vsc.install.headers '{}' 1
不要忘记检查 diff。没有文档字符串(或魔法注释 '### END OF HEADER')的模块/脚本(包括测试模块)将得到正确头文件的追加。添加文档字符串(或魔法注释)以解决这个问题。
-
Python 脚本(即具有 python shebang 并作为脚本安装的)必须使用
#!/usr/bin/env python
作为 shebang -
删除任何
build_rpms_settings.sh
剩余文件 -
除非您真的知道自己在做什么(即它确实与默认值不同),否则
setup.py
中的TARGET
字典应该是最小的 -
删除
name
、scripts
等 -
例外:vsc 命名空间包不允许非共享命名空间
-
添加到
__init__.py
"""
Allow other packages to extend this namespace, zip safe setuptools style
"""
import pkg_resources
pkg_resources.declare_namespace(__name__)
bare-except
try:
# something
except:
这是不好的,因为此 except 也会捕获 sys.exit() 或 Keyboardinterupts,这些通常是不希望捕获的,如果您捕获这些,程序将处于奇怪的状态,然后继续运行,而刚刚按下 Ctrl+C 的人会想知道发生了什么以及为什么它没有停止。
所以至少将这个 except 改为 Exception(它不会捕获 sys.exit 和 KeyboardInterupt),如果您能真正弄清楚预期哪些异常,并只捕获这些异常,那么如果您无意中发生了某些事情,程序会崩溃,这有助于开发者更好地在其端捕获奇怪的错误。
如果您这样做
try:
Path(int(somestring)).write_text('important data')
except Exception:
pass # if somestring is not an integer, we didn't need to write anyway, but otherwise we do
因为您知道有时这个字符串不包含一个整数,所以 int() 调用可能会失败,您应该只捕获 ValueError,因为这也会在您的磁盘已满、您没有权限或 xxx 其他原因失败时失败,并且重要数据将不会被写出来,没有人会注意到任何事情!
if not 'a' in somelist -> if 'a' not in somelist
这并不是什么大问题,但如果每个人都保持一致,那么在不需要添加或删除 not 的情况下引入错误的几率会更小。这还有助于代码审查,可读性更好,就像英语一样。
arguments-differ
如果您覆盖了超类的一个函数但未使用相同数量的参数,这将给您错误。现在 linter 会为您捕获这个错误
unused-argument
如果您有一个函数定义接受了一个在函数体中从未使用的参数,这将现在给出一个错误。清理您的函数定义,或修复您实际需要考虑这个参数的错误。
unused-variable
定义一个变量然后不再使用它很不好,为什么你会这么做?有时你会做这样的事情
out, exit_code = run_command(something)
但是你并不关心 out,只关心退出代码,在这种情况下,写
_, exit_code = run_command(something)
使用 _ 作为变量名让 pylint 和其他读者知道您最初并不打算使用该输出。
reimported
当您在别处重新导入一个名称时,这通常只是一个过多导入,或者有两个具有相同名称的导入,请注意。
import six
from django import six
=>
import six
from django import six as django_six
未使用名称的重定义
这通常也指向您没有预料到的事情
from vsc.accountpageclient import VscGroup
<snip>
class VscGroup(object):
pass
=> 你需要这个导入吗?使用 import,就像你真的想使用相同的名称一样? ...
Redefined builtin
使用不同的名称,例如更改
def filter(b_b):
"""Function filter"""
return b_b
=>
def new_filter(b_b):
"""Function filter"""
return b_b
日志非延迟
如果不必要,请勿在日志中使用字符串插值
import logging
name = 'world'
program ='python'
logging.info('Hello %s! This is %s.' % (name, program))
=>
import logging
name = 'world'
program ='python'
logging.info('Hello %s! This is %s.', name, program)
修复 Python 3 失败的测试
- 我们尽量遵循https://docs.pythonlang.cn/3/howto/pyporting.html
- 一些有用的信息也可以在这里找到 https://portingguide.readthedocs.io/en/latest/index.html
异常处理中的解包/在处理器中重定义
多个异常必须像这样的元组中分组
...
except (ExceptionOne, ExceptionTwo) ...
...
(特别是当使用像 except A, B:
这样的方式时,应该使用 except (A, B):
。)
旧的 raise 语法
Python 2 的 raise 语句是在异常还不是类的时候设计的,一个异常的 类型、值 和 跟踪 部分是三个独立的对象。在 Python 3 中,一个单一的对象包含了有关异常的所有信息。
raise NameError, "Error"
=>
raise NameError("Error")
或更改
raise NameError, "Error", some_traceback
=>
raise NameError("Error")
e = NameError("Error")
e.__traceback__ = some_traceback
反引号
A = 2
B = `A`
=>
A = 2
B = str(A)
旧的 ne 操作符
if 2 <> 3:
=>
if 2 != 3:
八进制字面量
os.chmod(foo, 0700)
=>
os.chmod(foo, 0o700)
导入星号模块级别
不要导入 *,更具体一些。如果不可能,请在顶层导入(并抑制 pyflakes 错误 F403。)
def coords(angle, distance):
"""Function coords"""
from math import *
return distance * cos(angle), distance * sin(angle)
=>
from math import * # noqa: F403
def coords(angle, distance):
"""Function coords"""
return distance * cos(angle), distance * sin(angle)
引发字符串
raise ValueError, 'message'
=>
raise ValueError('message')
异常索引
except IndexError as err:
err[0]
=>
except IndexError as err:
IndexError.args[0]
关闭这些错误
如果你在这些情况下认为:是的,我确实需要这样做,我在修补猴子,我正在添加额外的功能,这些功能确实有额外的(默认)参数等,你可以通过添加例如的注释 # pylint: disable=<name or numeric id of pylint code>
来让 pylint 知道忽略这个错误在这个特定代码块中。
class Something(object):
def dosomething(self, some, thing):
# do something
class MyFancyThing(SomeThing):
# pylint: disable=arguments-differ
def dosomething(self, some, thing, fancy=None):
# do something fancy
所有代码的完整列表可在 http://pylint-messages.wikidot.com/all-codes 获取
自动生成的 Jenkinsfile
/ tox.ini
vsc-install
支持通过以下方式自动生成 Jenkinsfile
(以及相应的 tox.ini
):
python -m vsc.install.ci
在 Jenkinsfile
或 tox.ini
上的失败检查
有专门的测试来检查 Jenkinsfile
和 tox.ini
文件是否由 vsc-install
自动生成。
要修复测试,只需使用 python -m vsc.install.ci
并使用最新版本的 vsc-install
来重新生成 Jenkinsfile
和 tox.ini
,然后提交并推送更改。
如果最新版本的 vsc-install
自动生成的文件内容因任何原因不正确,你可以通过添加一个名为 Jenkinsfile.NOT_AUTOGENERATED_YET
或 tox.ini.NOT_AUTOGENERATED_YET
的文件来暂时绕过失败的测试。
该文件 必须 包含通过 https://github.com/hpcugent/vsc-install/issues/new 创建的 vsc-install 问题的 URL,其中报告了不正确生成的文件。
示例
echo "see https://github.com/hpcugent/vsc-install/issues/1234 for more info" > Jenkinsfile.NOT_AUTOGENERATED_YET
在 PR 标题中要求 JIRA 问题引用
要也在 Jenkinsfile
中添加对 JIRA 问题引用(如 [HPC-1234]
)的检查,请将配置文件 python -m vsc.install.ci
命名为 vsc-ci.ini
并将其添加到存储库中,如下所示
[vsc-ci]
jira_issue_id_in_pr_title=1
运行 shellcheck
要也在生成的 Jenkinsfile
中运行 shellcheck
,请通过 vsc-ci.ini
配置文件指定
[vsc-ci]
run_shellcheck=1
向 Jenkinsfile 添加额外的测试命令
如果需要通过 Jenkinsfile
运行额外的自定义测试命令(除 shellcheck
之外),您可以通过 additional_test_commands
在 vsc-ci.ini
配置文件中指定此内容。
添加单个自定义测试命令
[vsc-ci]
additional_test_commands=./more_test.sh
添加多个测试命令
[vsc-ci]
additional_test_commands=
first-test-cmd
second-test-cmd
third-test-cmd
覆盖脚本安装位置
在某些存储库中,我们通过 setup.cfg
(例如,查看 icinga-checks
存储库)指定脚本的全局安装位置,这会在在 tox 环境中安装 vsc-install
时引起问题。
要覆盖脚本的安装前缀(仅在运行测试的 tox 环境中),请通过 vsc-ci.ini
配置文件指定此内容
[vsc-ci]
install_scripts_prefix_override=1
使用 'easy_install' 安装 tox
由于历史原因,easy_install 仍然被支持。如果您仍然需要它,可以启用它(不推荐)
[vsc-ci]
easy_install_tox=1
避免在仓库检出时运行 pip install
对于某些仓库,由于 setup.cfg
包含 pip
不应获取的内容,因此从检出仓库中运行 pip install
来安装 tox
会导致问题。
对于这些仓库,您可以通过以下方式指定 Jenkinsfile
中的安装命令应从 $HOME
运行:
[vsc-ci]
home_install=1
利用系统(Python)包
如果仓库需要作为操作系统包安装的 Python 包作为依赖项(例如,pyslurm
),tox 必须配置为在测试环境中继承这些包。这可以通过以下方式启用:
[vsc-ci]
inherit_site_packages=1
在运行测试前预装依赖项
尽管 vsc-install
将在运行测试之前自动安装 setup.py
中列出的所有依赖项,但有些情况下这并不按预期工作。一些 Python 包仅支持使用 pip install
安装(例如,因为它们使用跨越多个不同 Python 包的命名空间,如 fs
和 fs.sshfs
)。
您可以通过 vsc-ci.ini
中的 pip_install_test_deps
指定在运行测试之前应安装(使用 pip install
)的 Python 包
[vsc-ci]
pip_install_test_deps=
foo
bar<1.0
这将在 tox.ini
的 commands_pre
部分添加相应的 pip install
命令
[testenv]
commands_pre =
pip install 'foo'
pip install 'bar<1.0'
pip install 'setuptools<42.0'
python -m easy_install -U vsc-install
项目详情
vsc_install-0.21.0.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 991617ea9bb884a89d32eb0c88a360a4c3d85d15f1ecbdefe8cfcee2c4c21e14 |
|
MD5 | afbb24261e9384f6c29154c7f3165c71 |
|
BLAKE2b-256 | 9f3a0bc31269a5effab0800f76d6ea0c82db1fdf2c72811ef1fc7a3e9be0ac94 |