Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specifying external dependencies #1712

Open
BlueMagma2 opened this issue Sep 5, 2024 · 5 comments
Open

Specifying external dependencies #1712

BlueMagma2 opened this issue Sep 5, 2024 · 5 comments

Comments

@BlueMagma2
Copy link

Introduction

There currently exists a draft proposing a way to declare external dependencies in pyproject,toml: https://peps.python.org/pep-0725/

For example in some of my project I specify the following section in my pyproject.toml:

[external]
dependencies = ["pkg:generic/ffmpeg"]

What I expect this will do is add a line in the METADATA file of my build packages as specified here: https://packaging.python.org/en/latest/specifications/core-metadata/#requires-external-multiple-use

Requires-External: pkg:generic/ffmpeg

Currently no build system properly handle this. Since I was using poetry I made a poetry plugin that takes care of detecting this section and adding the relevant line in METADATA during build: https://pypi.org/project/poetry-external-dependencies/

Then when deploying my package to different system I use a script that detect the external dependency and install what's required on the host system, in the example case it would automatically install ffmpeg using apt or apk or other package manager the system offer.

Question

Is there an existing way to have hatch automatically add the Requires-External line in METADATA ?

If not, is there any way to achieve this, or would the plugin system of hatch be capable of supporting this ?

@ofek
Copy link
Collaborator

ofek commented Sep 5, 2024

Thanks! Does it look like the PEP will be accepted? I haven't followed the progress on it.

@BlueMagma2
Copy link
Author

I have no idea whether the pep will be accepted. But regardless of that, Requires-External is part of the spec for packages metadata , so there need to be a way to specify it

@BlueMagma2
Copy link
Author

In case anyone is wondering how to do this, I solve my issue using a build hook, I might turn this into a plugin if I get the time:

from copy import deepcopy

from hatchling.builders.hooks.plugin.interface import BuildHookInterface
from hatchling.metadata.core import ProjectMetadata

class CustomBuildHook(BuildHookInterface):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def initialize(self, version: str, build_data: dict[str, any]) -> None:
        self._default_constructor = self.build_config.core_metadata_constructor

        def metadata_constructor_extended(local_self, metadata: ProjectMetadata, extra_dependencies: tuple[str] | None = None) -> str:
            metadata_file = self._default_constructor(metadata, extra_dependencies)

            external_dependencies = None
            if 'external-dependencies' in metadata.core.config:
                external_dependencies = deepcopy(metadata.core.config['external-dependencies'])

            elif 'external' in metadata.config and 'dependencies' in metadata.config['external']:
                external_dependencies = deepcopy(metadata.config['external']['dependencies'])

            if external_dependencies:
                header_section = metadata_file
                content_section = ''
                if 'Description-Content-Type' in metadata_file:
                    split_file = metadata_file.split('Description-Content-Type')
                    header_section = split_file[0]
                    content_section = split_file[1]
                
                print(f"  - {self.PLUGIN_NAME}")
                for dependency in external_dependencies:
                    print(f"    - Requires-External: {dependency}")
                    header_section += f'Requires-External: {dependency}\n'
                metadata_file = header_section +'Description-Content-Type' + content_section
            
            return metadata_file

        type(self.build_config).core_metadata_constructor = metadata_constructor_extended

@BlueMagma2
Copy link
Author

For reference, I've made it into a plugin: https://pypi.org/project/hatch-external-dependencies/

@ofek
Copy link
Collaborator

ofek commented Sep 11, 2024

Thanks! I'll keep this open until there is official support, likely when the PEP gets accepted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
@ofek @BlueMagma2 and others