从源文件获取conda meta.yaml的包版本

时间:2016-08-12 13:58:14

标签: python conda

我正在尝试重新组织我的python包版本,所以我只需要在一个地方更新版本,最好是python模块或文本文件。对于我需要我的版本的所有地方,似乎有一种方法从源from mypkg import __version__加载它或至少将其作为文本从文件中解析出来。我似乎找不到使用我的conda meta.yaml文件的方法。有没有办法从meta.yaml文件中的外部源加载版本?

我知道有git环境变量,但我不想标记通过本地conda存储库测试的每个alpha / beta / rc提交。我可以在pyyaml中使用!!python/object加载python对象,但是conda不支持任意python执行。我没有看到任何其他jinja2功能的方法。我还可以编写一个脚本来更新多个版本号,但我真的希望只修改一个文件作为最终版本号。谢谢你的帮助。

3 个答案:

答案 0 :(得分:5)

conda-build-3.16.1(2018年11月)开始,这是在conda配方中以编程方式设置version的方法。

here所述,这些示例是传递给meta.yaml的{​​{1}}的一部分。

A。点按conda-build的版本:

如果您构建python软件包,则此食谱非常理想,因为setup.py仍然需要它,因此您必须已经弄清楚了。

setup.py

请注意,有时候,如果与{% set data = load_setup_py_data() %} package: name: mypackage version: {{ data.get('version') }} 不在同一个目录中,则必须明确告知conda配方在哪里可以找到它:

setup.py

,然后继续:

{% set data = load_setup_py_data(setup_file='../setup.py', from_recipe_dir=True) %}

B。 Git环境变量

如果您的项目使用git标记,并且您使用conda接受为有效版本号的标记格式(例如$ conda-build conda-recipe 2.5.1),则此食谱很好。

v2.5.1

,然后继续:

package:
  name: hub
  version: {{ GIT_DESCRIBE_TAG }}

C。传递环境变量:

这对于非Python conda软件包很有用,该软件包的版本来自不同的地方,您可以完善其价值-例如将$ conda-build conda-recipe 转换为v2.5.1

2.5.1

然后创建一个获取版本的可执行脚本,我们将其称为package: name: mypkg version: {{ environ.get('MYPKG_VERSION', '') }}

,现在继续加载将设置版本的环境变量:

script-to-get-mypkg-version

根据conda-build版本的不同,您可能必须使用$ MYPKG_VERSION=`script-to-get-mypkg-version` conda-build conda-recipe 而不是os.environ.getdocs使用后者。


这不起作用

请注意,如果过去曾经奏效,如2016年的一份答复所述,现在就行不通了。

environ.get

package: name: mypkg build: script_env: - VERSION $ VERSION=`script-to-get-mypkg-version` conda-build conda-recipe 在这种情况下会忽略环境变量conda-build

source

答案 1 :(得分:3)

有很多方法可以访问您的终端。这就是康达本身所做的事情......

conda的版本信息的真实来源是__version__中的conda/__init__.py。它可以像你建议的那样在python代码中以from conda import __version__的形式加载。它也很难连接到setup.py here(注意this code),因此从命令行python setup.py --version获取该信息的规范方法。< / p>

在1.x版本的conda-build中,添加一行

$PYTHON setup.py --version > __conda_version__.txt
build.sh中的

将使用我们的真实来源为构建的包设置版本。 不推荐使用__conda_version__.txt文件,并且可能会在发布conda-build 2.0时将其删除。在conda-build的最新版本中,执行此操作的首选方法是在jinja2上下文中使用load_setup_py_data(),这样您就可以访问setup.py中的所有元数据。具体来说,在meta.yaml文件中,我们有类似的内容

package:
  name: conda
  version: "{{ load_setup_py_data().version }}"

现在,如何在__version__ ...

中设置conda/__init__.py变量

