簡體   English   中英

Python package 帶有可選的命名空間子包

[英]Python package with optional namespace sub-packages

問題

我正在努力創建一個單一的入口點來安裝 python package,它利用命名空間子包來允許用戶有選擇地下載其他模塊。 下面是我在這個例子中掙扎的部分。 我還在下面提供了額外的上下文來澄清問題。

starwars\setup.py [不起作用]

import setuptools

setuptools.setup(
    name="starwars",
    packages=setuptools.find_namespace_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent"
    ],
    python_requires=">=3.7",
    install_requires=[
        'common'
    ],
    extra_requires={
        'characters': ['characters'],
        'weapons': ['weapons']
    }
)
$ pwd
> ~/starwars

$ pip install .
> ERROR: No matching distribution found for common

$ pip install .[characters]
> zsh: no matches found: .[characters]

$ pip install .[weapons]
> zsh: no matches found: .[weapons]

項目目標

我正在嘗試創建一個 python package 和可選的命名空間子包依賴項,我可以從私有 git 存儲庫安裝它。 以下是命令外觀的示例。

# Installs only the common subpackage
$ pip install -e git+https://github.com/user/project.git#egg=starwars
# OR
$ $ pip install -e .

# Installs the common and characters subpackage
$ pip install -e git+https://github.com/user/project.git#egg=starwars[characters]
# OR
$ $ pip install -e .[characters]

# Installs only the common and weapons subpackage
$ pip install -e git+https://github.com/user/project.git#egg=starwars[weapons]
# OR
$ $ pip install -e .[weapons]

項目結構

\starwars
-- setup.py

-- common
  |-- setup.py
  |-- starwars
     |-- utils
     |-- abstract

-- characters (Optional)
  |-- setup.py
  |-- starwars
     |-- jedi
     |-- sith
     |-- senators

-- weapons (Optional)
  |-- setup.py
  |-- starwars
     |-- blaster
     |-- lightsabers

starwars\common\setup.py

import setuptools


setuptools.setup(
    name="common",
    packages=setuptools.find_namespace_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent"
    ],
    python_requires=">=3.7",
    install_requires=[
        "asyncio",
        "turtle"
    ]
)

starwars\characters\setup.py

import setuptools


setuptools.setup(
    name="characters",
    packages=setuptools.find_namespace_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent"
    ],
    python_requires=">=3.7",
    install_requires=['common']
)

starwars\weapons\setup.py

import setuptools


setuptools.setup(
    name="weapons",
    packages=setuptools.find_namespace_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent"
    ],
    python_requires=">=3.7",
    install_requires=['common']
)

當前狀態

我已經成功設置了本機命名空間子包,並且可以使用以下命令單獨安裝它們。

$ pwd
> ~/starwars

# Installing the common package
$ pushd ./common
$ pip install .
$ python -c 'import starwars.utils;'
$ popd

# Installing the characters package
$ pushd ./characters
$ pip install .
$ python -c 'import starwars.jedi;'
$ popd

# Installing the weapons package
$ pushd ./weapons
$ pip install .
$ python -c 'import starwars.lightsabers'
$ popd

參考

這是對我有用的 setup.py。 我從這篇文章中得到靈感

starwars/setup.py

import subprocess
from setuptools import setup
from setuptools.command.install import install


try:
    import pypandoc
    long_description = pypandoc.convert_file('README.md', 'rst')
except(IOError, ImportError):
    long_description = open('README.md').read()


class InstallLocalPackage(install):
    description = "Installs the subpackage specified"
    user_options = install.user_options + [
        ('extra=', None, '<extra to setup package with>'),
    ]

    def initialize_options(self):
        install.initialize_options(self)
        self.db = None

    def finalize_options(self):
        assert self.db in (None, 'characters', 'weapons'), 'Invalid extra!'
        install.finalize_options(self)

    @staticmethod
    def install_subpackage(subpackage_dir: str):
        dir_map = {
            'common': './common',
            'characters': './characters',
            'weapons': './weapons'
        }

        subprocess.call(
            f"pushd ./{dir_map[subpackage_dir]}; "
            f"pip install .;"
            f"popd;",
            shell=True
        )

    def install_subpackages(self):
        if self.db is None:
            [self.install_subpackage(package) for package in ['common', 'characters', 'weapons']]
        else:
            [self.install_subpackage(package) for package in ['common', self.db]]

    def run(self):
        install.run(self)
        self.install_subpackages()



setup(
    name="starwars",
    version_format='{tag}.{commits}',
    setup_requires=['very-good-setuptools-git-version'],
    author_email="will.udstrand@emailprovider.com",
    description="Star Wars Python Package",
    long_description=long_description,
    long_description_content_type="text/markdown",
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent"
    ],
    python_requires=">=3.7",
    cmdclass={ 'install': InstallLocalPackage },
    install_requires=[
        "pandas",
        "asyncio"
    ]
)


暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM