Search code examples
pythonsetuptools

how to execute a script that will modify my package at build time?


We have the following package structure:

.
├── genreate_source/
│   ├── generate_schema.py
│   ├── generate_source.py
│   └── __init__.py
├── ipyvuetify/
│   ├── template.py
│   ├── Html.py
│   ├── Themes.py
│   ├── Template.py
│   └── _init__.py
├── pyproject.toml
└── setup.py

the main package is ipyvuetify but the content is generated from the vuetify.js API. To buid the source, we need to execute a function that live in generate_source.py. Until now we were adding these source at release time but that makes developping in the lib complicated. We try to make the build automatic and included in the python build.

When we try to importe "genreate_source" module in the setup.py it doesn't work (moduleNotFound). Is it normal and can we call this script from septup ?


Solution

  • at the beggining of the setup.py file, You need to add the parent directory to sys so that the included files become callable.

    Here is the skeleton of a build command that will create extra file:

    import sys
    from pathlib import Path
    
    from pynpm import NPMPackage
    from setuptools import Command, setup
    from setuptools.command.egg_info import egg_info
    
    ROOT = Path(__file__).parent
    sys.path.append(str(ROOT))
    
    from generate_source import generate_source  # noqa
    
    
    def js_prerelease(command: Command) -> None:
        """Decorator for building minified js/css prior to another command"""
    
        class DecoratedCommand(command):
            """Decorated command to install jsdeps first."""
    
            def run(self):
                """Run the command"""
                NPMPackage(ROOT / "js" / "package.json").install()
                generate_source.generate()
                self.distribution.data_files = get_data_files()
                command.run(self)
    
        return DecoratedCommand
    
    
    setup(cmdclass={"egg_info": js_prerelease(egg_info)})