see in the source codeauxlib.packaging.get_version()函数的调用setup.py file。此功能按顺序执行以下操作

  1. 首先查找文件conda/.version,如果找到则返回内容作为版本标识符
  2. 查看VERSION环境变量的下一个,如果设置,则返回值作为版本标识符
  3. 查看git describe --tags输出的最后一个,并在可能的情况下返回版本标识符(必须安装git,必须是git repo等等)
  4. 如果以上都不产生版本标识符,请返回None
  5. 现在还有一个最后的伎俩。在conda的Dart JS Library, how to pass callback functions中,我们将cmdclassbuild_py的{​​{1}}设置为sdist提供的auxlib.packaging。基本上我们有

    from auxlib import packaging
    setup(
        cmdclass={
            'build_py': packaging.BuildPyCommand,
            'sdist': packaging.SDistCommand,
        }
    )
    

    这些特殊的命令类实际上修改了构建/安装包中的conda/__init__.py文件,因此__version__变量被硬编码为字符串文字,并且不使用{{1}功能。

    在您的情况下,不想标记每个版本,您可以使用上述所有内容,并从命令行使用auxlib.packaging.get_version()环境变量设置版本。像

    这样的东西
    VERSION

    在您的VERSION=1.0.0alpha1 conda build conda.recipe 部分meta.yaml配方中,您需要添加一个build密钥,告诉conda-build将script_env环境变量一直传递给构建环境。

    VERSION

答案 2 :(得分:0)

手册__version__

如果您在单独的_version.py中拥有版本,则可以在不加载整个程序包的情况下进行导入。

# coding: utf-8
# file generated by setuptools_scm
# don't change, don't track in version control
version = '0.0.9.post2+g6481728.d20200518.dirty'

对于我来说,这是自动生成的,但下一步保持不变。

__init__.py中,您有一行from ._version import version as __version__

,然后在setup.py中可以执行以下操作。 这也是我在狮身人面像conf.py

中导入版本的方式
source_dir = Path("src/<my_package>")
sys.path.insert(0, str(source_dir))

from _version import  version

setup(version=version)
...

或者,您可以尝试手动解析文件,而不是导入_version文件,因此不必向sys.path添加文件

,然后在meta.yaml

{% set data = load_setup_py_data() %}
{% set version = data.get('version')  %}


package:
  name: <my_package>
  version: {{ version }}

我遇到了相反的问题。我忘了不时更新其版本,因此一直在寻找一种方法来将git存储库作为软件包版本的单一来源。我使用了setuptools_scm

我已经尝试了很多方法,无论是否符合pep517标准pyproject.toml等,但最终,这是最适合我的方法。

这样做的好处是您不需要那么大的versioneer.py,但是它会在构建时写入_version.py

setup.py

from setuptools import setup
import setuptools_scm


def my_local_scheme(version: setuptools_scm.version.ScmVersion) -> str:
    """My local node and date version."""
    node_and_date = setuptools_scm.version.get_local_node_and_date(version)
    dirty = ".dirty" if version.dirty else ""
    return str(node_and_date) + dirty

version = setuptools_scm.get_version(
    write_to="src/<my_package>/_version.py",
    version_scheme="post-release",
    local_scheme=my_local_scheme,
)
setup(version=version,)

setup()中其余的setup.cfg元数据和选项。需要在那里的一个是

[options]
package_dir=
    =src
packages = <my_package>
install_requires = setuptools_scm

src/<my_package>/_version.py

生成:

# coding: utf-8
# file generated by setuptools_scm
# don't change, don't track in version control
version = '0.0.3.post0+g887e418.d20200518.dirty'

,然后将其添加到我的.gitignore

src/<my_package>/__init__.py

"""<package_description>"""
from ._version import version as  __version__

meta.yaml

{% set data = load_setup_py_data() %}
{% set version = data.get('version')  %}


package:
  name: capacity_simulation
  version: {{ version }}

source:
  path: .

build:
  noarch: python
  number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }}
  script: python -m pip install --no-deps --ignore-installed .
  include_recipe: False

requirements:
  build:
    - setuptools_scm
...

pyproject.toml

也可以使用pip wheel .

您需要pyproject.toml

中的此部分
[build-system]
requires = ["setuptools>=34.4", "wheel", "setuptools_scm"]
build-backend = "setuptools.build_meta"